From: d11n Date: Wed, 6 Oct 2021 20:24:16 +0000 (+0200) Subject: Vuepress migration (#55) X-Git-Url: http://internal-gitweb-vhost/script/%22https:/database/scripts/static/struct.Init.html?a=commitdiff_plain;h=4b283c6e4749b1bbc0991a288ee2e05fc34b77fd;p=bitcoindevkit.org Vuepress migration (#55) * Vuepress migration basics * Integrate mermaid plugin * Update homepage content * Update colors * Start extracting theme * Extract theme config * Move theme to external package * Extract common variables and fonts * Update theme and colors * Update CTA color * Upgrade dependencies * Update theme * Update landing page copy and site navigation * Updates main copy and add Discord to main navigation * Add tutorials page * Updates main copy and add Discord to main navigation * Fix paper wallet iframe * Improve supporters list * Improve descriptor tables * Integrate playground * Fix blog article URLs * Update code and note colors * Fix links * Fix links Co-authored-by: ConorOkus --- diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000000..c306b6fe4c --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,46 @@ +name: Build + +on: + # Run the build for pushes and pull requests targeting master + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [16] + + steps: + # Checkout doc repo and its dependencies + - name: Checkout + uses: actions/checkout@v2 + # Setup Node + - name: Setup (Node.js ${{ matrix.node-version }}) + uses: actions/setup-node@v1 + with: + node-version: ${{ matrix.node-version }} + # Install and build + - name: Install + run: npm ci + - name: Build + run: npm run build + # Deploy, limited to the master branch + - name: Deploy + if: success() && github.ref == 'refs/heads/master' + uses: peaceiris/actions-gh-pages@v3 + with: + publish_dir: ./docs/.vuepress/dist + github_token: ${{ secrets.GITHUB_TOKEN }} + cname: bitcoindevkit.org + user_name: 'github-actions[bot]' + user_email: 'github-actions[bot]@users.noreply.github.com' + # Run linkcheck, propagate linkcheck failure through grep pipe + - name: Linkcheck + run: set -o pipefail; npm run linkcheck 2>/dev/null | grep "Getting links from\|BROKEN" + continue-on-error: true diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml deleted file mode 100644 index 425285cfe8..0000000000 --- a/.github/workflows/publish.yml +++ /dev/null @@ -1,27 +0,0 @@ -name: publish -on: - push: - branches: - - master - -jobs: - build: - name: Build and publish - runs-on: ubuntu-latest - env: - HUGO_VERSION: 0.79.0 - if: github.ref == 'refs/heads/master' - steps: - - name: Checkout - uses: actions/checkout@v2 - with: - fetch-depth: '0' - submodules: 'recursive' - - name: Configure git - run: git config user.email "github-actions@github.com" && git config user.name "github-actions" - - name: Install Hugo - run: curl -OL https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_${HUGO_VERSION}_Linux-64bit.deb && sudo dpkg -i hugo_${HUGO_VERSION}_Linux-64bit.deb && rm -v hugo_*.deb - - name: Run build - run: ./publish_to_ghpages.sh - - name: Push commit - run: cd public && git push origin gh-pages diff --git a/.gitignore b/.gitignore index 69d9321068..612c2b4cf2 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,14 @@ -/public +# Dependencies +node_modules -*.swp +# Production +/docs/.vuepress/dist + +# Misc +.DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local + +npm-debug.log* diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 6433a7d0e7..0000000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "themes/learn"] - path = themes/learn - url = https://github.com/matcornic/hugo-theme-learn.git diff --git a/README.md b/README.md index 4c966c512c..1b87635e3f 100644 --- a/README.md +++ b/README.md @@ -1,45 +1,107 @@ # bitcoindevkit.org -This website is built with [Hugo](https://gohugo.io). +[![Build Status](https://github.com/bitcoindevkit/bitcoindevkit.org/workflows/Build/badge.svg)](https://github.com/bitcoindevkit/bitcoindevkit.org/actions?query=workflow%3A%22Build%22) -To clone this project use the --recursive option to also clone the themes/learn submodule: +### Build the Documentation Locally - ``` - git clone --recursive git@github.com:bitcoindevkit/bitcoindevkit.org.git - ``` +In order to build the website locally, you'll need [Node.js](https://nodejs.org/) >= 14.16 (or basically the latest LTS version). -If you are editing this website, you can run +The setup is straight forward: - ``` - hugo server - ``` +```bash +# Install dependencies +npm install -to start a local webserver at [`http://localhost:1313`](http://localhost:1313). +# Serve locally (by default on port 8080) +npm start +``` + +### Text Highlights + +There are [three types of text highlights](https://vuepress.vuejs.org/guide/markdown.html#custom-containers) that can be used to display different colored boxes. + +A green box displaying a friendly tip: -# generating docs-rs +```md +:::tip +foo +::: +``` + +A yellow box with a cautious warning: + +```md +:::warning +foo +::: +``` -To create or re-create the contents of `static/docs-rs/bdk/`, copy the contents of +A red box with a clear danger, you can also add a title `foo` to any container: + +```md +:::danger foo +bar +::: +``` + +### SEO improvements + +We are using the [Vuepress SEO plugin](https://www.npmjs.com/package/vuepress-plugin-seo) to add relevant meta tags to the site and individual pages. + +To improve the meta attributes of a specific page, you can add them as YAML frontmatter like this: (see the WooCommerce page for an example) + +```text +--- +description: How to integrate BDK +tags: +- Bitcoin +- BDK +--- +# BDK integration + +This document explains how to **integrate BDK into your stack**. +``` + +### Embedding YouTube videos + +To add a YouTube video with a preview, you can so so by linking to it like this: + +```md +[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/YOUTUBE_VIDEO_ID_HERE/mqdefault.jpg)](https://www.youtube.com/watch?v=YOUTUBE_VIDEO_ID_HERE) +``` + +Note that the link item need to be a preview image (either from YouTube or a custom one) to result in an embedded video. + +### Check for broken links + +The GitHub Actions pipeline checks for broken links after deploying the production site. +You can also run the link check locally using `npm run linkcheck:local`. +The dev server needs to be running alongside for this to work. + +## Generating docs-rs + +To create or re-create the contents of `static/docs-rs/bdk/`, copy the contents of the `bdk/target/doc` directory after running the below commands from the `bdk` project directory: - ``` - cargo clean - cargo +nightly rustdoc --features=compiler,electrum,esplora,compact_filters,key-value-db -- --cfg docsrs - ``` +```bash +cargo clean +cargo +nightly rustdoc --features=compiler,electrum,esplora,compact_filters,key-value-db -- --cfg docsrs +``` A nightly toolchain is required because some cool features, like `intra_rustdoc_links` and `doc_cfg`, are still unstable. -# adding a blog post +## Adding a blog post Add a markdown file to `content/blog/.md`. At the beginning of the file add the following header: -``` +```yaml --- title: "" description: "" author: "" date: "" -tags: ["", "] +tags: ["", ""] hidden: true draft: false --- diff --git a/archetypes/default.md b/archetypes/default.md deleted file mode 100644 index 00e77bd79b..0000000000 --- a/archetypes/default.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -title: "{{ replace .Name "-" " " | title }}" -date: {{ .Date }} -draft: true ---- - diff --git a/config.toml b/config.toml deleted file mode 100644 index bf32f9ed37..0000000000 --- a/config.toml +++ /dev/null @@ -1,73 +0,0 @@ -baseURL = "https://bitcoindevkit.org/" -languageCode = "en-us" -title = "Bitcoin Dev Kit" -theme = "learn" - -[outputs] -home = ["HTML", "RSS", "JSON"] - -[params] -# Prefix URL to edit current page. Will display an "Edit this page" button on top right hand corner of every page. -# Useful to give opportunity to people to create merge request for your doc. -# See the config.toml file from this documentation site to have an example. -editURL = "https://github.com/bitcoindevkit/bitcoindevkit.org/edit/master/content/" -# Author of the site, will be used in meta information -author = "Alekos Filini - @afilini" -# Description of the site, will be used in meta information -description = "The Bitcoin Dev Kit project aims to build a collection of tools and libraries that are designed to be a solid foundation for Bitcoin wallets." -# A title for shortcuts in menu is set by default. Set this to true to disable it. -# disableShortcutsTitle = false -# Hide breadcrumbs in the header and only show the current page title -disableBreadcrumb = true -# Hide Next and Previous page buttons normally displayed full height beside content -disableNextPrev = true -# Order sections in menu by "weight" or "title". Default to "weight" -ordersectionsby = "weight" -# Change default color scheme with a variant one. Can be "red", "blue", "green". -themeVariant = "blue" -# Provide a list of custom css files to load relative from the `static/` folder in the site root. -custom_css = ["css/style.css", "css/jsonview.css", "css/blog.css"] -# Used for social media preview cards -images = ["images/logo-wide.jpg"] - -# Disable the "copy to clipboard" button for inline code -disableInlineCopyToClipBoard = true - -[permalinks] -tags = "/blog/tags/:slug" -author = "/blog/authors/:slug" -blog = "/blog/:year/:month/:title/" - -[taxonomies] -tag = "tags" -author = "authors" -category = "categories" - -# render raw html -[markup.goldmark.renderer] -unsafe = true - -[[Languages.en.menu.shortcuts]] -name = " Stable Docs" -url = "https://docs.rs/bdk" -weight = 5 - -[[Languages.en.menu.shortcuts]] -name = " Nightly Docs" -url = "/docs-rs/bdk/nightly/latest/bdk" -weight = 5 - -[[Languages.en.menu.shortcuts]] -name = " Playground" -url = "/bdk-cli/playground" -weight = 10 - -[[Languages.en.menu.shortcuts]] -name = " Follow on Twitter" -url = "https://twitter.com/intent/follow?screen_name=bitcoindevkit" -weight = 15 - -[[Languages.en.menu.shortcuts]] -name = " Chat on Discord" -url = "https://discord.gg/dstn4dQ" -weight = 20 diff --git a/content/Supporters/_index.md b/content/Supporters/_index.md deleted file mode 100644 index c5851a558e..0000000000 --- a/content/Supporters/_index.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: "Supporters" -date: 2020-04-28T14:40:12+02:00 -draft: false -weight: 10 -pre: ' ' ---- - -The Bitcoin Dev Kit project is proudly supported by: - -{{% sponsors %}} \ No newline at end of file diff --git a/content/_index.md b/content/_index.md deleted file mode 100644 index 90fbd26b7f..0000000000 --- a/content/_index.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: "Home" -date: 2020-04-28T09:46:18+02:00 -draft: false ---- - -# Bitcoin Dev Kit - -The [Bitcoin Dev Kit (BDK)](https://github.com/bitcoindevkit) project (originally called Magical Bitcoin 🧙) aims to build a collection of tools and libraries that are designed to be a solid foundation for cross platform Bitcoin wallets, along with a fully working *reference implementation* wallet called Magical Bitcoin. -All BDK components are designed to be lightweight and modular so that they can be adapted for virtually any use-case: from single-sig mobile wallets to multi-billion-dollar cold storage vaults. - -The main long-term goal is to concentrate the development efforts of multiple people and companies into one open source and very well reviewed project, instead of dispersing them over multiple closed/semi-closed or -poorly designed projects. - -While some parts of the library are still considered "experimental" (check the docs for more info), the core `Wallet` architecture is now considered stable. We still can't commit to keeping this same exact API forever, -but we are not expecting to do any major breaking change in that area. - -If you want to try out the library for your projects, now it's finally a good time to do it! You can start by checking out the ["getting started"](/blog/tags/getting-started/) section in our blog or joining our [Discord](https://discord.gg/dstn4dQ) -server to chat with us. - -## Playground - -As a way of demonstrating the flexibly of this project, a minimalistic command line tool (called `bdk-cli`) is available as a debugging tool in the [`bdk-cli`](https://github.com/bitcoindevkit/bdk-cli) -repo. It has been compiled to WebAssembly and can be used directly from the browser. See the [playground](/bdk-cli/playground) section to give it a try! - -The playground relies on [Esplora](https://blockstream.info) to monitor the blockchain and is currently locked in testnet-only mode, for obvious safety reasons. The native command line tool can also be used in regtest mode when installed on -a computer. See the [bdk-cli](/bdk-cli) section to learn more. - -## Descriptors - -One of the original milestones of this project was to provide wallets with "almost magically" support for very complex spending policies, without having to individually translate them into code. It may sound disappointing, but there isn't, in fact, -any real magic in this wallet: the generalization is achieved thanks to *descriptors*, that are now slowly starting to see adoption in a few other Bitcoin projects as well. - -The author of this project strongly believes descriptors will be a big part of the future generation of Bitcoin wallets, since they provide a very flexible scripting language that can also be extended as the -technology and tooling of Bitcoin evolves and changes (Schnorr signatures, Taproot, etc). - -To learn more, check out the specific [Descriptors section](/descriptors). diff --git a/content/authors/alekos-filini/_index.md b/content/authors/alekos-filini/_index.md index db7e6452cb..45246c1506 100644 --- a/content/authors/alekos-filini/_index.md +++ b/content/authors/alekos-filini/_index.md @@ -1,6 +1,6 @@ --- name: Alekos Filini -photo: +photo: twitter: afilini mastodon: https://bitcoinhackers.org/@afilini github: https://github.com/afilini/ diff --git a/content/authors/gabriele-domenichini/_index.md b/content/authors/gabriele-domenichini/_index.md index 2fc54d6fd7..b65238ef80 100644 --- a/content/authors/gabriele-domenichini/_index.md +++ b/content/authors/gabriele-domenichini/_index.md @@ -1,8 +1,8 @@ --- name: Gabriele Domenichini -photo: +photo: twitter: Gabridome mastodon: https://bitcoinhackers.org/@Gabridome github: https://github.com/gabridome/ -web: +web: --- diff --git a/content/authors/rajarshi-maitra/_index.md b/content/authors/rajarshi-maitra/_index.md index 3e3220876f..0ccc46e040 100644 --- a/content/authors/rajarshi-maitra/_index.md +++ b/content/authors/rajarshi-maitra/_index.md @@ -1,8 +1,8 @@ --- name: Rajarshi Maitra -photo: +photo: twitter: rajarshimaitra mastodon: https://bitcoinhackers.org/@raj github: https://github.com/rajarshimaitra/ web: ---- \ No newline at end of file +--- diff --git a/content/authors/riccardo-casatta/_index.md b/content/authors/riccardo-casatta/_index.md index ae30b1da87..d22cef3fd5 100644 --- a/content/authors/riccardo-casatta/_index.md +++ b/content/authors/riccardo-casatta/_index.md @@ -1,8 +1,8 @@ --- name: Riccardo Casatta -photo: +photo: twitter: RCasatta mastodon: https://bitcoinhackers.org/@rcasatta github: https://github.com/RCasatta/ -web: +web: --- diff --git a/content/authors/steve-myers/_index.md b/content/authors/steve-myers/_index.md index b52d8a7ccf..3102c971f0 100644 --- a/content/authors/steve-myers/_index.md +++ b/content/authors/steve-myers/_index.md @@ -1,6 +1,6 @@ --- name: Steve Myers -photo: +photo: twitter: notmandatory mastodon: https://bitcoinhackers.org/@notmandatory github: https://github.com/notmandatory/ diff --git a/content/authors/thunderbiscuit/_index.md b/content/authors/thunderbiscuit/_index.md index f03daff947..98b1ec7298 100644 --- a/content/authors/thunderbiscuit/_index.md +++ b/content/authors/thunderbiscuit/_index.md @@ -1,6 +1,6 @@ --- name: Thunderbiscuit -photo: +photo: twitter: thunderB__ mastodon: https://fosstodon.org/@thunderbiscuit github: https://github.com/thunderBiscuit diff --git a/content/bdk-cli/_index.md b/content/bdk-cli/_index.md deleted file mode 100644 index 92b80b0b48..0000000000 --- a/content/bdk-cli/_index.md +++ /dev/null @@ -1,13 +0,0 @@ -+++ -title = "BDK CLI" -date = 2020-04-28T17:03:00+02:00 -weight = 1 -chapter = true -pre = ' ' -+++ - -# BDK-CLI - -The [bdk-cli](https://github.com/bitcoindevkit/bdk-cli) repo has an example interactive shell built -using the `bdk` library called `bdk-cli` that acts both as a reference implementation of a wallet -and a tool to quickly experiment with descriptors and transactions. diff --git a/content/bdk-cli/compiler.md b/content/bdk-cli/compiler.md deleted file mode 100644 index da497eaa51..0000000000 --- a/content/bdk-cli/compiler.md +++ /dev/null @@ -1,151 +0,0 @@ ---- -title: "Compiler" -date: 2020-04-29T12:06:50+02:00 -draft: false -weight: 5 -pre: "5. " ---- - -## Introduction - -If you want to play around with more complicated spending policies, you'll start to find it harder and harder to manually create the descriptors. This is where the miniscript compiler comes in! The `bdk` library -includes a very simple compiler that can produce a descriptor given a spending policy. The syntax used to encode the spending policy is very well described [in this page](http://bitcoin.sipa.be/miniscript/), -specifically in the "Policy to Miniscript compiler". The compiler included in BDK does basically the same job, but produces descriptors for `rust-miniscript` that have some minor differences from -the ones made by the C++ implementation used in that website. - -## Installation - -To install the miniscript compiler run the following command: - -```bash -cargo install --git https://github.com/bitcoindevkit/bdk --features="compiler" --example miniscriptc -``` - -Once the command is done, you should have a `miniscriptc` command available. You can check if that's the case by running `miniscriptc --help`. - -## Usage - -In this case the interface is very simple: it accepts two arguments called "POLICY" and "TYPE", in this order. The first one, as the name implies, sets the spending policy to compile. The latter defines the type -of address that should be used to encapsulate the produced script, like a P2SH, P2WSH, etc. - -Optionally, the `--parsed_policy` flag can be enabled and it will make the compiler print the JSON "human-readable" version of the spending policy, as described in the [`policies subcommand`](/bdk-cli/interface/#policies) of the CLI. - -The `--network` flag can be used to change the network encoding of the address shown. - -{{% notice tip %}} -Keep in mind that since the compiler loads and interprets the descriptor, all the public keys specified in the policy must be valid public keys. This differs from the web tool linked above that also accepts -placeholders too. As described in the previous sections of this guide, the keys can be either `xpub`/`xprv` with or without metadata and a derivation path, WIF keys or raw hex public keys. -{{% /notice %}} - -## Example - -Let's take this policy for example: - -```bash -miniscriptc --parsed_policy "and(pk(cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR),or(50@pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),older(1000)))" sh-wsh -``` - -The compiler should print something like: - -```text -[2020-04-29T10:42:05Z INFO miniscriptc] Compiling policy: and(pk(cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR),or(50@pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),older(1000))) -[2020-04-29T10:42:05Z INFO miniscriptc] ... Descriptor: sh(wsh(and_v(or_c(c:pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),v:older(1000)),c:pk(cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR)))) -[2020-04-29T10:42:05Z INFO miniscriptc] ... First address: 2MsqrJuZewY3o3ADAy1Uhi5vsBqTANjH3Cf -``` - -JSON policy: - -{{% json %}} -{ - "type":"THRESH", - "items":[ - { - "type":"THRESH", - "items":[ - { - "type":"SIGNATURE", - "pubkey":"02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c", - "satisfaction":{ - "type":"NONE" - }, - "contribution":{ - "type":"NONE" - } - }, - { - "type":"RELATIVETIMELOCK", - "value":1000, - "satisfaction":{ - "type":"NONE" - }, - "contribution":{ - "type":"COMPLETE", - "condition":{ - "csv":1000 - } - } - } - ], - "threshold":1, - "satisfaction":{ - "type":"NONE" - }, - "contribution":{ - "type":"PARTIALCOMPLETE", - "n":2, - "m":1, - "items":[ - 1 - ], - "conditions":{ - "[1]":[ - { - "csv":1000 - } - ] - } - } - }, - { - "type":"SIGNATURE", - "pubkey":"02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c", - "satisfaction":{ - "type":"NONE" - }, - "contribution":{ - "type":"COMPLETE", - "condition":{ - - } - } - } - ], - "threshold":2, - "satisfaction":{ - "type":"NONE" - }, - "contribution":{ - "type":"PARTIALCOMPLETE", - "n":2, - "m":2, - "items":[ - 0, - 1 - ], - "conditions":{ - "[0, 1]":[ - { - "csv":1000 - } - ] - } - } -} -{{% /json %}} - -## Troubleshooting - -#### Nothing is printed - -This might mean that you have a `RUST_LOG` variable set to a value that suppresses the compiler's log. You can try adding `miniscriptc=info` to your `RUST_LOG` value and see if that works, or open a new clean -shell. diff --git a/content/bdk-cli/concept.md b/content/bdk-cli/concept.md deleted file mode 100644 index 96078eacd1..0000000000 --- a/content/bdk-cli/concept.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "Concept" -date: 2020-04-28T17:38:20+02:00 -draft: false -weight: 2 -pre: "2. " ---- - -Now, in order to better grasp some of the design choices made by BDK, it's important to understand the main concept driving the development of this project, and the goal that it's trying to -achieve. - -BDK is aiming first of all to be a **set of libraries and tools**, all meant to be very reusable and adaptable. Developers working on their own wallets or other projects that are trying to integrate -Bitcoin can pick the tools they need and piece them together to prototype and quickly ship a working product. This means that the `bdk-cli` that we've just installed is designed to be a **very thin layer** over the -APIs exposed by the various components of the library, **not a full, end-user-ready Bitcoin wallet**. - -This concept leads to a few design choices that are arguably very bad for the "UX" of this wallet, but that allow developers to work more directly with the underlying library. For instance: - -* BDK has an internal database that's used to store data about received transactions, spendable UTXOs, etc. This database is stored by default in your home folder, in `~/.bdk-bitcoin`. The database - **will never** contain any data that can't be recreated purely by looking at the blockchain. Keys, descriptors, Electrum endpoints **are not stored in the database**. This explains why you'll have to specify them every - time in the command line. It can be seen more like a *cache* and can be safely deleted without risking funds. -* BDK doesn't automatically "monitor" the blockchain, instead there's a `sync` command that has to be called by the user. -* When you create a transaction and then sign it, it's not automatically broadcast to the network. There's a `broadcast` command that does this. Moreover, the command doesn't accept a normal Bitcoin raw transaction, - but instead a *PSBT*. That's because internally transactions are always moved as PSBTs, and again, the `broadcast` command is just a very thin wrapper over the raw library call. - -There are probably more of these examples, but hopefully by this point you'll have more or less understood the gist of it. If you are not a developer, some parts of this will feel weird, inefficient, hard -to understand, and that's absolutely normal. Just try to survive through the pain and you'll be rewarded! diff --git a/content/bdk-cli/installation.md b/content/bdk-cli/installation.md deleted file mode 100644 index e6ded74d3c..0000000000 --- a/content/bdk-cli/installation.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: "Installation" -date: 2020-04-28T17:11:29+02:00 -draft: false -weight: 1 -pre: "1. " ---- - -## Requirements - -The only requirement to run the `bdk-cli` tool is a Linux/macOS system with a fairly recent Rust -toolchain installed. Since Linux distros tend to lag behind with updates, the quickest way to -install the Rust compiler and Cargo is [rustup.rs](https://rustup.rs/). You can head there and -follow their instructions, after which you can test if everything went fine by running -`cargo version`, which should print something like: - -``` -cargo 1.53.0 (53cb7b09b 2021-06-17) -``` - -If you really don't want to pipe the output of `curl` into `sh`, you can also try using a -[Docker image](https://hub.docker.com/_/rust) and working inside of it, but that's meant for more -advanced users and won't be covered in this guide. - -{{% notice note %}} -At the time of writing, the project requires cargo >= 1.46.0, which is our minimum supported rust version (MSRV) as of July 2021. If you have an older version installed with rustup.rs, you can upgrade it with `rustup update`. -{{% /notice %}} - -## Installing the `bdk-cli` tool - -Once Cargo is installed, you can proceed to install the interactive `bdk-cli` tool directly from -the GitHub repository, by running: - -```bash -# all features -cargo install --git https://github.com/bitcoindevkit/bdk-cli --features=esplora,compiler - -# minimal install -cargo install --git https://github.com/bitcoindevkit/bdk-cli -``` - -This command may take a while to finish, since it will fetch and compile all the dependencies and the `bdk` library itself. - -Once it's done, you can check if everything went fine by running `bdk-cli --help` which should print something like this: - -```text -BDK CLI 0.2.1-dev -Alekos Filini :Riccardo Casatta :Steve Myers -Top level options and command modes - -USAGE: - bdk-cli [OPTIONS] - -FLAGS: - -h, --help Prints help information - -V, --version Prints version information - -OPTIONS: - -n, --network Sets the network [default: testnet] - -SUBCOMMANDS: - compile Compile a miniscript policy to an output descriptor - help Prints this message or the help of the given subcommand(s) - key Key management sub-commands - repl Enter REPL command loop mode - wallet Wallet options and sub-commands - -``` - -An example command to sync a testnet wallet to a default electrum server looks like this: - -```bash -bdk-cli wallet -w example --descriptor "wpkh(tprv8ZgxMBicQKsPexGYyaFwnAsCXCjmz2FaTm6LtesyyihjbQE3gRMfXqQBXKM43DvC1UgRVv1qom1qFxNMSqVAs88qx9PhgFnfGVUdiiDf6j4/0/*)" sync -``` diff --git a/content/bdk-cli/interface.md b/content/bdk-cli/interface.md deleted file mode 100644 index 83f966610d..0000000000 --- a/content/bdk-cli/interface.md +++ /dev/null @@ -1,531 +0,0 @@ ---- -title: "Interface" -date: 2020-04-28T18:20:28+02:00 -draft: false -weight: 3 -pre: "3. " ---- - -Remember the `bdk-cli --help` command you ran before? Let's analyze its output here to figure out the interface: - -## Flags - -```text -FLAGS: - -h, --help Prints help information - -V, --version Prints version information -``` - -These are the optional flags that can be set with every command. The `-h` flag prints the help message, the `-V` flag only prints the version. - -### Verbosity - -If you want to increase the verbosity of the output, you should use the `RUST_LOG` environment variable. You can set it like so to see a lot more of what's going on behind the scenes, before running the `bdk-cli` -command. You only have to do this once when you open a new shell, after that you can run the `bdk-cli` command multiple times. - -```bash -export RUST_LOG="bdk=debug" -``` - -## Options - -```text -OPTIONS: - -c, --change_descriptor Sets the descriptor to use for internal addresses - -d, --descriptor Sets the descriptor to use for the external addresses - --esplora_concurrency Concurrency of requests made to the esplora server [default: 4] - -e, --esplora Use the esplora server if given as parameter - -n, --network Sets the network [default: testnet] - -p, --proxy Sets the SOCKS5 proxy for the Electrum client - -s, --server - Sets the Electrum server to use [default: ssl://electrum.blockstream.info:60002] - - -w, --wallet Selects the wallet to use [default: main] -``` - -These are the global options that can be set. They are pretty much like the flags, but they also take a value. The only **required** one is the `--descriptor` or `-d` flag, since every wallet **must have an -associated descriptor**. - -The `--change-descriptor` flag can be used to set a different descriptor for the change addresses, sometimes called "internal" addresses in Bitcoin Core. Unfortunately there isn't -[really consensus](https://freenode.irclog.whitequark.org/bitcoin-wizards/2020-01-25#26222504;) on a nice way to encode information about the change derivation inside the standard descriptor, so we are -stuck with having two separate ones. Keep in mind though, that even if you don't specify a change descriptor, you'll still be able to create transactions - the change address will simply be generated from the -standard descriptor. - -The `--network` flag can be used to change the network. Right now only `testnet` and `regtest` are supported since the code is very much not production-ready yet. - -The `--server` flag can be used to select the Electrum server to use. By default it's connecting to Blockstream's electrum servers, which seems pretty stable. -If you are having connection issues, you can also try with one of the other servers [listed here](https://1209k.com/bitcoin-eye/ele.php?chain=tbtc) and see if you have more luck with those. -Right now both plaintext and ssl servers are supported (prefix `tcp://` or no prefix at all for tcp, prefix `ssl://` for ssl). - -The `--esplora` flag can be used to connect to an Esplora instance instead of using Electrum. It should be set to the API's "base url". For public instances of Esplora this is `https://blockstream.info/api` for mainnet -and `https://blockstream.info/testnet/api` for testnet. - -The `--proxy` flag can be optionally used to specify a SOCKS5 proxy to use when connecting to the Electrum server. Spawning a local Tor daemon and using it as a proxy will allow you to connect to `.onion` Electrum -URLs. **Keep in mind that only plaintext server are supported over a proxy.** - -The `--wallet` flag can be used to select which wallet to use, if you have more than one of them. If you get a `ChecksumMismatch` error when you make some changes to your descriptor, it's because it does not -match anymore the one you've used to initialize the cache. One solution could be to switch to a new wallet name, or delete the cache directory at `~/.bdk-bitcoin` and start from scratch. - -## Subcommands - -| Command | Description | -| ------- | ----------- | -| [broadcast](#broadcast) | Broadcasts a transaction to the network. Takes either a raw transaction or a PSBT to extract | -| [bump_fee](#bump_fee) | Bumps the fees of an RBF transaction | -| [combine_psbt](#combine_psbt) | Combines multiple PSBTs into one | -| [create_tx](#create_tx) | Creates a new unsigned tranasaction | -| [extract_psbt](#extract_psbt) | Extracts a raw transaction from a PSBT | -| [finalize_psbt](#finalize_psbt) | Finalizes a psbt | -| [get_balance](#get_balance) | Returns the current wallet balance | -| [get_new_address](#get_new_address) | Generates a new external address | -| [list_transactions](#list_transactions) | Lists all the incoming and outgoing transactions of the wallet | -| [list_unspent](#list_unspent) | Lists the available spendable UTXOs | -| [policies](#policies) | Returns the available spending policies for the descriptor | -| [public_descriptor](#public_descriptor) | Returns the public version of the wallet's descriptor(s) | -| [repl](#repl) | Opens an interactive shell | -| [sign](#sign) | Signs and tries to finalize a PSBT | -| [sync](#sync) | Syncs with the chosen Electrum server | - -These are the main "functions" of the wallet. Most of them are pretty self explanatory, but we'll go over them quickly anyways. You can get more details about every single command by running `bdk-cli --help`. - -### broadcast - -```text -OPTIONS: - --psbt Sets the PSBT to extract and broadcast - --tx Sets the raw transaction to broadcast -``` - -Broadcasts a transaction. The transaction can be a raw hex transaction or a PSBT, in which case it also has to be "finalizable" (i.e. it should contain enough partial signatures to construct a finalized valid scriptsig/witness). - -### bump\_fee - -```text -FLAGS: - -a, --send_all Allows the wallet to reduce the amount of the only output in order to increase fees. This is - generally the expected behavior for transactions originally created with `send_all` - -OPTIONS: - -f, --fee_rate The new targeted fee rate in sat/vbyte - -t, --txid TXID of the transaction to update - --unspendable ... Marks an utxo as unspendable, in case more inputs are needed to cover the extra - fees - --utxos ... Selects which utxos *must* be added to the tx. Unconfirmed utxos cannot be used -``` - -Bumps the fee of a transaction made with RBF. The transaction to bump is specified using the `--txid` flag and the new fee rate with `--fee_rate`. - -The `--send_all` flag should be enabled if the original transaction was also made with `--send_all`. - -### combine\_psbt - -```text -OPTIONS: - --psbt ... Add one PSBT to comine. This option can be repeated multiple times, one for each PSBT -``` - -Combines multiple PSBTs by merging metadata and partial signatures. It can be used to merge multiple signed PSBTs into a single PSBT that contains every signature and is ready to be [finalized](#finalize_psbt). - -### create\_tx - -```text -FLAGS: - -r, --enable_rbf Enables Replace-By-Fee (BIP125) - --offline_signer Make a PSBT that can be signed by offline signers and hardware wallets. Forces the addition - of `non_witness_utxo` and more details to let the signer identify the change output - -a, --send_all Sends all the funds (or all the selected utxos). Requires only one recipients of value 0 - -OPTIONS: - --to ... Adds a recipient to the transaction - --unspendable ... Marks a utxo as unspendable - --external_policy - Selects which policy should be used to satisfy the external descriptor - - --internal_policy - Selects which policy should be used to satisfy the internal descriptor - - --utxos ... Selects which utxos *must* be spent - -f, --fee_rate Fee rate to use in sat/vbyte -``` - -Creates a new unsigned PSBT. The flags allow to set a custom fee rate (the default is 1.0 sat/vbyte) with `--fee_rate` or `-f`, the list of UTXOs that should be considered unspendable with `--unspendable` (this -option can be specified multiple times) and a list of UTXOs that must be spent with `--utxos` (again, this option can also be specified multiple times). - -The `--to` option sets the receiver address of the transaction, and should contain the address and amount in Satoshi separated by a colon, like: `--to 2NErbQPsooXRatRJdrXDm9wKR2fRiZDT9wL:50000`. This option -can also be specified multiple times to send to multiple addresses at once. - -The `--send_all` flag can be used to send the value of all the spendable UTXOs to a single address, without creating a change output. If this flag is set, there must be only one `--to` address, and its value will -be ignored (it can be set to 0). - -The `--external_policy` and `--internal_policy` options are two advanced flags that can be used to select the spending policy that the sender intends to satisfy in this transaction. They are normally not required if there's no ambiguity, but sometimes -with a complex descriptor one or both of them have to be specified, or you'll get a `SpendingPolicyRequired` error. Those flags should be set to a JSON object that maps a policy node id to the list of child indexes that -the user intends to satisfy for that node. This is probably better explained with an example: - -Let's assume our descriptor is: `sh(thresh(2,pk(A),sj:and_v(v:pk(B),n:older(6)),snj:and_v(v:pk(C),after(630000))))`. There are three conditions and we need to satisfy two of them to be able to spend. The conditions are: - -1. Sign with the key corresponding to `pk(A)` -2. Sign with the key corresponding to `pk(B)` AND wait 6 blocks -2. Sign with the key corresponding to `pk(C)` AND wait that block 630,000 is reached - -So if we write down all the possible outcomes when we combine them, we get: - -1. Sign with `pk(A)` + `pk(B)` + wait 6 blocks -2. Sign with `pk(A)` + `pk(C)` + wait block 630,000 -3. Sign with `pk(B)` + `pk(C)` + wait 6 blocks + wait block 630,000 - -In other words: - -* If we choose option #1, the final transaction will need to have the `nSequence` of its inputs set to a value greather than or equal to 6, but the `nLockTime` can stay at 0. -* If we choose option #2, the final transaction will need to have its `nLockTime` set to a value greater than or equal to 630,000, but the `nSequence` can be set to a final value. -* If we choose option #3, both the `nSequence` and `nLockTime` must be set. - -The wallet can't choose by itself which one of these combination to use, so the user has to provide this information with the `--external_policy` flag. - -Now, let's draw the condition tree to understand better how the chosen policy is represented: every node has its id shown right next to its name, like `qd3um656` for the root node. These ids can be seen by running the [policies](#policies) command. -Some ids have been omitted since they are not particularly relevant, in this example we will actually only use the root id. - -{{}} -graph TD; - subgraph " " - R["Root - qd3um656"] --> A["pk(A) - ykfuwzkl"] - R["Root - qd3um656"] --> B["B - ms3xjley"] - B["B - ms3xjley"] --> B_0["pk(B)"] - B["B - ms3xjley"] --> B_1["older(6)"] - end - C["C - d8jph6ax"] --> C_0["pk(C)"] - C["C - d8jph6ax"] --> C_1["after(630,000)"] - R["Root - qd3um656"] --> C["C - d8jph6ax"] -{{< /mermaid >}} - -Let's imagine that we are walking down from the root, and we want to use option #1. So we will have to select `pk(A)` + the whole `B` node. Since these nodes have an id, we can use it to refer to them and say which children -we want to use. In this case we want to use children #0 and #1 of the root, so our final policy will be: `--external_policy {"qd3um656":[0,1]}`. - -### extract\_psbt - -```text -OPTIONS: - --psbt Sets the PSBT to extract -``` - -Extracts the global transaction from a PSBT. **Note that partial signatures are ignored in this step. If you want to merge the partial signatures back into the global transaction first, please use [finalize_psbt](#finalize_psbt) first** - -### finalize\_psbt - -```text -OPTIONS: - --psbt Sets the PSBT to finalize - --assume_height Assume the blockchain has reached a specific height -``` - -Tries to finalize a PSBT by merging all the partial signatures and other elements back into the global transaction. This command fails if there are timelocks that have not yet expired, but the check can be overridden -by specifying `--assume_height` to make the wallet assume that a future height has already been reached. - -### get\_balance - -This subcommand has no extra flags, and simply returns the available balance in Satoshis. This command **should normally be called after [`sync`](#sync)**, since it only looks into the local cache to determine the list of UTXOs. - -### get\_new\_address - -This subcommand has no extra flags and returns a new address. It internally increments the derivation index and saves it in the database. - -### list\_transactions - -This subcommand has no extra flags and returns the history of transactions made or received by the wallet, with their txid, confirmation height and the amounts (in Satoshi) "sent" (meaning, the sum of the wallet's inputs spent in the transaction) and -"received" (meaning, the sum of the outputs received by the wallet). Just like [`get_balance`](#get_balance) it **should normally be called after [`sync`](#sync)**, since it only operates -on the internal cache. - -### list\_unspent - -This subcommand has no extra flags and returns the list of available UTXOs and their value in Satoshi. Just like [`get_balance`](#get_balance) it **should normally be called after [`sync`](#sync)**, since it only operates -on the internal cache. - -### policies - -This subcommand has no extra flags and returns the spending policies encoded by the descriptor in a more human-readable format. As an example, running the `policies` command on the descriptor shown earlier for the -in the explanation of the [create_tx](#create_tx) command, it will return this: - -{{% json %}} -{ - "id":"qd3um656", - "type":"THRESH", - "items":[ - { - "id":"ykfuwzkl", - "type":"SIGNATURE", - "pubkey":"...", - "satisfaction":{ - "type":"NONE" - }, - "contribution":{ - "type":"COMPLETE", - "condition":{ - - } - } - }, - { - "id":"ms3xjley", - "type":"THRESH", - "items":[ - { - "id":"xgfnp9rt", - "type":"SIGNATURE", - "pubkey":"...", - "satisfaction":{ - "type":"NONE" - }, - "contribution":{ - "type":"COMPLETE", - "condition":{ - - } - } - }, - { - "id":"5j96ludf", - "type":"RELATIVETIMELOCK", - "value":6, - "satisfaction":{ - "type":"NONE" - }, - "contribution":{ - "type":"COMPLETE", - "condition":{ - "csv":6 - } - } - } - ], - "threshold":2, - "satisfaction":{ - "type":"NONE" - }, - "contribution":{ - "type":"PARTIALCOMPLETE", - "n":2, - "m":2, - "items":[ - 0, - 1 - ], - "conditions":{ - "[0, 1]":[ - { - "csv":6 - } - ] - } - } - }, - { - "id":"d8jph6ax", - "type":"THRESH", - "items":[ - { - "id":"gdl039m6", - "type":"SIGNATURE", - "pubkey":"...", - "satisfaction":{ - "type":"NONE" - }, - "contribution":{ - "type":"COMPLETE", - "condition":{ - - } - } - }, - { - "id":"xpf2twg8", - "type":"ABSOLUTETIMELOCK", - "value":630000, - "satisfaction":{ - "type":"NONE" - }, - "contribution":{ - "type":"COMPLETE", - "condition":{ - "timelock":630000 - } - } - } - ], - "threshold":2, - "satisfaction":{ - "type":"NONE" - }, - "contribution":{ - "type":"PARTIALCOMPLETE", - "n":2, - "m":2, - "items":[ - 0, - 1 - ], - "conditions":{ - "[0, 1]":[ - { - "timelock":630000 - } - ] - } - } - } - ], - "threshold":2, - "satisfaction":{ - "type":"NONE" - }, - "contribution":{ - "type":"PARTIALCOMPLETE", - "n":3, - "m":2, - "items":[ - 0, - 1, - 2 - ], - "conditions":{ - "[0, 1]":[ - { - "csv":6 - } - ], - "[0, 2]":[ - { - "timelock":630000 - } - ], - "[1, 2]":[ - { - "csv":6, - "timelock":630000 - } - ] - } - } -} -{{% /json %}} - -This is a tree-like recursive structure, so it tends to get huge as more and more pieces are added, but it's in fact fairly simple. Let's analyze a simple node of the tree: - -```json -{ - "id":"qd3um656", - "type":"SIGNATURE", - "pubkey":"...", - "satisfaction":{ - "type":"NONE" - }, - "contribution":{ - "type":"COMPLETE", - "condition":{} - } -} -``` - -* `id` is a unique identifier to this specific node in the tree. -* `type`, as the name implies, represents the type of node. It defines what should be provided to satisfy that particular node. Generally some other data are provided to give meaning to - the type itself (like the `pubkey` field here in the example). There are basically two families of types: some of them can only be used as leaves, while some other can only be used as intermediate nodes. - - Possible leaf nodes are: - - `SIGNATURE`, requires a signature made with the specified key. Has a `pubkey` if it's a single key, a `fingerprint` if the key is an xpub, or a `pubkey_hash` if the full public key is not present in the descriptor. - - `SIGNATUREKEY`, requires a signature plus the raw public key. Again, it can have a `pubkey`, `fingerprint` or `pubkey_hash`. - - `SHA256PREIMAGE`, requires the preimage of a given `hash`. - - `HASH256PREIMAGE`, requires the preimage of a given `hash`. - - `RIPEMD160PREIMAGE`, requires the preimage of a given `hash`. - - `HASH160PREIMAGE`, requires the preimage of a given `hash`. - - `ABSOLUTETIMELOCK`, doesn't technically require anything to be satisfied, just waiting for the timelock to expire. Has a `value` field with the raw value of the timelock (can be both in blocks or time-based). - - `RELATIVETIMELOCK`, again only requires waiting for the timelock to expire. Has a `value` like `ABSOLUTETIMELOCK`. - - Possible non-leaf nodes are: - - `THRESH`, defines a threshold of policies that has to be met to satisfy the node. Has an `items` field, which is a list of policies to satisfy and a `threshold` field that defines the threshold. - - `MULTISIG`, Similar to `THRESH`, has a `keys` field, which is a list of keys represented again as either `pubkey`, `fingerprint` or `pubkey_hash` and a `threshold` field. - -* `satisfaction` is currently not implemented and will be used to provide PSBT introspection, like understanding whether or not a node is already satisfied and to which extent in a PSBT. -* `contribution` represents if so and how much, the provided descriptor can contribute to the node. - - The possible types are: - - `NONE`, which means that the descriptor cannot contribute. - - `COMPLETE`, which means that the descriptor by itself is enough to completely satisfy the node. It also adds a `condition` field which represent any potential extra condition that has to be met to - consider the node complete. An example are the timelock nodes, that are always complete *but* they have an extra `csv` or `timelock` condition. - - `PARTIAL`, which means that the descriptor can partially satisfy the descriptor. This adds a `m`, `n`, `items` that respectively represent the threshold, the number of available items to satisfy and the items - that the provided descriptor can satisfy. Also adds a `conditions` field which is an integer to list of conditions map. The key is the child index and the map are all the possibile extra conditions that - have to be satisfied if that node is used in the threshold. For instance, if you have a threshold of a SIGNATURE and a RELATIVETIMELOCK, in this order, the `conditions` field will be `1 ⇒ csv(x)`, - because the item at index 1 needs the extra csv condition. - - `PARTIALCOMPLETE`, which is basically a `PARTIAL` with the size of `items` >= `m`. It's treated as a separate entity to make the code a bit more clean and easier to implement. Like `PARTIAL`, it also has - a `m`, `n`, `items` fields but the `conditions field` is a bit different: it's a list of integers to list of conditions map. The key represents the combination that can be used to satisfy the threshold, - and the value contains all the possible conditions that also have to be satisfied. For instance, if you have a 2-of-2 threshold of a TIMELOCK and a RELATIVETIMELOCK, the `conditions` field will be `[0, 1] ⇒ - csv(x) + timelock(y)`, because if the combination of items 0 and 1 is picked, both of their conditions will have to be meet too. - -While the structure contains all of the intermediate nodes too, the root node is the most important one because defines how the descriptor can contribute to spend outputs sent to its addresses. - -For instance, looking at the root node of the previous example (with the internal `items` omitted) from a descriptor that has all the three private keys for keys A, B and C, we can clearly see that it can satisfy -the descriptor (type = `PARTIALCOMPLETE`) and the three options are `[0, 1] ⇒ csv(6)` (Option #1), `[0, 2] ⇒ timelock(630,000)` (Option #2) or `[1, 2] ⇒ csv(6) + timelock(630,000)` (Option #3). - -```json -{ - "type":"THRESH", - "items":[], - "threshold":2, - "satisfaction":{ - "type":"NONE" - }, - "contribution":{ - "type":"PARTIALCOMPLETE", - "n":3, - "m":2, - "items":[ - 0, - 1, - 2 - ], - "conditions":{ - "[0, 1]":[ - { - "csv":6 - } - ], - "[0, 2]":[ - { - "timelock":630000 - } - ], - "[1, 2]":[ - { - "csv":6, - "timelock":630000 - } - ] - } - } -} -``` - -### `public_descriptor` - -This subcommand has no extra flags and returns the "public" version of the wallet's descriptor(s). It can be used to bootstrap a watch-only instance for the wallet. - -### `repl` - -This subcommand has no extra flags and launches an interactive shell session. - -### `sign` - -```text -OPTIONS: - --psbt Sets the PSBT to sign - --assume_height Assume the blockchain has reached a specific height. This affects the transaction - finalization, if there are timelocks in the descriptor -``` - -Adds to the PSBT all the signatures it can produce with the secrets embedded in the descriptor (xprv or WIF keys). Returns the signed PSBT and, if there are enough item to satisfy the script, also the extracted raw -Bitcoin transaction. - -Optionally, the `assume_height` option can be specified to let the wallet assume the blockchain has reached a specific height. This affects the finalization of the PSBT which is done right at the end of the signing -process: the wallet tries to satisfy the spending condition of each input using the partial signatures collected. In case timelocks are present the wallet needs to know whether or not they have expired. This flag -is particularly useful for offline wallets. - -### `sync` - -This subcommand has no extra flags. It connects to the chosen Electrum server and synchronizes the list of transactions received and available UTXOs. diff --git a/content/bdk-cli/playground.md b/content/bdk-cli/playground.md deleted file mode 100644 index f135f93619..0000000000 --- a/content/bdk-cli/playground.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Playground" -date: 2020-05-08T15:42:22+02:00 -draft: false -weight: 6 -pre: "6. " ---- - -{{< playground >}} diff --git a/content/bdk-cli/regtest.md b/content/bdk-cli/regtest.md deleted file mode 100644 index 723d09d1dc..0000000000 --- a/content/bdk-cli/regtest.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "Regtest" -date: 2020-04-29T00:19:34+02:00 -draft: false -weight: 4 -pre: "4. " ---- - -Running the `bdk-cli` tool in regtest requires having a local Electrum server set-up. There are two main implementations, [`electrs`](https://github.com/romanz/electrs) in Rust and [`ElectrumX`](https://github.com/spesmilo/electrumx) in Python. Since the Rust toolchain is already required to -use BDK, this page will focus mostly on the former. - -Electrs can be installed by running: - -```bash -cargo install --git https://github.com/romanz/electrs --bin electrs -``` - -Just like before, this command will probably take a while to finish. - -Once it's done, assuming you have a regtest bitcoind running in background, you can launch a new terminal and run the following command to actually start electrs: - -```bash -electrs -vv --timestamp --db-dir /tmp/electrs-db --electrum-rpc-addr="127.0.0.1:50001" --network=regtest --cookie-file=$HOME/.bitcoin/regtest/.cookie -``` - -on macOS you should change the cookie-file to `$HOME/Library/Application Support/Bitcoin/regtest/.cookie`. - -This will start the Electrum server on port 50001. You can then add the `-n regtest -s 127.0.0.1:50001` to the `bdk-cli` commands to switch to the local regtest. - -## Troubleshooting - -#### Stuck with "*wait until bitcoind is synced (i.e. initialblockdownload = false)*" - -Just generate a few blocks with `bitcoin-cli generatetoaddress 1
` - -## Bonus: Docker - -If you have already installed Docker on your machine, you can also use 🍣 [Nigiri CLI](https://github.com/vulpemventures/nigiri) to spin-up a complete development environment in `regtest` that includes a `bitcoin` node, an `electrs` explorer and the [`esplora`](https://github.com/blockstream/esplora) web-app to visualize blocks and transactions in the browser. - -Install 🍣 Nigiri -```bash -$ curl https://getnigiri.vulpem.com | bash -``` - -Start Docker daemon and run Nigiri box -``` -$ nigiri start -``` - -This will start electrum RPC interface on port `51401`, the REST interface on `3000` and the esplora UI on `5000` (You can visit with the browser and look for blocks, addresses and transactions) - -You can then add the `-n regtest -s 127.0.0.1:51401` to the `bdk-cli` commands to switch to the local regtest. diff --git a/content/blog/2020/descriptors_in_the_wild.md b/content/blog/2020/descriptors_in_the_wild.md deleted file mode 100644 index fb66311d8f..0000000000 --- a/content/blog/2020/descriptors_in_the_wild.md +++ /dev/null @@ -1,345 +0,0 @@ ---- -title: "Descriptors in the wild" -description: "Guide to setup a 2-of-2 multisig using Bitcoin Core and BDK" -authors: - - Gabriele Domenichini -date: "2020-11-18" -tags: ["guide", "descriptor"] -hidden: true -draft: false ---- - -I have tried to setup a 2 of 2 multi signature infrastructure with two -different wallets, which know nothing about each other, but are compliant with -two very important protocols: [Output Descriptors] and [Partially Signed -Bitcoin Transactions][PSBT] described in BIP 174. - -Before these two protocols came into existence, making a multi signature setup -and spending from it was possible only if the involved parties were using the -same wallet (eg. Electrum Desktop Wallet). This limitation was due to the fact -that the two parties had to agree: - -* on the particular type of script and address to use -* on the way the transaction would be shared composed and signed with all the -involved parties. - -[Output Descriptors] are a way to express which kind scriptPubKey and -addresses to produce with a key or a series of keys. - -[PSBT] is instead the standard protocol used to create a transaction and to enrich -it with the necessary signatures and other components, to make it valid and complete. - -Together they provide a common ground to create and use a multi signature -infrastructure in a heterogeneous environment, and this is what I have put -to test. - -## The use case - -Imagine Alice and Bob owning a company and being willing to put the corporate cash -in a 2of2 multi signature setup, so that each one of them have to agree and sign each -transaction. - -## The role of Descriptors - -If Alice and Bob cannot agree on the software to use, to monitor the same financial -situation, the two software must control and produce exactly the same series -of multisignature addresses. - -To make two different software produce the same addresses in a deterministic way -we must ensure that they: -* produce the same pair of public keys -* combine them in the same order -* put them inside the same scriptPubKey to produce the same address - -Here is where the [Output Descriptors] come into play. They describe: - -* the sequence of public keys each extended key (xpub) will produce -* the sequence in which the new public keys of various parties will enter into -the script -* the type of script the wallet will prepare with that group keys and so the type -of address the group of keys will produce. - -**By sharing the same Descriptor, every compliant wallet will derive -deterministically the same series of multisig addresses**. - -Imagine Alice using Bitcoin Core (from now on ["Core"][Bitcoin Core]) as a -Wallet and Bob using a "Last generation" wallet, Bitcoin Development Kit -(from now on ["BDK"][BDK]), which uses descriptors and miniscript natively. - -Each of these two software wallets should be able to: - -* Create a new address which is seen as belonging to the multi signature -wallet in both software -* Express the consent of each party by partially signing the transaction in a way -the other wallet can understand and complete it with its own signature. - -The infrastructure of multiple Extended keys combined toghether to produce -multiple multisignature addresses is often referred as -*[Hierarchical Deterministic][HDWallet] multi signature wallet or HDM*. - -What follows are the steps to create the HDM usable both in Core and -in BDK. - -*Note: In Core, [Descriptor wallets] are still experimental and in general, -both wallets should be tested for descriptor capabilities only in testnet.* - -## Our playground - -We will build a 2of2 key set up that will be used cooperatively by Bitcoin Core -and Bitcoin Development Kit. -The steps Alice and Bob will do are: - -1. creation of the seed and the derived Extended Master Public and send it to -the other party -2. Create the multi signature descriptor for each wallet -3. Use each other's software to receive testnet coins from a faucet -4. return part of the coins to the faucet signing the transaction with both -wallets. - -We need: -* [Bitcoin Dev Kit][BDK] -* [Bitcoin Core] (v0.21.0 or later) - -### 1. Creating the seeds and the derived Extended Public keys - -#### Seeds and Extended Master Public - -We build an Extended Private Master Key for both wallet and derive a BIP84 -Extended Master Public for Bitcoin Core and then for BDK. - -For Bitcoin Core (Alice): - -``` -# new Extended wallet data -export core_key=$(bdk-cli key generate) - -# New Extended Master Private - -export core_xprv=$(echo $core_key | jq -r '.xprv') - -# Now I derive the xpubs (one for receiving and one for the change) -# together with informations about the derivation path to be communicated -# to BDK wallet's owner (Bob). - -export core_xpub_84_for_rec_desc=$(bdk-cli key derive --path m/84h/0h/0h/0 --xprv $core_xprv | jq -r '.xpub') -export core_xpub_84_for_chg_desc=$(bdk-cli key derive --path m/84h/0h/0h/1 --xprv $core_xprv | jq -r '.xpub') -``` - -For BDK (Bob) we do the same: - -``` -# new Extended wallet data - -export BDK_key=$(bdk-cli key generate) - -# New Extended Master Private - -export BDK_xprv=$(echo $BDK_key | jq -r '.xprv') - -# Now I build the derived xpubs to be communicated (to Alice). - -export BDK_xpub_84_for_rec_desc=$(bdk-cli key derive --path m/84h/0h/0h/0 --xprv $BDK_xprv | jq -r '.xpub') -export BDK_xpub_84_for_chg_desc=$(bdk-cli key derive --path m/84h/0h/0h/1 --xprv $BDK_xprv | jq -r '.xpub') -``` - -### 2. Creation of the multi signature descriptor for each wallet - -To build a multisig wallet, each wallet owner must compose the descriptor -adding: -* his derived extended **private** key AND -* all the extended **public** keys of the other wallets involved in the -multi signature setup - -*The different nature of the two keys (one is private and one is public) is -due to the fact that each wallet, to be able to partially sign the transaction, -**must manage the private key of the wallet's owner*** AND have the other -party's public key. Otherwise, if we put both public keys, we would obtain -a watch-only wallet unable to sign the transactions. If we -had both extended private keys inside the descriptor, we would allow each party -to finalize the transactions autonomously. - -#### In Bitcoin Core: - -In our case, the multi signature descriptor for Bitcoin Core will be composed -with: - -* The BIP84 derived Extended **Public** Key from BDK -* The BIP84 derived Extended **Private** Key from Core. - -BDK wallet's owner will send to Core's owner the derived xpub for this purpose. -This is how the Core's multisig descriptor will be created and put into an -environment variable: - -``` -export core_rec_desc="wsh(multi(2,$BDK_xpub_84_for_rec_desc,$core_xprv/84'/0'/0'/0/*))" -``` - -Where of course `$BDK_xpub_84_for_rec_desc`is the derived master public created -in BDK and received by Core's owner. - -The meaning of what is before and after is illustrated in the doc that explain -the use of [Output Descriptors in Bitcoin Core][Output Descriptors]. - -We add the necessary checksum using the specific `bitcoin-cli` call. - -``` -export core_rec_desc_chksum=$core_rec_desc#$(bitcoin-cli -testnet getdescriptorinfo $core_rec_desc | jq -r '.checksum') -``` - -We repeat the same to build the descriptor to receive the change. - -``` -export core_chg_desc="wsh(multi(2,$BDK_xpub_84_for_chg_desc,$core_xprv/84'/0'/0'/1/*))" -export core_chg_desc_chksum=$core_chg_desc#$(bitcoin-cli -testnet getdescriptorinfo $core_chg_desc|jq -r '.checksum') -``` - -#### In BDK: - -For BDK we set the derivation for receiving addresses and change addresses -in the command line (maybe setting an alias) - -Building the descriptor: - -``` -export BDK_rec_desc="wsh(multi(2,$BDK_xprv/84'/0'/0'/0/*,$core_xpub_84_for_rec_desc))"` -``` - -Please note that the order of the extended key in the descriptor MUST be the -same in the 2 wallets. - -*We have chosen to put BDK first and in each software wallet, the public key -derived from BDK will always come first. In alternative, we could have chosen to -produce the descriptor, [chosing a `soretedmulti` multisignature setup][sortedmulti]*. - -``` -export BDK_rec_desc_chksum=$BDK_rec_desc#$(bitcoin-cli -testnet getdescriptorinfo $BDK_rec_desc | jq -r '.checksum') -export BDK_chg_desc="wsh(multi(2,$BDK_xprv/84'/0'/0'/1/*,$core_xpub_84_for_chg_desc))" -export BDK_chg_desc_chksum=$BDK_chg_desc#$(bitcoin-cli -testnet getdescriptorinfo $BDK_chg_desc | jq -r '.checksum') -``` - -To take a look at the variables we have produced so far: -``` -env | grep 'core_' -env | grep 'BDK_' -``` - -Now we will use the multisig descriptor wallet to receive testnet coins with -Alice and Bob's software - -### 3. Use each other's software to receive testnet coins from a faucet - -#### In Bitcoin Core - -Alice must create an empty, experimental new "descriptors wallet" in Core and -to import the multisig Output Descriptor. - -``` -bitcoin-cli -testnet createwallet "multisig2of2withBDK" false true "" false true false -```` -The flag are to: -* use the private keys -* make it empty -* no password provided to the wallet -* reusing of addresses not allowed -* "new experimental descriptors wallet" -* don't load it on start up - -``` -bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK importdescriptors "[{\"desc\":\"$core_rec_desc_chksum\",\"timestamp\":\"now\",\"active\":true,\"internal\":false},{\"desc\":\"$core_chg_desc_chksum\",\"timestamp\":\"now\",\"active\":true,\"internal\":true}]" -``` -Now Alice asks for her first receiving multisignature address. - -``` -export first_address=$(bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK getnewaddress) -echo $first_address -``` - -#### BDK -In BDK Bob can specify directly the descriptors on the command line to produce -the multisig address, because BDK is descriptors aware natively. - -``` -repl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint get_new_address` -``` - -Et voilà: if we have done everything correctly, the newly created address in -Core is the same of the newly created address in BDK. this is part of the -"miracle" of descriptors' interoperability. - -#### We ask for testnet coins giving the first created address. - -To find testnet coins for free, you can just google "testnet faucet" and you -should find some satoshis to play with. Just give to the site your first -generated address and, in twenty minutes, you will find the satoshis in -your balance both in Core and in BDK. - -``` -# to check it in Core: - -bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK getbalance - -# In BDK: - -# Sync with the blockchain -repl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint sync -# Get the balance -repl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint get_balance -``` -Some testnet faucets have an address to send back the unused satoshi after -the use. Take note of that because we will use it in the next step. - -### 4. we return part of the satoshis received back to the faucet - -``` -export psbt=$(bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK walletcreatefundedpsbt "[]" "[{\"tb1qrcesfj9f2d7x40xs6ztnlrcgxhh6vsw8658hjdhdy6qgkf6nfrds9rp79a\":0.000012}]" | jq -r '.psbt') - -export psbt=$(bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK walletprocesspsbt $psbt | jq -r '.psbt') -{ - "psbt": "cHNidP8BAIkCAAAAATj90EC+NAuXj7y6SseZJucoJM6sGnUcVm9koTveZECTAAAAAAD+////AmACAAAAAAAAIgAg98ol9j4AalD71E0mV5QV0uM6/vCT+pi2twxr/zrvLROwBAAAAAAAACIAIB4zBMipU3xqvNDQlz+PCDXvpkHH1Q95Nu0mgIsnU0jbAAAAAAABAIkCAAAAAQS+ObgGG6UwtvaO3KYph2E3/ws7Q83RbmR3rxC0fKYSAQAAAAD+////AtAHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNDAHQAAAAAAACIAIBQpiDTgPIMt0ld8cmuYqlY+EIPjvrmMqZruDhs61hQNAAAAAAEBK9AHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNAiAgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAAQEFR1IhArn3tec7n7318rnWqf0dIIwtLtfxo6Zt0HV70UvZYaWvIQNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfVKuIgYCufe15zufvfXyudap/R0gjC0u1/Gjpm3QdXvRS9lhpa8YNEw2cFQAAIAAAACAAAAAgAAAAAAAAAAAIgYDbdI+wHtIgO6pS6Ja7jai1pDwPeidKoDCytTO1jhjAH0YO/laXFQAAIAAAACAAAAAgAAAAAAAAAAAAAEBR1IhAqccvA3rL13D1K4GeWjcahDsO3P8oaVNBttk4MlCKXIcIQLHKhjmPuCQjyS77ZfaMN2tdgNKcf/+57VXGZhz/UWTl1KuIgICpxy8DesvXcPUrgZ5aNxqEOw7c/yhpU0G22TgyUIpchwYNEw2cFQAAIAAAACAAAAAgAEAAAADAAAAIgICxyoY5j7gkI8ku+2X2jDdrXYDSnH//ue1VxmYc/1Fk5cYO/laXFQAAIAAAACAAAAAgAEAAAADAAAAAAA=", - "complete": false -} -``` - -Exactly! Note the `"complete": false`. We have processed the transaction with -Core but we miss one of the necessary key of the multisig 2of2 setup (The one -contained inside BDK). - -`tb1qrcesfj9f2d7x40xs6ztnlrcgxhh6vsw8658hjdhdy6qgkf6nfrds9rp79a` is the address -we got from the faucet site to return the satoshis. - -The [PSBT] is sent over to the BDK wallet owner who tries to sign the -transaction: - -``` -repl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint sign --psbt $psbt -{ - "is_finalized": true, - "psbt": "cHNidP8BAIkCAAAAATj90EC+NAuXj7y6SseZJucoJM6sGnUcVm9koTveZECTAAAAAAD+////AmACAAAAAAAAIgAg98ol9j4AalD71E0mV5QV0uM6/vCT+pi2twxr/zrvLROwBAAAAAAAACIAIB4zBMipU3xqvNDQlz+PCDXvpkHH1Q95Nu0mgIsnU0jbAAAAAAABAIkCAAAAAQS+ObgGG6UwtvaO3KYph2E3/ws7Q83RbmR3rxC0fKYSAQAAAAD+////AtAHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNDAHQAAAAAAACIAIBQpiDTgPIMt0ld8cmuYqlY+EIPjvrmMqZruDhs61hQNAAAAAAEBK9AHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNAiAgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAASICArn3tec7n7318rnWqf0dIIwtLtfxo6Zt0HV70UvZYaWvRzBEAiBkVDLgVEwvENnLx+04o7gGpGjFDBwAXTJmf8Yvo35oygIgbuBkHsvPC9jmZcMZ9P+Pwp01yxSaWo+5feyPmd3ai1kBAQVHUiECufe15zufvfXyudap/R0gjC0u1/Gjpm3QdXvRS9lhpa8hA23SPsB7SIDuqUuiWu42otaQ8D3onSqAwsrUztY4YwB9Uq4iBgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfRg7+VpcVAAAgAAAAIAAAACAAAAAAAAAAAAiBgK597XnO5+99fK51qn9HSCMLS7X8aOmbdB1e9FL2WGlrxg0TDZwVAAAgAAAAIAAAACAAAAAAAAAAAABBwABCNoEAEcwRAIgZFQy4FRMLxDZy8ftOKO4BqRoxQwcAF0yZn/GL6N+aMoCIG7gZB7LzwvY5mXDGfT/j8KdNcsUmlqPuX3sj5nd2otZAUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAAUdSIQK597XnO5+99fK51qn9HSCMLS7X8aOmbdB1e9FL2WGlryEDbdI+wHtIgO6pS6Ja7jai1pDwPeidKoDCytTO1jhjAH1SrgABAUdSIQKnHLwN6y9dw9SuBnlo3GoQ7Dtz/KGlTQbbZODJQilyHCECxyoY5j7gkI8ku+2X2jDdrXYDSnH//ue1VxmYc/1Fk5dSriICAqccvA3rL13D1K4GeWjcahDsO3P8oaVNBttk4MlCKXIcGDRMNnBUAACAAAAAgAAAAIABAAAAAwAAACICAscqGOY+4JCPJLvtl9ow3a12A0px//7ntVcZmHP9RZOXGDv5WlxUAACAAAAAgAAAAIABAAAAAwAAAAAA" -} -``` -The signature has succeded (note the "is_finalized": true,) and now we can -broadcast the transction. -``` -repl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint broadcast --psbt "cHNidP8BAIkCAAAAATj90EC+NAuXj7y6SseZJucoJM6sGnUcVm9koTveZECTAAAAAAD+////AmACAAAAAAAAIgAg98ol9j4AalD71E0mV5QV0uM6/vCT+pi2twxr/zrvLROwBAAAAAAAACIAIB4zBMipU3xqvNDQlz+PCDXvpkHH1Q95Nu0mgIsnU0jbAAAAAAABAIkCAAAAAQS+ObgGG6UwtvaO3KYph2E3/ws7Q83RbmR3rxC0fKYSAQAAAAD+////AtAHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNDAHQAAAAAAACIAIBQpiDTgPIMt0ld8cmuYqlY+EIPjvrmMqZruDhs61hQNAAAAAAEBK9AHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNAiAgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAASICArn3tec7n7318rnWqf0dIIwtLtfxo6Zt0HV70UvZYaWvRzBEAiBkVDLgVEwvENnLx+04o7gGpGjFDBwAXTJmf8Yvo35oygIgbuBkHsvPC9jmZcMZ9P+Pwp01yxSaWo+5feyPmd3ai1kBAQVHUiECufe15zufvfXyudap/R0gjC0u1/Gjpm3QdXvRS9lhpa8hA23SPsB7SIDuqUuiWu42otaQ8D3onSqAwsrUztY4YwB9Uq4iBgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfRg7+VpcVAAAgAAAAIAAAACAAAAAAAAAAAAiBgK597XnO5+99fK51qn9HSCMLS7X8aOmbdB1e9FL2WGlrxg0TDZwVAAAgAAAAIAAAACAAAAAAAAAAAABBwABCNoEAEcwRAIgZFQy4FRMLxDZy8ftOKO4BqRoxQwcAF0yZn/GL6N+aMoCIG7gZB7LzwvY5mXDGfT/j8KdNcsUmlqPuX3sj5nd2otZAUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAAUdSIQK597XnO5+99fK51qn9HSCMLS7X8aOmbdB1e9FL2WGlryEDbdI+wHtIgO6pS6Ja7jai1pDwPeidKoDCytTO1jhjAH1SrgABAUdSIQKnHLwN6y9dw9SuBnlo3GoQ7Dtz/KGlTQbbZODJQilyHCECxyoY5j7gkI8ku+2X2jDdrXYDSnH//ue1VxmYc/1Fk5dSriICAqccvA3rL13D1K4GeWjcahDsO3P8oaVNBttk4MlCKXIcGDRMNnBUAACAAAAAgAAAAIABAAAAAwAAACICAscqGOY+4JCPJLvtl9ow3a12A0px//7ntVcZmHP9RZOXGDv5WlxUAACAAAAAgAAAAIABAAAAAwAAAAAA" -{ - "txid": "a0b082e3b0579822d4a0b0fa95a4c4662f6b128ffd43fdcfe53c37473ce85dee" -} -``` - -## Conclusion - -We have built an HDM and we have used it with two indipendent wallets, which -are compatible with [BIP 174][PSBT] and [Output Descriptors]. Hopefully we -will see many other compatible wallets beyound [Bitcoin Core] and [BDK], -with which we will be able to easily set up multi signature schemes. - - -[Descriptor wallets]: https://github.com/bitcoin/bitcoin/pull/16528 -[Electrum]: https://electrum.org -[Output Descriptors]: https://bitcoinops.org/en/topics/output-script-descriptors/ -[PSBT]: https://en.bitcoin.it/wiki/BIP_0174 -[HDWallet]: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki -[sortedmulti]: https://github.com/bitcoin/bitcoin/pull/17056?ref=tokendaily -[BDK]: https://bitcoindevkit.org/ -[Bitcoin Core]: https://bitcoincore.org/ -[pycoin]: https://github.com/richardkiss/pycoin diff --git a/content/blog/2020/hello-world.md b/content/blog/2020/hello-world.md deleted file mode 100644 index 02b74785c7..0000000000 --- a/content/blog/2020/hello-world.md +++ /dev/null @@ -1,209 +0,0 @@ ---- -title: "Hello World!" -description: "Getting started using the BDK library in a very simple Rust project" -authors: - - Alekos Filini -date: "2020-12-18" -tags: ["getting started", "rust"] -hidden: true -draft: false ---- - -## Introduction - -This article should serve as a "getting started" guide for developers who are considering integrating BDK in their projects: it tries to introduce the reader to the basic concepts behind the library and some of its -modules and components that can be used to build a very simple functioning Bitcoin wallet. All the information written in this article are valid for the current `master` git branch, and should remain valid for the upcoming [`v0.2.0` release](https://github.com/bitcoindevkit/bdk/projects/1) -which is planned to be tagged pretty soon. - -## Design Goals - -The main goal of the library is to be a solid foundation for Bitcoin wallets of any kind, on any platform: in practice, this means that the library should be: - -- Very *well-reviewed* and tested -- *Lightweight*, so that it can be used easily on mobile devices as well -- *Extendable*, so that it can be adapted to perfectly suit different use-cases -- *Generalized*, meaning that it supports different types of Bitcoin scripts and wallets through the use of [descriptors][descriptor] -- *Reasonably easy* to use, exposing a "high level" interface to the user and hiding all the complexity inside - -These goals have a direct impact on the design of the internal components of the library, and as a consequence on the APIs that are exposed to the final user, which might in some cases feel counter-intuitive at first. -Throughout the article, I will try to focus on those points and try to explain them as best as I can. - -## The `Wallet` Structure - -The [`Wallet`][wallet] structure is in many ways the heart of the library: it represents an instance of a wallet and exposes some APIs to perform all the typical operations one might want to do with a Bitcoin wallet, -such as generating a new address, listing the transactions received, creating a transaction, etc. - -A `Wallet` instance can be constructed given at least one [descriptor] which would be used to derive both [`External`][KeychainKind] and [`Internal`][KeychainKind] addresses, or two if one prefers to keep them separated. `External` addresses are the -ones returned by an explicit [`Wallet::get_new_address()`][get_new_address] call, while `Internal` addresses are generated internally to receive the change whenever a new transaction is created. - -A `Wallet` also needs at least one other component to function properly, its [`Database`][Database]: it will be used as a *cache* to store the list of transactions synchronized with the blockchain, the UTXOs, the addresses generated, and a few other things. It's important -to note that the `Database` will never store any secret. Securely storing keys is explicitly left to the user of the library to implement, mainly because there isn't really one good way to do it, that would work reliably on every platform. On -mobile devices, for instance, the OS' keychain could be used, to allow unlocking the secrets with the use of biometric data (FaceID or fingerprint), while on desktop platform there isn't generally a similar -framework available and the user would have to implement something that meets their needs. It's not excluded that in the future we could provide a "reference implementation" of secure multi-platform storage for keys, -but that would very likely be released as a separate module outside of the `Wallet` structure, or potentially even as a separate library that could be reused for other applications as well. - -Going back to our `Wallet`: given a descriptor and a `Database` we can build an "air-gapped", or "Offline" wallet: basically, a wallet that physically can't to connect to the Bitcoin network. It will still be able to generate addresses and -sign [PSBTs][PSBT], but with a greatly reduced attack surface because a sizable part of the code that handles the logic to synchronize with the network would be entirely omitted in the final executable binary. - -This is how an `OfflineWallet` can be created. Notice that we are using [`MemoryDatabase`][MemoryDatabase] as our `Database`. We'll get to that in a second. - -```rust -use bdk::{Wallet, OfflineWallet}; -use bdk::database::MemoryDatabase; -use bdk::bitcoin::Network; - -fn main() -> Result<(), Box> { - let external_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/0/*)"; - let internal_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/1/*)"; - - let wallet: OfflineWallet<_> = Wallet::new_offline( - external_descriptor, - Some(internal_descriptor), - Network::Testnet, - MemoryDatabase::new(), - )?; - - Ok(()) -} -``` - -Once we have our `Wallet` instance we can generate a new address and print it out: - -```rust -// ... - -println!("Generated Address: {}", wallet.get_new_address()?); -``` - -Building and running this code will print out: - -```text -Generated Address: tb1q7w0t936xp5p994qx506xj53gjdcmzjr2mkqghn -``` - -Before we've talked about the benefits of an air-gapped wallet, but we should also talk about the disadvantages: the biggest one is the fact that it cannot create new transactions because -it doesn't know which UTXOs belong to the wallet. To get this information we generally need to `sync` with the network, but this wallet can't physically do that. - -To fix this we can add one more component to our `Wallet`: a [`Blockchain`][Blockchain] backend. In particular, we are going to use the [`ElectrumBlockchain`][ElectrumBlockchain] which syncs with an `Electrum` server, -since that's available out of the box in BDK and is pretty fast. - -We can change our `Wallet` construction to look something like this: - -```rust -use bdk::blockchain::ElectrumBlockchain; -use bdk::electrum_client::Client; - -// ... - -let wallet = Wallet::new( - external_descriptor, - Some(internal_descriptor), - Network::Testnet, - MemoryDatabase::new(), - ElectrumBlockchain::from(Client::new("ssl://electrum.blockstream.info:60002").unwrap()), -)?; -``` - -This piece of code is very similar to the one we wrote before, but this time we are using the [`Wallet::new()`][Wallet_new] constructor instead of [`Wallet::new_offline()`][Wallet_new_offline], and this takes an extra argument for the `Blockchain` type to use. -Specifically here, we create an `ElectrumBlockchain` and connect to Blockstream's public Electrum Testnet servers over SSL. - -Now, since we are running in the `Testnet` network, we can try to get some funds from a faucet online to this address we've generated. Once we have an incoming transaction we can do the first `sync` of our *online* wallet. -this is again something that might seem counterintuitive at first: why do we have to manually ask the `Wallet` to *sync* itself? Can't it do it periodically in background? The answer is that yes, that would definitely be possible, -but it would remove some control on what's happening inside the wallet from the user. This can be especially problematic on mobile platforms, where the OS tries very aggressively to suspend apps in background to save -battery. Having a thread running and trying to make network requests while the app is in background would very likely cause errors or potentially crashes somewhere. So for this reason this operation has to be performed manually, -to allow the user to call that function only at the right time. - -```rust -use bdk::blockchain::noop_progress; - -// ... - -wallet.sync(noop_progress(), None)?; -``` - -In this case, we are not interested in receiving updates about the progress, and we just want to use the default settings, so we use [`noop_progress()`][noop_progress] and `None` as arguments. This will make queries to the Electrum server -and store the list of transactions and UTXOs in our `Database`. In this case, we are using a `MemoryDatabase`, so those data are only going to be kept in RAM and dropped once our `Wallet` is dropped. This is very useful -for playing around and experimenting, but not so great for real-world wallets: for that, you can use [sled][sled] which is supported out of the box, or even use a custom database. More on that later! - -So now that we've synced with the blockchain we can create our first transaction. First of all, we will print out the balance of our wallet to make sure that our wallet has seen the incoming transaction. Then we -will create the actual transaction and we will specify some flags using the [`TxBuilder`][TxBuilder]. To finish it off, we will ask the wallet to sign the transaction and then broadcast it to the network. - -Right now we will not get into details of all the available options in `TxBuilder` since that is definitely out of the scope of a "getting started" guide. For now, you can just imagine the builder as your way to tell the library -how to build transactions. We'll come back to this in a future article. - -```rust -use std::str::FromStr; - -use bdk::bitcoin::Address; -use bdk::TxBuilder; - -// ... - -let balance = wallet.get_balance()?; -println!("Wallet balance in SAT: {}", balance); - -let faucet_address = Address::from_str("mkHS9ne12qx9pS9VojpwU5xtRd4T7X7ZUt")?; -let (unsigned_psbt, tx_details) = wallet.create_tx( - TxBuilder::with_recipients(vec![(faucet_address.script_pubkey(), balance / 2)]) - .enable_rbf(), -)?; -println!("Transaction details: {:#?}", tx_details); -``` - -In this case, we are sending back half the balance to the faucet's address and we are also enabling RBF since the default fees are at 1 satoshi/vbyte. With RBF we will be able to *bump the fees* of the transaction, should it get -stuck in the mempool due to the low fee rate. - -All that's left to do once we have our unsigned PSBT is to sign it: - -```rust -// ... - -let (signed_psbt, tx_finalized) = wallet.sign(unsigned_psbt, None)?; -assert!(tx_finalized, "Tx has not been finalized"); -``` - -And then broadcast it: - -```rust -// ... - -let raw_transaction = signed_psbt.extract_tx(); -let txid = wallet.broadcast(raw_transaction)?; -println!( - "Transaction sent! TXID: {txid}.\nExplorer URL: https://blockstream.info/testnet/tx/{txid}", - txid = txid -); -``` - -## Custom Database and Blockchain types - -We briefly mentioned before that for our example we used the `MemoryDatabase`, but that it could also be swapped for a different one: this is one example of the *modularity* of BDK. By default, some database -types are implemented in the library, namely (as of now) the `MemoryDatabase` which only keeps data in RAM and the [sled][sled] database that can store data on a filesystem. But since the `Database` trait is public, -users of the library can also implement different database types more suitable for their use-case. - -The same is true for the `Blockchain` types: the library provides (through the use of opt-in features) implementations for the `Electrum`, `Esplora` and `CompactFilters` (*Neutrino*) backends. Those again can also be -swapped with custom types if the user desires to do so. - -## Conclusion - -Hopefully, this article will help you get started with BDK! This is just a very quick and gentle introduction to the library, and only barely scratches the surface of what's inside: we will keep publishing more -articles in the future to explain some of the more advanced features of BDK, like key generation, using complex [descriptors][descriptor] with multiple keys and/or timelocks, using external signers, etc. - -If you'd like to learn more about the library feel free to ask any questions in the comment section down below, or join our [Discord Community](https://discord.gg/d7NkDKm) to chat with us directly! - - -[descriptor]: /descriptors -[PSBT]: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki -[sled]: https://docs.rs/sled/ - -[Wallet]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html -[KeychainKind]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.KeychainKind.html -[get_new_address]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html#method.get_new_address -[Database]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.Database.html -[MemoryDatabase]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/struct.MemoryDatabase.html -[Blockchain]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.Blockchain.html -[ElectrumBlockchain]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/struct.ElectrumBlockchain.html -[Wallet_new]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html#method.new -[Wallet_new_offline]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html#method.new_offline -[noop_progress]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.noop_progress.html -[TxBuilder]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.TxBuilder.html diff --git a/content/blog/2020/release-0.2.0.md b/content/blog/2020/release-0.2.0.md deleted file mode 100644 index 1eccd6a73d..0000000000 --- a/content/blog/2020/release-0.2.0.md +++ /dev/null @@ -1,191 +0,0 @@ ---- -title: "Release v0.2.0" -description: "Announcing the v0.2.0 release of BDK" -authors: - - Alekos Filini -date: "2020-12-21" -tags: ["rust", "release"] -hidden: true -draft: false ---- - -A new release of BDK is finally out! The `v0.2.0` release contains many exciting new features, bug fixes and overall improvements. This release also marks the beginning of our new regular [release schedule][release_schedule], which will see us pushing -out a new release every four weeks. We think this is a good compromise to ensure that developers using BDK have access to all the new features and fixes as soon as possible, at least while the library is still evolving very fast as it is -right now. After `v1.0.0` we will increase this time to a more relaxed 6 weeks. - -You can find the full [v0.2.0 changelog][changelog] on GitHub. - -## What's new in v0.2.0 - -Considering the sheer amount of new things being added we don't have room here to explain every new feature in detail, but below is a quick overview of some you could find useful in your projects. - -### A new name - -The `0.1.0-beta.1` release was tagged right before the project was renamed `bdk`: at that time the library was still called "Magical Bitcoin Library", or `magical` for short. With this release we have now renamed it to `bdk`. If you were using the library -before, it should only be a matter of renaming the imports to match the new name. Alternatively you can also rename `bdk` to `magical` in your Cargo.toml, but you'll still have to do some changes here and there because the APIs have been changed in a few -places. - -This release being particularly large contains a few different API-breaking changes: going forward we expect to make the interface more and more stable, which in turn will make applying updates easier. - -### Branch and Bound coin selection - -We now support the state-of-the-art coin selection algorithm called "branch and bound", with an implementation derived straight from Bitcoin Core. This algorithm is now enabled by default, but it can be replaced with a different one (either -the old default, [`LargestFirstCoinSelection`][`LargestFirstCoinSelection`] or a custom [`CoinSelectionAlgorithm`][`CoinSelectionAlgorithm`]) by using the [`TxBuilder::coin_selection()`][`TxBuilder::coin_selection()`] option. - -Branch and bound works by trying to find a set of inputs that perfectly matches the amount being sent by a transaction, to avoid making an extra change output which takes up more space in the transaction, requires more fees, and in general lowers the privacy -of a user if the change is later spent together with other outputs. - -### Key generation - -If you need to generate a new `bip32::ExtendedPrivKey`, or perhaps a new BIP39 mnemonic, you can use the unified [`GeneratableKey`][`GeneratableKey`] trait to do so: paired with [`GeneratableDefaultOptions`][`GeneratableDefaultOptions`] they provide many different ways to generate keys, -with or without a custom source of entropy, and with or without customized options. - -```rust -use bdk::bitcoin::PrivateKey; -use bdk::keys::{GeneratableKey, GeneratableDefaultOptions, PrivateKeyGenerateOptions}; - -let default_options_key = PrivateKey::generate_default()?; -let custom_options_key = PrivateKey::generate(PrivateKeyGenerateOptions { compressed: false })?; -``` - -### Generic key types - -With this update there's now a generalized trait for keys that can be used in descriptors, which is called [`ToDescriptorKey`][`ToDescriptorKey`]. This trait is already implemented for the native `rust-bitcoin` key types, like `PrivateKey`, `PublicKey`, `bip32::ExtendedPrivKey` -and `bip32::ExtendedPubKey`. It's also implemented for BIP39 mnemonic and seeds, when the the opt-in `keys-bip39` feature is enabled. As always, being this a public trait, you can also implement it for custom types to better suit your needs. - -```rust -impl ToDescriptorKey for MyKeyType { - fn to_descriptor_key(self) -> Result, KeyError> { - // Custom conversion to `bitcoin::PrivateKey` - let privkey: bitcoin::PrivateKey = ... ; - privkey.to_descriptor_key() - } -} -``` - -If your custom key type is simply a different representation of an `xprv` or `xpub`, you can also consider implementing the [`DerivableKey`][`DerivableKey`] trait instead: for a type `K` that implements [`DerivableKey`][`DerivableKey`], the [`ToDescriptorKey`][`ToDescriptorKey`] trait is automatically -implemented for the [`(K, bip32::DerivationPath)`][K_path] and [`(K, bip32::KeySource, bip32::DerivationPath)`][K_src_path] tuples. - -```rust -impl DerivableKey for MyKeyType { - fn add_metadata( - self, - origin: Option, - derivation_path: DerivationPath - ) -> Result, KeyError> { - // Custom conversion to `bip32::ExtendedPrivKey` - let xprv: bip32::ExtendedPrivKey = ... ; - xprv.add_metadata(origin, derivation_path) - } -} -``` - -### Descriptor templates - -Instead of having to serialize keys to strings using `format!()` just to place them somewhere inside a descriptor, you can now use descriptor templates to build a descriptor starting from a key and some other options -in a couple of lines of code. You can use one of the [provided templates][desc_templates_mod] or make a custom one by implementing the [`DescriptorTemplate`][`DescriptorTemplate`] trait on a `struct` or `enum`. - -```rust -let key = bip32::ExtendedPrivKey::from_str("...")?; -let wallet: OfflineWallet<_> = Wallet::new_offline( - BIP84(key.clone(), KeychainKind::External), - Some(BIP84(key, KeychainKind::Internal)), - Network::Testnet, - MemoryDatabase::default(), -)?; -``` - -### Easier creation of `Blockchain` and `Database` - -We've added a new way to create a [`Blockchain`][`Blockchain`] instance from a configuration, with the [`ConfigurableBlockchain`][`ConfigurableBlockchain`] trait. All the [`Blockchain`][`Blockchain`] types provided by the library implement this trait, which allows you to easily build an -instance of them starting from a configuration `struct`: moreover, the configuration structures implement `Serialize` and `Deserialize`, so that they can be easily stored/loaded using `serde`. - -We've also added a new [`Blockchain`][`Blockchain`] type called [`AnyBlockchain`][`AnyBlockchain`], which is essentially an `enum` that wraps all the [`Blockchain`][`Blockchain`] types exposed by the library. This allows you to build a [`Wallet`][`Wallet`] that always has the same -Rust type, but that can internally use different [`Blockchain`][`Blockchain`] backends chosen at runtime. - -```rust -use bdk::blockchain::{AnyBlockchain, AnyBlockchainConfig, ConfigurableBlockchain, ElectrumBlockchainConfig}; - -let config = r#"{"Electrum":{"url":"ssl://electrum.blockstream.info:50002","socks5":null,"retry":3,"timeout":5}}"#; -let config = serde_json::from_str(config)?; -let blockchain = AnyBlockchain::from_config(&config)?; -``` - -The same is true for [`Database`][`Database`] types, thanks to the [`ConfigurableDatabase`][`ConfigurableDatabase`] trait and the [`AnyDatabase`][`AnyDatabase`] `enum`. While we think most people generally prefer to choose a single database type and then stick to it, it's still good -to offer the choice to switch them at runtime, should somebody need that. - -### `descriptor!()` macro - -If you start writing complex descriptor templates, you'll soon find yourself with the need of building large descriptor syntax trees: you can very easily do that with the [`descriptor!()`][`descriptor!()`] macro, with the added bonus that some additional checks on the -syntax of your descriptor will be performed at compile-time, rather than at runtime by. You can use any type that implements [`ToDescriptorKey`][`ToDescriptorKey`] (even strings!) as keys in `pk()`, `multi()` and `sortedmulti()` fragments, and you can even mix -them in the same descriptor. - -The syntax supported by the macro is almost exactly the same as the standard descriptor syntax we all know, with the only difference that modifiers should be specified individually rather than -grouped in a series of characters (see the example below). - -```rust -pub struct TimeDecayingMultisig { - pk_a: K, - pk_b: K, - timelock: u32, -} - -impl> DescriptorTemplate for TimeDecayingMultisig { - fn build(self) -> Result { - Ok(bdk::descriptor!(wsh(thresh(2,pk(self.pk_a),s:pk(self.pk_b),s:d:v:older(self.timelock)))) - .map_err(|e| KeyError::Message(e.to_string()))?) - } -} -``` - -### Support for `sortedmulti()` - -Thanks to the addition of `sortedmulti()` in `rust-miniscript`, we can now also support them in BDK, which means we are getting more and more compatible with other descriptor-based wallets out there like Bitcoin Core. - -## Contributors - -A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports. - -Since the `0.1.0-beta.1` release over three months ago, we've had `213` new commits made by `10` different contributors for a total of `9990` additions and `2993` deletions. Here's the [full diff][gh_diff]. - -A special thanks to the `7` new contributors: - -- [@eupn][@eupn] -- [@justinmoon][@justinmoon] - Justin Moon -- [@Xekyo][@Xekyo] - Mark Erhardt -- [@RCasatta][@RCasatta] - Riccardo Casatta -- [@ulrichard][@ulrichard] - Richard Ulrich -- [@notmandatory][@notmandatory] - Steve Myers -- [@willcl-ark][@willcl-ark] - Will Clark - -[release_schedule]: https://github.com/bitcoindevkit/bdk/blob/7d6cd6d4f5a26194830f90e6460e0b82bddf9594/DEVELOPMENT_CYCLE.md -[changelog]: https://github.com/bitcoindevkit/bdk/blob/7d6cd6d4f5a26194830f90e6460e0b82bddf9594/CHANGELOG.md#v020---010-beta1 -[gh_diff]: https://github.com/bitcoindevkit/bdk/compare/0.1.0-beta.1...v0.2.0 - -[`LargestFirstCoinSelection`]: https://docs.rs/bdk/0.2.0/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html -[`CoinSelectionAlgorithm`]: https://docs.rs/bdk/0.2.0/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html -[`TxBuilder::coin_selection()`]: https://docs.rs/bdk/0.2.0/bdk/wallet/tx_builder/struct.TxBuilder.html#method.coin_selection -[`ToDescriptorKey`]: https://docs.rs/bdk/0.2.0/bdk/keys/trait.ToDescriptorKey.html -[`DerivableKey`]: https://docs.rs/bdk/0.2.0/bdk/keys/trait.DerivableKey.html -[K_path]: https://docs.rs/bdk/0.2.0/bdk/keys/trait.ToDescriptorKey.html#impl-ToDescriptorKey%3CCtx%3E-for-(T%2C%20DerivationPath) -[K_src_path]: https://docs.rs/bdk/0.2.0/bdk/keys/trait.ToDescriptorKey.html#impl-ToDescriptorKey%3CCtx%3E-for-(T%2C%20KeySource%2C%20DerivationPath) -[`GeneratableKey`]: https://docs.rs/bdk/0.2.0/bdk/keys/trait.GeneratableKey.html -[`GeneratableDefaultOptions`]: https://docs.rs/bdk/0.2.0/bdk/keys/trait.GeneratableDefaultOptions.html -[`DescriptorTemplate`]: https://docs.rs/bdk/0.2.0/bdk/descriptor/template/trait.DescriptorTemplate.html -[desc_templates_mod]: https://docs.rs/bdk/0.2.0/bdk/descriptor/template/index.html -[`Blockchain`]: https://docs.rs/bdk/0.2.0/bdk/blockchain/trait.Blockchain.html -[`ConfigurableBlockchain`]: https://docs.rs/bdk/0.2.0/bdk/blockchain/trait.ConfigurableBlockchain.html -[`Database`]: https://docs.rs/bdk/0.2.0/bdk/database/trait.Database.html -[`ConfigurableDatabase`]: https://docs.rs/bdk/0.2.0/bdk/database/trait.ConfigurableDatabase.html -[`AnyBlockchain`]: https://docs.rs/bdk/0.2.0/bdk/blockchain/any/enum.AnyBlockchain.html -[`AnyDatabase`]: https://docs.rs/bdk/0.2.0/bdk/database/any/enum.AnyDatabase.html -[`Wallet`]: https://docs.rs/bdk/0.2.0/bdk/wallet/struct.Wallet.html -[`descriptor!()`]: https://docs.rs/bdk/0.2.0/bdk/macro.descriptor.html - -[@notmandatory]: https://github.com/notmandatory -[@willcl-ark]: https://github.com/willcl-ark -[@ulrichard]: https://github.com/ulrichard -[@Xekyo]: https://github.com/Xekyo -[@RCasatta]: https://github.com/RCasatta -[@justinmoon]: https://github.com/justinmoon -[@eupn]: https://github.com/eupn diff --git a/content/blog/2021/compact_filters_demo.md b/content/blog/2021/compact_filters_demo.md deleted file mode 100644 index e7dc051a30..0000000000 --- a/content/blog/2021/compact_filters_demo.md +++ /dev/null @@ -1,386 +0,0 @@ ---- -title: "Using BDK to create BIP157 SPV wallet (aka Neutrino)" -description: "Tutorial showing usage of compact filters (BIP157) using bdk-cli command line tools" -authors: - - Rajarshi Maitra -date: "2021-06-20" -tags: ["tutorial", "BDK", "bdk-cli", "compact_filters", "BIP157", "Neutrino"] -hidden: true -draft: false ---- - -## Introduction - -#### Compact Filters: -Compact filters are the latest specification of Bitcoin SPV node implementation as per [BIP157](https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki) and [BIP158](https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki). Such light clients were envisioned by Satoshi himself in his original white paper, but due to lack of robust privacy and trust guarantees using conventional [bloomfilters](https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki), these type of nodes never got popular. - -Enters [BIP157](https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki), which described a new type of filters for Bitcoin Blockchain data, known as `compact_filters`. The [Neutrino](https://github.com/lightninglabs/neutrino) project pioneered the use of compact filter based light client nodes for using with Lightning Network wallets. Using compact filters, a light-node can talk to one or more full nodes, and fetch relevant information from the blockchain, with much more robust privacy and security guarantees than previously possible. Compact filter based nodes are best suitable to be used with mobile wallets, to create more trustless mobile applications on Bitcoin. Any wallet application that needs to have an "eye on the blockchain" has an use for such light clients. - -`BIP157` type filters allows to create tiny sized SPV nodes, that can fetch blockchain data and can identify inconsistency, so it can actively defend itself, while also preserving its privacy. Such nodes are most useful for Lightning Network mobile applications. - -Example of such `compact_filters` wallets in wild is [Breeze](https://github.com/breez/breezmobile) Lightning mobile wallet. - -Bitcoin core supports serving `BIP157` type filters from `v0.21.0`. - -#### BDK and Compact filters -BDK is a bitcoin wallet development library that can be used to create bitcoin wallets with custom `Database` and `Blockchain` backends. BDK is a [descriptor](https://bitcoindevkit.org/descriptors/) based wallet, i.e. the wallet keychain is described by a set of descriptors. - -Using BDK one can instantiate wallets of various kinds as per requirement. BDK abstracts away all the heavy lifting works, and allow wallet devs to concentrate on logic that they care about, i.e. writing wallet codes. For more detailed documentation on BDK capabilities check these [blog](https://bitcoindevkit.org/blog/2020/12/hello-world/), [bog](https://bitcoindevkit.org/blog/2020/11/descriptors-in-the-wild/) and [docs](https://docs.rs/bdk/). - -The main three components of abstraction in BDK are - - `Database` - - `Descriptors` - - `Blockchain` - -BDK comes with default implementations of all them that developers can start with out of the box. Developers can also create there own custom implementations and plug it into BDK (thanks to rust magic of `Traits`). - -BDK also supports [BIP158](https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki) communication protocol, which allows creation of `BIP157` type compact filter SPV nodes. This capability is extended to wallet with BDK's `Blockchain` data structure. The [API](https://docs.rs/bdk/0.8.0/bdk/blockchain/trait.Blockchain.html) for `compact_filters` backend is similar to any other kind of backends, so wallet devs don't need to worry about all the details. Its ok if the dev haven't even heard of `BIP157`, BDK takes care of that in background. - -This capability can be unlocked by compiling BDK with the `compact_filters` feature. Once enabled, BDK will be able to create wallets with the `compact_filters` type `Blockchain` backend. (The default backend is electrum server) - -#### bdk-cli -`bdk-cli` is a lightweight [REPL](https://codewith.mu/en/tutorials/1.0/repl) wrapper over the BDK library to facilitate quick and easy demonstration of BDK capabilities in command-line. Wallet devs can use this tool to quickly try out different possibilities with BDK. - -In this tutorial, We will use `bdk-cli` to demonstrate some basic wallet functionalities using `compact_filters` backend. - -## Tutorial Scope -Basic wallet workflow we will cover: - - - create and sync a wallet, - - receive a transaction, - - create a transaction, - - sign and broadcast the transaction, - - fetch updated balance, - -The BDK wallet will have a `BIP157` SPV backend (aka `compact_filters` backend) that will connect with a Bitcoin core node serving filter data. - -It will publish and extract transaction data through that node. - -We will have a Bitcoin Core wallet and a BDK wallet, sending and receiving transactions between each other, in regtest. - -## Prerequisites -Following things are required to start with the tutorial. - -1. A Bitcoin Core regtest node listening at `localhost:18444` signalling for compact filter support. -2. `bdk-cli` compiled with `compact_filter` features. - -If you already have these two setup and working, you can skip this and jump to the [Tutorial](#tutorial) section. - -#### Install and run `bitcoind` -You can definitely do it with your own `bitcoind` installation. `BIP157` support has been included in Bitcoin Core `v0.21.0`. So anything above that will work. - -You also need to ensure proper configuration settings for signalling `compact_filters` support. - -For ease of testing, the BDK project hosts docker images that can be used to spawn Bitcoin Core with all the relevant configurations. - -- spawn a regtest node using [bitcoin-regtest-box](https://github.com/bitcoindevkit/bitcoin-regtest-box) docker file. - - Start the regtest box docker container. - - ```shell - $ docker run --detach --rm -p 127.0.0.1:18443-18444:18443-18444/tcp --name bdk-box bitcoindevkit/bitcoind - ``` - This will spin up a docker container running `bicoind` and listening to port `18444` and `18333`. You can keep this terminal alive to see communication events with BDK and the node. - -- Check node is reachable - - In another terminal try connecting to the node with `bitcoin-cli` - ```shell - $ docker exec -it bdk-box /root/bitcoin-cli -regtest getnetworkinfo - { - "version": 210000, - "subversion": "/Satoshi:0.21.1/", - "protocolversion": 70016, - "localservices": "0000000000000449", - "localservicesnames": [ - "NETWORK", - "WITNESS", - "COMPACT_FILTERS", - "NETWORK_LIMITED" - ... - ], - } - - ``` - In the output, the `version` should show `210000`. `localservicesnames` should contain `"COMPACT_FILTERS"`. If you see this, then Bitcoin Core is correctly configured. - -#### Install and run bdk-cli -- Install `bdk-cli` with `compact_filters` feature - - ```shell - $ cargo install --git https://github.com/bitcoindevkit/bdk-cli.git bdk-cli --features compact_filters - ``` -- Check installation - ```shell - $ bdk-cli --help - ... - USAGE: - bdk-cli [OPTIONS] - FLAGS: - -h, --help Prints help information - -V, --version Prints version information - OPTIONS: - -n, --network Sets the network [default: testnet] - - SUBCOMMANDS: - help Prints this message or the help of the given subcommand(s) - key Key management sub-commands - repl Enter REPL command loop mode - wallet Wallet options and sub-commands - ``` -Once these are setup correctly, you can start with the tutorial next. - - - -## Tutorial -[Note: For brevity `bdk-cli` results are stored in command line variables using `jq` tool. It is recommended to check the full results to see different information returned by `bdk-cli` commands.] - -### Bitcoin Core Wallet Generation - -This is standard procedure with `bitcoin-cli`. - -- Create a wallet and generate 101 blocks. - ```shell - $ docker exec -it bdk-box /root/bitcoin-cli -regtest createwallet test - { - "name": "test", - "warning": "" - } - ``` - - ```shell - $ docker exec -it bdk-box /root/bitcoin-cli -regtest getnewaddress - bcrt1qatd7yq0jukwusuaufltlejmeydpvnpv43r5gc2 - ``` - ```shell - $ docker exec -it bdk-box /root/bitcoin-cli -regtest generatetoaddress 101 bcrt1qatd7yq0jukwusuaufltlejmeydpvnpv43r5gc2 - [ - "3813ed6eb716f4743b9657d918799acf743add985a8ded28d8aa3629dd4496b6", - "70da855913bdf791b6e458c611cebdef79b7a9840eb103ce58c71c1c7e3c49bc", - "682ca732ef72719cd6f82c5047c7690fb1cd2df2543d035ac4ea99e974b8d172", - "78799e4771017d4f46aa3c240054e2d61f54cea07ec44cb18ae712761e0aaa1e", - ... - ] - ``` - ```shell - $ docker exec -it bdk-box /root/bitcoin-cli -regtest getbalance - 50.00000000 - ``` - Now the core wallet has generated new blocks and is funded with test bitcoin. - - -### BDK Wallet Generation -BDK is a descriptor based wallet library. So in order to use it we will need some descriptors to work with. - -BDK wallet will ask for two descriptors as input, corresponding to `receive` and `change` addresses. Its recommended to have these two descriptors separate as BDK will handle them separately and ensure `change` addresses are never used for receiving funds. - -Or developers can decide to use a single descriptor too, in that case BDK will use that descriptor for deriving both `receive` and `change` addresses. - -We will use `bdk-cli` itself to generate such descriptors. - -- #### Generate a privatekey - ```shell - $ BDK_xprv=$(bdk-cli key generate | jq -r '.xprv') - $ echo $BDK_xprv - tprv8ZgxMBicQKsPefY7tdq7EKny81n9tfSvUYfSHAZByXdjPAZVysvaB6sFd2YavqfqMBgbHaXUG5oWM6sYvdJn6vnUizzQKTYAJ36bQsfPv4N - ``` - `bdk-cli key generate` will generate a fresh master key with `mnemonic` and `xprv`. We have extracted the value of extended private key and stored it in `BDK_xprv` variable. - - The returned `mnemonic` can be used to restore back the wallet if wallet data directory is lost. - -- #### Generate Descriptors - `bdk-cli key derive` can derive an `xpub`s given a `master key` and `derivation_path`. - - We will use the following paths for our `receive` and `change` descriptors - - - `receive` path: `m/84h/1h/0h/0` - - `change` path: `m/84h/1h/0h/1`, - - We can then simply wrap them in a `"wpkh()"` to create our descriptors string and store them. - - When asked for a new address, BDK will derive one from the `receive` descriptor. - - And while constructing transaction, BDK will use the `change` descriptor to derive change address. - - ```shell - $ BDK_recv_desc="wpkh($(bdk-cli key derive --path m/84h/1h/0h/0 --xprv $BDK_xprv | jq -r '.xprv'))" - $ echo $BDK_recv_desc - wpkh([ff09c7c9/84'/1'/0'/0]tprv8hkdEGgwLLnqsdfkJFidpTj5d6z5qFdP6Qwzsviea3HrS9C2mXXaDivPKCCgcaWvnGNX9eciLUQs91PWYXJqrChfnAagViCgG6L5phaNyWr/*) - ``` - ```shell - $ BDK_chng_desc="wpkh($(bdk-cli key derive --path m/84h/1h/0h/1 --xprv $BDK_xprv | jq -r '.xprv'))" - $ echo $BDK_chng_desc - wpkh([ff09c7c9/84'/1'/0'/1]tprv8hkdEGgwLLnqtbYkGG7fSy7v43RF2SQGGjNuZtmBzEHh7H8xgpXBETQAbVPqi8rkvLNFKLYY4rDzXA4fn5Ha1yuazZqhQPe3uNKmFS7648s/*) - ``` - Note: `BDK_xprv` has been used as the `master key`, this will allow BDK to have signing capabilities. - We could have used an `xpub` master key here instead, that would create an `watch-only` wallet. - -- #### Create and Sync a wallet - We will now instruct BDK to create a new wallet with following instructions - - ```shell - $ bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc sync - {} - ``` - - name (`--wallet`) `bdk-test`, - - `receive` descriptor (`-d`) as `$BDK_recv_desc` and change descriptor (`-c`) as `$BDK_chng_desc`, - - connected to a full node (`--node`) listening at `127.0.0.1:18444`, - - and finally create and sync the wallet with the `sync` command. - - If you are using a `regtest` node, also add `--network regtest`, the default is `testnet`. - - `bdk-cli` makes multiple parallel connections that can be configured with the `--conn-count` parameter (default is 4). This makes syncing parallel and fast. Use `bdk-cli --help` to see all other options. - - Getting an empty return means wallet creation succeeded. - - BDK has created a wallet named `bdk-test` in its data directory. Which is by default stored at `~/.bdk-bitcoin/compact_filters` folder. - - Looking into that folder different files and directories maintained by BDK can be seen. - ```shell - $ ls .bdk-bitcoin/compact_filters/ - 000004.log CURRENT LOCK MANIFEST-000003 OPTIONS-000010 - bdk-test IDENTITY LOG OPTIONS-000008 - ``` -### Recieve Coins - -We will use the `core` wallet to send 5 BTC to our`bdk-test` wallet. - -- Fetch a new address using `bdk-cli` - ```shell - $ bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc get_new_address - { - "address": "bcrt1qx2479wywulf50pqx5uy64zhxq9f3tuvlh8u0s9" - } - ``` - -- Transfer funds to the previous address and generate a block, using `bitcoin-cli` - ```shell - $ docker exec -it bdk-box /root/bitcoin-cli -regtest sendtoaddress bcrt1qx2479wywulf50pqx5uy64zhxq9f3tuvlh8u0s9 5 - - - $ docker exec -it bdk-box /root/bitcoin-cli -regtest generatetoaddress 1 bcrt1qw3ht9xtc9pgyvmqay0ap9fw8mxd27az8el0uz3 - ``` - - `core` has sent 5 BTC to our `bdk-test` wallet. Which is confirmed in a new block. - - `bdk-test` can see that now by syncing again. - - (Note: BDK required explicit `sync()` calls to give wallet developers flexibility on when to sync). - ```shell - $ bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc sync - {} - - $ bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc get_balance - { - "satoshi": 500000000 - } - ``` - - We can see `500000000` sats balance in our `bdk-test` wallet. - - BDK has fetched blockchain details concerning its wallet descriptors, from the core node, using compact filters. - -### Creating a transaction. - Now we want to create a transaction sending coins from `bdk-test` wallet to the `core` wallet. - -- fetch a new `core` address - ```shell - $ core_addrs=$(docker exec -it bdk-box /root/bitcoin-cli -regtest getnewaddress | tr -d '\r') - ``` - -- Create a raw transaction using `bdk-cli` to the above address. This will generate a `psbt` which we will sign. - ```shell - $ psbt=$(bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc create_tx --to $core_addrs:200000000 | jq -r '.psbt') - ``` - (Recommended to check all the other information returned by `bdk-cli create_tx`) - -### Sign and Broadcast the transaction -Asking BDK to sign a transaction is as straight forward as it can get. BDK already holds the `xprv` deatils to sign a transaction. It returns a finalised `signed_psbt` which we will next broadcast to the network. - -- Sign the transaction - ```shell - $ signed_psbt=$(bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc sign --psbt $psbt | jq -r '.psbt') - ``` - -- Broadcast the transaction - ```shell - $ bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc broadcast --psbt $signed_psbt - { - "txid": "c343f5b25372e285308eba912d1fe8fade9f64afde6d95306e248e52e0852252" - } - ``` - This makes BDK broadcast the transaction via the connected core node, and it returns the corresponding Txid. - -### Confirming the Transaction - The transaction has been received by the `core` node and waiting in its mempool for inclusion in block. - We can see the transaction via its `txid` received in previous step. - -- Check transaction in mempool - ```shell - $ docker exec -it bdk-box /root/bitcoin-cli -regtest gettransaction c343f5b25372e285308eba912d1fe8fade9f64afde6d95306e2248e52e0852252 - { - "amount": 2.00000000, - "confirmations": 0, - "trusted": false, - "txid": "c343f5b25372e285308eba912d1fe8fade9f64afde6d95306e248e52e0852252", - "walletconflicts": [ - ], - "time": 1621697202, - "timereceived": 1621697202, - "bip125-replaceable": "no", - "details": [ - { - "address": "bcrt1q3h4hs6mve5dcl7da3d4acmlp20hh8c3t4mldwe", - "category": "receive", - "amount": 2.00000000, - "label": "", - "vout": 1 - } - ], - "hex": "01000000000101d84e8cb7477f9fe6f265b56d5416ff47da9a70be18f65ec50731b8257c67f2bd0100000000ffffffff0273a2e11100000000160014874270187001febc4cebd8cb083cf2c783e8f1ac00c2eb0b000000001600148deb786b6ccd1b8ff9bd8b6bdc6fe153ef73e22b0247304402201037d9ef5b80392296311c8899b1f12a0987778d694a442a88bafa6fbd7a7c9a022011293176255897444d9c71b0b9cd13b2aedb749b142577566c90a63d61025e2c01210202427d16b29c1c8546255363a74326ee9ab3196770bb3fccc7b679d52f9c1ccf00000000" - } - ``` - This means, core has recieved the transaction in its mempool and waiting for confirmation. - -- Generate 1 block to confirm the transaction - ```shell - $ docker exec -it bdk-box /root/bitcoin-cli -regtest generatetoaddress 1 bcrt1qatd7yq0jukwusuaufltlejmeydpvnpv43r5gc2 - [ - "55436ff0169bbb3e70ab10cb7cdd45ab86204d5d7864a109142d91120d023197" - ] - ``` - -- Sync the `bdk-test` wallet and ask for available balance. - ```shell - $ bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc sync - {} - - $ bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc get_balance - { - "satoshi": 299999859 - } - ``` - - If you see the balance updated, voila! - - What happened here is: - - core created a new block containing the transaction. - - `bdk-cli` fetched the corresponding filter data. - - It noticed it got a concerning transaction. - - It asked for the details of that transaction from the core node. - - It updated its wallet details with this new information. - - The update is reflected in the wallet balance. - -### Shutdown Docker ### - -You may now shutdown the regtest docker container. - -Note: This will also clean up any data in the bitcoin core, including the wallet. - -```shell -$ docker kill bdk-box -``` - -## End Words - -In this tutorial we went through the process of receiving, creating, signing and broadcasting transaction using the BDK wallet with `compact_filters` feature. This demonstrates how BDK capabilities can be used to create SPV light wallets with integrated `BIP157` type `compact_filters` node. \ No newline at end of file diff --git a/content/blog/2021/descriptor_based_paper_wallet.md b/content/blog/2021/descriptor_based_paper_wallet.md deleted file mode 100644 index 0e1c34999c..0000000000 --- a/content/blog/2021/descriptor_based_paper_wallet.md +++ /dev/null @@ -1,191 +0,0 @@ ---- -title: "Descriptor-based paper wallets" -description: "Demonstrate how to create descriptor-based paper wallet and how to spend them with bdk" -authors: - - Riccardo Casatta - - Steve Myers -date: "2021-03-30" -tags: ["guide", "descriptor", "paper wallets"] -hidden: true -draft: false ---- - -In this post, we will use the [Rusty Paper Wallet] tool to create a multi-owned descriptor-based paper wallet. We will use [bdk] via the [bdk-cli] tool to test our descriptor and to be able to sweep the funds from our paper wallet to a new address. - -## About paper wallets - -Paper wallets have a lot of drawbacks, as explained in the [paper wallet Wiki article], as always, do your own research before deciding to use it with mainnet bitcoins. In this post we will -only be using testnet coins. - -## Descriptors - -The [previous version] of the [Rusty Paper Wallet] followed the original paper wallet design: WIF[^WIF] as secret part with the option to generate a different kind of addresses (legacy, nested segwit, and segwit). - -There were plans to [support mnemonic](https://github.com/RCasatta/rusty-paper-wallet/issues/5) instead of WIF keys because it may[^WIF core] save the sweep transaction[^sweep] and there are more wallets capable of importing a mnemonic instead of a WIF. - -However, choosing a single address type or having wallet support for a specific format is the kind of problem [descriptors] solve perfectly, so the latest [Rusty Paper Wallet] version now accepts a descriptor and the network as parameters. - -## Example use case - -So let's say your grandma wants to buy bitcoin and asked for your help. - -You are a little afraid she may lose the private key. At the same time, you don't want to duplicate the keys and give those to her daughters Alice and Barbara, because both of them could spend and accuse the other of having done so. - -Even though we trust everyone in the family it is better to play it safe and divide the responsibility of protecting Grandma's bitcoin. - -This is a perfect case for a 2 of 3 multi-signature paper wallet. This way also protects the participants from having their copy of the wallet stolen. To compromise Grandma's wallet a thief would need to find and steal at least two of them. - -Note that you as the wallet creator are still the single point of trust because you are going to generate the keys for everyone. Setups combining self generated keys from the participants is possible future work. - -## Creating the paper wallet - -For this example the spending descriptor would be: - -`wsh(multi(2,Grandma,Alice,Barbara))` - -You need [rust] installed to use [Rusty Paper Wallet]. The -n option below explicitly selects -generating `testnet` keys. Use `rusty-paper-wallet --help` to see usage instructions and other -options. - -```shell -$ cargo install rusty-paper-wallet -$ rusty-paper-wallet "wsh(multi(2,Grandma,Alice,Barbara))" -n testnet -data:text/html;base64,PCFET0N... -``` - -The [output] of the command is very long and has been shortened. The string is a [data URI scheme] paste-able in the address bar of a browser. By using a data URI no files are written on the hard disk, leaving less trace of secret material on the computer. -It's also a good idea to use incognito mode in the browser to prevent it from saving the page in the history. - -The following is the result: - - - -Under the hood, the command created a key pair randomly for every alias present in the descriptor, then replaced the aliases with the created keys and generated the corresponding address. This address is the same for every paper wallet and it is shown in the upper part of the paper wallet (the public part) along with the alias, linking the paper wallet to the owner. - -The lower part is the secret part, the written part is the descriptor with the aliases, followed by a legend linking the aliases with the keys. In the legend, all the keys are public but the one of the owner which is a private WIF. The secret QR code instead contains the descriptor already with the keys. - -The paper wallet must then be printed, and it is better to use a printer without wifi and also to be aware that some sensitive data may remain in the printer's cache. - -Then the paper wallet must be cut along the dotted lines, the secret part should be folded twice over the black zone[^black zone]. The black zone helps to avoid showing the secret parts in the presence of back-light. Once the folding is done the paper wallet should be plasticized to prevent being damaged by water. - -## BDK - -Any descriptor based wallet can be used to check the balance of and sweep the funds from -Grandma's paper wallet. For this post we'll demonstrate using the [bdk-cli] tool to do these steps. -Another area where [bdk] could be used with [Rusty Paper Wallet] is to compile a more -complicated miniscript spending policy into a descriptor, as we have done in the [spending policy demo] post. - -## Funding tx - -Since Grandma's wallet was created as a `wsh` descriptor, bitcoin can be sent to it from any -segwit capable wallet, we'll use a public [bitcoin testnet faucet]. Once the funds are sent the -deposit address `tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw` we can also use this -address and a testnet explorer to [confirm the funds were received]. - -## Sweep tx - -Now that Grandma's paper wallet is funded it's time to demonstrate how to use [bdk-cli] to sweep these -funds to a new address. Let's assume Grandma lost her original paper wallet and has asked -her daughters to sweep them to a new single signature wallet so she can spend them. - -### Step 1: Alice creates and signs a PSBT - -Alice uses the private text or QR code from her paper wallet to find her private key and the -public keys for Grandma and Barbara. With this info she creates a PSBT to sweep Grandma's funds -to a new address (in this example we'll send them back to our [bitcoin testnet faucet]). Notice how Alice -includes her wallet's descriptor checksum '#em3q73l5', this [guarantees] she has entered her descriptor correctly. - -```shell -$ SWEEP_TO_ADDR=tb1qm5tfegjevj27yvvna9elym9lnzcf0zraxgl8z2 - -$ ALICE_WIF=cSSKRHDmQEEutp5LD14tAcixu2ehSNPDTqNek1zMa9Pet98qxHq3 -$ BARBARA_PUBKEY=02a3f3f2658b9812ddeabfbde2fde03f8a65369e4ed621f29fa8ba0cc519b789fb -$ GRANDMA_PUBKEY=03f1bd2bff8e9c61f58a8d46d18fd8f3149b1f2d76b3c423a7874a5d5811d67cee -$ ALICE_DESCRIPTOR="wsh(multi(2,$GRANDMA_PUBKEY,$ALICE_WIF,$BARBARA_PUBKEY))#em3q73l5" - -# confirm descriptor creates the expected deposit address -$ bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR get_new_address -{ - "address": "tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw" -} - -# sync the wallet and show the balance -$ bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR sync -{} - -$ bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR get_balance -{ - "satoshi": 10000 -} - -# create and sign PSBT -$ UNSIGNED_PSBT=$(bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR create_tx --send_all --to $SWEEP_TO_ADDR:0 | jq -r ".psbt") - -$ ALICE_SIGNED_PSBT=$(bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR sign --psbt $UNSIGNED_PSBT | jq -r ".psbt") -``` - -### Step 2: Barbara signs Alice's signed PSBT and broadcasts the tx - -Now it's Barbara's turn to use the private text or QR code from her paper wallet to get her private -key and the public keys for Grandma and Alice. With this info plus Alice's signed PSBT she can -create a fully signed PSBT to broadcast and complete the sweep of Grandma's funds. - -```shell -$ ALICE_PUBKEY=02e486e32f0f87136fa042cb53219ace8537ea1d036deb2f4293570b94325d11cb -$ BARBARA_WIF=cSfMLzSZ9NjWUTqL3sFpgWJssnu2qgmE2cm5N1jPDRRJuDcrsPEB -$ GRANDMA_PUBKEY=03f1bd2bff8e9c61f58a8d46d18fd8f3149b1f2d76b3c423a7874a5d5811d67cee -$ BARBARA_DESCRIPTOR="wsh(multi(2,$GRANDMA_PUBKEY,$ALICE_PUBKEY,$BARBARA_WIF))#nxfa5n0z" - -# confirm descriptor creates the expected deposit address -$ bdk-cli wallet -w barbara -d $BARBARA_DESCRIPTOR get_new_address -{ - "address": "tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw" -} - -# sync the wallet and show the balance -$ bdk-cli wallet -w barbara -d $BARBARA_DESCRIPTOR sync -{} - -$ bdk-cli wallet -w barbara -d $BARBARA_DESCRIPTOR get_balance -{ - "satoshi": 10000 -} - -$ FINAL_PSBT=$(bdk-cli wallet -w barbara -d $BARBARA_DESCRIPTOR sign --psbt $ALICE_SIGNED_PSBT | jq -r ".psbt") - -$ bdk-cli wallet -w barbara -d $BARBARA_DESCRIPTOR broadcast --psbt $FINAL_PSBT -{ - "txid": "9ecd8e6be92b7edd8bf1799f8f7090e58f813825f826bdb771b4cdb444cdeb59" -} -``` - -And finally we verify that Alice and Barbara successfully created and broadcast Grandma's [sweep tx]. - -## Conclusion - -In this post we showed how to create a multi-sig descriptor based paper wallet using -[Rusty Paper Wallet] and then sweep the funds from our example paper wallet to a new address. If you -found this post interesting please comment below. Or give it a try yourself and if you run into any -problems or would like to suggest improvements leave an issue in the [Rusty Paper Wallet] or -[bdk-cli] github repos. Thanks! - -[paper wallet wiki article]: https://en.bitcoin.it/wiki/Paper_wallet -[previous version]: https://github.com/RCasatta/rusty-paper-wallet/tree/339fa4418d94f6fdd96f3d0301cab8a0bc09e8bd -[Rusty Paper Wallet]: https://github.com/RCasatta/rusty-paper-wallet -[support mnemonic]: https://github.com/RCasatta/rusty-paper-wallet/issues/5 -[descriptors]: /descriptors -[bdk]: https://github.com/bitcoindevkit/bdk -[rust]: https://www.rust-lang.org/tools/install -[output]: /images/descriptor-based-paper-wallets/data-url.txt -[data URI scheme]: https://en.wikipedia.org/wiki/Data_URI_scheme -[bdk-cli]: https://github.com/bitcoindevkit/bdk-cli -[bitcoin testnet faucet]: https://bitcoinfaucet.uo1.net/ -[confirm the funds were received]: https://mempool.space/testnet/address/tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw -[sweep tx]: https://mempool.space/testnet/tx/9ecd8e6be92b7edd8bf1799f8f7090e58f813825f826bdb771b4cdb444cdeb59 -[spending policy demo]: /blog/2021/02/spending-policy-demo/#step-4-create-wallet-descriptors-for-each-participant -[guarantees]: https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md#checksums - -[^WIF]: Wallet Input Format, a string encoding a ECDSA private key https://en.bitcoin.it/wiki/Wallet_import_format -[^WIF core]: Unless the user import the WIF directly into bitcoin core -[^sweep]: Some wallets refers to sweep as the action to create a transaction taking all the funds from the paper wallet and sending those to the wallet itself. -[^black zone]: Ideally, the black zone should be twice as long as the secret part to cover it back and front, long descriptor may leave a shorter black zone, ensure to have you printer set with vertical layout for best results. diff --git a/content/blog/2021/fee_estimation_for_light_clients_part_1.md b/content/blog/2021/fee_estimation_for_light_clients_part_1.md deleted file mode 100644 index 460e463ff4..0000000000 --- a/content/blog/2021/fee_estimation_for_light_clients_part_1.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: "Fee estimation for light-clients (Part 1)" -description: "Applying machine learning to the bitcoin fee estimation problem" -authors: - - Riccardo Casatta -date: "2021-01-25" -tags: ["fee", "machine learning"] -hidden: true -draft: false ---- - -This post is part 1 of 3 of a series. ([Part 2], [Part 3]) - -- [Introduction: what is fee estimation?](#introduction-what-is-fee-estimation) -- [The problem](#the-problem) - + [The challenges and the solution](#the-challenges-and-the-solution) - + [The question](#the-question) - + [The data logger](#the-data-logger) - -## Introduction: what is fee estimation? - -Fee estimation is the process of selecting the fee rate[^fee rate] for a bitcoin transaction being created, according to two main factors: - -* The current congestion of the Bitcoin network. -* The urgency, or lack thereof, for the transaction confirmation, i.e, its inclusion in a block. - -A fee rate should be adequate to the above factors: a fee too high would be a waste of money, because the same result could have been achieved with a lower expense. On the other hand, a fee rate too low would wait for a confirmation longer than planned or, even worse, the transaction could not be confirmed at all. - -## The problem - -Bitcoin Core offers fee estimation through the [`estimatesmartfee`] RPC method, and there are also a lot of third-party [fee estimators] online, so do we need yet another estimator? - -The model used by Bitcoin Core is not well suited for light-clients such as mobile wallets, even when running in pruned mode. Online estimators are lacking in terms of: - -* Privacy: Contacting the server leaks your IP (unless you are using Tor or a VPN), and the request timing may be used to correlate the request to a transaction broadcasted to the network soon thereafter. -* Security: A malicious estimator could provide a high fee rate leading to a waste of money, or a low fee rate hampering the transaction confirmation. - -Replace By Fee (RBF) and Child Pays For Parent (CPFP) are techniques that can somewhat minimize the fee estimation problem, because one could simply underestimate the fee rate and then raise it when necessary, however: -* RBF and CPFP may leak more information, such as patterns that may allow to detect the kind of wallet used, or which one of the transaction outputs is the change. -* Requires additional interaction: the client must come back "online" to perform the fee bump. Sometimes this might be impractical or risky, for instance when using an offline signer or a multisignature with geographically distributed keys. - -Thus, this work is an effort to build a **good fee estimator for purely peer to peer light clients** such as [neutrino] based ones, or at least determine whether the approach we take is infeasible and open the discussion -for other, better, models. - -In the meantime, another sub-goal is pursued: attract the interest of data scientists; Indeed the initial step for this analysis consists in constructing a data set, which could also also help kickstart other studies on fee estimation or, more broadly, on the Bitcoin mempool. - -#### The challenges and the solution - -The hardest part of doing fee estimation on a light client is the lack of information: for example, Bitcoin Core's `estimatesmartfee` uses up to the last 1008 blocks and knows everything about the mempool[^mempool], such as the fee rate of every transaction it contains, but a light-client does not. - -Also, there are other factors that may help doing fee estimation, such as the day of the week (the mempool usually empties during the [weekend]) or the time of the day to anticipate recurring daily events -(such as the batch of [bitmex withdrawals]). - -The idea is to apply Machine Learning (ML) techniques[^disclaimer] to discover patterns over what a light-client knows and see if they are enough to achieve consistently good estimations. - -#### The question - -We are going to use a DNN (Deep Neural Network), a ML technique in the supervised learning branch. The "ELI5" is: give a lot of example inputs and the desired output to a black box; if there are correlations between inputs and outputs, -and there are enough examples, the black box will eventually start predicting the correct output even with inputs it has never seen before. - -To define our inputs and outputs, we need to start from the question we want to answer. For a fee estimator this is: - -*"Which minimum fee rate should I use if I want this transaction to be confirmed in at most `n` blocks?"* - -This can be translated to a table with many rows like: - -confirms_in | other_information | fee_rate --|-|- -1|...|100.34 -2|...| 84.33 -10|...| 44.44 - -where the `fee_rate` column is the output we want, also called the "*target*" or "*label*" in ML terminology, and the other columns are our inputs. - -Can we build this table just by looking at the Bitcoin blockchain? Unfortunately, we can't: -The main thing that's missing is an indication of when the node first saw a transaction that has been later confirmed in a block. With that knowledge we can say that the fee rate of that transaction was the exact value required to confirm -within the number of blocks it actually took to be confirmed. For instance, if we see transaction `t` when the blockchain is at height `1000` and then we notice that `t` has been included in block `1006`, we can deduce that the -fee rate paid by `t` was the exact value required to get confirmed within the next `6` blocks. - -So to build our model, we first need to gather these data, and machine learning needs a *lot* of data to work well. - -#### The data logger - -The [data logger] is built with the purpose of collecting all the data we need, and it's MIT licensed open source software written in Rust. - -We need to register the moment in time when transactions enter in the node's mempool; to be efficient and precise we should not only call the RPC endpoints but listen to [ZMQ] events. Luckily, the just released bitcoin core 0.21.0 added a new [ZMQ] topic `zmqpubsequence` notifying mempool events (and block events). The logger is also listening to `zmqpubrawtx` and `zmqpubrawblock` topics, to make less RPC calls. - -We are not only interested in the timestamp of the transaction entering the mempool, but also how many blocks it will take until the same transaction is confirmed. -In the final dataset this field is called `confirms_in`[^blocks target]; if `confirms_in = 1` it means the transaction is confirmed in the first block created after it has been seen for the first time. - -Another critical piece of information logged by the data logger is the `fee_rate` of the transaction, since the absolute fee value paid by a bitcoin transaction is not available nor derivable given only the transaction itself, as the inputs don't have explicit amounts. - -All these data (apart from the time of the transaction entering in the mempool) can actually be reconstructed simply by looking at the blockchain. However, querying the bitcoin node can be fairly slow, and during the model training iterations we want to recreate the ML dataset rapidly[^fast], for example whenever we need to modify or add a new field. - -For these reasons, the logger is split into two parts: a process listening to the events sent by our node, which creates raw logs, and then a second process that uses these logs to create the final CSV dataset. -Raw logs are self-contained: for example, they contain all the previous transaction output values for every relevant transaction. This causes some redundancy, but in this case it's better to trade some efficiency for more performance -when recreating the dataset. - -![High level graph](/images/fee-estimation-for-light-clients/high-level-graph.svg) - -My logger instance started collecting data on the 18th of December 2020, and as of today (25th January 2020), the raw logs are about 16GB. - -I expect (or at least hope) the raw logs, the CSV dataset, or the data logger will be useful also for other projects as well, like monitoring the propagation of transactions or other works involving raw mempool data. We will share raw logs data through torrent soon. - -In the following [Part 2] we are going to talk about the dataset. - -[^fee rate]: The transaction fee rate is the ratio between the absolute fee expressed in satoshi, over the weight of the transaction measured in virtual bytes. The weight of the transaction is similar to the byte size, however a part of the transaction (the segwit part) is discounted, their byte size is considered less because it creates less burden for the network. -[^mempool]: mempool is the set of transactions that are valid by consensus rules (for example, they are spending existing bitcoin), broadcasted in the bitcoin peer to peer network, but they are not yet part of the blockchain. -[^disclaimer]: DISCLAIMER: I am not an expert data-scientist! -[^blocks target]: Conceptually similar to bitcoin core `estimatesmartfee` parameter called "blocks target", however, `confirms_in` is the real value not the desired target. -[^fast]: 16GB of compressed raw logs are processed and a compressed CSV produced in about 5 minutes. - -[Part 1]: /blog/2021/01/fee-estimation-for-light-clients-part-1/ -[Part 2]: /blog/2021/01/fee-estimation-for-light-clients-part-2/ -[Part 3]: /blog/2021/01/fee-estimation-for-light-clients-part-3/ -[`estimatesmartfee`]: https://bitcoincore.org/en/doc/0.20.0/rpc/util/estimatesmartfee/ -[bitmex withdrawals]: https://b10c.me/mempool-observations/2-bitmex-broadcast-13-utc/ -[fee estimators]: https://b10c.me/blog/003-a-list-of-public-bitcoin-feerate-estimation-apis/ -[neutrino]: https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki -[weekend]: https://www.blockchainresearchlab.org/2020/03/30/a-week-with-bitcoin-transaction-timing-and-transaction-fees/ -[ZMQ]: https://github.com/bitcoin/bitcoin/blob/master/doc/zmq.md -[data logger]: https://github.com/RCasatta/bitcoin_logger diff --git a/content/blog/2021/fee_estimation_for_light_clients_part_2.md b/content/blog/2021/fee_estimation_for_light_clients_part_2.md deleted file mode 100644 index 3ff87771e6..0000000000 --- a/content/blog/2021/fee_estimation_for_light_clients_part_2.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: "Fee estimation for light-clients (Part 2)" -description: "Applying machine learning to the bitcoin fee estimation problem" -authors: - - Riccardo Casatta -date: "2021-01-25" -tags: ["fee", "machine learning"] -hidden: true -draft: false ---- - -This post is part 2 of 3 of a series. ([Part 1], [Part 3]) - -- [The dataset](#the-dataset) - + [The mempool](#the-mempool) - + [The outliers](#the-outliers) - + [Recap](#recap) - -## The dataset - -The [dataset] is publicly available (~500MB gzip compressed, ~2GB as plain CSV). - -The output of the model is the fee rate, expressed in `[satoshi/vbytes]`. - -What about the inputs? Generally speaking, we have two main requirements for what can be included as input for our model: - -* It must be correlated to the output, even with a non-linear relation. -* It must be available to a light client: for instance, assuming to have knowledge and an index of the last 1000 blocks is considered too much. - -To evaluate the approach we are taking, we also want to compare our model's results with another available estimation: for this reason the dataset includes data to compute the error agains Bitcoin Core's `estimatesmartfee` results, even though we are not going to use it for this model. - -The dataset will contain only transactions that spend already confirmed inputs. If we wanted to include transactions with unconfirmed inputs as well, the fee rate would have to be computed as a whole; -for example if transaction `t2` spends an unconfirmed input from `t1` (while `t1` only spends confirmed inputs, and all its other outputs are unspent), the aggregated fee rate would have to be used. -Supposing `f()` is extracts the absolute fee and `w()` the transaction weight, the aggregated fee rate would be `(f(t1) + f(t2)) / (w(t1) + w(t2))`. Thus, as already said previously, to keep things simple the model simply discards all the transaction -that would need to perform this computation. - -For the same reason the dataset has the `parent_in_cpfp` flag. When a transaction has inputs confirmed (so it's not excluded by the previous rule) but one or more of its output have been spent by a transaction confirmed in the same block, `parent_in_cpfp` is `1`. -Transactions with `parent_in_cpfp = 1` are included in the dataset but excluded by the current model, since the miner probably considered an aggregated fee rate while picking the transactions to build a block. - -#### The mempool - -The most important input of our model is the current *status* of the mempool itself. However, we cannot feed the model with a list of the fee rate of every unconfirmed transaction, because this array would have a variable length. -To overcome this, the transaction contained in the mempool are grouped in "buckets" which are basically subsets of the mempool where all the transactions contained in a bucket have a similar fee rate. In particular we only care about the -*number* of transaction in every *bucket*, not which transactions it contains. - -The mempool buckets array is defined by two parameters, the `percentage_increment` and the `array_max` value. -Starting from the minimum fee rate value `min_relay_fee=1.0`, the `ith` element is: `a_i=min_relay_fee * (1+percentage_increment)^(i+1)` - -For instance, choosing the mempool buckets array to have parameters `percentage_increment = 50%` and `array_max = 500.0 sat/vbytes` the buckets would be constructed like so: - -bucket | bucket min fee rate | bucket max fee rate --|-|- -a_0| 1.0 | 1.5 -a_1| 1.5 | 2.25 -a_2| 2.25 | 3.375 -a_15| 437.89 | inf - -The array stops at `a15` because `a16` would have a bucket min greater than `array_max`. - -The model is for light-client such as [neutrino] based ones. In these clients the mempool is already available (it's needed to check for received transactions) but we can't compute fee rates of this transactions because previous confirmed inputs are not in the mempool! - -Luckily, **thanks to temporal locality [^temporal locality], an important part of mempool transactions spend outputs created very recently**, for example in the last 6 blocks. -The blocks are available through the p2p network, and downloading the last 6 is considered a good compromise between resource consumption and accurate prediction. We need the model to be built with the same data available in the prediction phase, as a consequence *the mempool data in the dataset refers only to transactions having their inputs in the last 6 blocks*. However the `bitcoin-csv` tool inside the [data logger] allows to configure this parameter. - -#### The outliers - -The dataset also contains the block percentile fee rate `q_k`, considering `r_i` to be the rate of the `ith` transaction in a block, `q_k` is the fee rate value such that for each transaction in a block `r_i` < `q_k` returns the `k%` transactions in the block that are paying lower fees. - -Percentiles are not used to feed the model but to filter some outliers tx. -Removing this observations is controversial at best and considered cheating at worse. However, it should be considered that Bitcoin Core `estimatesmartfee` doesn't even bother to give estimation for the next block, we think this is due to the fact that many transactions that are confirming in the next block are huge overestimation, or clearly errors like [this one] we found when we started logging data. -These outliers are several for transactions confirming in the next block (`confirms_in=1`), less so for `confirms_in=2`, mostly disappeared for `confirms_in=3` or more. It's counterintuitive that overestimation exists for `confirms_in>1`, by definition an overestimation is a fee rate way higher than needed, so how is possible that an overestimation doesn't enter the very next block? There are a couple of reasons why a block is discovered without containing a transaction with high fee rate: -* network latency: my node saw the transaction but the miner didn't see that transaction yet, -* block building latency: the miner saw the transaction, but didn't finish to rebuild the block template or decided it's more efficient to finish a cycle on the older block template. - -To keep the model balanced, when overestimation is filtered out, underestimation are filtered out as well. This also has the effect to remove some of the transactions possibly included because a fee is payed out-of-band. -Another reason to filter transactions is that the dataset is over-represented by transactions with low `confirms_in`: more than 50% of transactions get confirmed in the next block, so we think it's good to filter some of these transactions. - -The applied filters are the following: - -confirms_in|lower|higher --|-|- -1|q45|q55 -2|q30|q70 -3|q1|q99 - -Not yet convinced by the removal of these outliers? The [dataset] contains all the observations, make your model :) - -#### Recap - -column | used in the model | description --|-|- -txid | no | Transaction hash, useful for debugging -timestamp | converted | The time when the transaction has been added in the mempool, in the model is used in the form `day_of_week` and `hour` -current_height | no | The blockchain height seen by the node in this moment -confirms_in | yes | This transaction confirmed at block height `current_height+confirms_in` -fee_rate | target | This transaction fee rate measured in `[sat/vbytes]` -fee_rate_bytes | no | fee rate in satoshi / bytes, used to check Bitcoin Core `estimatesmartfee` predictions -block_avg_fee | no | block average fee rate `[sat/vbytes]` of block `current_height+confirms_in` -core_econ | no | bitcoin `estimatesmartfee` result for `confirms_in` block target and in economic mode. Could be not available `?` when a block is connected more recently than the estimation has been requested, estimation are requested every 10 secs. -core_cons | no | Same as above but with conservative mode -mempool_len | no | Sum of the mempool transactions with fee rate available (sum of every `a*` field) -parent_in_cpfp | no | It's 1 when the transaction has outputs that are spent in the same block in which the transaction is confirmed (they are parent in a CPFP relations). -q1-q30-... | no | Transaction confirming fast could be outliers, usually paying a lot more than required, this percentiles are used to filter those transactions, -a1-a2-... | yes | Contains the number of transaction in the mempool with known fee rate in the ith bucket. - - -![The good, the bad and the ugly](/images/fee-estimation-for-light-clients/the-good-the-bad-the-ugly.jpg) -
My biological neural network fired this, I think it's because a lot of chapters start with "The"
-

- -In the previous [Part 1] we talked about the problem. - -In the following [Part 3] we are going to talk about the model. - -[^temporal locality]: In computer science temporal locality refers to the tendency to access recent data more often than older data. - -[Part 1]: /blog/2021/01/fee-estimation-for-light-clients-part-1/ -[Part 2]: /blog/2021/01/fee-estimation-for-light-clients-part-2/ -[Part 3]: /blog/2021/01/fee-estimation-for-light-clients-part-3/ -[neutrino]: https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki -[data logger]: https://github.com/RCasatta/bitcoin_logger -[this one]: https://blockstream.info/tx/33291156ab79e9b4a1019b618b0acfa18cbdf8fa6b71c43a9eed62a849b86f9a -[dataset]: https://storage.googleapis.com/bitcoin_log/dataset_18.csv.gz diff --git a/content/blog/2021/fee_estimation_for_light_clients_part_3.md b/content/blog/2021/fee_estimation_for_light_clients_part_3.md deleted file mode 100644 index 78ec4ac3b2..0000000000 --- a/content/blog/2021/fee_estimation_for_light_clients_part_3.md +++ /dev/null @@ -1,227 +0,0 @@ ---- -title: "Fee estimation for light-clients (Part 3)" -description: "Applying machine learning to the bitcoin fee estimation problem" -authors: - - Riccardo Casatta -date: "2021-01-25" -tags: ["fee", "machine learning"] -hidden: true -draft: false ---- - -This post is part 3 of 3 of a series. ([Part 1], [Part 2]) - -- [The model](#the-model) - + [Splitting](#splitting) - + [Preprocessing](#preprocessing) - + [Build](#build) - + [Finally, training](#finally--training) -- [The prediction phase](#the-prediction-phase) -- [Conclusion and future development](#conclusion-and-future-development) -- [Acknowledgements](#acknowledgements) - -## The model - -The code building and training the model with [tensorflow] is available in [google colab notebook] (jupyter notebook); you can also download the file as plain python and run it locally. At least 1 hour is needed to train the full model, but it heavily depends on the hardware available. - -![graph confirm_in blocks vs fee_rate](/images/fee-estimation-for-light-clients/20210125-091313-confirms_in-fee_rate.png) -
Do you want to choose the fee without a model? In the last 5 weeks a ~50 sat/vbyte transaction never took more than a day to confirm and a ~10 sat/vbyte never took more than a week

- -As a reference, in the code we have a calculation of the bitcoin core `estimatesmartfee` MAE[^MAE] and drift[^drift]. -MAE is computed as `avg(abs(fee_rate - core_econ))` when `core_econ` is available (about 1.2M observations, sometime the value is not available when considered too old). - - -estimatesmartfee mode | MAE [satoshi/vbytes] | drift --|-|- -economic| 28.77 | 20.79 -conservative | 46.49 | 44.73 - -As seen from the table, the error is quite high, but the positive drift suggests `estimatesmartfee` prefers to overestimate to avoid transactions not confirming. - -As we said in the introduction, network traffic is correlated with time and we have the timestamp of when the transaction has been first seen, however a ML model doesn't like plain numbers too much, but it behaves better with "number that repeats", like categories, so we are converting the timestamp in `day_of_week` a number from 0 to 6, and `hours` a number from 0 to 24. - -#### Splitting - -The dataset is splitted in training and test data with a 80/20 proportion. As the name suggest the training part is used to train the model, the test is composed of other observations to test if the model is good with observations that has never seen (proving the model can generalize, not just memorizing the answer). - -During the training the data is splitted again in 80/20 for training and validation respectively, validation is basically testing during training. - -During splitting, the dataset is converted from a pandas data frame to tensorflow dataset, decreasing training times. - -#### Preprocessing - -The preprocessing phase is part of the model however it contains transformations without parameters trained by the model. -This transformations are useful because model trains better if data are in some format, and having this phase inside the model helps to avoid to prepare the data before feeding the model at prediction phase. - -Our model performs 2 kind of preprocessing: - -* Normalization: model trains faster if numerical features have mean 0 and standard deviation equal to 1, so this layer is built by computing the `mean` and `std` from the series of a feature before training, and the model is feed with `(feature - mean)/std`. Our model normalize `confirms_in` feature and all the buckets `a*` - -* one-hot vector: Numerical categories having a small number of different unique values like our `day_of_week` and `hours` could be trained better/faster by being converted in one hot vector. For example `day_of_week=6` (Sunday) is converted in a vector `['0', '0', '0', '0', '0', '0', '1']` while `day_of_week=5` (Saturday) is converted in the vector `['0', '0', '0', '0', '0', '1', '0']` - -#### Build - -```python3 -all_features = tf.keras.layers.concatenate(encoded_features) -x = tf.keras.layers.Dense(64, activation="relu")(all_features) -x = tf.keras.layers.Dense(64, activation="relu")(x) -output = tf.keras.layers.Dense(1, activation=clip)(x) -model = tf.keras.Model(all_inputs, output) -optimizer = tf.optimizers.Adam(learning_rate=0.01) -model.compile(loss='mse', - optimizer=optimizer, - metrics=['mae', 'mse']) -``` - -![model graph](/images/fee-estimation-for-light-clients/20210125-091313-model.png) - -The model is fed with the `encoded_features` coming from the processing phase, then there are 2 layers with 64 neurons each followed by one neuron giving the `fee_rate` as output. - -With this configurations the model has: -* Total params: `7,412` -* Trainable params: `7,361` -* Non-trainable params: `51` - -Non-trainable params comes from the normalization layer and are computed in the pre-processing phase (it contains, for example, the mean of a series). Trainable parameters are values initialized randomly and changed during the training phase. The trainable parameters are `7,361`, this number comes from the following, every neuron has an associated bias and a weight for every element in the inputs, thus: - -```shell -(48 input_values_weights + 1 bias) * (64 first_layer_neurons) -+ (64 input_values_weights + 1 bias) * (64 second layer neurons) -+ (64 input values weights + 1 bias) - -49*64+65*64+65 = 7361 -``` - -Honestly, neural network parameters are mostly the one taken from this tensorflow [example], we even tried to [tune hyperparameters], however, we decided to follow this [advice]: *"The simplest way to prevent overfitting is to start with a small model:"*. We hope this work will attract other data scientists to this bitcoin problem, improving the model. We also think that a longer time for the data collection is needed to capture various situations. - -A significant part of a ML model are the activation functions, `relu` (Rectified Linear Unit) is one of the most used lately, because it's simple and works well as we learned in this [introducing neural network video]. `relu` it's equal to zero for negative values and equal to the input for positive values. Being non-linear allows the whole model to be non-linear. - -For the last layer it is different: we want to enforce a minimum for the output, which is the minimum relay fee `1.0`[^minimum relay fee]. One could not simply cut the output of the model after prediction because all the training would not consider this constraint. So we need to build a custom activation function that the model training will be able to use for the [gradient descent] optimization step. Luckily this is very simple using tensorflow primitives: - -``` -def clip(x): - min = tf.constant(1.0) - return tf.where(tf.less(x, min), min, x) -``` - -Another important part is the optimizer, when we first read the aforementioned [example] the optimizer used was `RMSProp` however the example updated lately and we noticed the optimizer changed in favor of `Adam` which we read is the [latest trend] in data science. We changed the model to use `Adam` and effectively the training is faster with `Adam` and even slightly lower error is achieved. -Another important parameter is the learning rate, which we set to `0.01` after manual trials; however there might be space for improvements such as using [exponential decay], starting with an high learning rate and decreasing it through training epochs. - -The last part of the model configuration is the loss function: the objective of the training is to find the minimum of this function. Usually for regression problem (the ones having a number as output, not a category) the most used is the Mean squared error (MSE). MSE is measured as the average of squared difference between predictions and actual observations, giving larger penalties to large difference because of the square. An interesting property is that the bigger the error the faster the changes is good at the beginning of the training, while slowing down when the model predicts better is desirable to avoid "jumping out" the local minimum. - -#### Finally, the model training - -``` -PATIENCE = 20 -MAX_EPOCHS = 200 - -def train(): - early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=PATIENCE) - history = model.fit(train_ds, epochs=MAX_EPOCHS, validation_data=val_ds, verbose=1, callbacks=[early_stop]) - return history - -history = train() -``` - -This steps is the core of the neural network, it takes a while, let's analyze the output: - -``` -Epoch 1/200 -7559/7559 [==============================] - 34s 3ms/step - loss: 547.8023 - mae: 16.9547 - mse: 547.8023 - val_loss: 300.5965 - val_ma -e: 11.9202 - val_mse: 300.5965 -... -Epoch 158/200 -7559/7559 [==============================] - 31s 3ms/step - loss: 163.2548 - mae: 8.3126 - mse: 163.2548 - val_loss: 164.8296 - val_mae: 8.3402 - val_mse: 164.8296 -``` - -Training is done in epochs, under every epoch all the training data is iterated and model parameters updated to minimize the loss function. - -The number `7559` represent the number of steps. Theoretically the whole training data should be processed at once and parameters updated accordingly, however in practice this is infeasible for example for memory resource, thus the training happens in batch. In our case we have `1,934,999` observations in the training set and our batch size is `256`, thus we have `1,437,841/256=7,558.58` which by excess result in `7559` steps. - -The `~31s` is the time it takes to process the epoch on a threadripper CPU but GPU or TPU could do better. - -The value `loss` is the MSE on the training data while `val_loss` is the MSE value on the validation data. As far as we understand the separated validation data helps to detect the machine learning enemy, overfitting. Because in case of overfitting the value `loss` continue to improve (almost indefinitely) while `val_loss` start improving with the loss but a certain point diverge, indicating the network is memorizing the training data to improve `loss` but in doing so losing generalizing capabilities. - -Our model doesn't look to suffer overfitting cause `loss` and `val_loss` doesn't diverge during training - -![train history](/images/fee-estimation-for-light-clients/20210125-091313-train-history.png) - -While we told the training to do 200 epochs, the training stopped at 158 because we added an `early_stop` call back with `20` as `PATIENCE`, meaning that after 20 epoch and no improvement in `val_loss` the training is halted, saving time and potentially avoiding overfitting. - -## The prediction phase - -A [prediction test tool] is available on github. At the moment it uses a bitcoin core node to provide network data for simplicity, but it queries it only for the mempool and the last 6 blocks, so it's something that also a light-client could do[^disabled bloom filter]. - -The following chart is probably the best visualization to evaluate the model, on the x axis there is the real fee rate while on the y axis there is the prediction, the more the points are centered on the bisection, the more the model is good. -We can see the model is doing quite well, the MAE is 8 which is way lower than `estimatesmartfee`. However, there are big errors some times, in particular for prediction for fast confirmation (`confirms_in=1 or confirms_in=2`) as shown by the orange points. Creating a model only for blocks target greater than 2 instead of simply remove some observations may be an option. - -![prediction results](/images/fee-estimation-for-light-clients/20210125-091313-true-and-predictions.png) - -The following chart is instead a distribution of the errors, which for good model should resemble the normal distribution centered in 0, and it loooks like the model is respecting that. - -![error distribution](/images/fee-estimation-for-light-clients/20210125-091313-error-distribution.png) - -## Conclusion and future development - -The results have shown deep neural network are a tool capable of good bitcoin transaction fee estimations; this suggests that further ML research in this area might be promising. - -This is just a starting point, there are many future improvements such as: - -* Build a separate model with full knowledge, thus for full, always-connected nodes could be interesting and improve network resource allocation with respect to current estimators. -* Tensorflow is a huge dependency, and since it contains all the feature to build and train a model, most of the feature are not needed in the prediction phase. In fact tensorflow lite exists which is specifically created for embedded and mobile devices; the [prediction test tool] and the final integration in [bdk] should use it. -* Explore other fields to improve model predictions such as: - * A bucket array of the transactions in the last 6 blocks with known fee rates. This should in particular help estimations with almost empty mempool. - * Transaction weight - * Time from last block -* Some fields are very important and could benefit from pre-processing expansion, for instance applying [hashed feature columns] to `confirms_in`. -* Bitcoin logger could be improved by a merge command to unify raw logs files, reducing redundancy and consequently disk occupation. -* The dataset could be created in multiple files to allow more parallelism and use less memory during training. -* Saving the dataset in [TFRecord format] instead of CSV -* At the moment we are training the model on a threadripper CPU, training the code on GPU or even TPU will be needed to decrease training time, especially because input data will grow. -* The [prediction test tool] should estimate only using the p2p bitcoin network, without requiring a node. This work would be propedeutic for [bdk] integration -* At the moment mempool buckets are multiple inputs `a*` as show in the model graph; since they are related, is it possible to merge them in one TensorArray? -* Sometimes the model does not learn and [gets stuck]. The reason is the `clip` function applied in the last layer is constant for a value lower than 1. In this case, the derivative is 0 and the gradient descent doesn't know where to go. Instead of using the `clip` function apply penalties to the loss function for values lower than 1. -* There are issues regarding dead neurons (going to 0) or neurons with big weight, weight results should be monitored for this events, and also weight decay and L2 regularization should be explored. -* Tune hyper-parameters technique should be re-tested. -* Predictions should be monotonic decreasing for growing `confirms_in` parameter; for obvious reason it doesn't make sense that an higher fee rate will result in a higher confirmation time. But since this is not enforced anywhere in the model, at the moment this could happen. -* Since nodes with bloom filter disabled doesn't serve the mempool anymore, a model based only on last blocks should be evaluated. - -## Acknowledgements - -Thanks to [Square crypto] for sponsoring this work and thanks to the reviewers: [Leonardo Comandini], [Domenico Gabriele], [Alekos Filini], [Ferdinando Ametrano]. - -And also this tweet that remembered me [I] had this work in my TODO list - - - -This is the final part of the series. In the previous [Part 1] we talked about the problem and in [Part 2] we talked about the dataset. - -[^MAE]: MAE is Mean Absolute Error, which is the average of the series built by the absolute difference between the real value and the estimation. -[^drift]: drift like MAE, but without the absolute value -[^minimum relay fee]: Most node won't relay transactions with fee lower than the min relay fee, which has a default of `1.0` -[^disabled bloom filter]: An important issue emerged after the article came out, a bitcoin core client with bloom filter disabled (default as of 0.21) doesn't serve the mempool via p2p. - -[Part 1]: /blog/2021/01/fee-estimation-for-light-clients-part-1/ -[Part 2]: /blog/2021/01/fee-estimation-for-light-clients-part-2/ -[Part 3]: /blog/2021/01/fee-estimation-for-light-clients-part-3/ -[google colab notebook]: https://colab.research.google.com/drive/1yamwh8nE4NhmGButep-pfUT-1uRKs49a?usp=sharing -[example]: https://www.tensorflow.org/tutorials/keras/regression -[tune hyperparameters]: https://www.tensorflow.org/tutorials/keras/keras_tuner -[advice]: https://www.tensorflow.org/tutorials/keras/overfit_and_underfit#demonstrate_overfitting -[introducing neural network video]: https://youtu.be/aircAruvnKk?t=1035 -[gradient descent]: https://en.wikipedia.org/wiki/Gradient_descent#:~:text=Gradient%20descent%20is%20a%20first,the%20direction%20of%20steepest%20descent. -[latest trend]: https://towardsdatascience.com/adam-latest-trends-in-deep-learning-optimization-6be9a291375c -[exponential decay]: https://www.tensorflow.org/api_docs/python/tf/compat/v1/train/exponential_decay -[prediction test tool]: https://github.com/RCasatta/estimate_ml_fee -[bdk]: https://github.com/bitcoindevkit/bdk -[Square crypto]: https://squarecrypto.org/ -[get stuck]: https://github.com/RCasatta/bitcoin_logger/blob/master/notes.md -[hashed feature columns]: https://www.tensorflow.org/tutorials/structured_data/feature_columns#hashed_feature_columns -[tensorflow]: https://www.tensorflow.org/ -[TFRecord format]: https://www.tensorflow.org/tutorials/load_data/tfrecord -[gets stuck]: https://github.com/RCasatta/bitcoin_logger/blob/master/notes.md -[Leonardo Comandini]: https://twitter.com/LeoComandini -[Domenico Gabriele]: https://twitter.com/domegabri -[Alekos Filini]: https://twitter.com/afilini -[Ferdinando Ametrano]: https://twitter.com/Ferdinando1970 -[I]: https://twitter.com/RCasatta diff --git a/content/blog/2021/release-0.3.0.md b/content/blog/2021/release-0.3.0.md deleted file mode 100644 index a155c2462c..0000000000 --- a/content/blog/2021/release-0.3.0.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: "Release v0.3.0" -description: "Announcing the v0.3.0 release of BDK" -authors: - - Alekos Filini -date: "2021-01-20" -tags: ["rust", "release"] -hidden: true -draft: false ---- - -A new release of BDK is out: the [`v0.3.0`] is a relatively small update compared to `v0.2.0`, but it still brings some nice APIs improvements and general bugfixes. - -You can find the full [v0.3.0 changelog][changelog] on GitHub. - -## What's new in v0.3.0 - -Below are some highlights of the new improved APIs coming with this release: - -### Less verbosity when using `Wallet::new_offline()` - -Now you don't have to explicitly provide the `OfflineWallet<_>` type anymore, saving you one import and making it much less verbose to use. - -Where before you were doing: - -```rust -let wallet: OfflineWallet<_> = Wallet::new_offline(...)?; -``` - -Now you can just write: - -```rust -let wallet = Wallet::new_offline(...)?; -``` - -### No more error conversions in `DescriptorTemplate` - -The `DescriptorTemplate` trait has been updated to return a [`descriptor::error::Error`] instead of a `KeyError`. The [`descriptor!()`] macro has been updated as well, which means that now you can use the macro inside a `DescriptorTemplate::build()` implementation -without having to [map the error](/blog/2020/12/release-v0.2.0/#descriptor-macro), like so: - -```rust -pub struct TimeDecayingMultisig { - pk_a: K, - pk_b: K, - timelock: u32, -} - -impl> DescriptorTemplate for TimeDecayingMultisig { - fn build(self) -> Result { - bdk::descriptor!(wsh(thresh(2,pk(self.pk_a),s:pk(self.pk_b),s:d:v:older(self.timelock)))) - } -} -``` - -### A new repo for the CLI - -The `cli` module (and it's related `cli-utils` feature) have been removed from the main BDK repo and moved to their new home, the [bdk-cli] repo. The APIs exposed were mainly used internally, for the `repl` and the [playground](/bdk-cli/playground) -in our website, but in case you were using one of those keep that in mind. - -## Contributors - -A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports. - -Since the `v0.2.0` release around a month ago, we've had `24` new commits made by `6` different contributors for a total of `404` additions and `1243` deletions. Here's the [full diff][gh_diff]. - -A special thanks to the new contributor for this release: - -- [@tcharding][@tcharding] - Tobin C. Harding - -[changelog]: https://github.com/bitcoindevkit/bdk/blob/75669049268bbc294564f8c6e0528e07a546258f/CHANGELOG.md#v030---v020 -[gh_diff]: https://github.com/bitcoindevkit/bdk/compare/v0.2.0...v0.3.0 -[bdk-cli]: https://github.com/bitcoindevkit/bdk-cli - -[`descriptor!()`]: https://docs.rs/bdk/0.3.0/bdk/macro.descriptor.html -[`descriptor::error::Error`]: https://docs.rs/bdk/0.3.0/bdk/descriptor/error/enum.Error.html - -[`v0.3.0`]: https://crates.io/crates/bdk/0.3.0 - -[@tcharding]: https://github.com/tcharding diff --git a/content/blog/2021/release-0.4.0.md b/content/blog/2021/release-0.4.0.md deleted file mode 100644 index 0dc8cfec6a..0000000000 --- a/content/blog/2021/release-0.4.0.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: "Release v0.4.0" -description: "Announcing the v0.4.0 release of BDK" -authors: - - Alekos Filini -date: "2021-02-17" -tags: ["rust", "release"] -hidden: true -draft: false ---- - -A new release of BDK is out: the [`v0.4.0`] release brings updated dependencies, more sanity checks and an overhauled API to build transactions. - -You can find the full [v0.4.0 changelog][changelog] on GitHub. - -## What's new in v0.4.0 - -Below are some highlights of the new improved APIs coming with this release: - -### A new API to build transaction - -The star of this release is the new API designed and implemented by [@llfourn] that brings much more flexibility to the way we create transactions: originally the process of making a transaction involved the creation of a `TxBuilder` which was used -to configure *how* the wallet should build the transaction. Things like which outputs to create, what `nLockTime` to use, which UTXOs to spend, and much more. - -Once fully configured, this builder was then given to the `Wallet` itself in a `Wallet::create_tx()` or `Wallet::bump_fee()` call: the `Wallet` would try to follow the *instructions* given by the builder, but in -case of conflicting or straight-up wrong options it would have to fail and force the user to start over. - -The new API maintains the concept of a *builder*, but it changes the way it's created so that it always contains a reference to the main `Wallet` instance. What this means is that most checks can now be performed right -when something is added to the builder, not at the end, allowing the user to recover from errors instead of having to start over. - -This also opens the door to even more improvements and additions, such as a way to [spend foreign utxos][foreign_utxo] in a transaction, or even a way to [bump the fees of multiple transactions at once][bump_fee_batched] by batching them together, which -saves a bit of space and money. - -```rust -let send_to = wallet.get_new_address()?; -let (psbt, details) = { - let mut builder = wallet.build_tx(); - builder - .add_recipient(send_to.script_pubkey(), 50_000) - .enable_rbf() - .do_not_spend_change() - .fee_rate(FeeRate::from_sat_per_vb(5.0)); - builder.finish()? -}; -``` - -### Upgraded dependencies - -This release also brings many updates to our dependencies, including: - -- `bitcoin` to `v0.26` -- `miniscript` to `v5.1` -- `electrum-client` to `v0.6` -- `tokio` to `v1` -- `reqwest` to `v0.11` -- `cc` to `>= v1.0.64` - -### Compact Filters example - -Thanks to the upgrade to `bitcoin v0.26` all the issues related to new networking messages in the P2P Bitcoin network have been fixed, which means that we can finally use our (experimental) compact filters `Blockchain` with -standard Bitcoin Core 0.21 full nodes. - -The following example has also been added to the repository and can be run with `cargo run --features=compact_filters --example compact_filters_balance`. - -```rust -/// This will return wallet balance using compact filters -/// Requires a synced local bitcoin node 0.21 running on testnet with blockfilterindex=1 and peerblockfilters=1 -fn main() -> Result<(), CompactFiltersError> { - env_logger::init(); - info!("start"); - - let num_threads = 4; - let mempool = Arc::new(Mempool::default()); - let peers = (0..num_threads) - .map(|_| Peer::connect("localhost:18333", Arc::clone(&mempool), Network::Testnet)) - .collect::>()?; - let blockchain = CompactFiltersBlockchain::new(peers, "./wallet-filters", Some(500_000))?; - info!("done {:?}", blockchain); - let descriptor = "wpkh(tpubD6NzVbkrYhZ4X2yy78HWrr1M9NT8dKeWfzNiQqDdMqqa9UmmGztGGz6TaLFGsLfdft5iu32gxq1T4eMNxExNNWzVCpf9Y6JZi5TnqoC9wJq/*)"; - - let database = MemoryDatabase::default(); - let wallet = - Arc::new(Wallet::new(descriptor, None, Network::Testnet, database, blockchain).unwrap()); - wallet.sync(noop_progress(), None).unwrap(); - info!("balance: {}", wallet.get_balance()?); - Ok(()) -} -``` - -## Contributors - -A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports. - -Since the `v0.3.0` release around a month ago, we've had `59` new commits made by `8` different contributors for a total of `2463` additions and `1991` deletions. Here's the [full diff][gh_diff]. - -A special thanks to the new contributor for this release: - -- [@luckysori][@luckysori] - Lucas Soriano - -[changelog]: https://github.com/bitcoindevkit/bdk/blob/5e352489a0ac9dd92002a73aa64789a9ae2f0794/CHANGELOG.md#v040---v030 -[foreign_utxo]: https://github.com/bitcoindevkit/bdk/pull/279 -[bump_fee_batched]: https://github.com/bitcoindevkit/bdk/issues/280 -[gh_diff]: https://github.com/bitcoindevkit/bdk/compare/v0.3.0...v0.4.0 - -[`v0.4.0`]: https://crates.io/crates/bdk/0.4.0 - -[@luckysori]: https://github.com/luckysori -[@llfourn]: https://github.com/llfourn diff --git a/content/blog/2021/release-0.5.0.md b/content/blog/2021/release-0.5.0.md deleted file mode 100644 index 09f177c16f..0000000000 --- a/content/blog/2021/release-0.5.0.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "Release v0.5.0" -description: "Announcing the v0.5.0 release of BDK" -authors: - - Alekos Filini -date: "2021-03-18" -tags: ["rust", "release"] -hidden: true -draft: false ---- - -A new release of BDK is out: [`v0.5.0`] is our first release licensed under Apache 2.0 and MIT, brings new features, bugfixes and some internal refactoring. - -You can find the full [v0.5.0 changelog][changelog] on GitHub. - -## What's new in v0.5.0 - -Below are some highlights of the new release: - -### Dual Licensing - -From now on BDK will be released under both Apache 2.0 and MIT, at your discretion. This change aligns our project with many other Rust crates and reiterates our commitment to a permissive licensing model. - -### Spending *foreign* UTXOs - -This release adds a new `TxBuilder` method called [`add_foreign_utxo()`], which can be used to spend UTXOs that don't belong to the `Wallet`. We think this is going to be very useful to developers working on multiparty -protocols like CoinJoins, Pay Join, etc. - -It's as easy as giving the library a PSBT input and the satisfaction cost for that input: - -```rust -let mut builder = wallet.build_tx(); -builder - .add_recipient(addr.script_pubkey(), 60_000) - .add_foreign_utxo(foreign_utxo.outpoint, foreign_utxo_psbt_input, foreign_utxo_satisfaction_weight)? -``` - -## Contributors - -A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports. - -Since the `v0.4.0` release around a month ago, we've had `54` new commits made by `7` different contributors for a total of `1430` additions and `1212` deletions. Here's the [full diff][gh_diff]. - -A special thanks to the new contributor for this release: - -- [@davemo88][@davemo88] - -[changelog]: https://github.com/bitcoindevkit/bdk/blob/f786f0e6241a3df47b96bbb07f1aba374bc73b2f/CHANGELOG.md#v050---v040 -[gh_diff]: https://github.com/bitcoindevkit/bdk/compare/v0.4.0...v0.5.0 - -[`add_foreign_utxo()`]: https://docs.rs/bdk/0.5.0/bdk/wallet/tx_builder/struct.TxBuilder.html#method.add_foreign_utxo -[`v0.5.0`]: https://crates.io/crates/bdk/0.5.0 - -[@davemo88]: https://github.com/davemo88 diff --git a/content/blog/2021/release-0.6.0.md b/content/blog/2021/release-0.6.0.md deleted file mode 100644 index 32e35e17a4..0000000000 --- a/content/blog/2021/release-0.6.0.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: "Release v0.6.0" -description: "Announcing the v0.6.0 release of BDK" -authors: - - Alekos Filini -date: "2021-04-15" -tags: ["rust", "release"] -hidden: true -draft: false ---- - -A new release of BDK is out: [`v0.6.0`] brings some new API calls, renamed types and some bugfixes. - -You can find the full [v0.6.0 changelog][changelog] on GitHub. - -## What's new in v0.6.0 - -Below are some highlights of the new release: - -### A new way to generate addresses - -The old `get_new_address()` method has been upgraded into a more generic `get_address()`, which takes a [`AddressIndex`] argument. `AddressIndex` is defined as an enum with the following variants: -- `AddressIndex::New` increments the derivation index stored in the database and returns a new address. It's equivalent to the old `get_new_address()`. -- `AddressIndex::LastUnused` returns the address for the current derivation index if no usage has been detected. `sync()` should be called to ensure the internal database is up to date. -- `AddressIndex::Peek(index)` returns the address at a given derivation index, without updating the database. -- `AddressIndex::Reset(index)` returns the address at a given derivation index, and stores that value in the database. - -```rust -// Prints the first ten addresses without updating the derivation index -for index in 0..10 { - println!("Address #{}: {}", index, wallet.get_address(AddressIndex::Peek(index)?)); -} -``` - -### Easier multiparty transaction creation - -A new method called [`get_psbt_input()`] has been added to the `Wallet` structure, and it makes it very easy to get a complete PSBT input with all the required metadata for a given UTXO. This can be very convenient -when working with `add_foreign_utxo()`, which was added in the previous release: - -```rust -// On Alice's wallet -let alice_utxo = LocalUtxo { ... }; -let alice_psbt_input = wallet_alice.get_psbt_input(alice_utxo.clone())?; -send_input_to_bob(alice_utxo.outpoint, alice_psbt_input)?; - -// On Bob's wallet -let mut builder = wallet_bob.build_tx(); -builder - .add_recipient(addr.script_pubkey(), 60_000) - .add_foreign_utxo(alice_outpoint, alice_psbt_input, satisfaction_weight)? - .... -``` - -### Renamed types - -To keep our coding style in line with the best practices defined by the Rust language, we've renamed some of our types and enum variants to avoid using [upper case acronyms](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms). - -Some examples are: -- `UTXO` -> `Utxo` -- `RBFValue` -> `RbfValue` -- `BIP69Lexicographic` -> `Bip69Lexicographic` -- `P2PKH` -> `P2Pkh` -- `BIP44Public` -> `Bip44Public` - -### New MSRV - -Due to some changes in one of our dependency, our MSRV has been bumped up from `1.45` to `1.46`, which was released in August 2020. The last release fully supporting `1.45` is `v0.5.1`. - -## Contributors - -A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports. - -Since the `v0.5.1` release around a month ago, we've had `37` new commits made by `7` different contributors for a total of `1092` additions and `548` deletions. Here's the [full diff][gh_diff]. - -A special thanks to the new contributor for this release: - -- [@da-kami][@da-kami] - Daniel Karzel - -[changelog]: https://github.com/bitcoindevkit/bdk/blob/2bddd9baedc3744cd7647176c2f31405ee7bb54a/CHANGELOG.md#v060---v051 -[gh_diff]: https://github.com/bitcoindevkit/bdk/compare/v0.5.1...v0.6.0 - -[`AddressIndex`]: https://docs.rs/bdk/0.6.0/bdk/wallet/enum.AddressIndex.html -[`get_psbt_input()`]: https://docs.rs/bdk/0.6.0/bdk/wallet/struct.Wallet.html#method.get_psbt_input -[`v0.6.0`]: https://crates.io/crates/bdk/0.6.0 - -[@da-kami]: https://github.com/da-kami diff --git a/content/blog/2021/release-0.7.0.md b/content/blog/2021/release-0.7.0.md deleted file mode 100644 index 1b99550fe3..0000000000 --- a/content/blog/2021/release-0.7.0.md +++ /dev/null @@ -1,83 +0,0 @@ ---- -title: "Release v0.7.0" -description: "Announcing the v0.7.0 release of BDK" -authors: - - Alekos Filini -date: "2021-05-17" -tags: ["rust", "release"] -hidden: true -draft: false ---- - -A new release of BDK is out: [`v0.7.0`] improved APIs, a more robust signing process and various bugfixes and improvements. - -You can find the full [v0.7.0 changelog][changelog] on GitHub. - -## What's new in v0.7.0 - -Below are some highlights of the new release: - -### New Signing API - -The `Wallet::sign()` method has been updated to take a *mutable reference* to a PSBT rather than consuming it entirely. This makes it easier to sign the same PSBT multiple times with different signers: - -```rust -let mut psbt = ...; - -let alice_finalized = wallet_alice.sign(&mut psbt, SignOptions::default())?; -let bob_finalized = wallet_bob.sign(&mut psbt, SignOptions::default())?; -``` - -Under the hood, even more has changed around the way we make signatures: starting from this release, our signer will require by default that SegWit PSBTs also provide the `non_witness_utxo` to mitigate the fee bruning "[SegWit bug][segwit_bug]". - -For this reason, the second argument of `Wallet::sign()`, which was initially used to optionally provide a different "current height" that the wallet would consider when trying to finalize the transaction, has been replaced with a more generic "options" -argument of type [`SignOptions`]. This allows setting a different assumed block height and also opting out of requiring `non_witness_utxo` by enabling the `trust_witness_utxo` flag. - -As a result of these new more strict requirements, BDK will also, by default, fill-in the `non_witness_utxo` field when creating new PSBTs. The `TxBuilder::force_non_witness_utxo()` option has been removed and a new one called -`TxBuilder::only_witness_utxo()` has been added, to allow users to opt-out of this new default behavior. - -```rust -// Make a transaction that only contains the `witness_utxo` -let (psbt, details) = { - let mut builder = wallet.build_tx(); - builder - .add_recipient(send_to.script_pubkey(), 50_000) - .only_witness_utxo(); - builder.finish()? -}; -// Sign it by explicitly trusting just the `witness_utxo` -let finalized = wallet.sign(&mut psbt, SignOptions { trust_witness_utxo: true, ..Default::default() })?; -``` - -### Support Timelocks in the `policy` Module - -A less-known part of BDK is its "policy" module: its goal is to take a descriptor and encode the spending policy represented by that descriptor in a more "user-friendly" format. On top of that, the module -tries to provide a summary for what a user's descriptor can *contribute* to a transaction. For instance, given a 2-of-2 multisig policy, a descriptor that contains only the two public keys can't *contribute* anything, -while a descriptor that has one or both private keys can, respectively, *contribute to* and *satisfy* the policy by making signatures. - -In release `v0.5.0` we added support for computing which parts of a policy are already satisfied by a given PSBT. This, combined with the contribution part, allow users to get a complete picture of what's already present -and what's missing to fully satisfy a descriptor. - -In this release we are starting to take timelocks into consideration when computing the *satisfaction* component of a policy: this means that we can consider timelocks that are already expired as fully satisfied and also -exclude policy branches that require specific `nLockTime` or `nSequence` values, if those aren't correctly set in the transaction. - -Ultimately with those changes we are able to give our users a more complete picture of the completion stage of a PSBT, which also takes into account the expiration of timelocks. - -## Contributors - -A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports. - -Since the `v0.6.0` release around a month ago, we've had `39` new commits made by `6` different contributors for a total of `698` additions and `309` deletions. Here's the [full diff][gh_diff]. - -A special thanks to the new contributor for this release: - -- [@rajarshimaitra][@rajarshimaitra] - Raj - -[changelog]: https://github.com/bitcoindevkit/bdk/blob/aaa9943a5f614da522cdac44af80adf941879210/CHANGELOG.md#v070---v060 -[gh_diff]: https://github.com/bitcoindevkit/bdk/compare/v0.6.0...v0.7.0 - -[segwit_bug]: https://blog.trezor.io/details-of-firmware-updates-for-trezor-one-version-1-9-1-and-trezor-model-t-version-2-3-1-1eba8f60f2dd -[`SignOptions`]: https://docs.rs/bdk/0.7.0/bdk/wallet/signer/struct.SignOptions.html -[`v0.7.0`]: https://crates.io/crates/bdk/0.7.0 - -[@rajarshimaitra]: https://github.com/rajarshimaitra diff --git a/content/blog/2021/release-0.8.0.md b/content/blog/2021/release-0.8.0.md deleted file mode 100644 index ab80e68e51..0000000000 --- a/content/blog/2021/release-0.8.0.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: "Release v0.8.0" -description: "Announcing the v0.8.0 release of BDK" -authors: - - Alekos Filini -date: "2021-06-14" -tags: ["rust", "release"] -hidden: true -draft: false ---- - -A new release of BDK is out: [`v0.8.0`] brings new APIs and other minor bugfixes and internal improvements. - -You can find the full [v0.8.0 changelog][changelog] on GitHub. - -## What's new in v0.8.0 - -Below are some highlights of the new release: - -### Getting the Derivation Index - -The `Wallet::get_address()` method now returns an [`AddressInfo`] structure, rather than a simple `Address`. This new structure contains the address but also the derivation index, which can be useful in some contexts. - -Since the structure implements `Deref` it can be used directly as a `&Address`, which simplifies migrating to this change a little bit. - -```rust -let address_info = wallet.get_address(AddressInfo::New)?; - -// Print the address and derivation index -println!("Address #{}: {}", address_info.index, address_info.address); - -// Use the `AddressInfo` structure directly like an `Address` -let script_pubkey = address_info.script_pubkey(); -``` - -### Explicitly Enable non-ALL Sighashes - -To mitigate potential attacks in multiparty protocols, this release includes a new [`SignOptions::allow_all_sighashes`][sign_option] option that must be explicitly enabled to let the signers produce signatures -with any non-ALL sighash. - -```rust -let mut psbt = ...; - -// Fails if the psbt uses non-ALL sighashes -let finalized = wallet.sign(&mut psbt, SignOptions::default())?; - -// Produces a signature successfully -let finalized = wallet.sign(&mut psbt, SignOptions { allow_all_sighashes: true, ..Default::default() })?; -``` - -## Contributors - -A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports. - -Since the `v0.7.0` release around a month ago, we've had `39` new commits made by `6` different contributors for a total of `1540` additions and `1380` deletions. Here's the [full diff][gh_diff]. - -A special thanks to the new contributor for this release: - -- [@futurepaul][@futurepaul] - Paul Miller - -[changelog]: https://github.com/bitcoindevkit/bdk/blob/67714adc80669129eff2cad8991609d3b1c41cb9/CHANGELOG.md -[gh_diff]: https://github.com/bitcoindevkit/bdk/compare/v0.7.0...v0.8.0 - -[`AddressInfo`]: https://docs.rs/bdk/0.8.0/bdk/wallet/struct.AddressInfo.html -[sign_option]: https://docs.rs/bdk/0.8.0/bdk/wallet/signer/struct.SignOptions.html#structfield.allow_all_sighashes -[`v0.8.0`]: https://crates.io/crates/bdk/0.8.0 diff --git a/content/blog/2021/release-0.9.0.md b/content/blog/2021/release-0.9.0.md deleted file mode 100644 index d8165310b8..0000000000 --- a/content/blog/2021/release-0.9.0.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: "Release v0.9.0" -description: "Announcing the v0.9.0 release of BDK" -authors: - - Alekos Filini -date: "2021-07-11" -tags: ["rust", "release"] -hidden: true -draft: false ---- - -A new release of BDK is out: [`v0.9.0`] brings support for Bitcoin Core backends, more sanity checks and bugfixes. - -You can find the full [v0.9.0 changelog][changelog] on GitHub. - -## What's new in v0.9.0 - -Below are some highlights of the new release: - -## Bitcoin Core `Blockchain` Backend - -This release finally adds support for using a Bitcoin Core node as the `Blockchain` backend for a wallet, through the RPC. This is still considered experimental for the time being, since there are a few missing -things that we'd like to add, and adding those could force us to change the API a little. - -Nonetheless, if you don't mind a breaking-change later on it's already fully functional. - -The backend works by importing addresses in Bitcoin Core using the `importmulti` call. - -Using it is pretty straightforward, here's a quick example: - -```rust -let config = RpcConfig { - url: "127.0.0.1:18332".to_string(), - auth: bitcoincore_rpc::Auth::CookieFile("/home/user/.bitcoin/.cookie".into()), - network: bdk::bitcoin::Network::Testnet, - wallet_name: "wallet_name".to_string(), - skip_blocks: None, -}; -let blockchain = RpcBlockchain::from_config(&config); -``` - -Similarly to the compact filters backend, the `skip_blocks` field allows for starting a rescan of the blockchain at a given height rather than the genesis, saving some time. The rescan is only performed once, the -first time an address is imported. Afterwards every `sync()` call will only perform a few queries on the node and it will be much faster. - -## Updated `TransactionDetails` Struct - -To better accomodate the Bitcoin Core RPC and potentially more future new backends, the [`TransactionDetails`] structure have been updated as follows: - -- The `fees` field has been renamed to `fee` and it has been made optional. `Blockchain` backends can set this to `None` when they have no way of computing the fee of a transaction -- The `timestamp` and `height` fields have been merged into an optional [`ConfirmationTime`] struct - -## Verify Downloaded TXs - -This release also introduces an opt-in feature called `verify` that can be enabled to verify the unconfirmed transactions that BDK downloads from untrusted sources like Electrum servers. - -Verifying the transactions against the consensus rules can be an additional protection against some kind of attacks that could trick a wallet into creating wrong RBF (BIP 125) "bump" transactions. Check out [the issue][issue_verify] -for more details. - -## Contributors - -A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports. - -Since the `v0.8.0` release around a month ago, we've had `45` new commits made by `6` different contributors for a total of `1336` additions and `266` deletions. Here's the [full diff][gh_diff]. - -A special thanks to the new contributor for this release: - -- [@jb55][@jb55] - William Casarin - -[changelog]: https://github.com/bitcoindevkit/bdk/blob/7a9b691f68c41116dc7857bc0267a2e3b2eafdd3/CHANGELOG.md -[gh_diff]: https://github.com/bitcoindevkit/bdk/compare/v0.8.0...v0.9.0 - -[issue_verify]: https://github.com/bitcoindevkit/bdk/issues/352 - -[`TransactionDetails`]: https://docs.rs/bdk/0.9.0/bdk/struct.TransactionDetails.html -[`ConfirmationTime`]: https://docs.rs/bdk/0.9.0/bdk/struct.ConfirmationTime.html - -[`v0.9.0`]: https://crates.io/crates/bdk/0.9.0 diff --git a/content/blog/2021/spending_policy_demo.md b/content/blog/2021/spending_policy_demo.md deleted file mode 100644 index 9be9f32f75..0000000000 --- a/content/blog/2021/spending_policy_demo.md +++ /dev/null @@ -1,442 +0,0 @@ ---- -title: "Spending Policy Demo" -description: "Demonstrate how to use a descriptor wallet with different spending policies" -authors: - - Steve Myers - - Thunderbiscuit" -date: "2021-02-23" -tags: ["guide", "descriptor"] -hidden: true -draft: false ---- - -In this post we will use the [bdk-cli](https://github.com/bitcoindevkit/bdk-cli) tool to demonstrate how to use the [bdk](https://github.com/bitcoindevkit/bdk) library to: - -1. generate *testnet* public and private keys -2. create [PSBT](https://bitcoinops.org/en/topics/psbt/)s that can be spent based on different [miniscript spending policies](http://bitcoin.sipa.be/miniscript/) -3. cooperatively sign and finalize the resulting PSBTs -4. broadcast and confirm spending transactions - -The scenario we will simulate is a wallet with two spending policies: - -A. **three** out of **three** signers must sign spending transaction input [UTXO](https://developer.bitcoin.org/glossary.html)s, **OR** - -B. **two** out of **three** signers must sign **AND** the input UTXOs must be a relative number of blocks older than the spending transaction's block - -In a real-world wallet a longer relative time-lock would probably be used, but we chose a two block time-lock to make testing easier. - -*Note: If you repeat these instructions on your own your extended keys, addresses, and other values will be different than shown in this post, but the end results should be the same.* - -## Initial Setup - -### Step 0: Install a recent version `bdk-cli` - -```bash -cargo install bdk-cli --features repl,electrum,esplora - -# confirm bdk-cli is installed -bdk-cli --version -BDK CLI 0.2.0 - -# bdk-cli usage can be explored with the `help` sub-command -bdk-cli help -``` - -### Step 1: Generate private extended keys - -Generate new extended private keys for each of our wallet participants: - -```bash -bdk-cli key generate | tee alice-key.json -{ - "fingerprint": "5adb4683", - "mnemonic": "witness poverty pulse crush era item game rose bargain quantum spawn sure way behave also basket journey worry stem entry toddler floor way bone", - "xprv": "tprv8ZgxMBicQKsPeAuGznXJZwfWHgWo86dFuufRBZN7ZT44UzoNG2cYmZLNLrnsm7eXhGSeccRU2nTtxunT11UkpqrRhJQefBnFJeHBddF68bg" -} - -bdk-cli key generate | tee bob-key.json -{ - "fingerprint": "5fdec309", - "mnemonic": "shiver atom february jealous spy gallery upset height captain snake tooth master ugly orbit amazing nice parrot elevator own olympic great relief ozone violin", - "xprv": "tprv8ZgxMBicQKsPei56wJPNt9u2132Ynncp2qXdfSHszobnyjaGjQwxQBGASUidc1unmEmpyMQ9XzLgvbN36MDW7LNziVFdXVGMrx6ckMHuRmd" -} - -bdk-cli key generate | tee carol-key.json -{ - "fingerprint": "de41e56d", - "mnemonic": "upon bridge side tool style lounge need faculty middle nation armed corn valve that undo ribbon rent digital adapt capable embody zero shiver carpet", - "xprv": "tprv8ZgxMBicQKsPf2edJLnXsF2AKwkCshCy2Z7fQD6FxiNVGsbkvpLRfxM8FSKrLqqpLFzLzVUBwgE9F5MQASrbedKCrGk1NG8oJgqYtmTLQEU" -} -``` - -### Step 2: Extract private extended keys - -Here we use the `jq` Unix command to parse the json output of the `bdk-cli` commands. - -```bash -export ALICE_XPRV=$(cat alice-key.json | jq -r '.xprv') - -export BOB_XPRV=$(cat bob-key.json | jq -r '.xprv') - -export CAROL_XPRV=$(cat carol-key.json | jq -r '.xprv') -``` - -### Step 3: Derive public extended keys - -For this example we are using the [BIP-84](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki) key path: `m/84h/1h/0h/0/*` to derive extended public keys to share with other wallet participants. - -Note that the `key derive` sub-command will generate a tpub for the last hardened node in the given derivation path. You'll also notice that `bdk-cli` will returns our tpub with the key origin (fingerprint/path) added to it (the metadata part that looks like `[5adb4683/84'/1'/0']` right before the tpub). This key origin information is not necessary in order to use a tpub and generate addresses, but it's good practice to include it because some signers require it. - -```bash -export ALICE_XPUB=$(bdk-cli key derive --xprv $ALICE_XPRV --path "m/84'/1'/0'/0" | jq -r ".xpub") -echo \"$ALICE_XPUB\" -"[5adb4683/84'/1'/0']tpubDCyRBuncqwyAjSNiw1GWLmwQsWyhgPMEBpx3ZNpnCwZwf3HXerspTpaneN81KRxkwj8vjqH9pNWEPgNhen7dfE212SHfxBBbsCywxQGxvvu/0/*" - -export BOB_XPUB=$(bdk-cli key derive --xprv $BOB_XPRV --path "m/84'/1'/0'/0" | jq -r ".xpub") -echo \"$BOB_XPUB\" -"[5fdec309/84'/1'/0']tpubDDQcUeBH9JFtgZEsHZBhmRu8AuZ8ceJY1umnipPVEg1had2coGMCWdFBXNnZWKoCPic3EMgDZTdmkAVNoakwNZu2ESSW36rQvts6VXGx4bU/0/*" - -export CAROL_XPUB=$(bdk-cli key derive --xprv $CAROL_XPRV --path "m/84'/1'/0'/0" | jq -r ".xpub") -echo \"$CAROL_XPUB\" -"[de41e56d/84'/1'/0']tpubDCdxmvzJ5QBjTN8oCjjyT2V58AyZvA1fkmCeZRC75QMoaHcVP2m45Bv3hmnR7ttAwkb2UNYyoXdHVt4gwBqRrJqLUU2JrM43HippxiWpHra/0/*" -``` - -### Step 4: Create wallet descriptors for each participant - -We used the [BDK Playground Policy Compiler](https://bitcoindevkit.org/bdk-cli/playground/) to compile the [miniscript](http://bitcoin.sipa.be/miniscript/) policy: - -`thresh(3,pk(Alice),pk(Bob),pk(Carol),older(2))` - -To the [output descriptor](https://bitcoindevkit.org/descriptors/): - -`wsh(thresh(3,pk(Alice),s:pk(Bob),s:pk(Carol),sdv:older(2)))` - -This descriptor requires spending transaction inputs must be signed by all three signers, or by two signers and the spent UTXOs must be older than two blocks. - -Each participant's descriptor only uses their own XPRV key plus the XPUB keys of the other participants. - -```bash -export ALICE_DESCRIPTOR="wsh(thresh(3,pk($ALICE_XPRV/84'/1'/0'/0/*),s:pk($BOB_XPUB),s:pk($CAROL_XPUB),sdv:older(2)))" - -export BOB_DESCRIPTOR="wsh(thresh(3,pk($ALICE_XPUB),s:pk($BOB_XPRV/84'/1'/0'/0/*),s:pk($CAROL_XPUB),sdv:older(2)))" - -export CAROL_DESCRIPTOR="wsh(thresh(3,pk($ALICE_XPUB),s:pk($BOB_XPUB),s:pk($CAROL_XPRV/84'/1'/0'/0/*),sdv:older(2)))" -``` - -## Policy A. Three signatures - -### Step 1a: Create a testnet [segwit0](https://en.bitcoin.it/wiki/Segregated_Witness) receive address - -This step can be done independently by Alice, Bob, or Carol. - -```bash -bdk-cli wallet -w carol -d $CAROL_DESCRIPTOR get_new_address -{ - "address": "tb1qpqglt6yntay0se5vj3a7g36rql5pyzzp0w6jknfch2c0unwphsxs22g96e" -} -``` - -### Step 2a: Send testnet bitcoin from a faucet to receive address - -After a faucet payment is sent, use a testnet block explorer to confirm the transaction was included in a block. - -[https://mempool.space/testnet/address/tb1qpqglt6yntay0se5vj3a7g36rql5pyzzp0w6jknfch2c0unwphsxs22g96e](https://mempool.space/testnet/address/tb1qpqglt6yntay0se5vj3a7g36rql5pyzzp0w6jknfch2c0unwphsxs22g96e) - -### Step 3a: Sync participant wallets and confirm balance - -This step must be done by Alice, Bob, and Carol so their individual descriptor wallets know about the faucet transaction they will later be spending the output of. - -```bash -bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR sync -{} -bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR get_balance -{ - "satoshi": 10000 -} - -bdk-cli wallet -w bob -d $BOB_DESCRIPTOR sync -{} -bdk-cli wallet -w bob -d $BOB_DESCRIPTOR get_balance -{ - "satoshi": 10000 -} - -bdk-cli wallet -w carol -d $CAROL_DESCRIPTOR sync -{} -bdk-cli wallet -w carol -d $CAROL_DESCRIPTOR get_balance -{ - "satoshi": 10000 -} -``` - -### Step 4a: View wallet spending policies - -This can also be done by any wallet participant, as long as they have the same descriptor and extended public keys from the other particpants.. - -```bash -bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR policies -{ - "external": { - "contribution": { - "conditions": { - "0": [ - {} - ], - "3": [ - { - "csv": 2 - } - ] - }, - "items": [ - 0, - 3 - ], - "m": 3, - "n": 4, - "type": "PARTIAL" - }, - "id": "ydtnup84", - "items": [ - { - "contribution": { - "condition": {}, - "type": "COMPLETE" - }, - "fingerprint": "5adb4683", - "id": "uyxvyzqt", - "satisfaction": { - "type": "NONE" - }, - "type": "SIGNATURE" - }, - { - "contribution": { - "type": "NONE" - }, - "fingerprint": "5fdec309", - "id": "dzkmxcgu", - "satisfaction": { - "type": "NONE" - }, - "type": "SIGNATURE" - }, - { - "contribution": { - "type": "NONE" - }, - "fingerprint": "de41e56d", - "id": "ekfu5uaw", - "satisfaction": { - "type": "NONE" - }, - "type": "SIGNATURE" - }, - { - "contribution": { - "condition": { - "csv": 2 - }, - "type": "COMPLETE" - }, - "id": "8kel7sdw", - "satisfaction": { - "type": "NONE" - }, - "type": "RELATIVETIMELOCK", - "value": 2 - } - ], - "satisfaction": { - "type": "NONE" - }, - "threshold": 3, - "type": "THRESH" - }, - "internal": null -} -``` - -### Step 5a: Create spending transaction - -The transaction can also be created by Alice, Bob, or Carol, or even an untrusted coordinator that only has all three tpubs. - -Note that the argument provided to the --external_policy flag contains the id retrieved from the `policies` subcommand in the above step, in this case `ydtnup84`. - -```bash -bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR create_tx -a --to tb1qm5tfegjevj27yvvna9elym9lnzcf0zraxgl8z2:0 --external_policy "{\"ydtnup84\": [0,1,2]}" -{ - "details": { - "fees": 169, - "height": null, - "received": 0, - "sent": 10000, - "timestamp": 1614058791, - "transaction": null, - "txid": "3b9a7ac610afc91f1d1a0dd844e609376278fe7210c69b7ef663c5a8e8308f3e" - }, - "psbt": "cHNidP8BAFIBAAAAAYx7T0cL7EoUYBEU0mSL6+DS4VQafUzJgAf0Ftlbkya5AQAAAAD/////AWcmAAAAAAAAFgAU3RacollkleIxk+lz8my/mLCXiH0AAAAAAAEBKxAnAAAAAAAAIgAgCBH16JNfSPhmjJR75EdDB+gSCEF7tStNOLqw/k3BvA0BBXchA3c1Ak2kcGOzOh6eRXFKfpnpzP1lzfcXIYhxFGZG51mxrHwhA75YDXRLDLt+eX5UsE03mIGUSsQP2MrJ9lm17cGXDw2mrJN8IQIvNjaP+mwNC0DtgaB6ENB/DPPlbUDR6+NZ4Sw070jzOKyTfHZjUrJpaJNThyIGAi82No/6bA0LQO2BoHoQ0H8M8+VtQNHr41nhLDTvSPM4DO66tnIAAAAAAAAAACIGA3c1Ak2kcGOzOh6eRXFKfpnpzP1lzfcXIYhxFGZG51mxGFrbRoNUAACAAQAAgAAAAIAAAAAAAAAAACIGA75YDXRLDLt+eX5UsE03mIGUSsQP2MrJ9lm17cGXDw2mDEMxpeYAAAAAAAAAAAAA" -} - -export UNSIGNED_PSBT=$(bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR create_tx -a --to tb1qm5tfegjevj27yvvna9elym9lnzcf0zraxgl8z2:0 --external_policy "{\"ydtnup84\": [0,1,2]}" | jq -r ".psbt") -``` - -### Step 6a: Sign and finalize PSBTs - -```bash -# ALICE SIGNS -export ALICE_SIGNED_PSBT=$(bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR sign --psbt $UNSIGNED_PSBT | jq -r ".psbt") - -# BOB SIGNS -export ALICE_BOB_SIGNED_PSBT=$(bdk-cli wallet -w bob -d $BOB_DESCRIPTOR sign --psbt $ALICE_SIGNED_PSBT | jq -r ".psbt") - -# CAROL SIGNS -export FINAL_PSBT=$(bdk-cli wallet -w carol -d $CAROL_DESCRIPTOR sign --psbt $ALICE_BOB_SIGNED_PSBT | jq -r ".psbt") - -## PSBT is finalized -bdk-cli wallet -w carol -d $CAROL_DESCRIPTOR sign --psbt $ALICE_BOB_SIGNED_PSBT -{ - "is_finalized": true, - "psbt": "cHNidP8BAFIBAAAAAYx7T0cL7EoUYBEU0mSL6+DS4VQafUzJgAf0Ftlbkya5AQAAAAD/////AWcmAAAAAAAAFgAU3RacollkleIxk+lz8my/mLCXiH0AAAAAAAEBKxAnAAAAAAAAIgAgCBH16JNfSPhmjJR75EdDB+gSCEF7tStNOLqw/k3BvA0iAgIvNjaP+mwNC0DtgaB6ENB/DPPlbUDR6+NZ4Sw070jzOEcwRAIgRPXSwFLfzD1YQzw5FGYA0TgiQ+D88hSOVDbvyUZDiPUCIAbguaSGgCbBAXo5sIxpZ4c1dcGkYyrrqnDjc1jcdJ1CASICA3c1Ak2kcGOzOh6eRXFKfpnpzP1lzfcXIYhxFGZG51mxSDBFAiEA0kdkvlA+k5kUBWVUM8SkR4Ua9pnXF66ECVwIM1l0doACIF0aMiORVC35+M3GHF2Vl8Q7t455mebrr1HuLaAyxBOYASICA75YDXRLDLt+eX5UsE03mIGUSsQP2MrJ9lm17cGXDw2mRzBEAiBPJlQEnuVDHgfgOdTZNlIcRZz2iqHoMWfDmLMFqJSOQAIgCuOcTKp/VaaqwIjnYfMKO3eQ1k9pOygSWt6teT1o13QBAQV3IQN3NQJNpHBjszoenkVxSn6Z6cz9Zc33FyGIcRRmRudZsax8IQO+WA10Swy7fnl+VLBNN5iBlErED9jKyfZZte3Blw8NpqyTfCECLzY2j/psDQtA7YGgehDQfwzz5W1A0evjWeEsNO9I8zisk3x2Y1KyaWiTU4ciBgIvNjaP+mwNC0DtgaB6ENB/DPPlbUDR6+NZ4Sw070jzOBjeQeVtVAAAgAEAAIAAAACAAAAAAAAAAAAiBgN3NQJNpHBjszoenkVxSn6Z6cz9Zc33FyGIcRRmRudZsQwpbm6KAAAAAAAAAAAiBgO+WA10Swy7fnl+VLBNN5iBlErED9jKyfZZte3Blw8NpgxDMaXmAAAAAAAAAAABBwABCP1TAQUARzBEAiBE9dLAUt/MPVhDPDkUZgDROCJD4PzyFI5UNu/JRkOI9QIgBuC5pIaAJsEBejmwjGlnhzV1waRjKuuqcONzWNx0nUIBRzBEAiBPJlQEnuVDHgfgOdTZNlIcRZz2iqHoMWfDmLMFqJSOQAIgCuOcTKp/VaaqwIjnYfMKO3eQ1k9pOygSWt6teT1o13QBSDBFAiEA0kdkvlA+k5kUBWVUM8SkR4Ua9pnXF66ECVwIM1l0doACIF0aMiORVC35+M3GHF2Vl8Q7t455mebrr1HuLaAyxBOYAXchA3c1Ak2kcGOzOh6eRXFKfpnpzP1lzfcXIYhxFGZG51mxrHwhA75YDXRLDLt+eX5UsE03mIGUSsQP2MrJ9lm17cGXDw2mrJN8IQIvNjaP+mwNC0DtgaB6ENB/DPPlbUDR6+NZ4Sw070jzOKyTfHZjUrJpaJNThwAA" -``` - -### Step 7a: Broadcast finalized PSBT - -```bash -bdk-cli wallet -w carol -d $CAROL_DESCRIPTOR broadcast --psbt $FINAL_PSBT -{ - "txid": "3b9a7ac610afc91f1d1a0dd844e609376278fe7210c69b7ef663c5a8e8308f3e" -} -``` - -### Step 8a: Confirm transaction included in a testnet block - -[https://mempool.space/testnet/tx/3b9a7ac610afc91f1d1a0dd844e609376278fe7210c69b7ef663c5a8e8308f3e](https://mempool.space/testnet/tx/3b9a7ac610afc91f1d1a0dd844e609376278fe7210c69b7ef663c5a8e8308f3e) - -And new wallet balance is now zero. - -```bash -bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR sync -{} -bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR get_balance -{ - "satoshi": 0 -} -``` - -### DONE! - -## Policy B. Two signatures after a relative time lock - -Now we will use the same extended private and public keys, and the same descriptors to receive and spend testnet bitcoin using only two of our participants signatures after the transaction input's relative time-lock has expired. - -### Step 1b: Create a new testnet receive address - -The receive address can still be generated by Alice, Bob, or Carol. - -```bash -bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR get_new_address -{ - "address": "tb1q886w2zmtakwxpngs9kn7y0a7tvd6e24u58sse2sv92zrjpnenfhqtfnmw9" -} -``` - -### Step 2b: Fund new address from testnet faucet - -After the faucet payment is sent, confirm using a testnet block explorer to verify the transaction was included in a block. - -[https://mempool.space/testnet/address/tb1q886w2zmtakwxpngs9kn7y0a7tvd6e24u58sse2sv92zrjpnenfhqtfnmw9](https://mempool.space/testnet/address/tb1q886w2zmtakwxpngs9kn7y0a7tvd6e24u58sse2sv92zrjpnenfhqtfnmw9) - -### Step 3b: Sync wallet and confirm wallet balance - -This step must be done by Alice and Bob so their individual descriptor wallets know about the faucet transaction they will later be spending the output of. - -```bash -bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR sync -{} -bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR get_balance -{ - "satoshi": 10000 -} - -bdk-cli wallet -w bob -d $BOB_DESCRIPTOR sync -{} -bdk-cli wallet -w bob -d $BOB_DESCRIPTOR get_balance -{ - "satoshi": 10000 -} - -# NO CAROL SHE LOST HER KEY! -``` - -### Step 4b: Create spending transaction - -This spending transaction uses Alice and Bob's keys plus a two block relative time-lock, see above [Step 4a](#step-4a-view-wallet-spending-policies) for the policy id. The transaction can be created by Alice or Bob. - -A time based relative time-lock can be used instead of one based on blocks but is slightly more complicated to calculate. See -[BIP-68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki#specification) for the details. - -```bash -bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR create_tx -a --to tb1qm5tfegjevj27yvvna9elym9lnzcf0zraxgl8z2:0 --external_policy "{\"ydtnup84\": [0,1,3]}" -{ - "details": { - "fees": 169, - "height": null, - "received": 0, - "sent": 10000, - "timestamp": 1614059434, - "transaction": null, - "txid": "6a04c60dff8eeb14dc0848c663d669c34ddc30125d9564364c9414e3ff4a7d28" - }, - "psbt": "cHNidP8BAFICAAAAAYmc6mhj4Cf4pcJyBvxSbCd9IB1yDGs+plzb95t7++v0AAAAAAACAAAAAWcmAAAAAAAAFgAU3RacollkleIxk+lz8my/mLCXiH0AAAAAAAEBKxAnAAAAAAAAIgAgOfTlC2vtnGDNEC2n4j++Wxusqryh4QyqDCqEOQZ5mm4BBXchAlUVWMkNwGkCxDe4ZAcyz7HI+Vpmo4A5//OvkV33PCpprHwhAq9NOHBbPEdKr8IzYEomNTk1eokAkLQ9+ZMuS/OlX+nFrJN8IQOrU70B/wo/oUUCKFQ2cIsBxx6SysE7uVwxyu0ozM4zYqyTfHZjUrJpaJNThyIGAlUVWMkNwGkCxDe4ZAcyz7HI+Vpmo4A5//OvkV33PCppGFrbRoNUAACAAQAAgAAAAIAAAAAAAQAAACIGAq9NOHBbPEdKr8IzYEomNTk1eokAkLQ9+ZMuS/OlX+nFDEMxpeYAAAAAAQAAACIGA6tTvQH/Cj+hRQIoVDZwiwHHHpLKwTu5XDHK7SjMzjNiDO66tnIAAAAAAQAAAAAA" -} - -export UNSIGNED_PSBT2=$(bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR create_tx -a --to tb1qm5tfegjevj27yvvna9elym9lnzcf0zraxgl8z2:0 --external_policy "{\"ydtnup84\": [0,1,3]}" | jq -r ".psbt") -``` - -### Step 5b: Sign and finalize PSBTs - -```bash -# ALICE SIGNS -export ALICE_SIGNED_PSBT2=$(bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR sign --psbt $UNSIGNED_PSBT2 | jq -r ".psbt") - -# BOB SIGNS -export FINAL_PSBT2=$(bdk-cli wallet -w bob -d $BOB_DESCRIPTOR sign --psbt $ALICE_SIGNED_PSBT2 | jq -r ".psbt") - -# CAROL DOES *NOT* SIGN -``` - -### Step 6b: Broadcast finalized PSBT - -```bash -bdk-cli wallet -w bob -d $BOB_DESCRIPTOR broadcast --psbt $FINAL_PSBT2 -thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Electrum(Protocol(String("sendrawtransaction RPC error: {\"code\":-26,\"message\":\"non-BIP68-final\"}")))', src/bdk_cli.rs:168:50 - -# Oops we didn't wait long enough for the relative time lock to expire - -# Try again in ~20 mins and it is successfully broadcast - -bdk-cli wallet -w bob -d $BOB_DESCRIPTOR broadcast --psbt $FINAL_PSBT2 -{ - "txid": "6a04c60dff8eeb14dc0848c663d669c34ddc30125d9564364c9414e3ff4a7d28" -} -``` - -### Step 7b: View confirmed transaction - -[https://mempool.space/testnet/tx/6a04c60dff8eeb14dc0848c663d669c34ddc30125d9564364c9414e3ff4a7d28](https://mempool.space/testnet/tx/6a04c60dff8eeb14dc0848c663d669c34ddc30125d9564364c9414e3ff4a7d28) - -And wallet balance is again zero - -```bash -bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR sync -{} -bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR get_balance -{ - "satoshi": 0 -} -``` - -### Done again! - -In this demo we showed how to receive and spend bitcoin using two different descriptor wallet policies using the `bdk` library and `bdk-cli` wallet tool. diff --git a/content/blog/_index.md b/content/blog/_index.md deleted file mode 100644 index 8df61f49c7..0000000000 --- a/content/blog/_index.md +++ /dev/null @@ -1,9 +0,0 @@ -+++ -title = "Blog" -weight = 1 -chapter = false -pre = ' ' -+++ - -This blog is used to publish announcements, guides and more regarding the BDK project. -Anybody can contribute by sending a pull request to our [GitHub repository](https://github.com/bitcoindevkit/bitcoindevkit.org). diff --git a/content/descriptors/_index.md b/content/descriptors/_index.md deleted file mode 100644 index 33c3fa303c..0000000000 --- a/content/descriptors/_index.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -title: "Descriptors" -date: 2020-04-28T14:40:12+02:00 -draft: false -weight: 5 -pre: ' ' ---- - -Descriptors are a compact and semi-standard way to easily encode, or "describe", how scripts (and subsequently, addresses) of a wallet should be generated. They can be especially helpful when working with multisigs or even -more complex scripts, where the structure of the script itself is not trivial. They are a big step forward in making wallets more portable across different tools and apps, because for the first time they create a common -language to describe a full bitcoin script that developers can use and integrate in their software. - -The ecosystem around descriptors is still very much in its early stage, but they are starting to see some adoption in [Bitcoin Core](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md) and other projects. BDK -aims to produce the first "Native Descriptor" Bitcoin library that can be used by developers to build their own ["Native Descriptor Wallets"](https://www.youtube.com/watch?v=xC25NzIjzog). - -### Compatibility Matrix - -Below are some tables to highlight the differences between Bitcoin Core's descriptor support, rust-miniscript's one and BDK's. - -#### Key Types - -
- -| Key Type | BDK | rust-miniscript | Bitcoin Core | -| -------- | --------------- | --------------- | ------------ | -| Hex PublicKey | ✓ | ✓ | ✓ | -| WIF PrivateKey | ✓ | ✗ | ✓ | -| Extended Keys (xpub/xprv) | ✓ | ✗ | ✓ | - -
- -#### Script Types (top level) - -
- -| Script Type | BDK | rust-miniscript | Bitcoin Core | -| -------- | --------------- | --------------- | ------------ | -| `pk()` | ✓ | ✓ | ✓ | -| `pkh()` | ✓ | ✓ | ✓ | -| `wpkh()` | ✓ | ✓ | ✓ | -| `sh(wpkh())` | ✓ | ✓ | ✓ | -| `sh()` | ✓ | ✓ | ✓ | -| `wsh()` | ✓ | ✓ | ✓ | -| `sh(wsh())` | ✓ | ✓ | ✓ | -| `combo()` | ✗ | ✗ | ✓ | -| `addr()` | ✗ | ✗ | ✓ | -| `raw()` | ✗ | ✗ | ✓ | -| Bare scripts | ✓ | ✓ | ✗ | - -
- -#### Operators - -
- -| Operator | BDK | rust-miniscript | Bitcoin Core | -| -------- | --------------- | --------------- | ------------ | -| `pk()` | ✓ | ✓ | ✓ | -| `pk_h()` | ✓ | ✓ | ✓ - as `pkh()` | -| `older()` | ✓ | ✓ | ✗ | -| `after()` | ✓ | ✓ | ✗ | -| `sha256()` | ✓ | ✓ | ✗ | -| `hash256()` | ✓ | ✓ | ✗ | -| `ripemd160()` | ✓ | ✓ | ✗ | -| `hash160()` | ✓ | ✓ | ✗ | -| `andor()` | ✓ | ✓ | ✗ | -| `and_{v,b,n}()` | ✓ | ✓ | ✗ | -| `or_{b,c,d,i}()` | ✓ | ✓ | ✗ | -| `multi()` | ✓ | ✓ | ✓ | -| `thresh()` | ✓ | ✓ | ✗ | -| `sortedmulti()` | ✓ | ✓ | ✓ | - -
- -#### Modifiers - -
- -| Script Type | BDK | rust-miniscript | Bitcoin Core | -| -------- | --------------- | --------------- | ------------ | -| `a:` | ✓ | ✓ | ✗ | -| `s:` | ✓ | ✓ | ✗ | -| `c:` | ✓ | ✓ | ✗ | -| `t:` | ✓ | ✓ | ✗ | -| `d:` | ✓ | ✓ | ✗ | -| `v:` | ✓ | ✓ | ✗ | -| `j:` | ✓ | ✓ | ✗ | -| `n:` | ✓ | ✓ | ✗ | -| `l:` | ✓ | ✓ | ✗ | -| `u:` | ✓ | ✓ | ✗ | - -
- -For a more thorough description of these operators and modifiers see [Sipa's Miniscript Page](http://bitcoin.sipa.be/miniscript/) and [Bitcoin Core's](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md). - -### Examples - -Some examples of valid BDK descriptors are: - -
- -| Spending Policy | Descriptor | Address 0 | Address 1 | -| --------------- | ---------- | --------- | --------- | -| Static P2PKH | `pkh(cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR)` | mrkwtj5xpYQjHeJe5wsweNjVeTKkvR5fCr | mrkwtj5xpYQjHeJe5wsweNjVeTKkvR5fCr | -| Static P2PKH, watch-only | `pkh(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)` | mrkwtj5xpYQjHeJe5wsweNjVeTKkvR5fCr | mrkwtj5xpYQjHeJe5wsweNjVeTKkvR5fCr | -| P2WSH 2-of-2 with one private key | `wsh(multi(2,tprv8ZgxMBicQKsPePmENhT9N9yiSfTtDoC1f39P7nNmgEyCB6Nm4Qiv1muq4CykB9jtnQg2VitBrWh8PJU8LHzoGMHTrS2VKBSgAz7Ssjf9S3P/0/*,tpubDBYDcH8P2PedrEN3HxWYJJJMZEdgnrqMsjeKpPNzwe7jmGwk5M3HRdSf5vudAXwrJPfUsfvUPFooKWmz79Lh111U51RNotagXiGNeJe3i6t/1/*))` | tb1qqsat6c82fvdy73rfzye8f7nwxcz3xny7t56azl73g95mt3tmzvgs9a8vjs | tb1q7sgx6gscgtau57jduend6a8l445ahpk3dt3u5zu58rx5qm27lhkqgfdjdr | -| P2WSH-P2SH one key + 10 days timelock | `sh(wsh(and_v(vc:pk_h(tprv8ZgxMBicQKsPePmENhT9N9yiSfTtDoC1f39P7nNmgEyCB6Nm4Qiv1muq4CykB9jtnQg2VitBrWh8PJU8LHzoGMHTrS2VKBSgAz7Ssjf9S3P/0/*),older(1440))))` | 2Mtk2nyS98MCi2P7TkoBGLaJviBy956XxB1 | 2MuEStKzYhqb5HCFgHz9153tZsL5sVqV5xC | - -
- -### Implementation Details - -BDK extends the capabilities of [rust-miniscript](https://github.com/apoelstra/rust-miniscript) by introducing the concept of an *ExtendedDescriptor*: it represents a descriptor that contains one or more "derivable keys" like `xpubs` or `xprvs` -and can be "derived" to a normal Descriptor by deriving every single one of its keys. It is currently called "StringDescriptor" in the code, because it's implemented as a wrapped `miniscript::Descriptor`. - -ExtendedDescriptors are derived using a single index instead of a full derivation path: this is because normally most of the path is fixed and can be represented right after the xpub/xprv itself, and only the -final index changes for each address. This is what's normally called a *DescriptorExtendedKey* in codebase, and it's the represented with a similar syntax to Bitcoin Core's, such as: - -``` -[d34db33f/44'/0'/0']xpub6ERApfZwUNrhL.......rBGRjaDMzQLcgJvLJuZZvRcEL/0/* -``` diff --git a/docs/.vuepress/config.js b/docs/.vuepress/config.js new file mode 100644 index 0000000000..c830bc0bdc --- /dev/null +++ b/docs/.vuepress/config.js @@ -0,0 +1,166 @@ +const { resolve } = require('path') +const themeConfig = require('squarecrypto-vuepress-devkit-theme/config') + +const title = 'Bitcoin Dev Kit Documentation' +const baseUrl = 'https://bitcoindevkit.org' +const githubUrl = 'https://github.com/bitcoindevkit' +const discordUrl = 'https://discord.gg/dstn4dQ' +const twitterUrl = 'https://twitter.com/intent/follow?screen_name=bitcoindevkit' +const themeColor = '#ffffff' + +const docsSidebar = [ + { + title: 'Documentation', + collapsable: false, + children: [ + ['/getting-started', 'Getting Started'], + { + title: "BDK-CLI", + collapsable: true, + children: [ + '/bdk-cli/installation', + '/bdk-cli/concept', + '/bdk-cli/interface', + '/bdk-cli/regtest', + '/bdk-cli/compiler', + '/bdk-cli/playground' + ] + }, + '/descriptors/', + ] + }, + { + title: 'API Reference', + collapsable: false, + children: [ + ['https://docs.rs/bdk/0.11.0/bdk/', 'Stable Docs'], + ['https://bitcoindevkit.org/docs-rs/bdk/nightly/latest/bdk/', 'Nightliy Docs'] + ], + } +] + +const tutorialSidebar = [ + { + title: 'Tutorials', + collapsable: false, + children: [ + '/tutorials/hello-world', + ], + } +] + +const blogSidebar = [ + { + title: 'Blog', + collapsable: false, + children: [ + ['/blog/', 'Articles'], + ['/blog/tags/', 'Tags'], + ['/blog/author/', 'Authors'] + ] + } +] + +module.exports = { + title, + description: 'The Bitcoin Dev Kit (BDK) project (originally called Magical Bitcoin 🧙) aims to build a collection of tools and libraries that are designed to be a solid foundation for cross platform Bitcoin wallets, along with a fully working reference implementation wallet called Magical Bitcoin.', + theme: resolve(__dirname, '../../node_modules/squarecrypto-vuepress-devkit-theme'), + ...themeConfig({ + baseUrl, + title, + themeColor + }), + themeConfig: { + domain: baseUrl, + logo: '/img/logo.svg', + displayAllHeaders: false, + repo: 'bitcoindevkit/bitcoindevkit.org', + docsDir: 'docs', + editLinks: true, + sidebarDepth: 0, + nav: [ + { + text: 'Docs', + link: '/getting-started/' + }, + { + text: 'Tutorials', + link: '/tutorials/hello-world' + }, + { + text: 'Blog', + link: '/blog/' + }, + { + text: 'Discord', + link: discordUrl + }, + { + text: 'GitHub', + link: githubUrl, + rel: 'noopener noreferrer' + } + ], + sidebar: { + '/_blog/': blogSidebar, + '/blog/': blogSidebar, + '/tutorials/': tutorialSidebar, + '/': docsSidebar, + }, + footer: { + links: [ + { + title: 'Docs', + children: [ + { + text: 'Getting Started', + link: '/getting-started/' + }, + { + text: 'BDK-CLI', + link: '/bdk-cli/installation/' + }, + { + text: 'Descriptors', + link: '/descriptors/' + } + ] + }, + { + title: 'Community', + children: [ + { + text: 'GitHub', + link: githubUrl, + rel: 'noopener noreferrer' + }, + { + text: 'Twitter', + link: twitterUrl, + rel: 'noopener noreferrer' + }, + { + text: 'Chat on Discord', + link: discordUrl, + rel: 'noopener noreferrer' + } + ] + }, + { + title: 'More', + children: [ + { + text: 'Blog', + link: '/blog/' + }, + { + text: 'Supporters', + link: '/supporters/' + } + ] + } + ], + copyright: `Copyright © ${(new Date()).getUTCFullYear()} BDK Developers` + } + } +} diff --git a/docs/.vuepress/public/bdk-cli/playground/1.playground.js b/docs/.vuepress/public/bdk-cli/playground/1.playground.js new file mode 100644 index 0000000000..b72c6096f4 --- /dev/null +++ b/docs/.vuepress/public/bdk-cli/playground/1.playground.js @@ -0,0 +1,19 @@ +(window.webpackJsonp=window.webpackJsonp||[]).push([[1],[,,,function(t,e,o){var i,n,s;n=[o(7)],void 0===(s="function"==typeof(i=function(t){ +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +"use strict";return t.setLocale=function(e){t.Msg=t.Msg||{},Object.keys(e).forEach((function(o){t.Msg[o]=e[o]}))},t})?i.apply(e,n):i)||(t.exports=s)},function(t,e,o){var i,n,s;n=[o(6)],void 0===(s="function"==typeof(i=function(t){ +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +"use strict";return t})?i.apply(e,n):i)||(t.exports=s)},function(t,e){var o;o=function(){return this}();try{o=o||new Function("return this")()}catch(t){"object"==typeof window&&(o=window)}t.exports=o},function(t,e,o){var i,n,s;n=[o(3),o(8),o(9),o(10)],void 0===(s="function"==typeof(i=function(t,e,o,i){ +/** + * @license + * Copyright 2019 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ +"use strict";return t.setLocale(e),t.Blocks=t.Blocks||{},Object.keys(o).forEach((function(e){t.Blocks[e]=o[e]})),t.JavaScript=i,t})?i.apply(e,n):i)||(t.exports=s)},function(t,e,o){(function(o){var i,n,s;n=[],void 0===(s="function"==typeof(i=function(){"use strict";var t={constants:{},LINE_MODE_MULTIPLIER:40,PAGE_MODE_MULTIPLIER:125,DRAG_RADIUS:5,FLYOUT_DRAG_RADIUS:10,SNAP_RADIUS:28};return t.CONNECTING_SNAP_RADIUS=t.SNAP_RADIUS,t.CURRENT_CONNECTION_PREFERENCE=8,t.BUMP_DELAY=250,t.BUMP_RANDOMNESS=10,t.COLLAPSE_CHARS=30,t.LONGPRESS=750,t.SOUND_LIMIT=100,t.DRAG_STACK=!0,t.HSV_SATURATION=.45,t.HSV_VALUE=.65,t.SPRITE={width:96,height:124,url:"sprites.png"},t.INPUT_VALUE=1,t.OUTPUT_VALUE=2,t.NEXT_STATEMENT=3,t.PREVIOUS_STATEMENT=4,t.DUMMY_INPUT=5,t.ALIGN_LEFT=-1,t.ALIGN_CENTRE=0,t.ALIGN_RIGHT=1,t.DRAG_NONE=0,t.DRAG_STICKY=1,t.DRAG_BEGIN=1,t.DRAG_FREE=2,t.OPPOSITE_TYPE=[],t.OPPOSITE_TYPE[t.INPUT_VALUE]=t.OUTPUT_VALUE,t.OPPOSITE_TYPE[t.OUTPUT_VALUE]=t.INPUT_VALUE,t.OPPOSITE_TYPE[t.NEXT_STATEMENT]=t.PREVIOUS_STATEMENT,t.OPPOSITE_TYPE[t.PREVIOUS_STATEMENT]=t.NEXT_STATEMENT,t.TOOLBOX_AT_TOP=0,t.TOOLBOX_AT_BOTTOM=1,t.TOOLBOX_AT_LEFT=2,t.TOOLBOX_AT_RIGHT=3,t.DELETE_AREA_NONE=null,t.DELETE_AREA_TRASH=1,t.DELETE_AREA_TOOLBOX=2,t.VARIABLE_CATEGORY_NAME="VARIABLE",t.VARIABLE_DYNAMIC_CATEGORY_NAME="VARIABLE_DYNAMIC",t.PROCEDURE_CATEGORY_NAME="PROCEDURE",t.RENAME_VARIABLE_ID="RENAME_VARIABLE_ID",t.DELETE_VARIABLE_ID="DELETE_VARIABLE_ID",t.utils={},t.utils.global=function(){return"object"==typeof self?self:"object"==typeof window?window:"object"==typeof o?o:this}(),t.Msg={},t.utils.global.Blockly||(t.utils.global.Blockly={}),t.utils.global.Blockly.Msg||(t.utils.global.Blockly.Msg=t.Msg),t.utils.colour={},t.utils.colour.parse=function(e){e=String(e).toLowerCase().trim();var o=t.utils.colour.names[e];if(o)return o;if(o="#"==(o="0x"==e.substring(0,2)?"#"+e.substring(2):e)[0]?o:"#"+o,/^#[0-9a-f]{6}$/.test(o))return o;if(/^#[0-9a-f]{3}$/.test(o))return["#",o[1],o[1],o[2],o[2],o[3],o[3]].join("");var i=e.match(/^(?:rgb)?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/);return i&&(e=Number(i[1]),o=Number(i[2]),i=Number(i[3]),0<=e&&256>e&&0<=o&&256>o&&0<=i&&256>i)?t.utils.colour.rgbToHex(e,o,i):null},t.utils.colour.rgbToHex=function(t,e,o){return e=t<<16|e<<8|o,16>t?"#"+(16777216|e).toString(16).substr(1):"#"+e.toString(16)},t.utils.colour.hexToRgb=function(e){return(e=t.utils.colour.parse(e))?[(e=parseInt(e.substr(1),16))>>16,e>>8&255,255&e]:[0,0,0]},t.utils.colour.hsvToHex=function(e,o,i){var n=0,s=0,r=0;if(0==o)r=s=n=i;else{var a=Math.floor(e/60),l=e/60-a;e=i*(1-o);var c=i*(1-o*l);switch(o=i*(1-o*(1-l)),a){case 1:n=c,s=i,r=e;break;case 2:n=e,s=i,r=o;break;case 3:n=e,s=c,r=i;break;case 4:n=o,s=e,r=i;break;case 5:n=i,s=e,r=c;break;case 6:case 0:n=i,s=o,r=e}}return t.utils.colour.rgbToHex(Math.floor(n),Math.floor(s),Math.floor(r))},t.utils.colour.blend=function(e,o,i){return(e=t.utils.colour.parse(e))&&(o=t.utils.colour.parse(o))?(e=t.utils.colour.hexToRgb(e),o=t.utils.colour.hexToRgb(o),t.utils.colour.rgbToHex(Math.round(o[0]+i*(e[0]-o[0])),Math.round(o[1]+i*(e[1]-o[1])),Math.round(o[2]+i*(e[2]-o[2])))):null},t.utils.colour.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00"},t.utils.Coordinate=function(t,e){this.x=t,this.y=e},t.utils.Coordinate.equals=function(t,e){return t==e||!(!t||!e)&&t.x==e.x&&t.y==e.y},t.utils.Coordinate.distance=function(t,e){var o=t.x-e.x;return t=t.y-e.y,Math.sqrt(o*o+t*t)},t.utils.Coordinate.magnitude=function(t){return Math.sqrt(t.x*t.x+t.y*t.y)},t.utils.Coordinate.difference=function(e,o){return new t.utils.Coordinate(e.x-o.x,e.y-o.y)},t.utils.Coordinate.sum=function(e,o){return new t.utils.Coordinate(e.x+o.x,e.y+o.y)},t.utils.Coordinate.prototype.scale=function(t){return this.x*=t,this.y*=t,this},t.utils.Coordinate.prototype.translate=function(t,e){return this.x+=t,this.y+=e,this},t.utils.string={},t.utils.string.startsWith=function(t,e){return 0==t.lastIndexOf(e,0)},t.utils.string.shortestStringLength=function(t){return t.length?t.reduce((function(t,e){return t.lengtho&&(o=i[n].length);n=-1/0;var s=1;do{var r=n,a=e;e=[];var l=i.length/s,c=1;for(n=0;nr);return a},t.utils.string.wrapScore_=function(t,e,o){for(var i=[0],n=[],s=0;ss&&(s=l,n=a)}return n?t.utils.string.wrapMutate_(e,n,i):o},t.utils.string.wrapToText_=function(t,e){for(var o=[],i=0;i=l?(s=2,r=l,(l=e.join(""))&&i.push(l),e.length=0):"{"==l?s=3:(e.push("%",l),s=0):2==s?"0"<=l&&"9">=l?r+=l:(i.push(parseInt(r,10)),a--,s=0):3==s&&(""==l?(e.splice(0,0,"%{"),a--,s=0):"}"!=l?e.push(l):(s=e.join(""),/[A-Z]\w*/i.test(s)?(l=s.toUpperCase(),(l=t.utils.string.startsWith(l,"BKY_")?l.substring(4):null)&&l in t.Msg?"string"==typeof(s=t.Msg[l])?Array.prototype.push.apply(i,t.utils.tokenizeInterpolation_(s,o)):o?i.push(String(s)):i.push(s):i.push("%{"+s+"}")):i.push("%{"+s+"}"),s=e.length=0))}for((l=e.join(""))&&i.push(l),o=[],a=e.length=0;ai;i++)o[i]=t.utils.genUid.soup_.charAt(Math.random()*e);return o.join("")},t.utils.genUid.soup_="!#$%()*+,-./:;=?@[]^_`{|}~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",t.utils.is3dSupported=function(){if(void 0!==t.utils.is3dSupported.cached_)return t.utils.is3dSupported.cached_;if(!t.utils.global.getComputedStyle)return!1;var e=document.createElement("p"),o="none",i={webkitTransform:"-webkit-transform",OTransform:"-o-transform",msTransform:"-ms-transform",MozTransform:"-moz-transform",transform:"transform"};for(var n in document.body.insertBefore(e,null),i)if(void 0!==e.style[n]){if(e.style[n]="translate3d(1px,1px,1px)",!(o=t.utils.global.getComputedStyle(e)))return document.body.removeChild(e),!1;o=o.getPropertyValue(i[n])}return document.body.removeChild(e),t.utils.is3dSupported.cached_="none"!==o,t.utils.is3dSupported.cached_},t.utils.runAfterPageLoad=function(t){if("object"!=typeof document)throw Error("Blockly.utils.runAfterPageLoad() requires browser document.");if("complete"==document.readyState)t();else var e=setInterval((function(){"complete"==document.readyState&&(clearInterval(e),t())}),10)},t.utils.getViewportBBox=function(){var e=t.utils.style.getViewportPageOffset();return{right:document.documentElement.clientWidth+e.x,bottom:document.documentElement.clientHeight+e.y,top:e.y,left:e.x}},t.utils.arrayRemove=function(t,e){return-1!=(e=t.indexOf(e))&&(t.splice(e,1),!0)},t.utils.getDocumentScroll=function(){var e=document.documentElement,o=window;return t.utils.userAgent.IE&&o.pageYOffset!=e.scrollTop?new t.utils.Coordinate(e.scrollLeft,e.scrollTop):new t.utils.Coordinate(o.pageXOffset||e.scrollLeft,o.pageYOffset||e.scrollTop)},t.utils.getBlockTypeCounts=function(t,e){var o=Object.create(null),i=t.getDescendants(!0);for(e&&(t=t.getNextBlock())&&(t=i.indexOf(t),i.splice(t,i.length-t)),t=0;e=i[t];t++)o[e.type]?o[e.type]++:o[e.type]=1;return o},t.utils.screenToWsCoordinates=function(e,o){var i=o.x;o=o.y;var n=e.getInjectionDiv().getBoundingClientRect();return i=new t.utils.Coordinate(i-n.left,o-n.top),o=e.getOriginOffsetInPixels(),t.utils.Coordinate.difference(i,o).scale(1/e.scale)},t.utils.parseBlockColour=function(e){var o="string"==typeof e?t.utils.replaceMessageReferences(e):e,i=Number(o);if(!isNaN(i)&&0<=i&&360>=i)return{hue:i,hex:t.utils.colour.hsvToHex(i,t.HSV_SATURATION,255*t.HSV_VALUE)};if(i=t.utils.colour.parse(o))return{hue:null,hex:i};throw i='Invalid colour: "'+o+'"',e!=o&&(i+=' (from "'+e+'")'),Error(i)},t.Events={},t.Events.group_="",t.Events.recordUndo=!0,t.Events.disabled_=0,t.Events.CREATE="create",t.Events.BLOCK_CREATE=t.Events.CREATE,t.Events.DELETE="delete",t.Events.BLOCK_DELETE=t.Events.DELETE,t.Events.CHANGE="change",t.Events.BLOCK_CHANGE=t.Events.CHANGE,t.Events.MOVE="move",t.Events.BLOCK_MOVE=t.Events.MOVE,t.Events.VAR_CREATE="var_create",t.Events.VAR_DELETE="var_delete",t.Events.VAR_RENAME="var_rename",t.Events.UI="ui",t.Events.COMMENT_CREATE="comment_create",t.Events.COMMENT_DELETE="comment_delete",t.Events.COMMENT_CHANGE="comment_change",t.Events.COMMENT_MOVE="comment_move",t.Events.FINISHED_LOADING="finished_loading",t.Events.BUMP_EVENTS=[t.Events.BLOCK_CREATE,t.Events.BLOCK_MOVE,t.Events.COMMENT_CREATE,t.Events.COMMENT_MOVE],t.Events.FIRE_QUEUE_=[],t.Events.fire=function(e){t.Events.isEnabled()&&(t.Events.FIRE_QUEUE_.length||setTimeout(t.Events.fireNow_,0),t.Events.FIRE_QUEUE_.push(e))},t.Events.fireNow_=function(){for(var e,o=t.Events.filter(t.Events.FIRE_QUEUE_,!0),i=t.Events.FIRE_QUEUE_.length=0;e=o[i];i++)if(e.workspaceId){var n=t.Workspace.getById(e.workspaceId);n&&n.fireChangeListener(e)}},t.Events.filter=function(e,o){e=e.slice(),o||e.reverse();for(var i,n=[],s=Object.create(null),r=0;i=e[r];r++)if(!i.isNull()){var a=[i.type,i.blockId,i.workspaceId].join(" "),l=s[a],c=l?l.event:null;l?i.type==t.Events.MOVE&&l.index==r-1?(c.newParentId=i.newParentId,c.newInputName=i.newInputName,c.newCoordinate=i.newCoordinate,l.index=r):i.type==t.Events.CHANGE&&i.element==c.element&&i.name==c.name?c.newValue=i.newValue:(i.type!=t.Events.UI||"click"!=i.element||"commentOpen"!=c.element&&"mutatorOpen"!=c.element&&"warningOpen"!=c.element)&&(s[a]={event:i,index:1},n.push(i)):(s[a]={event:i,index:r},n.push(i))}for(e=n.filter((function(t){return!t.isNull()})),o||e.reverse(),r=1;i=e[r];r++)i.type==t.Events.CHANGE&&"mutation"==i.element&&e.unshift(e.splice(r,1)[0]);return e},t.Events.clearPendingUndo=function(){for(var e,o=0;e=t.Events.FIRE_QUEUE_[o];o++)e.recordUndo=!1},t.Events.disable=function(){t.Events.disabled_++},t.Events.enable=function(){t.Events.disabled_--},t.Events.isEnabled=function(){return 0==t.Events.disabled_},t.Events.getGroup=function(){return t.Events.group_},t.Events.setGroup=function(e){t.Events.group_="boolean"==typeof e?e?t.utils.genUid():"":e},t.Events.getDescendantIds=function(t){var e=[];t=t.getDescendants(!1);for(var o,i=0;o=t[i];i++)e[i]=o.id;return e},t.Events.fromJson=function(e,o){switch(e.type){case t.Events.CREATE:var i=new t.Events.Create(null);break;case t.Events.DELETE:i=new t.Events.Delete(null);break;case t.Events.CHANGE:i=new t.Events.Change(null,"","","","");break;case t.Events.MOVE:i=new t.Events.Move(null);break;case t.Events.VAR_CREATE:i=new t.Events.VarCreate(null);break;case t.Events.VAR_DELETE:i=new t.Events.VarDelete(null);break;case t.Events.VAR_RENAME:i=new t.Events.VarRename(null,"");break;case t.Events.UI:i=new t.Events.Ui(null,"","","");break;case t.Events.COMMENT_CREATE:i=new t.Events.CommentCreate(null);break;case t.Events.COMMENT_CHANGE:i=new t.Events.CommentChange(null,"","");break;case t.Events.COMMENT_MOVE:i=new t.Events.CommentMove(null);break;case t.Events.COMMENT_DELETE:i=new t.Events.CommentDelete(null);break;case t.Events.FINISHED_LOADING:i=new t.Events.FinishedLoading(o);break;default:throw Error("Unknown event type.")}return i.fromJson(e),i.workspaceId=o.id,i},t.Events.disableOrphans=function(e){if((e.type==t.Events.MOVE||e.type==t.Events.CREATE)&&e.workspaceId){var o=t.Workspace.getById(e.workspaceId);if(e=o.getBlockById(e.blockId)){var i=e.getParent();if(i&&i.isEnabled())for(o=e.getDescendants(!1),e=0;i=o[e];e++)i.setEnabled(!0);else if((e.outputConnection||e.previousConnection)&&!o.isDragging())do{e.setEnabled(!1),e=e.getNextBlock()}while(e)}}},t.Events.Abstract=function(){this.workspaceId=void 0,this.group=t.Events.getGroup(),this.recordUndo=t.Events.recordUndo},t.Events.Abstract.prototype.toJson=function(){var t={type:this.type};return this.group&&(t.group=this.group),t},t.Events.Abstract.prototype.fromJson=function(t){this.group=t.group},t.Events.Abstract.prototype.isNull=function(){return!1},t.Events.Abstract.prototype.run=function(t){},t.Events.Abstract.prototype.getEventWorkspace_=function(){if(this.workspaceId)var e=t.Workspace.getById(this.workspaceId);if(!e)throw Error("Workspace is null. Event must have been generated from real Blockly events.");return e},t.utils.object={},t.utils.object.inherits=function(t,e){t.superClass_=e.prototype,t.prototype=Object.create(e.prototype),t.prototype.constructor=t},t.utils.object.mixin=function(t,e){for(var o in e)t[o]=e[o]},t.utils.object.deepMerge=function(e,o){for(var i in o)e[i]="object"==typeof o[i]?t.utils.object.deepMerge(e[i]||Object.create(null),o[i]):o[i];return e},t.utils.object.values=function(t){return Object.values?Object.values(t):Object.keys(t).map((function(e){return t[e]}))},t.Events.Ui=function(e,o,i,n){t.Events.Ui.superClass_.constructor.call(this),this.blockId=e?e.id:null,this.workspaceId=e?e.workspace.id:void 0,this.element=o,this.oldValue=i,this.newValue=n,this.recordUndo=!1},t.utils.object.inherits(t.Events.Ui,t.Events.Abstract),t.Events.Ui.prototype.type=t.Events.UI,t.Events.Ui.prototype.toJson=function(){var e=t.Events.Ui.superClass_.toJson.call(this);return e.element=this.element,void 0!==this.newValue&&(e.newValue=this.newValue),this.blockId&&(e.blockId=this.blockId),e},t.Events.Ui.prototype.fromJson=function(e){t.Events.Ui.superClass_.fromJson.call(this,e),this.element=e.element,this.newValue=e.newValue,this.blockId=e.blockId},t.utils.dom={},t.utils.dom.SVG_NS="http://www.w3.org/2000/svg",t.utils.dom.HTML_NS="http://www.w3.org/1999/xhtml",t.utils.dom.XLINK_NS="http://www.w3.org/1999/xlink",t.utils.dom.Node={ELEMENT_NODE:1,TEXT_NODE:3,COMMENT_NODE:8,DOCUMENT_POSITION_CONTAINED_BY:16},t.utils.dom.cacheWidths_=null,t.utils.dom.cacheReference_=0,t.utils.dom.canvasContext_=null,t.utils.dom.createSvgElement=function(e,o,i){for(var n in e=document.createElementNS(t.utils.dom.SVG_NS,e),o)e.setAttribute(n,o[n]);return document.body.runtimeStyle&&(e.runtimeStyle=e.currentStyle=e.style),i&&i.appendChild(e),e},t.utils.dom.addClass=function(t,e){var o=t.getAttribute("class")||"";return-1==(" "+o+" ").indexOf(" "+e+" ")&&(o&&(o+=" "),t.setAttribute("class",o+e),!0)},t.utils.dom.removeClass=function(t,e){var o=t.getAttribute("class");if(-1==(" "+o+" ").indexOf(" "+e+" "))return!1;o=o.split(/\s+/);for(var i=0;io||o>this.getChildCount())throw Error(t.Component.Error.CHILD_INDEX_OUT_OF_BOUNDS);if(this.childIndex_[e.getId()]=e,e.getParent()==this){var n=this.children_.indexOf(e);-1>>/g,e),(e=document.createElement("style")).id="blockly-common-style",i=document.createTextNode(i),e.appendChild(i),document.head.insertBefore(e,document.head.firstChild))}},t.Css.setCursor=function(t){console.warn("Deprecated call to Blockly.Css.setCursor. See https://github.com/google/blockly/issues/981 for context")},t.Css.CONTENT=[".blocklySvg {","background-color: #fff;","outline: none;","overflow: hidden;","position: absolute;","display: block;","}",".blocklyWidgetDiv {","display: none;","position: absolute;","z-index: 99999;","}",".injectionDiv {","height: 100%;","position: relative;","overflow: hidden;","touch-action: none;","}",".blocklyNonSelectable {","user-select: none;","-ms-user-select: none;","-webkit-user-select: none;","}",".blocklyWsDragSurface {","display: none;","position: absolute;","top: 0;","left: 0;","}",".blocklyWsDragSurface.blocklyOverflowVisible {","overflow: visible;","}",".blocklyBlockDragSurface {","display: none;","position: absolute;","top: 0;","left: 0;","right: 0;","bottom: 0;","overflow: visible !important;","z-index: 50;","}",".blocklyBlockCanvas.blocklyCanvasTransitioning,",".blocklyBubbleCanvas.blocklyCanvasTransitioning {","transition: transform .5s;","}",".blocklyTooltipDiv {","background-color: #ffffc7;","border: 1px solid #ddc;","box-shadow: 4px 4px 20px 1px rgba(0,0,0,.15);","color: #000;","display: none;","font-family: sans-serif;","font-size: 9pt;","opacity: .9;","padding: 2px;","position: absolute;","z-index: 100000;","}",".blocklyDropDownDiv {","position: absolute;","left: 0;","top: 0;","z-index: 1000;","display: none;","border: 1px solid;","border-color: #dadce0;","background-color: #fff;","border-radius: 2px;","padding: 4px;","box-shadow: 0px 0px 3px 1px rgba(0,0,0,.3);","}",".blocklyDropDownDiv.focused {","box-shadow: 0px 0px 6px 1px rgba(0,0,0,.3);","}",".blocklyDropDownContent {","max-height: 300px;","overflow: auto;","overflow-x: hidden;","}",".blocklyDropDownArrow {","position: absolute;","left: 0;","top: 0;","width: 16px;","height: 16px;","z-index: -1;","background-color: inherit;","border-color: inherit;","}",".blocklyDropDownButton {","display: inline-block;","float: left;","padding: 0;","margin: 4px;","border-radius: 4px;","outline: none;","border: 1px solid;","transition: box-shadow .1s;","cursor: pointer;","}",".blocklyArrowTop {","border-top: 1px solid;","border-left: 1px solid;","border-top-left-radius: 4px;","border-color: inherit;","}",".blocklyArrowBottom {","border-bottom: 1px solid;","border-right: 1px solid;","border-bottom-right-radius: 4px;","border-color: inherit;","}",".blocklyResizeSE {","cursor: se-resize;","fill: #aaa;","}",".blocklyResizeSW {","cursor: sw-resize;","fill: #aaa;","}",".blocklyResizeLine {","stroke: #515A5A;","stroke-width: 1;","}",".blocklyHighlightedConnectionPath {","fill: none;","stroke: #fc3;","stroke-width: 4px;","}",".blocklyPathLight {","fill: none;","stroke-linecap: round;","stroke-width: 1;","}",".blocklySelected>.blocklyPathLight {","display: none;","}",".blocklyDraggable {",'cursor: url("<<>>/handopen.cur"), auto;',"cursor: grab;","cursor: -webkit-grab;","}",".blocklyDragging {",'cursor: url("<<>>/handclosed.cur"), auto;',"cursor: grabbing;","cursor: -webkit-grabbing;","}",".blocklyDraggable:active {",'cursor: url("<<>>/handclosed.cur"), auto;',"cursor: grabbing;","cursor: -webkit-grabbing;","}",".blocklyBlockDragSurface .blocklyDraggable {",'cursor: url("<<>>/handclosed.cur"), auto;',"cursor: grabbing;","cursor: -webkit-grabbing;","}",".blocklyDragging.blocklyDraggingDelete {",'cursor: url("<<>>/handdelete.cur"), auto;',"}",".blocklyDragging>.blocklyPath,",".blocklyDragging>.blocklyPathLight {","fill-opacity: .8;","stroke-opacity: .8;","}",".blocklyDragging>.blocklyPathDark {","display: none;","}",".blocklyDisabled>.blocklyPath {","fill-opacity: .5;","stroke-opacity: .5;","}",".blocklyDisabled>.blocklyPathLight,",".blocklyDisabled>.blocklyPathDark {","display: none;","}",".blocklyInsertionMarker>.blocklyPath,",".blocklyInsertionMarker>.blocklyPathLight,",".blocklyInsertionMarker>.blocklyPathDark {","fill-opacity: .2;","stroke: none","}",".blocklyMultilineText {","font-family: monospace;","}",".blocklyNonEditableText>text {","pointer-events: none;","}",".blocklyFlyout {","position: absolute;","z-index: 20;","}",".blocklyText text {","cursor: default;","}",".blocklySvg text, .blocklyBlockDragSurface text {","user-select: none;","-ms-user-select: none;","-webkit-user-select: none;","cursor: inherit;","}",".blocklyHidden {","display: none;","}",".blocklyFieldDropdown:not(.blocklyHidden) {","display: block;","}",".blocklyIconGroup {","cursor: default;","}",".blocklyIconGroup:not(:hover),",".blocklyIconGroupReadonly {","opacity: .6;","}",".blocklyIconShape {","fill: #00f;","stroke: #fff;","stroke-width: 1px;","}",".blocklyIconSymbol {","fill: #fff;","}",".blocklyMinimalBody {","margin: 0;","padding: 0;","}",".blocklyHtmlInput {","border: none;","border-radius: 4px;","height: 100%;","margin: 0;","outline: none;","padding: 0;","width: 100%;","text-align: center;","display: block;","box-sizing: border-box;","}",".blocklyHtmlInput::-ms-clear {","display: none;","}",".blocklyMainBackground {","stroke-width: 1;","stroke: #c6c6c6;","}",".blocklyMutatorBackground {","fill: #fff;","stroke: #ddd;","stroke-width: 1;","}",".blocklyFlyoutBackground {","fill: #ddd;","fill-opacity: .8;","}",".blocklyMainWorkspaceScrollbar {","z-index: 20;","}",".blocklyFlyoutScrollbar {","z-index: 30;","}",".blocklyScrollbarHorizontal, .blocklyScrollbarVertical {","position: absolute;","outline: none;","}",".blocklyScrollbarBackground {","opacity: 0;","}",".blocklyScrollbarHandle {","fill: #ccc;","}",".blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,",".blocklyScrollbarHandle:hover {","fill: #bbb;","}",".blocklyFlyout .blocklyScrollbarHandle {","fill: #bbb;","}",".blocklyFlyout .blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,",".blocklyFlyout .blocklyScrollbarHandle:hover {","fill: #aaa;","}",".blocklyInvalidInput {","background: #faa;","}",".blocklyContextMenu {","border-radius: 4px;","max-height: 100%;","}",".blocklyDropdownMenu {","border-radius: 2px;","padding: 0 !important;","}",".blocklyWidgetDiv .blocklyDropdownMenu .goog-menuitem,",".blocklyDropDownDiv .blocklyDropdownMenu .goog-menuitem {","padding-left: 28px;","}",".blocklyWidgetDiv .blocklyDropdownMenu .goog-menuitem.goog-menuitem-rtl,",".blocklyDropDownDiv .blocklyDropdownMenu .goog-menuitem.goog-menuitem-rtl {","padding-left: 5px;","padding-right: 28px;","}",".blocklyVerticalMarker {","stroke-width: 3px;","fill: rgba(255,255,255,.5);","pointer-events: none","}",".blocklyWidgetDiv .goog-option-selected .goog-menuitem-checkbox,",".blocklyWidgetDiv .goog-option-selected .goog-menuitem-icon,",".blocklyDropDownDiv .goog-option-selected .goog-menuitem-checkbox,",".blocklyDropDownDiv .goog-option-selected .goog-menuitem-icon {","background: url(<<>>/sprites.png) no-repeat -48px -16px;","}",".blocklyWidgetDiv .goog-menu {","background: #fff;","border-color: transparent;","border-style: solid;","border-width: 1px;","cursor: default;","font: normal 13px Arial, sans-serif;","margin: 0;","outline: none;","padding: 4px 0;","position: absolute;","overflow-y: auto;","overflow-x: hidden;","max-height: 100%;","z-index: 20000;","box-shadow: 0px 0px 3px 1px rgba(0,0,0,.3);","}",".blocklyWidgetDiv .goog-menu.focused {","box-shadow: 0px 0px 6px 1px rgba(0,0,0,.3);","}",".blocklyDropDownDiv .goog-menu {","cursor: default;",'font: normal 13px "Helvetica Neue", Helvetica, sans-serif;',"outline: none;","z-index: 20000;","}",".blocklyWidgetDiv .goog-menuitem,",".blocklyDropDownDiv .goog-menuitem {","color: #000;","font: normal 13px Arial, sans-serif;","list-style: none;","margin: 0;","min-width: 7em;","border: none;","padding: 6px 15px;","white-space: nowrap;","cursor: pointer;","}",".blocklyWidgetDiv .goog-menu-nocheckbox .goog-menuitem,",".blocklyWidgetDiv .goog-menu-noicon .goog-menuitem,",".blocklyDropDownDiv .goog-menu-nocheckbox .goog-menuitem,",".blocklyDropDownDiv .goog-menu-noicon .goog-menuitem {","padding-left: 12px;","}",".blocklyWidgetDiv .goog-menuitem-content,",".blocklyDropDownDiv .goog-menuitem-content {","font-family: Arial, sans-serif;","font-size: 13px;","}",".blocklyWidgetDiv .goog-menuitem-content {","color: #000;","}",".blocklyDropDownDiv .goog-menuitem-content {","color: #000;","}",".blocklyWidgetDiv .goog-menuitem-disabled,",".blocklyDropDownDiv .goog-menuitem-disabled {","cursor: inherit;","}",".blocklyWidgetDiv .goog-menuitem-disabled .goog-menuitem-content,",".blocklyDropDownDiv .goog-menuitem-disabled .goog-menuitem-content {","color: #ccc !important;","}",".blocklyWidgetDiv .goog-menuitem-disabled .goog-menuitem-icon,",".blocklyDropDownDiv .goog-menuitem-disabled .goog-menuitem-icon {","opacity: .3;","filter: alpha(opacity=30);","}",".blocklyWidgetDiv .goog-menuitem-highlight ,",".blocklyDropDownDiv .goog-menuitem-highlight {","background-color: rgba(0,0,0,.1);","}",".blocklyWidgetDiv .goog-menuitem-checkbox,",".blocklyWidgetDiv .goog-menuitem-icon,",".blocklyDropDownDiv .goog-menuitem-checkbox,",".blocklyDropDownDiv .goog-menuitem-icon {","background-repeat: no-repeat;","height: 16px;","left: 6px;","position: absolute;","right: auto;","vertical-align: middle;","width: 16px;","}",".blocklyWidgetDiv .goog-menuitem-rtl .goog-menuitem-checkbox,",".blocklyWidgetDiv .goog-menuitem-rtl .goog-menuitem-icon,",".blocklyDropDownDiv .goog-menuitem-rtl .goog-menuitem-checkbox,",".blocklyDropDownDiv .goog-menuitem-rtl .goog-menuitem-icon {","left: auto;","right: 6px;","}",".blocklyWidgetDiv .goog-option-selected .goog-menuitem-checkbox,",".blocklyWidgetDiv .goog-option-selected .goog-menuitem-icon,",".blocklyDropDownDiv .goog-option-selected .goog-menuitem-checkbox,",".blocklyDropDownDiv .goog-option-selected .goog-menuitem-icon {","position: static;","float: left;","margin-left: -24px;","}",".blocklyWidgetDiv .goog-menuitem-rtl .goog-menuitem-checkbox,",".blocklyWidgetDiv .goog-menuitem-rtl .goog-menuitem-icon,",".blocklyDropDownDiv .goog-menuitem-rtl .goog-menuitem-checkbox,",".blocklyDropDownDiv .goog-menuitem-rtl .goog-menuitem-icon {","float: right;","margin-right: -24px;","}",".blocklyComputeCanvas {","position: absolute;","width: 0;","height: 0;","}",".blocklyNoPointerEvents {","pointer-events: none;","}"],t.utils.math={},t.utils.math.toRadians=function(t){return t*Math.PI/180},t.utils.math.toDegrees=function(t){return 180*t/Math.PI},t.utils.math.clamp=function(t,e,o){if(os.top?t.DropDownDiv.getPositionAboveMetrics_(i,n,s,r):o+r.heightdocument.documentElement.clientTop?t.DropDownDiv.getPositionAboveMetrics_(i,n,s,r):t.DropDownDiv.getPositionTopOfPageMetrics_(e,s,r)},t.DropDownDiv.getPositionBelowMetrics_=function(e,o,i,n){return{initialX:(e=t.DropDownDiv.getPositionX(e,i.left,i.right,n.width)).divX,initialY:o,finalX:e.divX,finalY:o+t.DropDownDiv.PADDING_Y,arrowX:e.arrowX,arrowY:-(t.DropDownDiv.ARROW_SIZE/2+t.DropDownDiv.BORDER_SIZE),arrowAtTop:!0,arrowVisible:!0}},t.DropDownDiv.getPositionAboveMetrics_=function(e,o,i,n){return{initialX:(e=t.DropDownDiv.getPositionX(e,i.left,i.right,n.width)).divX,initialY:o-n.height,finalX:e.divX,finalY:o-n.height-t.DropDownDiv.PADDING_Y,arrowX:e.arrowX,arrowY:n.height-2*t.DropDownDiv.BORDER_SIZE-t.DropDownDiv.ARROW_SIZE/2,arrowAtTop:!1,arrowVisible:!0}},t.DropDownDiv.getPositionTopOfPageMetrics_=function(e,o,i){return{initialX:(e=t.DropDownDiv.getPositionX(e,o.left,o.right,i.width)).divX,initialY:0,finalX:e.divX,finalY:0,arrowVisible:!1}},t.DropDownDiv.getPositionX=function(e,o,i,n){var s=e;return e=t.utils.math.clamp(o,e-n/2,i-n),s-=t.DropDownDiv.ARROW_SIZE/2,o=t.DropDownDiv.ARROW_HORIZONTAL_PADDING,{arrowX:n=t.utils.math.clamp(o,s-e,n-o-t.DropDownDiv.ARROW_SIZE),divX:e}},t.DropDownDiv.isVisible=function(){return!!t.DropDownDiv.owner_},t.DropDownDiv.hideIfOwner=function(e,o){return t.DropDownDiv.owner_===e&&(o?t.DropDownDiv.hideWithoutAnimation():t.DropDownDiv.hide(),!0)},t.DropDownDiv.hide=function(){var e=t.DropDownDiv.DIV_;e.style.transform="translate(0, 0)",e.style.opacity=0,t.DropDownDiv.animateOutTimer_=setTimeout((function(){t.DropDownDiv.hideWithoutAnimation()}),1e3*t.DropDownDiv.ANIMATION_TIME),t.DropDownDiv.onHide_&&(t.DropDownDiv.onHide_(),t.DropDownDiv.onHide_=null)},t.DropDownDiv.hideWithoutAnimation=function(){if(t.DropDownDiv.isVisible()){t.DropDownDiv.animateOutTimer_&&clearTimeout(t.DropDownDiv.animateOutTimer_);var e=t.DropDownDiv.DIV_;e.style.transform="",e.style.left="",e.style.top="",e.style.opacity=0,e.style.display="none",e.style.backgroundColor="",e.style.borderColor="",t.DropDownDiv.onHide_&&(t.DropDownDiv.onHide_(),t.DropDownDiv.onHide_=null),t.DropDownDiv.clearContent(),t.DropDownDiv.owner_=null,t.DropDownDiv.rendererClassName_&&(t.utils.dom.removeClass(e,t.DropDownDiv.rendererClassName_),t.DropDownDiv.rendererClassName_=""),t.DropDownDiv.themeClassName_&&(t.utils.dom.removeClass(e,t.DropDownDiv.themeClassName_),t.DropDownDiv.themeClassName_=""),t.getMainWorkspace().markFocused()}},t.DropDownDiv.positionInternal_=function(e,o,i,n){(e=t.DropDownDiv.getPositionMetrics_(e,o,i,n)).arrowVisible?(t.DropDownDiv.arrow_.style.display="",t.DropDownDiv.arrow_.style.transform="translate("+e.arrowX+"px,"+e.arrowY+"px) rotate(45deg)",t.DropDownDiv.arrow_.setAttribute("class",e.arrowAtTop?"blocklyDropDownArrow blocklyArrowTop":"blocklyDropDownArrow blocklyArrowBottom")):t.DropDownDiv.arrow_.style.display="none",o=Math.floor(e.initialX),i=Math.floor(e.initialY),n=Math.floor(e.finalX);var s=Math.floor(e.finalY),r=t.DropDownDiv.DIV_;return r.style.left=o+"px",r.style.top=i+"px",r.style.display="block",r.style.opacity=1,r.style.transform="translate("+(n-o)+"px,"+(s-i)+"px)",e.arrowAtTop},t.DropDownDiv.repositionForWindowResize=function(){if(t.DropDownDiv.owner_){var e=t.DropDownDiv.owner_,o=t.DropDownDiv.owner_.getSourceBlock();o=(e=t.DropDownDiv.positionToField_?t.DropDownDiv.getScaledBboxOfField_(e):t.DropDownDiv.getScaledBboxOfBlock_(o)).left+(e.right-e.left)/2,t.DropDownDiv.positionInternal_(o,e.bottom,o,e.top)}else t.DropDownDiv.hide()},t.Grid=function(t,e){this.gridPattern_=t,this.spacing_=e.spacing,this.length_=e.length,this.line2_=(this.line1_=t.firstChild)&&this.line1_.nextSibling,this.snapToGrid_=e.snap},t.Grid.prototype.scale_=1,t.Grid.prototype.dispose=function(){this.gridPattern_=null},t.Grid.prototype.shouldSnap=function(){return this.snapToGrid_},t.Grid.prototype.getSpacing=function(){return this.spacing_},t.Grid.prototype.getPatternId=function(){return this.gridPattern_.id},t.Grid.prototype.update=function(t){this.scale_=t;var e=this.spacing_*t||100;this.gridPattern_.setAttribute("width",e),this.gridPattern_.setAttribute("height",e);var o=(e=Math.floor(this.spacing_/2)+.5)-this.length_/2,i=e+this.length_/2;e*=t,o*=t,i*=t,this.setLineAttributes_(this.line1_,t,o,i,e,e),this.setLineAttributes_(this.line2_,t,e,e,o,i)},t.Grid.prototype.setLineAttributes_=function(t,e,o,i,n,s){t&&(t.setAttribute("stroke-width",e),t.setAttribute("x1",o),t.setAttribute("y1",n),t.setAttribute("x2",i),t.setAttribute("y2",s))},t.Grid.prototype.moveTo=function(e,o){this.gridPattern_.setAttribute("x",e),this.gridPattern_.setAttribute("y",o),(t.utils.userAgent.IE||t.utils.userAgent.EDGE)&&this.update(this.scale_)},t.Grid.createDom=function(e,o,i){return e=t.utils.dom.createSvgElement("pattern",{id:"blocklyGridPattern"+e,patternUnits:"userSpaceOnUse"},i),0e.indexOf(o))throw Error(o+" is not a valid modifier key.")},t.user.keyMap.createSerializedKey=function(e,o){var i="",n=t.utils.object.values(t.user.keyMap.modifierKeys);t.user.keyMap.checkModifiers_(o,n);for(var s,r=0;s=n[r];r++)-1");o.domToMutation(n)}t.Events.fire(new t.Events.Change(o,"mutation",null,i,e));break;default:console.warn("Unknown change type: "+this.element)}else console.warn("Can't change non-existent block: "+this.blockId)},t.Events.Create=function(e){e&&(t.Events.Create.superClass_.constructor.call(this,e),this.xml=e.workspace.rendered?t.Xml.blockToDomWithXY(e):t.Xml.blockToDom(e),this.ids=t.Events.getDescendantIds(e))},t.utils.object.inherits(t.Events.Create,t.Events.BlockBase),t.Events.BlockCreate=t.Events.Create,t.Events.Create.prototype.type=t.Events.CREATE,t.Events.Create.prototype.toJson=function(){var e=t.Events.Create.superClass_.toJson.call(this);return e.xml=t.Xml.domToText(this.xml),e.ids=this.ids,e},t.Events.Create.prototype.fromJson=function(e){t.Events.Create.superClass_.fromJson.call(this,e),this.xml=t.Xml.textToDom(e.xml),this.ids=e.ids},t.Events.Create.prototype.run=function(e){var o=this.getEventWorkspace_();if(e)(e=t.utils.xml.createElement("xml")).appendChild(this.xml),t.Xml.domToWorkspace(e,o);else{e=0;for(var i;i=this.ids[e];e++){var n=o.getBlockById(i);n?n.dispose(!1):i==this.blockId&&console.warn("Can't uncreate non-existent block: "+i)}}},t.Events.Delete=function(e){if(e){if(e.getParent())throw Error("Connected blocks cannot be deleted.");t.Events.Delete.superClass_.constructor.call(this,e),this.oldXml=e.workspace.rendered?t.Xml.blockToDomWithXY(e):t.Xml.blockToDom(e),this.ids=t.Events.getDescendantIds(e)}},t.utils.object.inherits(t.Events.Delete,t.Events.BlockBase),t.Events.BlockDelete=t.Events.Delete,t.Events.Delete.prototype.type=t.Events.DELETE,t.Events.Delete.prototype.toJson=function(){var e=t.Events.Delete.superClass_.toJson.call(this);return e.ids=this.ids,e},t.Events.Delete.prototype.fromJson=function(e){t.Events.Delete.superClass_.fromJson.call(this,e),this.ids=e.ids},t.Events.Delete.prototype.run=function(e){var o=this.getEventWorkspace_();if(e){e=0;for(var i;i=this.ids[e];e++){var n=o.getBlockById(i);n?n.dispose(!1):i==this.blockId&&console.warn("Can't delete non-existent block: "+i)}}else(e=t.utils.xml.createElement("xml")).appendChild(this.oldXml),t.Xml.domToWorkspace(e,o)},t.Events.Move=function(e){e&&(t.Events.Move.superClass_.constructor.call(this,e),e=this.currentLocation_(),this.oldParentId=e.parentId,this.oldInputName=e.inputName,this.oldCoordinate=e.coordinate)},t.utils.object.inherits(t.Events.Move,t.Events.BlockBase),t.Events.BlockMove=t.Events.Move,t.Events.Move.prototype.type=t.Events.MOVE,t.Events.Move.prototype.toJson=function(){var e=t.Events.Move.superClass_.toJson.call(this);return this.newParentId&&(e.newParentId=this.newParentId),this.newInputName&&(e.newInputName=this.newInputName),this.newCoordinate&&(e.newCoordinate=Math.round(this.newCoordinate.x)+","+Math.round(this.newCoordinate.y)),e},t.Events.Move.prototype.fromJson=function(e){t.Events.Move.superClass_.fromJson.call(this,e),this.newParentId=e.newParentId,this.newInputName=e.newInputName,e.newCoordinate&&(e=e.newCoordinate.split(","),this.newCoordinate=new t.utils.Coordinate(Number(e[0]),Number(e[1])))},t.Events.Move.prototype.recordNew=function(){var t=this.currentLocation_();this.newParentId=t.parentId,this.newInputName=t.inputName,this.newCoordinate=t.coordinate},t.Events.Move.prototype.currentLocation_=function(){var t=this.getEventWorkspace_().getBlockById(this.blockId),e={},o=t.getParent();return o?(e.parentId=o.id,(t=o.getInputWithBlock(t))&&(e.inputName=t.name)):e.coordinate=t.getRelativeToSurfaceXY(),e},t.Events.Move.prototype.isNull=function(){return this.oldParentId==this.newParentId&&this.oldInputName==this.newInputName&&t.utils.Coordinate.equals(this.oldCoordinate,this.newCoordinate)},t.Events.Move.prototype.run=function(e){var o=this.getEventWorkspace_(),i=o.getBlockById(this.blockId);if(i){var n=e?this.newParentId:this.oldParentId,s=e?this.newInputName:this.oldInputName;e=e?this.newCoordinate:this.oldCoordinate;var r=null;if(n&&!(r=o.getBlockById(n)))return void console.warn("Can't connect to non-existent block: "+n);if(i.getParent()&&i.unplug(),e)s=i.getRelativeToSurfaceXY(),i.moveBy(e.x-s.x,e.y-s.y);else{if(i=i.outputConnection||i.previousConnection,s){if(o=r.getInput(s))var a=o.connection}else i.type==t.PREVIOUS_STATEMENT&&(a=r.nextConnection);a?i.connect(a):console.warn("Can't connect to non-existent input: "+s)}}else console.warn("Can't move non-existent block: "+this.blockId)},t.Events.FinishedLoading=function(e){this.workspaceId=e.id,this.group=t.Events.getGroup(),this.recordUndo=!1},t.utils.object.inherits(t.Events.FinishedLoading,t.Events.Ui),t.Events.FinishedLoading.prototype.type=t.Events.FINISHED_LOADING,t.Events.FinishedLoading.prototype.toJson=function(){var t={type:this.type};return this.group&&(t.group=this.group),this.workspaceId&&(t.workspaceId=this.workspaceId),t},t.Events.FinishedLoading.prototype.fromJson=function(t){this.workspaceId=t.workspaceId,this.group=t.group},t.Events.VarBase=function(e){t.Events.VarBase.superClass_.constructor.call(this),this.varId=e.getId(),this.workspaceId=e.workspace.id},t.utils.object.inherits(t.Events.VarBase,t.Events.Abstract),t.Events.VarBase.prototype.toJson=function(){var e=t.Events.VarBase.superClass_.toJson.call(this);return e.varId=this.varId,e},t.Events.VarBase.prototype.fromJson=function(e){t.Events.VarBase.superClass_.toJson.call(this),this.varId=e.varId},t.Events.VarCreate=function(e){e&&(t.Events.VarCreate.superClass_.constructor.call(this,e),this.varType=e.type,this.varName=e.name)},t.utils.object.inherits(t.Events.VarCreate,t.Events.VarBase),t.Events.VarCreate.prototype.type=t.Events.VAR_CREATE,t.Events.VarCreate.prototype.toJson=function(){var e=t.Events.VarCreate.superClass_.toJson.call(this);return e.varType=this.varType,e.varName=this.varName,e},t.Events.VarCreate.prototype.fromJson=function(e){t.Events.VarCreate.superClass_.fromJson.call(this,e),this.varType=e.varType,this.varName=e.varName},t.Events.VarCreate.prototype.run=function(t){var e=this.getEventWorkspace_();t?e.createVariable(this.varName,this.varType,this.varId):e.deleteVariableById(this.varId)},t.Events.VarDelete=function(e){e&&(t.Events.VarDelete.superClass_.constructor.call(this,e),this.varType=e.type,this.varName=e.name)},t.utils.object.inherits(t.Events.VarDelete,t.Events.VarBase),t.Events.VarDelete.prototype.type=t.Events.VAR_DELETE,t.Events.VarDelete.prototype.toJson=function(){var e=t.Events.VarDelete.superClass_.toJson.call(this);return e.varType=this.varType,e.varName=this.varName,e},t.Events.VarDelete.prototype.fromJson=function(e){t.Events.VarDelete.superClass_.fromJson.call(this,e),this.varType=e.varType,this.varName=e.varName},t.Events.VarDelete.prototype.run=function(t){var e=this.getEventWorkspace_();t?e.deleteVariableById(this.varId):e.createVariable(this.varName,this.varType,this.varId)},t.Events.VarRename=function(e,o){e&&(t.Events.VarRename.superClass_.constructor.call(this,e),this.oldName=e.name,this.newName=o)},t.utils.object.inherits(t.Events.VarRename,t.Events.VarBase),t.Events.VarRename.prototype.type=t.Events.VAR_RENAME,t.Events.VarRename.prototype.toJson=function(){var e=t.Events.VarRename.superClass_.toJson.call(this);return e.oldName=this.oldName,e.newName=this.newName,e},t.Events.VarRename.prototype.fromJson=function(e){t.Events.VarRename.superClass_.fromJson.call(this,e),this.oldName=e.oldName,this.newName=e.newName},t.Events.VarRename.prototype.run=function(t){var e=this.getEventWorkspace_();t?e.renameVariableById(this.varId,this.newName):e.renameVariableById(this.varId,this.oldName)},t.Xml={},t.Xml.workspaceToDom=function(e,o){var i=t.utils.xml.createElement("xml"),n=t.Xml.variablesToDom(t.Variables.allUsedVarModels(e));n.hasChildNodes()&&i.appendChild(n);var s,r=e.getTopComments(!0);for(n=0;s=r[n];n++)i.appendChild(s.toXmlWithXY(o));for(e=e.getTopBlocks(!0),n=0;r=e[n];n++)i.appendChild(t.Xml.blockToDomWithXY(r,o));return i},t.Xml.variablesToDom=function(e){for(var o,i=t.utils.xml.createElement("variables"),n=0;o=e[n];n++){var s=t.utils.xml.createElement("variable");s.appendChild(t.utils.xml.createTextNode(o.name)),o.type&&s.setAttribute("type",o.type),s.id=o.getId(),i.appendChild(s)}return i},t.Xml.blockToDomWithXY=function(e,o){var i;e.workspace.RTL&&(i=e.workspace.getWidth()),o=t.Xml.blockToDom(e,o);var n=e.getRelativeToSurfaceXY();return o.setAttribute("x",Math.round(e.workspace.RTL?i-n.x:n.x)),o.setAttribute("y",Math.round(n.y)),o},t.Xml.fieldToDom_=function(e){if(e.isSerializable()){var o=t.utils.xml.createElement("field");return o.setAttribute("name",e.name||""),e.toXml(o)}return null},t.Xml.allFieldsToDom_=function(e,o){for(var i,n=0;i=e.inputList[n];n++)for(var s,r=0;s=i.fieldRow[r];r++)(s=t.Xml.fieldToDom_(s))&&o.appendChild(s)},t.Xml.blockToDom=function(e,o){var i=t.utils.xml.createElement(e.isShadow()?"shadow":"block");if(i.setAttribute("type",e.type),o||i.setAttribute("id",e.id),e.mutationToDom){var n=e.mutationToDom();n&&(n.hasChildNodes()||n.hasAttributes())&&i.appendChild(n)}if(t.Xml.allFieldsToDom_(e,i),n=e.getCommentText()){var s=e.commentModel.size,r=e.commentModel.pinned,a=t.utils.xml.createElement("comment");a.appendChild(t.utils.xml.createTextNode(n)),a.setAttribute("pinned",r),a.setAttribute("h",s.height),a.setAttribute("w",s.width),i.appendChild(a)}for(e.data&&((n=t.utils.xml.createElement("data")).appendChild(t.utils.xml.createTextNode(e.data)),i.appendChild(n)),s=0;r=e.inputList[s];s++){var l;if(a=!0,r.type!=t.DUMMY_INPUT){var c=r.connection.targetBlock();r.type==t.INPUT_VALUE?l=t.utils.xml.createElement("value"):r.type==t.NEXT_STATEMENT&&(l=t.utils.xml.createElement("statement")),!(n=r.connection.getShadowDom())||c&&c.isShadow()||l.appendChild(t.Xml.cloneShadow_(n,o)),c&&(l.appendChild(t.Xml.blockToDom(c,o)),a=!1),l.setAttribute("name",r.name),a||i.appendChild(l)}}return null!=e.inputsInline&&e.inputsInline!=e.inputsInlineDefault&&i.setAttribute("inline",e.inputsInline),e.isCollapsed()&&i.setAttribute("collapsed",!0),e.isEnabled()||i.setAttribute("disabled",!0),e.isDeletable()||e.isShadow()||i.setAttribute("deletable",!1),e.isMovable()||e.isShadow()||i.setAttribute("movable",!1),e.isEditable()||i.setAttribute("editable",!1),(s=e.getNextBlock())&&((l=t.utils.xml.createElement("next")).appendChild(t.Xml.blockToDom(s,o)),i.appendChild(l)),!(n=e.nextConnection&&e.nextConnection.getShadowDom())||s&&s.isShadow()||l.appendChild(t.Xml.cloneShadow_(n,o)),i},t.Xml.cloneShadow_=function(e,o){for(var i,n=e=e.cloneNode(!0);n;)if(o&&"shadow"==n.nodeName&&n.removeAttribute("id"),n.firstChild)n=n.firstChild;else{for(;n&&!n.nextSibling;)i=n,n=n.parentNode,i.nodeType==t.utils.dom.Node.TEXT_NODE&&""==i.data.trim()&&n.firstChild!=i&&t.utils.dom.removeNode(i);n&&(i=n,n=n.nextSibling,i.nodeType==t.utils.dom.Node.TEXT_NODE&&""==i.data.trim()&&t.utils.dom.removeNode(i))}return e},t.Xml.domToText=function(e){e=t.utils.xml.domToText(e);var o=/(<[^/](?:[^>]*[^/])?>[^<]*)\n([^<]*<\/)/;do{var i=e;e=e.replace(o,"$1 $2")}while(e!=i);return e.replace(/<(\w+)([^<]*)\/>/g,"<$1$2>")},t.Xml.domToPrettyText=function(e){e=t.Xml.domToText(e).split("<");for(var o="",i=1;i"!=n.slice(-2)&&(o+=" ")}return(e=(e=e.join("\n")).replace(/(<(\w+)\b[^>]*>[^\n]*)\n *<\/\2>/g,"$1")).replace(/^\n/,"")},t.Xml.textToDom=function(e){var o=t.utils.xml.textToDomDocument(e);if(!o||!o.documentElement||o.getElementsByTagName("parsererror").length)throw Error("textToDom was unable to parse: "+e);return o.documentElement},t.Xml.clearWorkspaceAndLoadFromXml=function(e,o){return o.setResizesEnabled(!1),o.clear(),e=t.Xml.domToWorkspace(e,o),o.setResizesEnabled(!0),e},t.Xml.domToWorkspace=function(e,o){if(e instanceof t.Workspace){var i=e;e=o,o=i,console.warn("Deprecated call to Blockly.Xml.domToWorkspace, swap the arguments.")}var n;o.RTL&&(n=o.getWidth()),i=[],t.utils.dom.startTextWidthCache();var s=t.Events.getGroup();s||t.Events.setGroup(!0),o.setResizesEnabled&&o.setResizesEnabled(!1);var r=!0;try{for(var a,l=0;a=e.childNodes[l];l++){var c=a.nodeName.toLowerCase(),h=a;if("block"==c||"shadow"==c&&!t.Events.recordUndo){var u=t.Xml.domToBlock(h,o);i.push(u.id);var p=h.hasAttribute("x")?parseInt(h.getAttribute("x"),10):10,_=h.hasAttribute("y")?parseInt(h.getAttribute("y"),10):10;isNaN(p)||isNaN(_)||u.moveBy(o.RTL?n-p:p,_),r=!1}else{if("shadow"==c)throw TypeError("Shadow block cannot be a top-level block.");if("comment"==c)o.rendered?t.WorkspaceCommentSvg?t.WorkspaceCommentSvg.fromXml(h,o,n):console.warn("Missing require for Blockly.WorkspaceCommentSvg, ignoring workspace comment."):t.WorkspaceComment?t.WorkspaceComment.fromXml(h,o):console.warn("Missing require for Blockly.WorkspaceComment, ignoring workspace comment.");else if("variables"==c){if(!r)throw Error("'variables' tag must exist once before block and shadow tag elements in the workspace XML, but it was found in another location.");t.Xml.domToVariables(h,o),r=!1}}}}finally{s||t.Events.setGroup(!1),t.utils.dom.stopTextWidthCache()}return o.setResizesEnabled&&o.setResizesEnabled(!0),t.Events.fire(new t.Events.FinishedLoading(o)),i},t.Xml.appendDomToWorkspace=function(e,o){var i;if(o.hasOwnProperty("scale")&&(i=o.getBlocksBoundingBox()),e=t.Xml.domToWorkspace(e,o),i&&i.top!=i.bottom){var n=i.bottom,s=o.RTL?i.right:i.left,r=1/0,a=-1/0,l=1/0;for(i=0;ia&&(a=c.x)}for(n=n-l+10,s=o.RTL?s-a:s-r,i=0;i document.")}else e=null;return e},t.Touch={},t.Touch.TOUCH_ENABLED="ontouchstart"in t.utils.global||!!(t.utils.global.document&&document.documentElement&&"ontouchstart"in document.documentElement)||!(!t.utils.global.navigator||!t.utils.global.navigator.maxTouchPoints&&!t.utils.global.navigator.msMaxTouchPoints),t.Touch.touchIdentifier_=null,t.Touch.TOUCH_MAP={},t.utils.global.PointerEvent?t.Touch.TOUCH_MAP={mousedown:["pointerdown"],mouseenter:["pointerenter"],mouseleave:["pointerleave"],mousemove:["pointermove"],mouseout:["pointerout"],mouseover:["pointerover"],mouseup:["pointerup","pointercancel"],touchend:["pointerup"],touchcancel:["pointercancel"]}:t.Touch.TOUCH_ENABLED&&(t.Touch.TOUCH_MAP={mousedown:["touchstart"],mousemove:["touchmove"],mouseup:["touchend","touchcancel"]}),t.longPid_=0,t.longStart=function(e,o){t.longStop_(),e.changedTouches&&1!=e.changedTouches.length||(t.longPid_=setTimeout((function(){e.changedTouches&&(e.button=2,e.clientX=e.changedTouches[0].clientX,e.clientY=e.changedTouches[0].clientY),o&&o.handleRightClick(e)}),t.LONGPRESS))},t.longStop_=function(){t.longPid_&&(clearTimeout(t.longPid_),t.longPid_=0)},t.Touch.clearTouchIdentifier=function(){t.Touch.touchIdentifier_=null},t.Touch.shouldHandleEvent=function(e){return!t.Touch.isMouseOrTouchEvent(e)||t.Touch.checkTouchIdentifier(e)},t.Touch.getTouchIdentifierFromEvent=function(t){return null!=t.pointerId?t.pointerId:t.changedTouches&&t.changedTouches[0]&&void 0!==t.changedTouches[0].identifier&&null!==t.changedTouches[0].identifier?t.changedTouches[0].identifier:"mouse"},t.Touch.checkTouchIdentifier=function(e){var o=t.Touch.getTouchIdentifierFromEvent(e);return void 0!==t.Touch.touchIdentifier_&&null!==t.Touch.touchIdentifier_?t.Touch.touchIdentifier_==o:("mousedown"==e.type||"touchstart"==e.type||"pointerdown"==e.type)&&(t.Touch.touchIdentifier_=o,!0)},t.Touch.setClientFromTouch=function(e){if(t.utils.string.startsWith(e.type,"touch")){var o=e.changedTouches[0];e.clientX=o.clientX,e.clientY=o.clientY}},t.Touch.isMouseOrTouchEvent=function(e){return t.utils.string.startsWith(e.type,"touch")||t.utils.string.startsWith(e.type,"mouse")||t.utils.string.startsWith(e.type,"pointer")},t.Touch.isTouchEvent=function(e){return t.utils.string.startsWith(e.type,"touch")||t.utils.string.startsWith(e.type,"pointer")},t.Touch.splitEventByTouches=function(t){var e=[];if(t.changedTouches)for(var o=0;o=i+this.handleLength_&&(n+=s),this.setHandlePosition(this.constrainHandle_(n)),this.onScroll_(),e.stopPropagation(),e.preventDefault()}},t.Scrollbar.prototype.onMouseDownHandle_=function(e){this.workspace_.markFocused(),this.cleanUp_(),t.utils.isRightButton(e)?e.stopPropagation():(this.startDragHandle=this.handlePosition_,this.workspace_.setupDragSurface(),this.startDragMouse_=this.horizontal_?e.clientX:e.clientY,t.Scrollbar.onMouseUpWrapper_=t.bindEventWithChecks_(document,"mouseup",this,this.onMouseUpHandle_),t.Scrollbar.onMouseMoveWrapper_=t.bindEventWithChecks_(document,"mousemove",this,this.onMouseMoveHandle_),e.stopPropagation(),e.preventDefault())},t.Scrollbar.prototype.onMouseMoveHandle_=function(t){this.setHandlePosition(this.constrainHandle_(this.startDragHandle+((this.horizontal_?t.clientX:t.clientY)-this.startDragMouse_))),this.onScroll_()},t.Scrollbar.prototype.onMouseUpHandle_=function(){this.workspace_.resetDragSurface(),t.Touch.clearTouchIdentifier(),this.cleanUp_()},t.Scrollbar.prototype.cleanUp_=function(){t.hideChaff(!0),t.Scrollbar.onMouseUpWrapper_&&(t.unbindEvent_(t.Scrollbar.onMouseUpWrapper_),t.Scrollbar.onMouseUpWrapper_=null),t.Scrollbar.onMouseMoveWrapper_&&(t.unbindEvent_(t.Scrollbar.onMouseMoveWrapper_),t.Scrollbar.onMouseMoveWrapper_=null)},t.Scrollbar.prototype.constrainHandle_=function(t){return 0>=t||isNaN(t)||this.scrollViewSize_t.Tooltip.RADIUS_OK&&t.Tooltip.hide()}else t.Tooltip.poisonedElement_!=t.Tooltip.element_&&(clearTimeout(t.Tooltip.showPid_),t.Tooltip.lastX_=e.pageX,t.Tooltip.lastY_=e.pageY,t.Tooltip.showPid_=setTimeout(t.Tooltip.show_,t.Tooltip.HOVER_MS))},t.Tooltip.dispose=function(){t.Tooltip.element_=null,t.Tooltip.poisonedElement_=null,t.Tooltip.hide()},t.Tooltip.hide=function(){t.Tooltip.visible&&(t.Tooltip.visible=!1,t.Tooltip.DIV&&(t.Tooltip.DIV.style.display="none")),t.Tooltip.showPid_&&clearTimeout(t.Tooltip.showPid_)},t.Tooltip.block=function(){t.Tooltip.hide(),t.Tooltip.blocked_=!0},t.Tooltip.unblock=function(){t.Tooltip.blocked_=!1},t.Tooltip.show_=function(){if(!t.Tooltip.blocked_&&(t.Tooltip.poisonedElement_=t.Tooltip.element_,t.Tooltip.DIV)){t.Tooltip.DIV.textContent="";for(var e=t.Tooltip.element_.tooltip;"function"==typeof e;)e=e();e=(e=t.utils.string.wrap(e,t.Tooltip.LIMIT)).split("\n");for(var o=0;oi+window.scrollY&&(s-=t.Tooltip.DIV.offsetHeight+2*t.Tooltip.OFFSET_Y),e?n=Math.max(t.Tooltip.MARGINS-window.scrollX,n):n+t.Tooltip.DIV.offsetWidth>o+window.scrollX-2*t.Tooltip.MARGINS&&(n=o-t.Tooltip.DIV.offsetWidth-2*t.Tooltip.MARGINS),t.Tooltip.DIV.style.top=s+"px",t.Tooltip.DIV.style.left=n+"px"}},t.WorkspaceDragSurfaceSvg=function(t){this.container_=t,this.createDom()},t.WorkspaceDragSurfaceSvg.prototype.SVG_=null,t.WorkspaceDragSurfaceSvg.prototype.dragGroup_=null,t.WorkspaceDragSurfaceSvg.prototype.container_=null,t.WorkspaceDragSurfaceSvg.prototype.createDom=function(){this.SVG_||(this.SVG_=t.utils.dom.createSvgElement("svg",{xmlns:t.utils.dom.SVG_NS,"xmlns:html":t.utils.dom.HTML_NS,"xmlns:xlink":t.utils.dom.XLINK_NS,version:"1.1",class:"blocklyWsDragSurface blocklyOverflowVisible"},null),this.container_.appendChild(this.SVG_))},t.WorkspaceDragSurfaceSvg.prototype.translateSurface=function(e,o){e=e.toFixed(0),o=o.toFixed(0),this.SVG_.style.display="block",t.utils.dom.setCssTransform(this.SVG_,"translate3d("+e+"px, "+o+"px, 0px)")},t.WorkspaceDragSurfaceSvg.prototype.getSurfaceTranslation=function(){return t.utils.getRelativeXY(this.SVG_)},t.WorkspaceDragSurfaceSvg.prototype.clearAndHide=function(e){if(!e)throw Error("Couldn't clear and hide the drag surface: missing new surface.");var o=this.SVG_.childNodes[0],i=this.SVG_.childNodes[1];if(!(o&&i&&t.utils.dom.hasClass(o,"blocklyBlockCanvas")&&t.utils.dom.hasClass(i,"blocklyBubbleCanvas")))throw Error("Couldn't clear and hide the drag surface. A node was missing.");if(null!=this.previousSibling_?t.utils.dom.insertAfter(o,this.previousSibling_):e.insertBefore(o,e.firstChild),t.utils.dom.insertAfter(i,o),this.SVG_.style.display="none",this.SVG_.childNodes.length)throw Error("Drag surface was not cleared.");t.utils.dom.setCssTransform(this.SVG_,""),this.previousSibling_=null},t.WorkspaceDragSurfaceSvg.prototype.setContentsAndShow=function(t,e,o,i,n,s){if(this.SVG_.childNodes.length)throw Error("Already dragging a block.");this.previousSibling_=o,t.setAttribute("transform","translate(0, 0) scale("+s+")"),e.setAttribute("transform","translate(0, 0) scale("+s+")"),this.SVG_.setAttribute("width",i),this.SVG_.setAttribute("height",n),this.SVG_.appendChild(t),this.SVG_.appendChild(e),this.SVG_.style.display="block"},t.ASTNode=function(e,o,i){if(!o)throw Error("Cannot create a node without a location.");this.type_=e,this.isConnection_=t.ASTNode.isConnectionType_(e),this.location_=o,this.processParams_(i||null)},t.ASTNode.types={FIELD:"field",BLOCK:"block",INPUT:"input",OUTPUT:"output",NEXT:"next",PREVIOUS:"previous",STACK:"stack",WORKSPACE:"workspace"},t.ASTNode.NAVIGATE_ALL_FIELDS=!1,t.ASTNode.DEFAULT_OFFSET_Y=-20,t.ASTNode.isConnectionType_=function(e){switch(e){case t.ASTNode.types.PREVIOUS:case t.ASTNode.types.NEXT:case t.ASTNode.types.INPUT:case t.ASTNode.types.OUTPUT:return!0}return!1},t.ASTNode.createFieldNode=function(e){return e?new t.ASTNode(t.ASTNode.types.FIELD,e):null},t.ASTNode.createConnectionNode=function(e){return e?e.type==t.INPUT_VALUE||e.type==t.NEXT_STATEMENT&&e.getParentInput()?t.ASTNode.createInputNode(e.getParentInput()):e.type==t.NEXT_STATEMENT?new t.ASTNode(t.ASTNode.types.NEXT,e):e.type==t.OUTPUT_VALUE?new t.ASTNode(t.ASTNode.types.OUTPUT,e):e.type==t.PREVIOUS_STATEMENT?new t.ASTNode(t.ASTNode.types.PREVIOUS,e):null:null},t.ASTNode.createInputNode=function(e){return e&&e.connection?new t.ASTNode(t.ASTNode.types.INPUT,e.connection):null},t.ASTNode.createBlockNode=function(e){return e?new t.ASTNode(t.ASTNode.types.BLOCK,e):null},t.ASTNode.createStackNode=function(e){return e?new t.ASTNode(t.ASTNode.types.STACK,e):null},t.ASTNode.createWorkspaceNode=function(e,o){return o&&e?new t.ASTNode(t.ASTNode.types.WORKSPACE,e,{wsCoordinate:o}):null},t.ASTNode.prototype.processParams_=function(t){t&&t.wsCoordinate&&(this.wsCoordinate_=t.wsCoordinate)},t.ASTNode.prototype.getLocation=function(){return this.location_},t.ASTNode.prototype.getType=function(){return this.type_},t.ASTNode.prototype.getWsCoordinate=function(){return this.wsCoordinate_},t.ASTNode.prototype.isConnection=function(){return this.isConnection_},t.ASTNode.prototype.findNextForInput_=function(){var e,o=this.location_.getParentInput(),i=o.getSourceBlock();for(o=i.inputList.indexOf(o)+1;e=i.inputList[o];o++){for(var n,s=e.fieldRow,r=0;n=s[r];r++)if(n.isClickable()||t.ASTNode.NAVIGATE_ALL_FIELDS)return t.ASTNode.createFieldNode(n);if(e.connection)return t.ASTNode.createInputNode(e)}return null},t.ASTNode.prototype.findNextForField_=function(){var e=this.location_,o=e.getParentInput(),i=e.getSourceBlock(),n=i.inputList.indexOf(o);for(e=o.fieldRow.indexOf(e)+1;o=i.inputList[n];n++){for(var s=o.fieldRow;ei)){var n=o.getSvgXY(e.getSvgRoot());e.outputConnection?(n.x+=(e.RTL?3:-3)*i,n.y+=13*i):e.previousConnection&&(n.x+=(e.RTL?-23:23)*i,n.y+=3*i),e=t.utils.dom.createSvgElement("circle",{cx:n.x,cy:n.y,r:0,fill:"none",stroke:"#888","stroke-width":10},o.getParentSvg()),t.blockAnimations.connectionUiStep_(e,new Date,i)}},t.blockAnimations.connectionUiStep_=function(e,o,i){var n=(new Date-o)/150;1e.workspace.scale)){var o=e.getHeightWidth().height;o=Math.atan(10/o)/Math.PI*180,e.RTL||(o*=-1),t.blockAnimations.disconnectUiStep_(e.getSvgRoot(),o,new Date)}},t.blockAnimations.disconnectUiStep_=function(e,o,i){var n=(new Date-i)/200;1o-t.CURRENT_CONNECTION_PREFERENCE)):!this.localConnection_&&!this.closestConnection_||(console.error("Only one of localConnection_ and closestConnection_ was set."),console.error("Returning true from shouldUpdatePreviews, but it's not clear why."),!0):!(!this.localConnection_||!this.closestConnection_)},t.InsertionMarkerManager.prototype.getCandidate_=function(t){for(var e=this.getStartRadius_(),o=null,i=null,n=0;nthis.remainingCapacityOfType(e))return!1;o+=t[e]}return!(o>this.remainingCapacity())},t.Workspace.prototype.hasBlockLimits=function(){return 1/0!=this.options.maxBlocks||!!this.options.maxInstances},t.Workspace.prototype.undo=function(e){var o=e?this.redoStack_:this.undoStack_,i=e?this.undoStack_:this.redoStack_,n=o.pop();if(n){for(var s=[n];o.length&&n.group&&n.group==o[o.length-1].group;)s.push(o.pop());for(o=0;n=s[o];o++)i.push(n);s=t.Events.filter(s,e),t.Events.recordUndo=!1;try{for(o=0;n=s[o];o++)n.run(e)}finally{t.Events.recordUndo=!0}}},t.Workspace.prototype.clearUndo=function(){this.undoStack_.length=0,this.redoStack_.length=0,t.Events.clearPendingUndo()},t.Workspace.prototype.addChangeListener=function(t){return this.listeners_.push(t),t},t.Workspace.prototype.removeChangeListener=function(e){t.utils.arrayRemove(this.listeners_,e)},t.Workspace.prototype.fireChangeListener=function(t){if(t.recordUndo)for(this.undoStack_.push(t),this.redoStack_.length=0;this.undoStack_.length>this.MAX_UNDO&&0<=this.MAX_UNDO;)this.undoStack_.shift();for(var e,o=0;e=this.listeners_[o];o++)e(t)},t.Workspace.prototype.getBlockById=function(t){return this.blockDB_[t]||null},t.Workspace.prototype.setBlockById=function(t,e){this.blockDB_[t]=e},t.Workspace.prototype.removeBlockById=function(t){delete this.blockDB_[t]},t.Workspace.prototype.getCommentById=function(t){return this.commentDB_[t]||null},t.Workspace.prototype.allInputsFilled=function(t){for(var e,o=this.getTopBlocks(!1),i=0;e=o[i];i++)if(!e.allInputsFilled(t))return!1;return!0},t.Workspace.prototype.getPotentialVariableMap=function(){return this.potentialVariableMap_},t.Workspace.prototype.createPotentialVariableMap=function(){this.potentialVariableMap_=new t.VariableMap(this)},t.Workspace.prototype.getVariableMap=function(){return this.variableMap_},t.Workspace.prototype.setVariableMap=function(t){this.variableMap_=t},t.Workspace.WorkspaceDB_=Object.create(null),t.Workspace.getById=function(e){return t.Workspace.WorkspaceDB_[e]||null},t.Workspace.getAll=function(){var e,o=[];for(e in t.Workspace.WorkspaceDB_)o.push(t.Workspace.WorkspaceDB_[e]);return o},t.Bubble=function(e,o,i,n,s,r){this.workspace_=e,this.content_=o,this.shape_=i,this.onMouseDownResizeWrapper_=this.onMouseDownBubbleWrapper_=this.moveCallback_=this.resizeCallback_=null,this.disposed=!1,i=t.Bubble.ARROW_ANGLE,this.workspace_.RTL&&(i=-i),this.arrow_radians_=t.utils.math.toRadians(i),e.getBubbleCanvas().appendChild(this.createDom_(o,!(!s||!r))),this.setAnchorLocation(n),s&&r||(s=(e=this.content_.getBBox()).width+2*t.Bubble.BORDER_WIDTH,r=e.height+2*t.Bubble.BORDER_WIDTH),this.setBubbleSize(s,r),this.positionBubble_(),this.renderArrow_(),this.rendered_=!0},t.Bubble.BORDER_WIDTH=6,t.Bubble.ARROW_THICKNESS=5,t.Bubble.ARROW_ANGLE=20,t.Bubble.ARROW_BEND=4,t.Bubble.ANCHOR_RADIUS=8,t.Bubble.onMouseUpWrapper_=null,t.Bubble.onMouseMoveWrapper_=null,t.Bubble.unbindDragEvents_=function(){t.Bubble.onMouseUpWrapper_&&(t.unbindEvent_(t.Bubble.onMouseUpWrapper_),t.Bubble.onMouseUpWrapper_=null),t.Bubble.onMouseMoveWrapper_&&(t.unbindEvent_(t.Bubble.onMouseMoveWrapper_),t.Bubble.onMouseMoveWrapper_=null)},t.Bubble.bubbleMouseUp_=function(e){t.Touch.clearTouchIdentifier(),t.Bubble.unbindDragEvents_()},t.Bubble.prototype.rendered_=!1,t.Bubble.prototype.anchorXY_=null,t.Bubble.prototype.relativeLeft_=0,t.Bubble.prototype.relativeTop_=0,t.Bubble.prototype.width_=0,t.Bubble.prototype.height_=0,t.Bubble.prototype.autoLayout_=!0,t.Bubble.prototype.createDom_=function(e,o){this.bubbleGroup_=t.utils.dom.createSvgElement("g",{},null);var i={filter:"url(#"+this.workspace_.getRenderer().getConstants().embossFilterId+")"};return t.utils.userAgent.JAVA_FX&&(i={}),i=t.utils.dom.createSvgElement("g",i,this.bubbleGroup_),this.bubbleArrow_=t.utils.dom.createSvgElement("path",{},i),this.bubbleBack_=t.utils.dom.createSvgElement("rect",{class:"blocklyDraggable",x:0,y:0,rx:t.Bubble.BORDER_WIDTH,ry:t.Bubble.BORDER_WIDTH},i),o?(this.resizeGroup_=t.utils.dom.createSvgElement("g",{class:this.workspace_.RTL?"blocklyResizeSW":"blocklyResizeSE"},this.bubbleGroup_),o=2*t.Bubble.BORDER_WIDTH,t.utils.dom.createSvgElement("polygon",{points:"0,x x,x x,0".replace(/x/g,o.toString())},this.resizeGroup_),t.utils.dom.createSvgElement("line",{class:"blocklyResizeLine",x1:o/3,y1:o-1,x2:o-1,y2:o/3},this.resizeGroup_),t.utils.dom.createSvgElement("line",{class:"blocklyResizeLine",x1:2*o/3,y1:o-1,x2:o-1,y2:2*o/3},this.resizeGroup_)):this.resizeGroup_=null,this.workspace_.options.readOnly||(this.onMouseDownBubbleWrapper_=t.bindEventWithChecks_(this.bubbleBack_,"mousedown",this,this.bubbleMouseDown_),this.resizeGroup_&&(this.onMouseDownResizeWrapper_=t.bindEventWithChecks_(this.resizeGroup_,"mousedown",this,this.resizeMouseDown_))),this.bubbleGroup_.appendChild(e),this.bubbleGroup_},t.Bubble.prototype.getSvgRoot=function(){return this.bubbleGroup_},t.Bubble.prototype.setSvgId=function(t){this.bubbleGroup_.dataset&&(this.bubbleGroup_.dataset.blockId=t)},t.Bubble.prototype.bubbleMouseDown_=function(t){var e=this.workspace_.getGesture(t);e&&e.handleBubbleStart(t,this)},t.Bubble.prototype.showContextMenu=function(t){},t.Bubble.prototype.isDeletable=function(){return!1},t.Bubble.prototype.resizeMouseDown_=function(e){this.promote(),t.Bubble.unbindDragEvents_(),t.utils.isRightButton(e)||(this.workspace_.startDrag(e,new t.utils.Coordinate(this.workspace_.RTL?-this.width_:this.width_,this.height_)),t.Bubble.onMouseUpWrapper_=t.bindEventWithChecks_(document,"mouseup",this,t.Bubble.bubbleMouseUp_),t.Bubble.onMouseMoveWrapper_=t.bindEventWithChecks_(document,"mousemove",this,this.resizeMouseMove_),t.hideChaff()),e.stopPropagation()},t.Bubble.prototype.resizeMouseMove_=function(t){this.autoLayout_=!1,t=this.workspace_.moveDrag(t),this.setBubbleSize(this.workspace_.RTL?-t.x:t.x,t.y),this.workspace_.RTL&&this.positionBubble_()},t.Bubble.prototype.registerResizeEvent=function(t){this.resizeCallback_=t},t.Bubble.prototype.registerMoveEvent=function(t){this.moveCallback_=t},t.Bubble.prototype.promote=function(){var t=this.bubbleGroup_.parentNode;return t.lastChild!==this.bubbleGroup_&&(t.appendChild(this.bubbleGroup_),!0)},t.Bubble.prototype.setAnchorLocation=function(t){this.anchorXY_=t,this.rendered_&&this.positionBubble_()},t.Bubble.prototype.layoutBubble_=function(){var t=this.workspace_.getMetrics();t.viewLeft/=this.workspace_.scale,t.viewWidth/=this.workspace_.scale,t.viewTop/=this.workspace_.scale,t.viewHeight/=this.workspace_.scale;var e=this.getOptimalRelativeLeft_(t),o=this.getOptimalRelativeTop_(t),i=this.shape_.getBBox(),n={x:e,y:-this.height_-this.workspace_.getRenderer().getConstants().MIN_BLOCK_HEIGHT},s={x:-this.width_-30,y:o};o={x:i.width,y:o};var r={x:e,y:i.height};e=i.widthe.viewWidth)return o;if(this.workspace_.RTL)var i=this.anchorXY_.x-o,n=i-this.width_,s=e.viewLeft+e.viewWidth,r=e.viewLeft+t.Scrollbar.scrollbarThickness/this.workspace_.scale;else i=(n=o+this.anchorXY_.x)+this.width_,r=e.viewLeft,s=e.viewLeft+e.viewWidth-t.Scrollbar.scrollbarThickness/this.workspace_.scale;return this.workspace_.RTL?ns&&(o=-(s-this.anchorXY_.x)):ns&&(o=s-this.anchorXY_.x-this.width_),o},t.Bubble.prototype.getOptimalRelativeTop_=function(e){var o=-this.height_/4;if(this.height_>e.viewHeight)return o;var i=this.anchorXY_.y+o,n=i+this.height_,s=e.viewTop;e=e.viewTop+e.viewHeight-t.Scrollbar.scrollbarThickness/this.workspace_.scale;var r=this.anchorXY_.y;return ie&&(o=e-r-this.height_),o},t.Bubble.prototype.positionBubble_=function(){var t=this.anchorXY_.x;t=this.workspace_.RTL?t-(this.relativeLeft_+this.width_):t+this.relativeLeft_,this.moveTo(t,this.relativeTop_+this.anchorXY_.y)},t.Bubble.prototype.moveTo=function(t,e){this.bubbleGroup_.setAttribute("transform","translate("+t+","+e+")")},t.Bubble.prototype.setDragging=function(t){!t&&this.moveCallback_&&this.moveCallback_()},t.Bubble.prototype.getBubbleSize=function(){return new t.utils.Size(this.width_,this.height_)},t.Bubble.prototype.setBubbleSize=function(e,o){var i=2*t.Bubble.BORDER_WIDTH;e=Math.max(e,i+45),o=Math.max(o,i+20),this.width_=e,this.height_=o,this.bubbleBack_.setAttribute("width",e),this.bubbleBack_.setAttribute("height",o),this.resizeGroup_&&(this.workspace_.RTL?this.resizeGroup_.setAttribute("transform","translate("+2*t.Bubble.BORDER_WIDTH+","+(o-i)+") scale(-1 1)"):this.resizeGroup_.setAttribute("transform","translate("+(e-i)+","+(o-i)+")")),this.autoLayout_&&this.layoutBubble_(),this.positionBubble_(),this.renderArrow_(),this.resizeCallback_&&this.resizeCallback_()},t.Bubble.prototype.renderArrow_=function(){var e=[],o=this.width_/2,i=this.height_/2,n=-this.relativeLeft_,s=-this.relativeTop_;if(o==n&&i==s)e.push("M "+o+","+i);else{s-=i,n-=o,this.workspace_.RTL&&(n*=-1);var r=Math.sqrt(s*s+n*n),a=Math.acos(n/r);0>s&&(a=2*Math.PI-a);var l=a+Math.PI/2;l>2*Math.PI&&(l-=2*Math.PI);var c=Math.sin(l),h=Math.cos(l),u=this.getBubbleSize();l=(u.width+u.height)/t.Bubble.ARROW_THICKNESS,l=Math.min(l,u.width,u.height)/4,n=o+(u=1-t.Bubble.ANCHOR_RADIUS/r)*n,s=i+u*s,u=o+l*h;var p=i+l*c;o-=l*h,i-=l*c,(c=a+this.arrow_radians_)>2*Math.PI&&(c-=2*Math.PI),a=Math.sin(c)*r/t.Bubble.ARROW_BEND,r=Math.cos(c)*r/t.Bubble.ARROW_BEND,e.push("M"+u+","+p),e.push("C"+(u+r)+","+(p+a)+" "+n+","+s+" "+n+","+s),e.push("C"+n+","+s+" "+(o+r)+","+(i+a)+" "+o+","+i)}e.push("z"),this.bubbleArrow_.setAttribute("d",e.join(" "))},t.Bubble.prototype.setColour=function(t){this.bubbleBack_.setAttribute("fill",t),this.bubbleArrow_.setAttribute("fill",t)},t.Bubble.prototype.dispose=function(){this.onMouseDownBubbleWrapper_&&t.unbindEvent_(this.onMouseDownBubbleWrapper_),this.onMouseDownResizeWrapper_&&t.unbindEvent_(this.onMouseDownResizeWrapper_),t.Bubble.unbindDragEvents_(),t.utils.dom.removeNode(this.bubbleGroup_),this.disposed=!0},t.Bubble.prototype.moveDuringDrag=function(t,e){t?t.translateSurface(e.x,e.y):this.moveTo(e.x,e.y),this.relativeLeft_=this.workspace_.RTL?this.anchorXY_.x-e.x-this.width_:e.x-this.anchorXY_.x,this.relativeTop_=e.y-this.anchorXY_.y,this.renderArrow_()},t.Bubble.prototype.getRelativeToSurfaceXY=function(){return new t.utils.Coordinate(this.workspace_.RTL?-this.relativeLeft_+this.anchorXY_.x-this.width_:this.anchorXY_.x+this.relativeLeft_,this.anchorXY_.y+this.relativeTop_)},t.Bubble.prototype.setAutoLayout=function(t){this.autoLayout_=t},t.Events.CommentBase=function(e){this.commentId=e.id,this.workspaceId=e.workspace.id,this.group=t.Events.getGroup(),this.recordUndo=t.Events.recordUndo},t.utils.object.inherits(t.Events.CommentBase,t.Events.Abstract),t.Events.CommentBase.prototype.toJson=function(){var e=t.Events.CommentBase.superClass_.toJson.call(this);return this.commentId&&(e.commentId=this.commentId),e},t.Events.CommentBase.prototype.fromJson=function(e){t.Events.CommentBase.superClass_.fromJson.call(this,e),this.commentId=e.commentId},t.Events.CommentChange=function(e,o,i){e&&(t.Events.CommentChange.superClass_.constructor.call(this,e),this.oldContents_=o,this.newContents_=i)},t.utils.object.inherits(t.Events.CommentChange,t.Events.CommentBase),t.Events.CommentChange.prototype.type=t.Events.COMMENT_CHANGE,t.Events.CommentChange.prototype.toJson=function(){var e=t.Events.CommentChange.superClass_.toJson.call(this);return e.newContents=this.newContents_,e},t.Events.CommentChange.prototype.fromJson=function(e){t.Events.CommentChange.superClass_.fromJson.call(this,e),this.newContents_=e.newValue},t.Events.CommentChange.prototype.isNull=function(){return this.oldContents_==this.newContents_},t.Events.CommentChange.prototype.run=function(t){var e=this.getEventWorkspace_().getCommentById(this.commentId);e?e.setContent(t?this.newContents_:this.oldContents_):console.warn("Can't change non-existent comment: "+this.commentId)},t.Events.CommentCreate=function(e){e&&(t.Events.CommentCreate.superClass_.constructor.call(this,e),this.xml=e.toXmlWithXY())},t.utils.object.inherits(t.Events.CommentCreate,t.Events.CommentBase),t.Events.CommentCreate.prototype.type=t.Events.COMMENT_CREATE,t.Events.CommentCreate.prototype.toJson=function(){var e=t.Events.CommentCreate.superClass_.toJson.call(this);return e.xml=t.Xml.domToText(this.xml),e},t.Events.CommentCreate.prototype.fromJson=function(e){t.Events.CommentCreate.superClass_.fromJson.call(this,e),this.xml=t.Xml.textToDom(e.xml)},t.Events.CommentCreate.prototype.run=function(e){t.Events.CommentCreateDeleteHelper(this,e)},t.Events.CommentCreateDeleteHelper=function(e,o){var i=e.getEventWorkspace_();o?((o=t.utils.xml.createElement("xml")).appendChild(e.xml),t.Xml.domToWorkspace(o,i)):(i=i.getCommentById(e.commentId))?i.dispose(!1,!1):console.warn("Can't uncreate non-existent comment: "+e.commentId)},t.Events.CommentDelete=function(e){e&&(t.Events.CommentDelete.superClass_.constructor.call(this,e),this.xml=e.toXmlWithXY())},t.utils.object.inherits(t.Events.CommentDelete,t.Events.CommentBase),t.Events.CommentDelete.prototype.type=t.Events.COMMENT_DELETE,t.Events.CommentDelete.prototype.toJson=function(){return t.Events.CommentDelete.superClass_.toJson.call(this)},t.Events.CommentDelete.prototype.fromJson=function(e){t.Events.CommentDelete.superClass_.fromJson.call(this,e)},t.Events.CommentDelete.prototype.run=function(e){t.Events.CommentCreateDeleteHelper(this,!e)},t.Events.CommentMove=function(e){e&&(t.Events.CommentMove.superClass_.constructor.call(this,e),this.comment_=e,this.oldCoordinate_=e.getXY(),this.newCoordinate_=null)},t.utils.object.inherits(t.Events.CommentMove,t.Events.CommentBase),t.Events.CommentMove.prototype.recordNew=function(){if(!this.comment_)throw Error("Tried to record the new position of a comment on the same event twice.");this.newCoordinate_=this.comment_.getXY(),this.comment_=null},t.Events.CommentMove.prototype.type=t.Events.COMMENT_MOVE,t.Events.CommentMove.prototype.setOldCoordinate=function(t){this.oldCoordinate_=t},t.Events.CommentMove.prototype.toJson=function(){var e=t.Events.CommentMove.superClass_.toJson.call(this);return this.newCoordinate_&&(e.newCoordinate=Math.round(this.newCoordinate_.x)+","+Math.round(this.newCoordinate_.y)),e},t.Events.CommentMove.prototype.fromJson=function(e){t.Events.CommentMove.superClass_.fromJson.call(this,e),e.newCoordinate&&(e=e.newCoordinate.split(","),this.newCoordinate_=new t.utils.Coordinate(Number(e[0]),Number(e[1])))},t.Events.CommentMove.prototype.isNull=function(){return t.utils.Coordinate.equals(this.oldCoordinate_,this.newCoordinate_)},t.Events.CommentMove.prototype.run=function(t){var e=this.getEventWorkspace_().getCommentById(this.commentId);if(e){t=t?this.newCoordinate_:this.oldCoordinate_;var o=e.getXY();e.moveBy(t.x-o.x,t.y-o.y)}else console.warn("Can't move non-existent comment: "+this.commentId)},t.BubbleDragger=function(e,o){this.draggingBubble_=e,this.workspace_=o,this.deleteArea_=null,this.wouldDeleteBubble_=!1,this.startXY_=this.draggingBubble_.getRelativeToSurfaceXY(),this.dragSurface_=t.utils.is3dSupported()&&o.getBlockDragSurface()?o.getBlockDragSurface():null},t.BubbleDragger.prototype.dispose=function(){this.dragSurface_=this.workspace_=this.draggingBubble_=null},t.BubbleDragger.prototype.startBubbleDrag=function(){t.Events.getGroup()||t.Events.setGroup(!0),this.workspace_.setResizesEnabled(!1),this.draggingBubble_.setAutoLayout(!1),this.dragSurface_&&this.moveToDragSurface_(),this.draggingBubble_.setDragging&&this.draggingBubble_.setDragging(!0);var e=this.workspace_.getToolbox();if(e){var o=this.draggingBubble_.isDeletable()?"blocklyToolboxDelete":"blocklyToolboxGrab";e.addStyle(o)}},t.BubbleDragger.prototype.dragBubble=function(e,o){o=this.pixelsToWorkspaceUnits_(o),o=t.utils.Coordinate.sum(this.startXY_,o),this.draggingBubble_.moveDuringDrag(this.dragSurface_,o),this.draggingBubble_.isDeletable()&&(this.deleteArea_=this.workspace_.isDeleteArea(e),this.updateCursorDuringBubbleDrag_())},t.BubbleDragger.prototype.maybeDeleteBubble_=function(){var t=this.workspace_.trashcan;return this.wouldDeleteBubble_?(t&&setTimeout(t.close.bind(t),100),this.fireMoveEvent_(),this.draggingBubble_.dispose(!1,!0)):t&&t.close(),this.wouldDeleteBubble_},t.BubbleDragger.prototype.updateCursorDuringBubbleDrag_=function(){this.wouldDeleteBubble_=this.deleteArea_!=t.DELETE_AREA_NONE;var e=this.workspace_.trashcan;this.wouldDeleteBubble_?(this.draggingBubble_.setDeleteStyle(!0),this.deleteArea_==t.DELETE_AREA_TRASH&&e&&e.setOpen(!0)):(this.draggingBubble_.setDeleteStyle(!1),e&&e.setOpen(!1))},t.BubbleDragger.prototype.endBubbleDrag=function(e,o){this.dragBubble(e,o),e=this.pixelsToWorkspaceUnits_(o),e=t.utils.Coordinate.sum(this.startXY_,e),this.draggingBubble_.moveTo(e.x,e.y),this.maybeDeleteBubble_()||(this.dragSurface_&&this.dragSurface_.clearAndHide(this.workspace_.getBubbleCanvas()),this.draggingBubble_.setDragging&&this.draggingBubble_.setDragging(!1),this.fireMoveEvent_()),this.workspace_.setResizesEnabled(!0),this.workspace_.getToolbox()&&(e=this.draggingBubble_.isDeletable()?"blocklyToolboxDelete":"blocklyToolboxGrab",this.workspace_.getToolbox().removeStyle(e)),t.Events.setGroup(!1)},t.BubbleDragger.prototype.fireMoveEvent_=function(){if(this.draggingBubble_.isComment){var e=new t.Events.CommentMove(this.draggingBubble_);e.setOldCoordinate(this.startXY_),e.recordNew(),t.Events.fire(e)}},t.BubbleDragger.prototype.pixelsToWorkspaceUnits_=function(e){return e=new t.utils.Coordinate(e.x/this.workspace_.scale,e.y/this.workspace_.scale),this.workspace_.isMutator&&e.scale(1/this.workspace_.options.parentWorkspace.scale),e},t.BubbleDragger.prototype.moveToDragSurface_=function(){this.draggingBubble_.moveTo(0,0),this.dragSurface_.translateSurface(this.startXY_.x,this.startXY_.y),this.dragSurface_.setBlocksAndShow(this.draggingBubble_.getSvgRoot())},t.WorkspaceDragger=function(e){this.workspace_=e,this.startScrollXY_=new t.utils.Coordinate(e.scrollX,e.scrollY)},t.WorkspaceDragger.prototype.dispose=function(){this.workspace_=null},t.WorkspaceDragger.prototype.startDrag=function(){t.selected&&t.selected.unselect(),this.workspace_.setupDragSurface()},t.WorkspaceDragger.prototype.endDrag=function(t){this.drag(t),this.workspace_.resetDragSurface()},t.WorkspaceDragger.prototype.drag=function(e){e=t.utils.Coordinate.sum(this.startScrollXY_,e),this.workspace_.scroll(e.x,e.y)},t.FlyoutDragger=function(e){t.FlyoutDragger.superClass_.constructor.call(this,e.getWorkspace()),this.scrollbar_=e.scrollbar_,this.horizontalLayout_=e.horizontalLayout_},t.utils.object.inherits(t.FlyoutDragger,t.WorkspaceDragger),t.FlyoutDragger.prototype.drag=function(e){e=t.utils.Coordinate.sum(this.startScrollXY_,e),this.horizontalLayout_?this.scrollbar_.set(-e.x):this.scrollbar_.set(-e.y)},t.Action=function(t,e){this.name=t,this.desc=e},t.navigation={},t.navigation.loggingCallback=null,t.navigation.STATE_FLYOUT=1,t.navigation.STATE_WS=2,t.navigation.STATE_TOOLBOX=3,t.navigation.WS_MOVE_DISTANCE=40,t.navigation.currentState_=t.navigation.STATE_WS,t.navigation.actionNames={PREVIOUS:"previous",NEXT:"next",IN:"in",OUT:"out",INSERT:"insert",MARK:"mark",DISCONNECT:"disconnect",TOOLBOX:"toolbox",EXIT:"exit",TOGGLE_KEYBOARD_NAV:"toggle_keyboard_nav",MOVE_WS_CURSOR_UP:"move workspace cursor up",MOVE_WS_CURSOR_DOWN:"move workspace cursor down",MOVE_WS_CURSOR_LEFT:"move workspace cursor left",MOVE_WS_CURSOR_RIGHT:"move workspace cursor right"},t.navigation.MARKER_NAME="local_marker_1",t.navigation.getMarker=function(){return t.getMainWorkspace().getMarker(t.navigation.MARKER_NAME)},t.navigation.focusToolbox_=function(){var e=t.getMainWorkspace().getToolbox();e&&(t.navigation.currentState_=t.navigation.STATE_TOOLBOX,t.navigation.resetFlyout_(!1),t.navigation.getMarker().getCurNode()||t.navigation.markAtCursor_(),e.selectFirstCategory())},t.navigation.focusFlyout_=function(){t.navigation.currentState_=t.navigation.STATE_FLYOUT;var e=t.getMainWorkspace(),o=e.getToolbox();e=o?o.flyout_:e.getFlyout(),t.navigation.getMarker().getCurNode()||t.navigation.markAtCursor_(),e&&e.getWorkspace()&&0<(e=e.getWorkspace().getTopBlocks(!0)).length&&(e=e[0],e=t.ASTNode.createStackNode(e),t.navigation.getFlyoutCursor_().setCurNode(e))},t.navigation.focusWorkspace_=function(){t.hideChaff();var e=t.getMainWorkspace(),o=e.getCursor(),i=!!e.getToolbox(),n=e.getTopBlocks(!0);t.navigation.resetFlyout_(i),t.navigation.currentState_=t.navigation.STATE_WS,0(this.flyout_?t.FLYOUT_DRAG_RADIUS:t.DRAG_RADIUS))},t.Gesture.prototype.updateIsDraggingFromFlyout_=function(){return!(!this.targetBlock_||!this.flyout_.isBlockCreatable_(this.targetBlock_)||this.flyout_.isScrollable()&&!this.flyout_.isDragTowardWorkspace(this.currentDragDeltaXY_)||(this.startWorkspace_=this.flyout_.targetWorkspace_,this.startWorkspace_.updateScreenCalculationsIfScrolled(),t.Events.getGroup()||t.Events.setGroup(!0),this.startBlock_=null,this.targetBlock_=this.flyout_.createBlock(this.targetBlock_),this.targetBlock_.select(),0))},t.Gesture.prototype.updateIsDraggingBubble_=function(){return!!this.startBubble_&&(this.isDraggingBubble_=!0,this.startDraggingBubble_(),!0)},t.Gesture.prototype.updateIsDraggingBlock_=function(){return!!this.targetBlock_&&(this.flyout_?this.isDraggingBlock_=this.updateIsDraggingFromFlyout_():this.targetBlock_.isMovable()&&(this.isDraggingBlock_=!0),!!this.isDraggingBlock_&&(this.startDraggingBlock_(),!0))},t.Gesture.prototype.updateIsDraggingWorkspace_=function(){(this.flyout_?this.flyout_.isScrollable():this.startWorkspace_&&this.startWorkspace_.isDraggable())&&(this.workspaceDragger_=this.flyout_?new t.FlyoutDragger(this.flyout_):new t.WorkspaceDragger(this.startWorkspace_),this.isDraggingWorkspace_=!0,this.workspaceDragger_.startDrag())},t.Gesture.prototype.updateIsDragging_=function(){if(this.calledUpdateIsDragging_)throw Error("updateIsDragging_ should only be called once per gesture.");this.calledUpdateIsDragging_=!0,this.updateIsDraggingBubble_()||this.updateIsDraggingBlock_()||this.updateIsDraggingWorkspace_()},t.Gesture.prototype.startDraggingBlock_=function(){this.blockDragger_=new t.BlockDragger(this.targetBlock_,this.startWorkspace_),this.blockDragger_.startBlockDrag(this.currentDragDeltaXY_,this.healStack_),this.blockDragger_.dragBlock(this.mostRecentEvent_,this.currentDragDeltaXY_)},t.Gesture.prototype.startDraggingBubble_=function(){this.bubbleDragger_=new t.BubbleDragger(this.startBubble_,this.startWorkspace_),this.bubbleDragger_.startBubbleDrag(),this.bubbleDragger_.dragBubble(this.mostRecentEvent_,this.currentDragDeltaXY_)},t.Gesture.prototype.doStart=function(e){t.utils.isTargetInput(e)?this.cancel():(this.hasStarted_=!0,t.blockAnimations.disconnectUiStop(),this.startWorkspace_.updateScreenCalculationsIfScrolled(),this.startWorkspace_.isMutator&&this.startWorkspace_.resize(),t.hideChaff(!!this.flyout_),this.startWorkspace_.markFocused(),this.mostRecentEvent_=e,t.Tooltip.block(),this.targetBlock_&&(!this.targetBlock_.isInFlyout&&e.shiftKey&&this.targetBlock_.workspace.keyboardAccessibilityMode?this.creatorWorkspace_.getCursor().setCurNode(t.navigation.getTopNode(this.targetBlock_)):this.targetBlock_.select()),t.utils.isRightButton(e)?this.handleRightClick(e):("touchstart"!=e.type.toLowerCase()&&"pointerdown"!=e.type.toLowerCase()||"mouse"==e.pointerType||t.longStart(e,this),this.mouseDownXY_=new t.utils.Coordinate(e.clientX,e.clientY),this.healStack_=e.altKey||e.ctrlKey||e.metaKey,this.bindMouseEvents(e)))},t.Gesture.prototype.bindMouseEvents=function(e){this.onMoveWrapper_=t.bindEventWithChecks_(document,"mousemove",null,this.handleMove.bind(this)),this.onUpWrapper_=t.bindEventWithChecks_(document,"mouseup",null,this.handleUp.bind(this)),e.preventDefault(),e.stopPropagation()},t.Gesture.prototype.handleMove=function(t){this.updateFromEvent_(t),this.isDraggingWorkspace_?this.workspaceDragger_.drag(this.currentDragDeltaXY_):this.isDraggingBlock_?this.blockDragger_.dragBlock(this.mostRecentEvent_,this.currentDragDeltaXY_):this.isDraggingBubble_&&this.bubbleDragger_.dragBubble(this.mostRecentEvent_,this.currentDragDeltaXY_),t.preventDefault(),t.stopPropagation()},t.Gesture.prototype.handleUp=function(e){this.updateFromEvent_(e),t.longStop_(),this.isEnding_?console.log("Trying to end a gesture recursively."):(this.isEnding_=!0,this.isDraggingBubble_?this.bubbleDragger_.endBubbleDrag(e,this.currentDragDeltaXY_):this.isDraggingBlock_?this.blockDragger_.endBlockDrag(e,this.currentDragDeltaXY_):this.isDraggingWorkspace_?this.workspaceDragger_.endDrag(this.currentDragDeltaXY_):this.isBubbleClick_()?this.doBubbleClick_():this.isFieldClick_()?this.doFieldClick_():this.isBlockClick_()?this.doBlockClick_():this.isWorkspaceClick_()&&this.doWorkspaceClick_(e),e.preventDefault(),e.stopPropagation(),this.dispose())},t.Gesture.prototype.cancel=function(){this.isEnding_||(t.longStop_(),this.isDraggingBubble_?this.bubbleDragger_.endBubbleDrag(this.mostRecentEvent_,this.currentDragDeltaXY_):this.isDraggingBlock_?this.blockDragger_.endBlockDrag(this.mostRecentEvent_,this.currentDragDeltaXY_):this.isDraggingWorkspace_&&this.workspaceDragger_.endDrag(this.currentDragDeltaXY_),this.dispose())},t.Gesture.prototype.handleRightClick=function(e){this.targetBlock_?(this.bringBlockToFront_(),t.hideChaff(!!this.flyout_),this.targetBlock_.showContextMenu(e)):this.startBubble_?this.startBubble_.showContextMenu(e):this.startWorkspace_&&!this.flyout_&&(t.hideChaff(),this.startWorkspace_.showContextMenu(e)),e.preventDefault(),e.stopPropagation(),this.dispose()},t.Gesture.prototype.handleWsStart=function(e,o){if(this.hasStarted_)throw Error("Tried to call gesture.handleWsStart, but the gesture had already been started.");this.setStartWorkspace_(o),this.mostRecentEvent_=e,this.doStart(e),this.startWorkspace_.keyboardAccessibilityMode&&t.navigation.setState(t.navigation.STATE_WS)},t.Gesture.prototype.handleFlyoutStart=function(t,e){if(this.hasStarted_)throw Error("Tried to call gesture.handleFlyoutStart, but the gesture had already been started.");this.setStartFlyout_(e),this.handleWsStart(t,e.getWorkspace())},t.Gesture.prototype.handleBlockStart=function(t,e){if(this.hasStarted_)throw Error("Tried to call gesture.handleBlockStart, but the gesture had already been started.");this.setStartBlock(e),this.mostRecentEvent_=t},t.Gesture.prototype.handleBubbleStart=function(t,e){if(this.hasStarted_)throw Error("Tried to call gesture.handleBubbleStart, but the gesture had already been started.");this.setStartBubble(e),this.mostRecentEvent_=t},t.Gesture.prototype.doBubbleClick_=function(){this.startBubble_.setFocus&&this.startBubble_.setFocus(),this.startBubble_.select&&this.startBubble_.select()},t.Gesture.prototype.doFieldClick_=function(){this.startField_.showEditor(this.mostRecentEvent_),this.bringBlockToFront_()},t.Gesture.prototype.doBlockClick_=function(){this.flyout_&&this.flyout_.autoClose?this.targetBlock_.isEnabled()&&(t.Events.getGroup()||t.Events.setGroup(!0),this.flyout_.createBlock(this.targetBlock_).scheduleSnapAndBump()):t.Events.fire(new t.Events.Ui(this.startBlock_,"click",void 0,void 0)),this.bringBlockToFront_(),t.Events.setGroup(!1)},t.Gesture.prototype.doWorkspaceClick_=function(e){var o=this.creatorWorkspace_;e.shiftKey&&o.keyboardAccessibilityMode?(e=new t.utils.Coordinate(e.clientX,e.clientY),e=t.utils.screenToWsCoordinates(o,e),e=t.ASTNode.createWorkspaceNode(o,e),o.getCursor().setCurNode(e)):t.selected&&t.selected.unselect()},t.Gesture.prototype.bringBlockToFront_=function(){this.targetBlock_&&!this.flyout_&&this.targetBlock_.bringToFront()},t.Gesture.prototype.setStartField=function(t){if(this.hasStarted_)throw Error("Tried to call gesture.setStartField, but the gesture had already been started.");this.startField_||(this.startField_=t)},t.Gesture.prototype.setStartBubble=function(t){this.startBubble_||(this.startBubble_=t)},t.Gesture.prototype.setStartBlock=function(t){this.startBlock_||this.startBubble_||(this.startBlock_=t,t.isInFlyout&&t!=t.getRootBlock()?this.setTargetBlock_(t.getRootBlock()):this.setTargetBlock_(t))},t.Gesture.prototype.setTargetBlock_=function(t){t.isShadow()?this.setTargetBlock_(t.getParent()):this.targetBlock_=t},t.Gesture.prototype.setStartWorkspace_=function(t){this.startWorkspace_||(this.startWorkspace_=t)},t.Gesture.prototype.setStartFlyout_=function(t){this.flyout_||(this.flyout_=t)},t.Gesture.prototype.isBubbleClick_=function(){return!!this.startBubble_&&!this.hasExceededDragRadius_},t.Gesture.prototype.isBlockClick_=function(){return!!this.startBlock_&&!this.hasExceededDragRadius_&&!this.isFieldClick_()},t.Gesture.prototype.isFieldClick_=function(){return!!this.startField_&&this.startField_.isClickable()&&!this.hasExceededDragRadius_&&(!this.flyout_||!this.flyout_.autoClose)},t.Gesture.prototype.isWorkspaceClick_=function(){return!(this.startBlock_||this.startBubble_||this.startField_||this.hasExceededDragRadius_)},t.Gesture.prototype.isDragging=function(){return this.isDraggingWorkspace_||this.isDraggingBlock_||this.isDraggingBubble_},t.Gesture.prototype.hasStarted=function(){return this.hasStarted_},t.Gesture.prototype.getInsertionMarkers=function(){return this.blockDragger_?this.blockDragger_.getInsertionMarkers():[]},t.Gesture.inProgress=function(){for(var e,o=t.Workspace.getAll(),i=0;e=o[i];i++)if(e.currentGesture_)return!0;return!1},t.Field=function(e,o,i){this.tooltip_=this.validator_=this.value_=null,this.size_=new t.utils.Size(0,0),this.constants_=this.mouseDownWrapper_=this.textContent_=this.textElement_=this.borderRect_=this.fieldGroup_=this.markerSvg_=this.cursorSvg_=null,i&&this.configure_(i),this.setValue(e),o&&this.setValidator(o)},t.Field.prototype.name=void 0,t.Field.prototype.disposed=!1,t.Field.prototype.maxDisplayLength=50,t.Field.prototype.sourceBlock_=null,t.Field.prototype.isDirty_=!0,t.Field.prototype.visible_=!0,t.Field.prototype.clickTarget_=null,t.Field.NBSP=" ",t.Field.prototype.EDITABLE=!0,t.Field.prototype.SERIALIZABLE=!1,t.Field.prototype.configure_=function(e){var o=e.tooltip;"string"==typeof o&&(o=t.utils.replaceMessageReferences(e.tooltip)),o&&this.setTooltip(o)},t.Field.prototype.setSourceBlock=function(t){if(this.sourceBlock_)throw Error("Field already bound to a block.");this.sourceBlock_=t},t.Field.prototype.getConstants=function(){return!this.constants_&&this.sourceBlock_&&this.sourceBlock_.workspace&&this.sourceBlock_.workspace.rendered&&(this.constants_=this.sourceBlock_.workspace.getRenderer().getConstants()),this.constants_},t.Field.prototype.getSourceBlock=function(){return this.sourceBlock_},t.Field.prototype.init=function(){this.fieldGroup_||(this.fieldGroup_=t.utils.dom.createSvgElement("g",{},null),this.isVisible()||(this.fieldGroup_.style.display="none"),this.sourceBlock_.getSvgRoot().appendChild(this.fieldGroup_),this.initView(),this.updateEditable(),this.setTooltip(this.tooltip_),this.bindEvents_(),this.initModel())},t.Field.prototype.initView=function(){this.createBorderRect_(),this.createTextElement_()},t.Field.prototype.initModel=function(){},t.Field.prototype.createBorderRect_=function(){this.borderRect_=t.utils.dom.createSvgElement("rect",{rx:this.getConstants().FIELD_BORDER_RECT_RADIUS,ry:this.getConstants().FIELD_BORDER_RECT_RADIUS,x:0,y:0,height:this.size_.height,width:this.size_.width,class:"blocklyFieldRect"},this.fieldGroup_)},t.Field.prototype.createTextElement_=function(){this.textElement_=t.utils.dom.createSvgElement("text",{class:"blocklyText"},this.fieldGroup_),this.getConstants().FIELD_TEXT_BASELINE_CENTER&&this.textElement_.setAttribute("dominant-baseline","central"),this.textContent_=document.createTextNode(""),this.textElement_.appendChild(this.textContent_)},t.Field.prototype.bindEvents_=function(){t.Tooltip.bindMouseEvents(this.getClickTarget_()),this.mouseDownWrapper_=t.bindEventWithChecks_(this.getClickTarget_(),"mousedown",this,this.onMouseDown_)},t.Field.prototype.fromXml=function(t){this.setValue(t.textContent)},t.Field.prototype.toXml=function(t){return t.textContent=this.getValue(),t},t.Field.prototype.dispose=function(){t.DropDownDiv.hideIfOwner(this),t.WidgetDiv.hideIfOwner(this),t.Tooltip.unbindMouseEvents(this.getClickTarget_()),this.mouseDownWrapper_&&t.unbindEvent_(this.mouseDownWrapper_),t.utils.dom.removeNode(this.fieldGroup_),this.disposed=!0},t.Field.prototype.updateEditable=function(){var e=this.fieldGroup_;this.EDITABLE&&e&&(this.sourceBlock_.isEditable()?(t.utils.dom.addClass(e,"blocklyEditableText"),t.utils.dom.removeClass(e,"blocklyNonEditableText"),e.style.cursor=this.CURSOR):(t.utils.dom.addClass(e,"blocklyNonEditableText"),t.utils.dom.removeClass(e,"blocklyEditableText"),e.style.cursor=""))},t.Field.prototype.isClickable=function(){return!!this.sourceBlock_&&this.sourceBlock_.isEditable()&&!!this.showEditor_&&"function"==typeof this.showEditor_},t.Field.prototype.isCurrentlyEditable=function(){return this.EDITABLE&&!!this.sourceBlock_&&this.sourceBlock_.isEditable()},t.Field.prototype.isSerializable=function(){var t=!1;return this.name&&(this.SERIALIZABLE?t=!0:this.EDITABLE&&(console.warn("Detected an editable field that was not serializable. Please define SERIALIZABLE property as true on all editable custom fields. Proceeding with serialization."),t=!0)),t},t.Field.prototype.isVisible=function(){return this.visible_},t.Field.prototype.setVisible=function(t){if(this.visible_!=t){this.visible_=t;var e=this.getSvgRoot();e&&(e.style.display=t?"block":"none")}},t.Field.prototype.setValidator=function(t){this.validator_=t},t.Field.prototype.getValidator=function(){return this.validator_},t.Field.prototype.classValidator=function(t){return t},t.Field.prototype.callValidator=function(t){var e=this.classValidator(t);if(null===e)return null;if(void 0!==e&&(t=e),e=this.getValidator()){if(null===(e=e.call(this,t)))return null;void 0!==e&&(t=e)}return t},t.Field.prototype.getSvgRoot=function(){return this.fieldGroup_},t.Field.prototype.applyColour=function(){},t.Field.prototype.render_=function(){this.textContent_&&(this.textContent_.nodeValue=this.getDisplayText_()),this.updateSize_()},t.Field.prototype.showEditor=function(t){this.isClickable()&&this.showEditor_(t)},t.Field.prototype.updateWidth=function(){console.warn("Deprecated call to updateWidth, call Blockly.Field.updateSize_ to force an update to the size of the field, or Blockly.utils.dom.getTextWidth() to check the size of the field."),this.updateSize_()},t.Field.prototype.updateSize_=function(e){var o=this.getConstants(),i=2*(e=null!=e?e:this.borderRect_?this.getConstants().FIELD_BORDER_RECT_X_PADDING:0),n=o.FIELD_TEXT_HEIGHT,s=0;this.textElement_&&(i+=s=t.utils.dom.getFastTextWidth(this.textElement_,o.FIELD_TEXT_FONTSIZE,o.FIELD_TEXT_FONTWEIGHT,o.FIELD_TEXT_FONTFAMILY)),this.borderRect_&&(n=Math.max(n,o.FIELD_BORDER_RECT_HEIGHT)),this.size_.height=n,this.size_.width=i,this.positionTextElement_(e,s),this.positionBorderRect_()},t.Field.prototype.positionTextElement_=function(t,e){if(this.textElement_){var o=this.getConstants(),i=this.size_.height/2;this.textElement_.setAttribute("x",this.sourceBlock_.RTL?this.size_.width-e-t:t),this.textElement_.setAttribute("y",o.FIELD_TEXT_BASELINE_CENTER?i:i-o.FIELD_TEXT_HEIGHT/2+o.FIELD_TEXT_BASELINE)}},t.Field.prototype.positionBorderRect_=function(){this.borderRect_&&(this.borderRect_.setAttribute("width",this.size_.width),this.borderRect_.setAttribute("height",this.size_.height),this.borderRect_.setAttribute("rx",this.getConstants().FIELD_BORDER_RECT_RADIUS),this.borderRect_.setAttribute("ry",this.getConstants().FIELD_BORDER_RECT_RADIUS))},t.Field.prototype.getSize=function(){return this.isVisible()?(this.isDirty_?(this.render_(),this.isDirty_=!1):this.visible_&&0==this.size_.width&&(console.warn("Deprecated use of setting size_.width to 0 to rerender a field. Set field.isDirty_ to true instead."),this.render_()),this.size_):new t.utils.Size(0,0)},t.Field.prototype.getScaledBBox=function(){if(this.borderRect_)e=this.borderRect_.getBoundingClientRect(),i=t.utils.style.getPageOffset(this.borderRect_),n=e.width,e=e.height;else{var e=this.sourceBlock_.getHeightWidth(),o=this.sourceBlock_.workspace.scale,i=this.getAbsoluteXY_(),n=e.width*o;e=e.height*o,t.utils.userAgent.GECKO?(i.x+=1.5*o,i.y+=1.5*o):t.utils.userAgent.EDGE||t.utils.userAgent.IE||(i.x-=.5*o,i.y-=.5*o),n+=1*o,e+=1*o}return{top:i.y,bottom:i.y+e,left:i.x,right:i.x+n}},t.Field.prototype.getDisplayText_=function(){var e=this.getText();return e?(e.length>this.maxDisplayLength&&(e=e.substring(0,this.maxDisplayLength-2)+"…"),e=e.replace(/\s/g,t.Field.NBSP),this.sourceBlock_&&this.sourceBlock_.RTL&&(e+="‏"),e):t.Field.NBSP},t.Field.prototype.getText=function(){if(this.getText_){var t=this.getText_.call(this);if(null!==t)return String(t)}return String(this.getValue())},t.Field.prototype.setText=function(t){throw Error("setText method is deprecated")},t.Field.prototype.markDirty=function(){this.isDirty_=!0,this.constants_=null},t.Field.prototype.forceRerender=function(){this.isDirty_=!0,this.sourceBlock_&&this.sourceBlock_.rendered&&(this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours(),this.updateMarkers_())},t.Field.prototype.setValue=function(e){if(null!==e){var o=this.doClassValidation_(e);if(!((e=this.processValidation_(e,o))instanceof Error)){if((o=this.getValidator())&&(o=o.call(this,e),(e=this.processValidation_(e,o))instanceof Error))return;(o=this.getValue())!==e&&(this.sourceBlock_&&t.Events.isEnabled()&&t.Events.fire(new t.Events.BlockChange(this.sourceBlock_,"field",this.name||null,o,e)),this.doValueUpdate_(e),this.isDirty_&&this.forceRerender())}}},t.Field.prototype.processValidation_=function(t,e){return null===e?(this.doValueInvalid_(t),this.isDirty_&&this.forceRerender(),Error()):(void 0!==e&&(t=e),t)},t.Field.prototype.getValue=function(){return this.value_},t.Field.prototype.doClassValidation_=function(t){return null==t?null:t=this.classValidator(t)},t.Field.prototype.doValueUpdate_=function(t){this.value_=t,this.isDirty_=!0},t.Field.prototype.doValueInvalid_=function(t){},t.Field.prototype.onMouseDown_=function(t){this.sourceBlock_&&this.sourceBlock_.workspace&&(t=this.sourceBlock_.workspace.getGesture(t))&&t.setStartField(this)},t.Field.prototype.setTooltip=function(t){var e=this.getClickTarget_();e?e.tooltip=t||""===t?t:this.sourceBlock_:this.tooltip_=t},t.Field.prototype.getClickTarget_=function(){return this.clickTarget_||this.getSvgRoot()},t.Field.prototype.getAbsoluteXY_=function(){return t.utils.style.getPageOffset(this.getClickTarget_())},t.Field.prototype.referencesVariables=function(){return!1},t.Field.prototype.getParentInput=function(){for(var t=null,e=this.sourceBlock_,o=e.inputList,i=0;ie||e>this.fieldRow.length)throw Error("index "+e+" out of bounds.");return o||""==o&&i?("string"==typeof o&&(o=new t.FieldLabel(o)),o.setSourceBlock(this.sourceBlock_),this.sourceBlock_.rendered&&o.init(),o.name=i,o.prefixField&&(e=this.insertFieldAt(e,o.prefixField)),this.fieldRow.splice(e,0,o),++e,o.suffixField&&(e=this.insertFieldAt(e,o.suffixField)),this.sourceBlock_.rendered&&(this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours()),e):e},t.Input.prototype.removeField=function(t){for(var e,o=0;e=this.fieldRow[o];o++)if(e.name===t)return e.dispose(),this.fieldRow.splice(o,1),void(this.sourceBlock_.rendered&&(this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours()));throw Error('Field "%s" not found.',t)},t.Input.prototype.isVisible=function(){return this.visible_},t.Input.prototype.setVisible=function(t){var e=[];if(this.visible_==t)return e;for(var o,i=(this.visible_=t)?"block":"none",n=0;o=this.fieldRow[n];n++)o.setVisible(t);return this.connection&&(t?e=this.connection.startTrackingAll():this.connection.stopTrackingAll(),n=this.connection.targetBlock())&&(n.getSvgRoot().style.display=i,t||(n.rendered=!1)),e},t.Input.prototype.markDirty=function(){for(var t,e=0;t=this.fieldRow[e];e++)t.markDirty()},t.Input.prototype.setCheck=function(t){if(!this.connection)throw Error("This input does not have a connection.");return this.connection.setCheck(t),this},t.Input.prototype.setAlign=function(t){return this.align=t,this.sourceBlock_.rendered&&this.sourceBlock_.render(),this},t.Input.prototype.init=function(){if(this.sourceBlock_.workspace.rendered)for(var t=0;tt&&(o=o.substring(0,t-3)+"..."),o},t.Block.prototype.appendValueInput=function(e){return this.appendInput_(t.INPUT_VALUE,e)},t.Block.prototype.appendStatementInput=function(e){return this.appendInput_(t.NEXT_STATEMENT,e)},t.Block.prototype.appendDummyInput=function(e){return this.appendInput_(t.DUMMY_INPUT,e||"")},t.Block.prototype.jsonInit=function(e){var o=e.type?'Block "'+e.type+'": ':"";if(e.output&&e.previousStatement)throw Error(o+"Must not have both an output and a previousStatement.");if(e.style&&e.style.hat&&(this.hat=e.style.hat,e.style=null),e.style&&e.colour)throw Error(o+"Must not have both a colour and a style.");e.style?this.jsonInitStyle_(e,o):this.jsonInitColour_(e,o);for(var i=0;void 0!==e["message"+i];)this.interpolate_(e["message"+i],e["args"+i]||[],e["lastDummyAlign"+i],o),i++;if(void 0!==e.inputsInline&&this.setInputsInline(e.inputsInline),void 0!==e.output&&this.setOutput(!0,e.output),void 0!==e.outputShape&&this.setOutputShape(e.outputShape),void 0!==e.previousStatement&&this.setPreviousStatement(!0,e.previousStatement),void 0!==e.nextStatement&&this.setNextStatement(!0,e.nextStatement),void 0!==e.tooltip&&(i=e.tooltip,i=t.utils.replaceMessageReferences(i),this.setTooltip(i)),void 0!==e.enableContextMenu&&(i=e.enableContextMenu,this.contextMenu=!!i),void 0!==e.helpUrl&&(i=e.helpUrl,i=t.utils.replaceMessageReferences(i),this.setHelpUrl(i)),"string"==typeof e.extensions&&(console.warn(o+"JSON attribute 'extensions' should be an array of strings. Found raw string in JSON for '"+e.type+"' block."),e.extensions=[e.extensions]),void 0!==e.mutator&&t.Extensions.apply(e.mutator,this,!0),Array.isArray(e.extensions))for(e=e.extensions,o=0;o=c||c>o.length)throw Error('Block "'+this.type+'": Message index %'+c+" out of range.");if(r[c])throw Error('Block "'+this.type+'": Message index %'+c+" duplicated.");r[c]=!0,a++,e.push(o[c-1])}else(c=c.trim())&&e.push(c)}if(a!=o.length)throw Error('Block "'+this.type+'": Message does not reference all '+o.length+" arg(s).");for(e.length&&("string"==typeof e[e.length-1]||t.utils.string.startsWith(e[e.length-1].type,"field_"))&&(l={type:"input_dummy"},i&&(l.align=i),e.push(l)),i={LEFT:t.ALIGN_LEFT,RIGHT:t.ALIGN_RIGHT,CENTRE:t.ALIGN_CENTRE,CENTER:t.ALIGN_CENTRE},o=[],l=0;l=this.inputList.length)throw RangeError("Input index "+t+" out of bounds.");if(e>this.inputList.length)throw RangeError("Reference input "+e+" out of bounds.");var o=this.inputList[t];this.inputList.splice(t,1),t--t?e-1:t}),this.highlightedIndex_)},t.Menu.prototype.highlightHelper=function(t,e){e=0>e?-1:e;var o=this.getChildCount();e=t.call(this,e,o);for(var i=0;i<=o;){var n=this.getChildAt(e);if(n&&this.canHighlightItem(n))return this.setHighlightedIndex(e),!0;i++,e=t.call(this,e,o)}return!1},t.Menu.prototype.canHighlightItem=function(t){return t.isEnabled()},t.Menu.prototype.handleMouseOver_=function(t){(t=this.getMenuItem(t.target))&&(t.isEnabled()?this.getHighlighted()!==t&&(this.unhighlightCurrent(),this.setHighlighted(t)):this.unhighlightCurrent())},t.Menu.prototype.handleClick_=function(e){var o=this.openingCoords;if(this.openingCoords=null,o&&"number"==typeof e.clientX){var i=new t.utils.Coordinate(e.clientX,e.clientY);if(1>t.utils.Coordinate.distance(o,i))return}(o=this.getMenuItem(e.target))&&o.handleClick(e)&&e.preventDefault()},t.Menu.prototype.handleMouseEnter_=function(t){this.focus()},t.Menu.prototype.handleMouseLeave_=function(t){this.getElement()&&(this.blur(),this.clearHighlighted())},t.Menu.prototype.handleKeyEvent=function(t){return!(0==this.getChildCount()||!this.handleKeyEventInternal(t)||(t.preventDefault(),t.stopPropagation(),0))},t.Menu.prototype.handleKeyEventInternal=function(e){var o=this.getHighlighted();if(o&&"function"==typeof o.handleKeyEvent&&o.handleKeyEvent(e))return!0;if(e.shiftKey||e.ctrlKey||e.metaKey||e.altKey)return!1;switch(e.keyCode){case t.utils.KeyCodes.ENTER:o&&o.performActionInternal(e);break;case t.utils.KeyCodes.UP:this.highlightPrevious();break;case t.utils.KeyCodes.DOWN:this.highlightNext();break;default:return!1}return!0},t.MenuItem=function(e,o){t.Component.call(this),this.setContentInternal(e),this.setValue(o),this.enabled_=!0},t.utils.object.inherits(t.MenuItem,t.Component),t.MenuItem.prototype.createDom=function(){var e=document.createElement("div");e.id=this.getId(),this.setElementInternal(e),e.className="goog-menuitem goog-option "+(this.enabled_?"":"goog-menuitem-disabled ")+(this.checked_?"goog-option-selected ":"")+(this.rightToLeft_?"goog-menuitem-rtl ":"");var o=this.getContentWrapperDom();e.appendChild(o);var i=this.getCheckboxDom();i&&o.appendChild(i),o.appendChild(this.getContentDom()),t.utils.aria.setRole(e,this.roleName_||(this.checkable_?t.utils.aria.Role.MENUITEMCHECKBOX:t.utils.aria.Role.MENUITEM)),t.utils.aria.setState(e,t.utils.aria.State.SELECTED,this.checkable_&&this.checked_||!1)},t.MenuItem.prototype.getCheckboxDom=function(){if(!this.checkable_)return null;var t=document.createElement("div");return t.className="goog-menuitem-checkbox",t},t.MenuItem.prototype.getContentDom=function(){var t=this.content_;return"string"==typeof t&&(t=document.createTextNode(t)),t},t.MenuItem.prototype.getContentWrapperDom=function(){var t=document.createElement("div");return t.className="goog-menuitem-content",t},t.MenuItem.prototype.setContentInternal=function(t){this.content_=t},t.MenuItem.prototype.setValue=function(t){this.value_=t},t.MenuItem.prototype.getValue=function(){return this.value_},t.MenuItem.prototype.setRole=function(t){this.roleName_=t},t.MenuItem.prototype.setCheckable=function(t){this.checkable_=t},t.MenuItem.prototype.setChecked=function(e){if(this.checkable_){this.checked_=e;var o=this.getElement();o&&this.isEnabled()&&(e?(t.utils.dom.addClass(o,"goog-option-selected"),t.utils.aria.setState(o,t.utils.aria.State.SELECTED,!0)):(t.utils.dom.removeClass(o,"goog-option-selected"),t.utils.aria.setState(o,t.utils.aria.State.SELECTED,!1)))}},t.MenuItem.prototype.setHighlighted=function(e){this.highlight_=e;var o=this.getElement();o&&this.isEnabled()&&(e?t.utils.dom.addClass(o,"goog-menuitem-highlight"):t.utils.dom.removeClass(o,"goog-menuitem-highlight"))},t.MenuItem.prototype.isEnabled=function(){return this.enabled_},t.MenuItem.prototype.setEnabled=function(e){this.enabled_=e,(e=this.getElement())&&(this.enabled_?t.utils.dom.removeClass(e,"goog-menuitem-disabled"):t.utils.dom.addClass(e,"goog-menuitem-disabled"))},t.MenuItem.prototype.handleClick=function(t){this.isEnabled()&&(this.setHighlighted(!0),this.performActionInternal())},t.MenuItem.prototype.performActionInternal=function(){this.checkable_&&this.setChecked(!this.checked_),this.actionHandler_&&this.actionHandler_.call(this.actionHandlerObj_,this)},t.MenuItem.prototype.onAction=function(t,e){this.actionHandler_=t,this.actionHandlerObj_=e},t.utils.uiMenu={},t.utils.uiMenu.getSize=function(e){e=e.getElement();var o=t.utils.style.getSize(e);return o.height=e.scrollHeight,o},t.utils.uiMenu.adjustBBoxesForRTL=function(t,e,o){e.left+=o.width,e.right+=o.width,t.left+=o.width,t.right+=o.width},t.ContextMenu={},t.ContextMenu.currentBlock=null,t.ContextMenu.eventWrapper_=null,t.ContextMenu.show=function(e,o,i){if(t.WidgetDiv.show(t.ContextMenu,i,null),o.length){var n=t.ContextMenu.populate_(o,i);t.ContextMenu.position_(n,e,i),setTimeout((function(){n.getElement().focus()}),1),t.ContextMenu.currentBlock=null}else t.ContextMenu.hide()},t.ContextMenu.populate_=function(e,o){var i=new t.Menu;i.setRightToLeft(o);for(var n,s=0;n=e[s];s++){var r=new t.MenuItem(n.text);r.setRightToLeft(o),i.addChild(r,!0),r.setEnabled(n.enabled),n.enabled&&r.onAction((function(){t.ContextMenu.hide(),this.callback()}),n)}return i},t.ContextMenu.position_=function(e,o,i){var n=t.utils.getViewportBBox();o={top:o.clientY+n.top,bottom:o.clientY+n.top,left:o.clientX+n.left,right:o.clientX+n.left},t.ContextMenu.createWidget_(e);var s=t.utils.uiMenu.getSize(e);i&&t.utils.uiMenu.adjustBBoxesForRTL(n,o,s),t.WidgetDiv.positionWithAnchor(n,o,s,i),e.getElement().focus()},t.ContextMenu.createWidget_=function(e){e.render(t.WidgetDiv.DIV);var o=e.getElement();t.utils.dom.addClass(o,"blocklyContextMenu"),t.bindEventWithChecks_(o,"contextmenu",null,t.utils.noEvent),e.focus()},t.ContextMenu.hide=function(){t.WidgetDiv.hideIfOwner(t.ContextMenu),t.ContextMenu.currentBlock=null,t.ContextMenu.eventWrapper_&&(t.unbindEvent_(t.ContextMenu.eventWrapper_),t.ContextMenu.eventWrapper_=null)},t.ContextMenu.callbackFactory=function(e,o){return function(){t.Events.disable();try{var i=t.Xml.domToBlock(o,e.workspace),n=e.getRelativeToSurfaceXY();n.x=e.RTL?n.x-t.SNAP_RADIUS:n.x+t.SNAP_RADIUS,n.y+=2*t.SNAP_RADIUS,i.moveBy(n.x,n.y)}finally{t.Events.enable()}t.Events.isEnabled()&&!i.isShadow()&&t.Events.fire(new t.Events.BlockCreate(i)),i.select()}},t.ContextMenu.blockDeleteOption=function(e){var o=e.getDescendants(!1).length,i=e.getNextBlock();return i&&(o-=i.getDescendants(!1).length),{text:1==o?t.Msg.DELETE_BLOCK:t.Msg.DELETE_X_BLOCKS.replace("%1",String(o)),enabled:!0,callback:function(){t.Events.setGroup(!0),e.dispose(!0,!0),t.Events.setGroup(!1)}}},t.ContextMenu.blockHelpOption=function(e){return{enabled:!("function"==typeof e.helpUrl?!e.helpUrl():!e.helpUrl),text:t.Msg.HELP,callback:function(){e.showHelp()}}},t.ContextMenu.blockDuplicateOption=function(e){var o=e.isDuplicatable();return{text:t.Msg.DUPLICATE_BLOCK,enabled:o,callback:function(){t.duplicate(e)}}},t.ContextMenu.blockCommentOption=function(e){var o={enabled:!t.utils.userAgent.IE};return e.getCommentIcon()?(o.text=t.Msg.REMOVE_COMMENT,o.callback=function(){e.setCommentText(null)}):(o.text=t.Msg.ADD_COMMENT,o.callback=function(){e.setCommentText("")}),o},t.ContextMenu.commentDeleteOption=function(e){return{text:t.Msg.REMOVE_COMMENT,enabled:!0,callback:function(){t.Events.setGroup(!0),e.dispose(!0,!0),t.Events.setGroup(!1)}}},t.ContextMenu.commentDuplicateOption=function(e){return{text:t.Msg.DUPLICATE_COMMENT,enabled:!0,callback:function(){t.duplicate(e)}}},t.ContextMenu.workspaceCommentOption=function(e,o){if(!t.WorkspaceCommentSvg)throw Error("Missing require for Blockly.WorkspaceCommentSvg");var i={enabled:!t.utils.userAgent.IE};return i.text=t.Msg.ADD_COMMENT,i.callback=function(){var i=new t.WorkspaceCommentSvg(e,t.Msg.WORKSPACE_COMMENT_DEFAULT_TEXT,t.WorkspaceCommentSvg.DEFAULT_SIZE,t.WorkspaceCommentSvg.DEFAULT_SIZE),n=e.getInjectionDiv().getBoundingClientRect();n=new t.utils.Coordinate(o.clientX-n.left,o.clientY-n.top);var s=e.getOriginOffsetInPixels();(n=t.utils.Coordinate.difference(n,s)).scale(1/e.scale),i.moveBy(n.x,n.y),e.rendered&&(i.initSvg(),i.render(),i.select())},i},t.RenderedConnection=function(e,o){t.RenderedConnection.superClass_.constructor.call(this,e,o),this.db_=e.workspace.connectionDBList[o],this.dbOpposite_=e.workspace.connectionDBList[t.OPPOSITE_TYPE[o]],this.offsetInBlock_=new t.utils.Coordinate(0,0),this.trackedState_=t.RenderedConnection.TrackedState.WILL_TRACK},t.utils.object.inherits(t.RenderedConnection,t.Connection),t.RenderedConnection.TrackedState={WILL_TRACK:-1,UNTRACKED:0,TRACKED:1},t.RenderedConnection.prototype.dispose=function(){t.RenderedConnection.superClass_.dispose.call(this),this.trackedState_==t.RenderedConnection.TrackedState.TRACKED&&this.db_.removeConnection(this,this.y)},t.RenderedConnection.prototype.getSourceBlock=function(){return t.RenderedConnection.superClass_.getSourceBlock.call(this)},t.RenderedConnection.prototype.targetBlock=function(){return t.RenderedConnection.superClass_.targetBlock.call(this)},t.RenderedConnection.prototype.distanceFrom=function(t){var e=this.x-t.x;return t=this.y-t.y,Math.sqrt(e*e+t*t)},t.RenderedConnection.prototype.bumpAwayFrom=function(e){if(!this.sourceBlock_.workspace.isDragging()){var o=this.sourceBlock_.getRootBlock();if(!o.isInFlyout){var i=!1;if(!o.isMovable()){if(!(o=e.getSourceBlock().getRootBlock()).isMovable())return;e=this,i=!0}var n=t.selected==o;n||o.addSelect();var s=e.x+t.SNAP_RADIUS+Math.floor(Math.random()*t.BUMP_RANDOMNESS)-this.x,r=e.y+t.SNAP_RADIUS+Math.floor(Math.random()*t.BUMP_RANDOMNESS)-this.y;i&&(r=-r),o.RTL&&(s=e.x-t.SNAP_RADIUS-Math.floor(Math.random()*t.BUMP_RANDOMNESS)-this.x),o.moveBy(s,r),n||o.removeSelect()}}},t.RenderedConnection.prototype.moveTo=function(e,o){this.trackedState_==t.RenderedConnection.TrackedState.WILL_TRACK?(this.db_.addConnection(this,o),this.trackedState_=t.RenderedConnection.TrackedState.TRACKED):this.trackedState_==t.RenderedConnection.TrackedState.TRACKED&&(this.db_.removeConnection(this,this.y),this.db_.addConnection(this,o)),this.x=e,this.y=o},t.RenderedConnection.prototype.moveBy=function(t,e){this.moveTo(this.x+t,this.y+e)},t.RenderedConnection.prototype.moveToOffset=function(t){this.moveTo(t.x+this.offsetInBlock_.x,t.y+this.offsetInBlock_.y)},t.RenderedConnection.prototype.setOffsetInBlock=function(t,e){this.offsetInBlock_.x=t,this.offsetInBlock_.y=e},t.RenderedConnection.prototype.getOffsetInBlock=function(){return this.offsetInBlock_},t.RenderedConnection.prototype.tighten=function(){var e=this.targetConnection.x-this.x,o=this.targetConnection.y-this.y;if(0!=e||0!=o){var i=this.targetBlock(),n=i.getSvgRoot();if(!n)throw Error("block is not rendered.");n=t.utils.getRelativeXY(n),i.getSvgRoot().setAttribute("transform","translate("+(n.x-e)+","+(n.y-o)+")"),i.moveConnections(-e,-o)}},t.RenderedConnection.prototype.closest=function(t,e){return this.dbOpposite_.searchForClosest(this,t,e)},t.RenderedConnection.prototype.highlight=function(){var e=this.sourceBlock_.workspace.getRenderer().getConstants(),o=e.shapeFor(this);this.type==t.INPUT_VALUE||this.type==t.OUTPUT_VALUE?(e=e.TAB_OFFSET_FROM_TOP,o=t.utils.svgPaths.moveBy(0,-e)+t.utils.svgPaths.lineOnAxis("v",e)+o.pathDown+t.utils.svgPaths.lineOnAxis("v",e)):(e=e.NOTCH_OFFSET_LEFT-e.CORNER_RADIUS,o=t.utils.svgPaths.moveBy(-e,0)+t.utils.svgPaths.lineOnAxis("h",e)+o.pathLeft+t.utils.svgPaths.lineOnAxis("h",e)),e=this.sourceBlock_.getRelativeToSurfaceXY(),t.Connection.highlightedPath_=t.utils.dom.createSvgElement("path",{class:"blocklyHighlightedConnectionPath",d:o,transform:"translate("+(this.x-e.x)+","+(this.y-e.y)+")"+(this.sourceBlock_.RTL?" scale(-1 1)":"")},this.sourceBlock_.getSvgRoot())},t.RenderedConnection.prototype.unhighlight=function(){t.utils.dom.removeNode(t.Connection.highlightedPath_),delete t.Connection.highlightedPath_},t.RenderedConnection.prototype.setTracking=function(e){e&&this.trackedState_==t.RenderedConnection.TrackedState.TRACKED||!e&&this.trackedState_==t.RenderedConnection.TrackedState.UNTRACKED||this.sourceBlock_.isInFlyout||(e?(this.db_.addConnection(this,this.y),this.trackedState_=t.RenderedConnection.TrackedState.TRACKED):(this.trackedState_==t.RenderedConnection.TrackedState.TRACKED&&this.db_.removeConnection(this,this.y),this.trackedState_=t.RenderedConnection.TrackedState.UNTRACKED))},t.RenderedConnection.prototype.stopTrackingAll=function(){if(this.setTracking(!1),this.targetConnection)for(var t=this.targetBlock().getDescendants(!1),e=0;eo)&&t.RenderedConnection.superClass_.isConnectionAllowed.call(this,e)},t.RenderedConnection.prototype.onFailedConnect=function(t){this.bumpAwayFrom(t)},t.RenderedConnection.prototype.disconnectInternal_=function(e,o){t.RenderedConnection.superClass_.disconnectInternal_.call(this,e,o),e.rendered&&e.render(),o.rendered&&(o.updateDisabled(),o.render())},t.RenderedConnection.prototype.respawnShadow_=function(){var e=this.getSourceBlock(),o=this.getShadowDom();if(e.workspace&&o&&t.Events.recordUndo){if(t.RenderedConnection.superClass_.respawnShadow_.call(this),!(o=this.targetBlock()))throw Error("Couldn't respawn the shadow block that should exist here.");o.initSvg(),o.render(!1),e.rendered&&e.render()}},t.RenderedConnection.prototype.neighbours=function(t){return this.dbOpposite_.getNeighbours(this,t)},t.RenderedConnection.prototype.connect_=function(e){t.RenderedConnection.superClass_.connect_.call(this,e);var o=this.getSourceBlock();e=e.getSourceBlock(),o.rendered&&o.updateDisabled(),e.rendered&&e.updateDisabled(),o.rendered&&e.rendered&&(this.type==t.NEXT_STATEMENT||this.type==t.PREVIOUS_STATEMENT?e.render():o.render())},t.RenderedConnection.prototype.onCheckChanged_=function(){!this.isConnected()||this.targetConnection&&this.checkType(this.targetConnection)||((this.isSuperior()?this.targetBlock():this.sourceBlock_).unplug(),this.sourceBlock_.bumpNeighbours())},t.Marker=function(){this.drawer_=this.curNode_=this.colour=null,this.type="marker"},t.Marker.prototype.setDrawer=function(t){this.drawer_=t},t.Marker.prototype.getDrawer=function(){return this.drawer_},t.Marker.prototype.getCurNode=function(){return this.curNode_},t.Marker.prototype.setCurNode=function(t){var e=this.curNode_;this.curNode_=t,this.drawer_&&this.drawer_.draw(e,this.curNode_)},t.Marker.prototype.draw=function(){this.drawer_&&this.drawer_.draw(this.curNode_,this.curNode_)},t.Marker.prototype.hide=function(){this.drawer_&&this.drawer_.hide()},t.Marker.prototype.dispose=function(){this.getDrawer()&&this.getDrawer().dispose()},t.Cursor=function(){t.Cursor.superClass_.constructor.call(this),this.type="cursor"},t.utils.object.inherits(t.Cursor,t.Marker),t.Cursor.prototype.next=function(){var e=this.getCurNode();if(!e)return null;for(e=e.next();e&&e.next()&&(e.getType()==t.ASTNode.types.NEXT||e.getType()==t.ASTNode.types.BLOCK);)e=e.next();return e&&this.setCurNode(e),e},t.Cursor.prototype.in=function(){var e=this.getCurNode();return e?(e.getType()!=t.ASTNode.types.PREVIOUS&&e.getType()!=t.ASTNode.types.OUTPUT||(e=e.next()),(e=e.in())&&this.setCurNode(e),e):null},t.Cursor.prototype.prev=function(){var e=this.getCurNode();if(!e)return null;for(e=e.prev();e&&e.prev()&&(e.getType()==t.ASTNode.types.NEXT||e.getType()==t.ASTNode.types.BLOCK);)e=e.prev();return e&&this.setCurNode(e),e},t.Cursor.prototype.out=function(){var e=this.getCurNode();return e?((e=e.out())&&e.getType()==t.ASTNode.types.BLOCK&&(e=e.prev()||e),e&&this.setCurNode(e),e):null},t.Cursor.prototype.onBlocklyAction=function(e){if(this.getCurNode()&&this.getCurNode().getType()===t.ASTNode.types.FIELD&&this.getCurNode().getLocation().onBlocklyAction(e))return!0;switch(e.name){case t.navigation.actionNames.PREVIOUS:return this.prev(),!0;case t.navigation.actionNames.OUT:return this.out(),!0;case t.navigation.actionNames.NEXT:return this.next(),!0;case t.navigation.actionNames.IN:return this.in(),!0;default:return!1}},t.BasicCursor=function(){t.BasicCursor.superClass_.constructor.call(this)},t.utils.object.inherits(t.BasicCursor,t.Cursor),t.BasicCursor.prototype.next=function(){var t=this.getCurNode();return t?((t=this.getNextNode_(t,this.validNode_))&&this.setCurNode(t),t):null},t.BasicCursor.prototype.in=function(){return this.next()},t.BasicCursor.prototype.prev=function(){var t=this.getCurNode();return t?((t=this.getPreviousNode_(t,this.validNode_))&&this.setCurNode(t),t):null},t.BasicCursor.prototype.out=function(){return this.prev()},t.BasicCursor.prototype.getNextNode_=function(t,e){if(!t)return null;var o=t.in()||t.next();return e(o)?o:o?this.getNextNode_(o,e):e(t=this.findSiblingOrParent_(t.out()))?t:t?this.getNextNode_(t,e):null},t.BasicCursor.prototype.getPreviousNode_=function(t,e){if(!t)return null;var o=t.prev();return e(o=o?this.getRightMostChild_(o):t.out())?o:o?this.getPreviousNode_(o,e):null},t.BasicCursor.prototype.validNode_=function(e){var o=!1;return(e=e&&e.getType())!=t.ASTNode.types.OUTPUT&&e!=t.ASTNode.types.INPUT&&e!=t.ASTNode.types.FIELD&&e!=t.ASTNode.types.NEXT&&e!=t.ASTNode.types.PREVIOUS&&e!=t.ASTNode.types.WORKSPACE||(o=!0),o},t.BasicCursor.prototype.findSiblingOrParent_=function(t){if(!t)return null;var e=t.next();return e||this.findSiblingOrParent_(t.out())},t.BasicCursor.prototype.getRightMostChild_=function(t){if(!t.in())return t;for(t=t.in();t.next();)t=t.next();return this.getRightMostChild_(t)},t.TabNavigateCursor=function(){t.TabNavigateCursor.superClass_.constructor.call(this)},t.utils.object.inherits(t.TabNavigateCursor,t.BasicCursor),t.TabNavigateCursor.prototype.validNode_=function(e){var o=!1,i=e&&e.getType();return e&&(e=e.getLocation(),i==t.ASTNode.types.FIELD&&e&&e.isTabNavigable()&&e.isClickable()&&(o=!0)),o},t.utils.Rect=function(t,e,o,i){this.top=t,this.bottom=e,this.left=o,this.right=i},t.utils.Rect.prototype.contains=function(t,e){return t>=this.left&&t<=this.right&&e>=this.top&&e<=this.bottom},t.BlockSvg=function(e,o,i){this.svgGroup_=t.utils.dom.createSvgElement("g",{},null),this.svgGroup_.translate_="",this.style=e.getRenderer().getConstants().getBlockStyle(null),this.pathObject=e.getRenderer().makePathObject(this.svgGroup_,this.style),this.rendered=!1,this.workspace=e,this.previousConnection=this.nextConnection=this.outputConnection=null,this.useDragSurface_=t.utils.is3dSupported()&&!!e.getBlockDragSurface();var n=this.pathObject.svgPath;n.tooltip=this,t.Tooltip.bindMouseEvents(n),t.BlockSvg.superClass_.constructor.call(this,e,o,i),this.svgGroup_.dataset&&(this.svgGroup_.dataset.id=this.id)},t.utils.object.inherits(t.BlockSvg,t.Block),t.BlockSvg.prototype.height=0,t.BlockSvg.prototype.width=0,t.BlockSvg.prototype.dragStartXY_=null,t.BlockSvg.prototype.warningTextDb_=null,t.BlockSvg.INLINE=-1,t.BlockSvg.COLLAPSED_WARNING_ID="TEMP_COLLAPSED_WARNING_",t.BlockSvg.prototype.initSvg=function(){if(!this.workspace.rendered)throw TypeError("Workspace is headless.");for(var e,o=0;e=this.inputList[o];o++)e.init();for(e=this.getIcons(),o=0;o=this.connections_.length)return-1;e=t.y;for(var i=o;0<=i&&this.connections_[i].y==e;){if(this.connections_[i]==t)return i;i--}for(;ot)){e=i;break}o=i}}return e},t.ConnectionDB.prototype.removeConnection=function(t,e){if(-1==(t=this.findIndexOfConnection_(t,e)))throw Error("Unable to find connection in connectionDB.");this.connections_.splice(t,1)},t.ConnectionDB.prototype.getNeighbours=function(t,e){function o(t){var o=n-i[t].x,r=s-i[t].y;return Math.sqrt(o*o+r*r)<=e&&l.push(i[t]),r(t=this.subscribedWorkspaces_.indexOf(t)))throw Error("Cannot unsubscribe a workspace that hasn't been subscribed.");this.subscribedWorkspaces_.splice(t,1)},t.ThemeManager.prototype.subscribe=function(t,e,o){this.componentDB_[e]||(this.componentDB_[e]=[]),this.componentDB_[e].push({element:t,propertyName:o}),e=this.theme_&&this.theme_.getComponentStyle(e),t.style[o]=e||""},t.ThemeManager.prototype.unsubscribe=function(t){if(t)for(var e,o=Object.keys(this.componentDB_),i=0;e=o[i];i++){for(var n=this.componentDB_[e],s=n.length-1;0<=s;s--)n[s].element===t&&n.splice(s,1);this.componentDB_[e].length||delete this.componentDB_[e]}},t.ThemeManager.prototype.dispose=function(){this.componentDB_=this.subscribedWorkspaces_=this.theme_=this.owner_=null},t.TouchGesture=function(e,o){t.TouchGesture.superClass_.constructor.call(this,e,o),this.isMultiTouch_=!1,this.cachedPoints_=Object.create(null),this.startDistance_=this.previousScale_=0,this.isPinchZoomEnabled_=this.onStartWrapper_=null},t.utils.object.inherits(t.TouchGesture,t.Gesture),t.TouchGesture.ZOOM_IN_MULTIPLIER=5,t.TouchGesture.ZOOM_OUT_MULTIPLIER=6,t.TouchGesture.prototype.doStart=function(e){this.isPinchZoomEnabled_=this.startWorkspace_.options.zoomOptions&&this.startWorkspace_.options.zoomOptions.pinch,t.TouchGesture.superClass_.doStart.call(this,e),!this.isEnding_&&t.Touch.isTouchEvent(e)&&this.handleTouchStart(e)},t.TouchGesture.prototype.bindMouseEvents=function(e){this.onStartWrapper_=t.bindEventWithChecks_(document,"mousedown",null,this.handleStart.bind(this),!0),this.onMoveWrapper_=t.bindEventWithChecks_(document,"mousemove",null,this.handleMove.bind(this),!0),this.onUpWrapper_=t.bindEventWithChecks_(document,"mouseup",null,this.handleUp.bind(this),!0),e.preventDefault(),e.stopPropagation()},t.TouchGesture.prototype.handleStart=function(e){!this.isDragging()&&t.Touch.isTouchEvent(e)&&(this.handleTouchStart(e),this.isMultiTouch()&&t.longStop_())},t.TouchGesture.prototype.handleMove=function(e){this.isDragging()?t.Touch.shouldHandleEvent(e)&&t.TouchGesture.superClass_.handleMove.call(this,e):this.isMultiTouch()?(t.Touch.isTouchEvent(e)&&this.handleTouchMove(e),t.longStop_()):t.TouchGesture.superClass_.handleMove.call(this,e)},t.TouchGesture.prototype.handleUp=function(e){t.Touch.isTouchEvent(e)&&!this.isDragging()&&this.handleTouchEnd(e),!this.isMultiTouch()||this.isDragging()?t.Touch.shouldHandleEvent(e)&&t.TouchGesture.superClass_.handleUp.call(this,e):(e.preventDefault(),e.stopPropagation(),this.dispose())},t.TouchGesture.prototype.isMultiTouch=function(){return this.isMultiTouch_},t.TouchGesture.prototype.dispose=function(){t.TouchGesture.superClass_.dispose.call(this),this.onStartWrapper_&&t.unbindEvent_(this.onStartWrapper_)},t.TouchGesture.prototype.handleTouchStart=function(e){var o=t.Touch.getTouchIdentifierFromEvent(e);this.cachedPoints_[o]=this.getTouchPoint(e),2==(o=Object.keys(this.cachedPoints_)).length&&(this.startDistance_=t.utils.Coordinate.distance(this.cachedPoints_[o[0]],this.cachedPoints_[o[1]]),this.isMultiTouch_=!0,e.preventDefault())},t.TouchGesture.prototype.handleTouchMove=function(e){var o=t.Touch.getTouchIdentifierFromEvent(e);this.cachedPoints_[o]=this.getTouchPoint(e),o=Object.keys(this.cachedPoints_),this.isPinchZoomEnabled_&&2===o.length?this.handlePinch_(e):t.TouchGesture.superClass_.handleMove.call(this,e)},t.TouchGesture.prototype.handlePinch_=function(e){var o=Object.keys(this.cachedPoints_);if(o=t.utils.Coordinate.distance(this.cachedPoints_[o[0]],this.cachedPoints_[o[1]])/this.startDistance_,0this.previousScale_){var i=o-this.previousScale_;i=0Object.keys(this.cachedPoints_).length&&(this.cachedPoints_=Object.create(null),this.previousScale_=0)},t.TouchGesture.prototype.getTouchPoint=function(e){return this.startWorkspace_?new t.utils.Coordinate(e.pageX?e.pageX:e.changedTouches[0].pageX,e.pageY?e.pageY:e.changedTouches[0].pageY):null},t.WorkspaceAudio=function(t){this.parentWorkspace_=t,this.SOUNDS_=Object.create(null)},t.WorkspaceAudio.prototype.lastSound_=null,t.WorkspaceAudio.prototype.dispose=function(){this.SOUNDS_=this.parentWorkspace_=null},t.WorkspaceAudio.prototype.load=function(e,o){if(e.length){try{var i=new t.utils.global.Audio}catch(t){return}for(var n,s=0;s=this.remainingCapacity()||(this.currentGesture_&&this.currentGesture_.cancel(),"comment"==t.tagName.toLowerCase()?this.pasteWorkspaceComment_(t):this.pasteBlock_(t))},t.WorkspaceSvg.prototype.pasteBlock_=function(e){t.Events.disable();try{var o=t.Xml.domToBlock(e,this),i=this.getMarker(t.navigation.MARKER_NAME).getCurNode();if(this.keyboardAccessibilityMode&&i&&i.isConnection()){var n=i.getLocation();return void t.navigation.insertBlock(o,n)}var s=parseInt(e.getAttribute("x"),10),r=parseInt(e.getAttribute("y"),10);if(!isNaN(s)&&!isNaN(r)){this.RTL&&(s=-s);do{e=!1;var a,l=this.getAllBlocks(!1);for(i=0;a=l[i];i++){var c=a.getRelativeToSurfaceXY();if(1>=Math.abs(s-c.x)&&1>=Math.abs(r-c.y)){e=!0;break}}if(!e){var h,u=o.getConnections_(!1);for(i=0;h=u[i];i++)if(h.closest(t.SNAP_RADIUS,new t.utils.Coordinate(s,r)).connection){e=!0;break}}e&&(s=this.RTL?s-t.SNAP_RADIUS:s+t.SNAP_RADIUS,r+=2*t.SNAP_RADIUS)}while(e);o.moveBy(s,r)}}finally{t.Events.enable()}t.Events.isEnabled()&&!o.isShadow()&&t.Events.fire(new t.Events.BlockCreate(o)),o.select()},t.WorkspaceSvg.prototype.pasteWorkspaceComment_=function(e){t.Events.disable();try{var o=t.WorkspaceCommentSvg.fromXml(e,this),i=parseInt(e.getAttribute("x"),10),n=parseInt(e.getAttribute("y"),10);isNaN(i)||isNaN(n)||(this.RTL&&(i=-i),o.moveBy(i+50,n+50))}finally{t.Events.enable()}t.Events.isEnabled(),o.select()},t.WorkspaceSvg.prototype.refreshToolboxSelection=function(){var t=this.isFlyout?this.targetWorkspace:this;t&&!t.currentGesture_&&t.toolbox_&&t.toolbox_.getFlyout()&&t.toolbox_.refreshSelection()},t.WorkspaceSvg.prototype.renameVariableById=function(e,o){t.WorkspaceSvg.superClass_.renameVariableById.call(this,e,o),this.refreshToolboxSelection()},t.WorkspaceSvg.prototype.deleteVariableById=function(e){t.WorkspaceSvg.superClass_.deleteVariableById.call(this,e),this.refreshToolboxSelection()},t.WorkspaceSvg.prototype.createVariable=function(e,o,i){return e=t.WorkspaceSvg.superClass_.createVariable.call(this,e,o,i),this.refreshToolboxSelection(),e},t.WorkspaceSvg.prototype.recordDeleteAreas=function(){this.deleteAreaTrash_=this.trashcan&&this.svgGroup_.parentNode?this.trashcan.getClientRect():null,this.deleteAreaToolbox_=this.flyout_?this.flyout_.getClientRect():this.toolbox_?this.toolbox_.getClientRect():null},t.WorkspaceSvg.prototype.isDeleteArea=function(e){return this.deleteAreaTrash_&&this.deleteAreaTrash_.contains(e.clientX,e.clientY)?t.DELETE_AREA_TRASH:this.deleteAreaToolbox_&&this.deleteAreaToolbox_.contains(e.clientX,e.clientY)?t.DELETE_AREA_TOOLBOX:t.DELETE_AREA_NONE},t.WorkspaceSvg.prototype.onMouseDown_=function(t){var e=this.getGesture(t);e&&e.handleWsStart(t,this)},t.WorkspaceSvg.prototype.startDrag=function(e,o){(e=t.utils.mouseToSvg(e,this.getParentSvg(),this.getInverseScreenCTM())).x/=this.scale,e.y/=this.scale,this.dragDeltaXY_=t.utils.Coordinate.difference(o,e)},t.WorkspaceSvg.prototype.moveDrag=function(e){return(e=t.utils.mouseToSvg(e,this.getParentSvg(),this.getInverseScreenCTM())).x/=this.scale,e.y/=this.scale,t.utils.Coordinate.sum(this.dragDeltaXY_,e)},t.WorkspaceSvg.prototype.isDragging=function(){return null!=this.currentGesture_&&this.currentGesture_.isDragging()},t.WorkspaceSvg.prototype.isDraggable=function(){return this.options.moveOptions&&this.options.moveOptions.drag},t.WorkspaceSvg.prototype.isContentBounded=function(){return this.options.moveOptions&&this.options.moveOptions.scrollbars||this.options.moveOptions&&this.options.moveOptions.wheel||this.options.moveOptions&&this.options.moveOptions.drag||this.options.zoomOptions&&this.options.zoomOptions.controls||this.options.zoomOptions&&this.options.zoomOptions.wheel||this.options.zoomOptions&&this.options.zoomOptions.pinch},t.WorkspaceSvg.prototype.isMovable=function(){return this.options.moveOptions&&this.options.moveOptions.scrollbars||this.options.moveOptions&&this.options.moveOptions.wheel||this.options.moveOptions&&this.options.moveOptions.drag||this.options.zoomOptions&&this.options.zoomOptions.wheel||this.options.zoomOptions&&this.options.zoomOptions.pinch},t.WorkspaceSvg.prototype.onMouseWheel_=function(e){if(t.Gesture.inProgress())e.preventDefault(),e.stopPropagation();else{var o=this.options.zoomOptions&&this.options.zoomOptions.wheel,i=this.options.moveOptions&&this.options.moveOptions.wheel;if(o||i){var n=t.utils.getScrollDeltaPixels(e);!o||!e.ctrlKey&&i?(o=this.scrollX-n.x,i=this.scrollY-n.y,e.shiftKey&&!n.x&&(o=this.scrollX-n.y,i=this.scrollY),this.scroll(o,i)):(n=-n.y/50,o=t.utils.mouseToSvg(e,this.getParentSvg(),this.getInverseScreenCTM()),this.zoom(o.x,o.y,n)),e.preventDefault()}}},t.WorkspaceSvg.prototype.getBlocksBoundingBox=function(){var e=this.getTopBlocks(!1),o=this.getTopComments(!1);if(!(e=e.concat(o)).length)return new t.utils.Rect(0,0,0,0);o=e[0].getBoundingRectangle();for(var i=1;io.bottom&&(o.bottom=n.bottom),n.lefto.right&&(o.right=n.right)}return o},t.WorkspaceSvg.prototype.cleanUp=function(){this.setResizesEnabled(!1),t.Events.setGroup(!0);for(var e,o=this.getTopBlocks(!0),i=0,n=0;e=o[n];n++)if(e.isMovable()){var s=e.getRelativeToSurfaceXY();e.moveBy(-s.x,i-s.y),e.snapToGrid(),i=e.getRelativeToSurfaceXY().y+e.getHeightWidth().height+this.renderer_.getConstants().MIN_BLOCK_HEIGHT}t.Events.setGroup(!1),this.setResizesEnabled(!0)},t.WorkspaceSvg.prototype.showContextMenu=function(e){function o(t){if(t.isDeletable())_=_.concat(t.getDescendants(!1));else{t=t.getChildren(!1);for(var e=0;e_.length?i():t.confirm(t.Msg.DELETE_ALL_BLOCKS.replace("%1",_.length),(function(t){t&&i()}))}},n.push(l),this.configureContextMenu&&this.configureContextMenu(n,e),t.ContextMenu.show(e,n,this.RTL)}},t.WorkspaceSvg.prototype.updateToolbox=function(e){if(e=t.Options.parseToolboxTree(e)){if(!this.options.languageTree)throw Error("Existing toolbox is null. Can't create new toolbox.");if(e.getElementsByTagName("category").length){if(!this.toolbox_)throw Error("Existing toolbox has no categories. Can't change mode.");this.options.languageTree=e,this.toolbox_.renderTree(e)}else{if(!this.flyout_)throw Error("Existing toolbox has categories. Can't change mode.");this.options.languageTree=e,this.flyout_.show(e.childNodes)}}else if(this.options.languageTree)throw Error("Can't nullify an existing toolbox.")},t.WorkspaceSvg.prototype.markFocused=function(){this.options.parentWorkspace?this.options.parentWorkspace.markFocused():(t.mainWorkspace=this,this.setBrowserFocus())},t.WorkspaceSvg.prototype.setBrowserFocus=function(){document.activeElement&&document.activeElement.blur();try{this.getParentSvg().focus({preventScroll:!0})}catch(t){try{this.getParentSvg().parentNode.setActive()}catch(t){this.getParentSvg().parentNode.focus({preventScroll:!0})}}},t.WorkspaceSvg.prototype.zoom=function(t,e,o){o=Math.pow(this.options.zoomOptions.scaleSpeed,o);var i=this.scale*o;if(this.scale!=i){i>this.options.zoomOptions.maxScale?o=this.options.zoomOptions.maxScale/this.scale:ithis.options.zoomOptions.maxScale?e=this.options.zoomOptions.maxScale:this.options.zoomOptions.minScale&&eo.viewBottom||o.contentLefto.viewRight){switch(i=null,e&&(i=t.Events.getGroup(),t.Events.setGroup(e.group)),e.type){case t.Events.BLOCK_CREATE:case t.Events.BLOCK_MOVE:var r=s.getBlockById(e.blockId);r&&(r=r.getRootBlock());break;case t.Events.COMMENT_CREATE:case t.Events.COMMENT_MOVE:r=s.getCommentById(e.commentId)}if(r){(n=r.getBoundingRectangle()).height=n.bottom-n.top,n.width=n.right-n.left;var a=o.viewTop,l=o.viewBottom-n.height;l=Math.max(a,l),a=t.utils.math.clamp(a,n.top,l)-n.top,l=o.viewLeft;var c=o.viewRight-n.width;o.RTL?l=Math.min(c,l):c=Math.max(l,c),o=t.utils.math.clamp(l,n.left,c)-n.left,r.moveBy(o,a)}e&&(!e.group&&r&&console.log("WARNING: Moved object in bounds but there was no event group. This may break undo."),null!==i&&t.Events.setGroup(i))}}})),t.svgResize(s),t.WidgetDiv.createDom(),t.DropDownDiv.createDom(),t.Tooltip.createDom(),s},t.init_=function(e){var o=e.options,i=e.getParentSvg();if(t.bindEventWithChecks_(i.parentNode,"contextmenu",null,(function(e){t.utils.isTargetInput(e)||e.preventDefault()})),i=t.bindEventWithChecks_(window,"resize",null,(function(){t.hideChaff(!0),t.svgResize(e)})),e.setResizeHandlerWrapper(i),t.inject.bindDocumentEvents_(),o.languageTree){i=e.getToolbox();var n=e.getFlyout(!0);i?i.init():n&&(n.init(e),n.show(o.languageTree.childNodes),n.scrollToStart())}i=t.Scrollbar.scrollbarThickness,o.hasTrashcan&&(i=e.trashcan.init(i)),o.zoomOptions&&o.zoomOptions.controls&&e.zoomControls_.init(i),o.moveOptions&&o.moveOptions.scrollbars?(e.scrollbar=new t.ScrollbarPair(e),e.scrollbar.resize()):e.setMetrics({x:.5,y:.5}),o.hasSounds&&t.inject.loadSounds_(o.pathToMedia,e)},t.inject.bindDocumentEvents_=function(){t.documentEventsBound_||(t.bindEventWithChecks_(document,"scroll",null,(function(){for(var e,o=t.Workspace.getAll(),i=0;e=o[i];i++)e.updateInverseScreenCTM&&e.updateInverseScreenCTM()})),t.bindEventWithChecks_(document,"keydown",null,t.onKeyDown),t.bindEvent_(document,"touchend",null,t.longStop_),t.bindEvent_(document,"touchcancel",null,t.longStop_),t.utils.userAgent.IPAD&&t.bindEventWithChecks_(window,"orientationchange",document,(function(){t.svgResize(t.getMainWorkspace())}))),t.documentEventsBound_=!0},t.inject.loadSounds_=function(e,o){var i=o.getAudioManager();i.load([e+"click.mp3",e+"click.wav",e+"click.ogg"],"click"),i.load([e+"disconnect.wav",e+"disconnect.mp3",e+"disconnect.ogg"],"disconnect"),i.load([e+"delete.mp3",e+"delete.ogg",e+"delete.wav"],"delete");var n=[];e=function(){for(;n.length;)t.unbindEvent_(n.pop());i.preload()},n.push(t.bindEventWithChecks_(document,"mousemove",null,e,!0)),n.push(t.bindEventWithChecks_(document,"touchstart",null,e,!0))},t.Names=function(t,e){if(this.variablePrefix_=e||"",this.reservedDict_=Object.create(null),t)for(t=t.split(","),e=0;e1'),n.appendChild(i),o.push(n)),t.Blocks.variables_get){e.sort(t.VariableModel.compareByName),i=0;for(var s;s=e[i];i++)(n=t.utils.xml.createElement("block")).setAttribute("type","variables_get"),n.setAttribute("gap",8),n.appendChild(t.Variables.generateVariableFieldDom(s)),o.push(n)}}return o},t.Variables.VAR_LETTER_OPTIONS="ijkmnopqrstuvwxyzabcdefgh",t.Variables.generateUniqueName=function(e){return t.Variables.generateUniqueNameFromOptions(t.Variables.VAR_LETTER_OPTIONS.charAt(0),e.getAllVariableNames())},t.Variables.generateUniqueNameFromOptions=function(e,o){if(!o.length)return e;for(var i=t.Variables.VAR_LETTER_OPTIONS,n="",s=i.indexOf(e);;){for(var r=!1,a=0;as?t.WidgetDiv.positionInternal_(e,0,i.height+s):t.WidgetDiv.positionInternal_(e,s,i.height)},t.WidgetDiv.calculateX_=function(t,e,o,i){return i?(e=Math.max(e.right-o.width,t.left),Math.min(e,t.right-o.width)):(e=Math.min(e.left,t.right-o.width),Math.max(e,t.left))},t.WidgetDiv.calculateY_=function(t,e,o){return e.bottom+o.height>=t.bottom?e.top-o.height:e.bottom},t.VERSION="3.20200402.1",t.mainWorkspace=null,t.selected=null,t.draggingConnections=[],t.clipboardXml_=null,t.clipboardSource_=null,t.clipboardTypeCounts_=null,t.cache3dSupported_=null,t.parentContainer=null,t.svgSize=function(t){return{width:t.cachedWidth_,height:t.cachedHeight_}},t.resizeSvgContents=function(t){t.resizeContents()},t.svgResize=function(t){for(;t.options.parentWorkspace;)t=t.options.parentWorkspace;var e=t.getParentSvg(),o=e.parentNode;if(o){var i=o.offsetWidth;o=o.offsetHeight,e.cachedWidth_!=i&&(e.setAttribute("width",i+"px"),e.cachedWidth_=i),e.cachedHeight_!=o&&(e.setAttribute("height",o+"px"),e.cachedHeight_=o),t.resize()}},t.onKeyDown=function(e){var o=t.mainWorkspace;if(o&&!(t.utils.isTargetInput(e)||o.rendered&&!o.isVisible()))if(o.options.readOnly)t.navigation.onKeyPress(e);else{var i=!1;if(e.keyCode==t.utils.KeyCodes.ESC)t.hideChaff(),t.navigation.onBlocklyAction(t.navigation.ACTION_EXIT);else{if(t.navigation.onKeyPress(e))return;if(e.keyCode==t.utils.KeyCodes.BACKSPACE||e.keyCode==t.utils.KeyCodes.DELETE){if(e.preventDefault(),t.Gesture.inProgress())return;t.selected&&t.selected.isDeletable()&&(i=!0)}else if(e.altKey||e.ctrlKey||e.metaKey){if(t.Gesture.inProgress())return;t.selected&&t.selected.isDeletable()&&t.selected.isMovable()&&(e.keyCode==t.utils.KeyCodes.C?(t.hideChaff(),t.copy_(t.selected)):e.keyCode!=t.utils.KeyCodes.X||t.selected.workspace.isFlyout||(t.copy_(t.selected),i=!0)),e.keyCode==t.utils.KeyCodes.V?t.clipboardXml_&&((e=t.clipboardSource_).isFlyout&&(e=e.targetWorkspace),t.clipboardTypeCounts_&&e.isCapacityAvailable(t.clipboardTypeCounts_)&&(t.Events.setGroup(!0),e.paste(t.clipboardXml_),t.Events.setGroup(!1))):e.keyCode==t.utils.KeyCodes.Z&&(t.hideChaff(),o.undo(e.shiftKey))}}i&&!t.selected.workspace.isFlyout&&(t.Events.setGroup(!0),t.hideChaff(),t.selected.dispose(!0,!0),t.Events.setGroup(!1))}},t.copy_=function(e){if(e.isComment)var o=e.toXmlWithXY();else{o=t.Xml.blockToDom(e,!0),t.Xml.deleteNext(o);var i=e.getRelativeToSurfaceXY();o.setAttribute("x",e.RTL?-i.x:i.x),o.setAttribute("y",i.y)}t.clipboardXml_=o,t.clipboardSource_=e.workspace,t.clipboardTypeCounts_=e.isComment?null:t.utils.getBlockTypeCounts(e,!0)},t.duplicate=function(e){var o=t.clipboardXml_,i=t.clipboardSource_;t.copy_(e),e.workspace.paste(t.clipboardXml_),t.clipboardXml_=o,t.clipboardSource_=i},t.onContextMenu_=function(e){t.utils.isTargetInput(e)||e.preventDefault()},t.hideChaff=function(e){t.Tooltip.hide(),t.WidgetDiv.hide(),t.DropDownDiv.hideWithoutAnimation(),e||((e=t.getMainWorkspace()).trashcan&&e.trashcan.flyout&&e.trashcan.flyout.hide(),(e=e.getToolbox())&&e.getFlyout()&&e.getFlyout().autoClose&&e.clearSelection())},t.getMainWorkspace=function(){return t.mainWorkspace},t.alert=function(t,e){alert(t),e&&e()},t.confirm=function(t,e){e(confirm(t))},t.prompt=function(t,e,o){o(prompt(t,e))},t.jsonInitFactory_=function(t){return function(){this.jsonInit(t)}},t.defineBlocksWithJsonArray=function(e){for(var o=0;o90-e||t>-90-e&&t<-90+e},t.HorizontalFlyout.prototype.getClientRect=function(){if(!this.svgGroup_)return null;var e=this.svgGroup_.getBoundingClientRect(),o=e.top;return this.toolboxPosition_==t.TOOLBOX_AT_TOP?new t.utils.Rect(-1e9,o+e.height,-1e9,1e9):new t.utils.Rect(o,1e9,-1e9,1e9)},t.HorizontalFlyout.prototype.reflowInternal_=function(){this.workspace_.scale=this.targetWorkspace_.scale;for(var e,o=0,i=this.workspace_.getTopBlocks(!1),n=0;e=i[n];n++)o=Math.max(o,e.getHeightWidth().height);if(o+=1.5*this.MARGIN,o*=this.workspace_.scale,o+=t.Scrollbar.scrollbarThickness,this.height_!=o){for(n=0;e=i[n];n++)e.flyoutRect_&&this.moveRectToBlock_(e.flyoutRect_,e);this.height_=o,this.position()}},t.VerticalFlyout=function(e){e.getMetrics=this.getMetrics_.bind(this),e.setMetrics=this.setMetrics_.bind(this),t.VerticalFlyout.superClass_.constructor.call(this,e),this.horizontalLayout_=!1},t.utils.object.inherits(t.VerticalFlyout,t.Flyout),t.VerticalFlyout.prototype.getMetrics_=function(){if(!this.isVisible())return null;try{var t=this.workspace_.getCanvas().getBBox()}catch(e){t={height:0,y:0,width:0,x:0}}var e=this.SCROLLBAR_PADDING,o=this.height_-2*this.SCROLLBAR_PADDING,i=this.width_;return this.RTL||(i-=this.SCROLLBAR_PADDING),{viewHeight:o,viewWidth:i,contentHeight:t.height*this.workspace_.scale+2*this.MARGIN,contentWidth:t.width*this.workspace_.scale+2*this.MARGIN,viewTop:-this.workspace_.scrollY+t.y,viewLeft:-this.workspace_.scrollX,contentTop:t.y,contentLeft:t.x,absoluteTop:e,absoluteLeft:0}},t.VerticalFlyout.prototype.setMetrics_=function(t){var e=this.getMetrics_();e&&("number"==typeof t.y&&(this.workspace_.scrollY=-e.contentHeight*t.y),this.workspace_.translate(this.workspace_.scrollX+e.absoluteLeft,this.workspace_.scrollY+e.absoluteTop))},t.VerticalFlyout.prototype.position=function(){if(this.isVisible()){var e=this.targetWorkspace_.getMetrics();e&&(this.height_=e.viewHeight,this.setBackgroundPath_(this.width_-this.CORNER_RADIUS,e.viewHeight-2*this.CORNER_RADIUS),this.positionAt_(this.width_,this.height_,this.targetWorkspace_.toolboxPosition==this.toolboxPosition_?e.toolboxWidth?this.toolboxPosition_==t.TOOLBOX_AT_LEFT?e.toolboxWidth:e.viewWidth-this.width_:this.toolboxPosition_==t.TOOLBOX_AT_LEFT?0:e.viewWidth:this.toolboxPosition_==t.TOOLBOX_AT_LEFT?0:e.viewWidth+e.absoluteLeft-this.width_,0))}},t.VerticalFlyout.prototype.setBackgroundPath_=function(e,o){var i=this.toolboxPosition_==t.TOOLBOX_AT_RIGHT,n=e+this.CORNER_RADIUS;(n=["M "+(i?n:0)+",0"]).push("h",i?-e:e),n.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,i?0:1,i?-this.CORNER_RADIUS:this.CORNER_RADIUS,this.CORNER_RADIUS),n.push("v",Math.max(0,o)),n.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,i?0:1,i?this.CORNER_RADIUS:-this.CORNER_RADIUS,this.CORNER_RADIUS),n.push("h",i?e:-e),n.push("z"),this.svgBackground_.setAttribute("d",n.join(" "))},t.VerticalFlyout.prototype.scrollToStart=function(){this.scrollbar_.set(0)},t.VerticalFlyout.prototype.wheel_=function(e){var o=t.utils.getScrollDeltaPixels(e);if(o.y){var i=this.getMetrics_();o=i.viewTop-i.contentTop+o.y,o=Math.min(o,i.contentHeight-i.viewHeight),o=Math.max(o,0),this.scrollbar_.set(o),t.WidgetDiv.hide()}e.preventDefault(),e.stopPropagation()},t.VerticalFlyout.prototype.layout_=function(t,e){this.workspace_.scale=this.targetWorkspace_.scale;for(var o,i=this.MARGIN,n=this.RTL?i:i+this.tabWidth_,s=0;o=t[s];s++)if("block"==o.type){for(var r,a=(o=o.block).getDescendants(!1),l=0;r=a[l];l++)r.isInFlyout=!0;o.render(),a=o.getSvgRoot(),l=o.getHeightWidth(),r=o.outputConnection?n-this.tabWidth_:n,o.moveBy(r,i),r=this.createRect_(o,this.RTL?r-l.width:r,i,l,s),this.addBlockListeners_(a,o,r),i+=l.height+e[s]}else"button"==o.type&&(this.initFlyoutButton_(o.button,n,i),i+=o.button.height+e[s])},t.VerticalFlyout.prototype.isDragTowardWorkspace=function(t){t=Math.atan2(t.y,t.x)/Math.PI*180;var e=this.dragAngleRange_;return t-e||t<-180+e||t>180-e},t.VerticalFlyout.prototype.getClientRect=function(){if(!this.svgGroup_)return null;var e=this.svgGroup_.getBoundingClientRect(),o=e.left;return this.toolboxPosition_==t.TOOLBOX_AT_LEFT?new t.utils.Rect(-1e9,1e9,-1e9,o+e.width):new t.utils.Rect(-1e9,1e9,o,1e9)},t.VerticalFlyout.prototype.reflowInternal_=function(){this.workspace_.scale=this.targetWorkspace_.scale;for(var e,o=0,i=this.workspace_.getTopBlocks(!1),n=0;e=i[n];n++){var s=e.getHeightWidth().width;e.outputConnection&&(s-=this.tabWidth_),o=Math.max(o,s)}for(n=0;e=this.buttons_[n];n++)o=Math.max(o,e.width);if(o+=1.5*this.MARGIN+this.tabWidth_,o*=this.workspace_.scale,o+=t.Scrollbar.scrollbarThickness,this.width_!=o){for(n=0;e=i[n];n++){if(this.RTL){s=e.getRelativeToSurfaceXY().x;var r=o/this.workspace_.scale-this.MARGIN;e.outputConnection||(r-=this.tabWidth_),e.moveBy(r-s,0)}e.flyoutRect_&&this.moveRectToBlock_(e.flyoutRect_,e)}if(this.RTL)for(n=0;e=this.buttons_[n];n++)i=e.getPosition().y,e.moveTo(o/this.workspace_.scale-e.width-this.MARGIN-this.tabWidth_,i);this.width_=o,this.position()}},t.FlyoutButton=function(e,o,i,n){this.workspace_=e,this.targetWorkspace_=o,this.text_=i.getAttribute("text"),this.position_=new t.utils.Coordinate(0,0),this.isLabel_=n,this.callbackKey_=i.getAttribute("callbackKey")||i.getAttribute("callbackkey"),this.cssClass_=i.getAttribute("web-class")||null,this.onMouseUpWrapper_=null},t.FlyoutButton.MARGIN_X=5,t.FlyoutButton.MARGIN_Y=2,t.FlyoutButton.prototype.width=0,t.FlyoutButton.prototype.height=0,t.FlyoutButton.prototype.createDom=function(){var e=this.isLabel_?"blocklyFlyoutLabel":"blocklyFlyoutButton";if(this.cssClass_&&(e+=" "+this.cssClass_),this.svgGroup_=t.utils.dom.createSvgElement("g",{class:e},this.workspace_.getCanvas()),!this.isLabel_)var o=t.utils.dom.createSvgElement("rect",{class:"blocklyFlyoutButtonShadow",rx:4,ry:4,x:1,y:1},this.svgGroup_);e=t.utils.dom.createSvgElement("rect",{class:this.isLabel_?"blocklyFlyoutLabelBackground":"blocklyFlyoutButtonBackground",rx:4,ry:4},this.svgGroup_);var i=t.utils.dom.createSvgElement("text",{class:this.isLabel_?"blocklyFlyoutLabelText":"blocklyText",x:0,y:0,"text-anchor":"middle"},this.svgGroup_),n=t.utils.replaceMessageReferences(this.text_);this.workspace_.RTL&&(n+="‏"),i.textContent=n,this.isLabel_&&(this.svgText_=i,this.workspace_.getThemeManager().subscribe(this.svgText_,"flyoutForegroundColour","fill"));var s=t.utils.style.getComputedStyle(i,"fontSize"),r=t.utils.style.getComputedStyle(i,"fontWeight"),a=t.utils.style.getComputedStyle(i,"fontFamily");return this.width=t.utils.dom.getFastTextWidthWithSizeString(i,s,r,a),n=t.utils.dom.measureFontMetrics(n,s,r,a),this.height=n.height,this.isLabel_||(this.width+=2*t.FlyoutButton.MARGIN_X,this.height+=2*t.FlyoutButton.MARGIN_Y,o.setAttribute("width",this.width),o.setAttribute("height",this.height)),e.setAttribute("width",this.width),e.setAttribute("height",this.height),i.setAttribute("x",this.width/2),i.setAttribute("y",this.height/2-n.height/2+n.baseline),this.updateTransform_(),this.onMouseUpWrapper_=t.bindEventWithChecks_(this.svgGroup_,"mouseup",this,this.onMouseUp_),this.svgGroup_},t.FlyoutButton.prototype.show=function(){this.updateTransform_(),this.svgGroup_.setAttribute("display","block")},t.FlyoutButton.prototype.updateTransform_=function(){this.svgGroup_.setAttribute("transform","translate("+this.position_.x+","+this.position_.y+")")},t.FlyoutButton.prototype.moveTo=function(t,e){this.position_.x=t,this.position_.y=e,this.updateTransform_()},t.FlyoutButton.prototype.getPosition=function(){return this.position_},t.FlyoutButton.prototype.getTargetWorkspace=function(){return this.targetWorkspace_},t.FlyoutButton.prototype.dispose=function(){this.onMouseUpWrapper_&&t.unbindEvent_(this.onMouseUpWrapper_),this.svgGroup_&&t.utils.dom.removeNode(this.svgGroup_),this.svgText_&&this.workspace_.getThemeManager().unsubscribe(this.svgText_)},t.FlyoutButton.prototype.onMouseUp_=function(t){(t=this.targetWorkspace_.getGesture(t))&&t.cancel(),this.isLabel_&&this.callbackKey_?console.warn("Labels should not have callbacks. Label text: "+this.text_):this.isLabel_||this.callbackKey_&&this.targetWorkspace_.getButtonCallback(this.callbackKey_)?this.isLabel_||this.targetWorkspace_.getButtonCallback(this.callbackKey_)(this):console.warn("Buttons should have callbacks. Button text: "+this.text_)},t.Css.register(".blocklyFlyoutButton {,fill: #888;,cursor: default;,},.blocklyFlyoutButtonShadow {,fill: #666;,},.blocklyFlyoutButton:hover {,fill: #aaa;,},.blocklyFlyoutLabel {,cursor: default;,},.blocklyFlyoutLabelBackground {,opacity: 0;,}".split(",")),t.Generator=function(t){this.name_=t,this.FUNCTION_NAME_PLACEHOLDER_REGEXP_=new RegExp(this.FUNCTION_NAME_PLACEHOLDER_,"g")},t.Generator.NAME_TYPE="generated_function",t.Generator.prototype.INFINITE_LOOP_TRAP=null,t.Generator.prototype.STATEMENT_PREFIX=null,t.Generator.prototype.STATEMENT_SUFFIX=null,t.Generator.prototype.INDENT=" ",t.Generator.prototype.COMMENT_WRAP=60,t.Generator.prototype.ORDER_OVERRIDES=[],t.Generator.prototype.workspaceToCode=function(e){e||(console.warn("No workspace specified in workspaceToCode call. Guessing."),e=t.getMainWorkspace());var o=[];this.init(e),e=e.getTopBlocks(!0);for(var i,n=0;i=e[n];n++){var s=this.blockToCode(i);Array.isArray(s)&&(s=s[0]),s&&(i.outputConnection&&(s=this.scrubNakedValue(s),this.STATEMENT_PREFIX&&!i.suppressPrefixSuffix&&(s=this.injectId(this.STATEMENT_PREFIX,i)+s),this.STATEMENT_SUFFIX&&!i.suppressPrefixSuffix&&(s+=this.injectId(this.STATEMENT_SUFFIX,i))),o.push(s))}return o=o.join("\n"),(o=(o=(o=this.finish(o)).replace(/^\s+\n/,"")).replace(/\n\s+$/,"\n")).replace(/[ \t]+\n/g,"\n")},t.Generator.prototype.prefixLines=function(t,e){return e+t.replace(/(?!\n$)\n/g,"\n"+e)},t.Generator.prototype.allNestedComments=function(t){var e=[];t=t.getDescendants(!0);for(var o=0;ot&&(t=(t=this.getParent())?t.getDepth()+1:0,this.setDepth_(t)),t},t.tree.BaseNode.prototype.setDepth_=function(t){if(t!=this.depth_){this.depth_=t;var e=this.getRowElement();if(e){var o=this.getPixelIndent_()+"px";this.rightToLeft_?e.style.paddingRight=o:e.style.paddingLeft=o}this.forEachChild((function(e){e.setDepth_(t+1)}))}},t.tree.BaseNode.prototype.contains=function(t){for(;t;){if(t==this)return!0;t=t.getParent()}return!1},t.tree.BaseNode.prototype.getChildren=function(){var t=[];return this.forEachChild((function(e){t.push(e)})),t},t.tree.BaseNode.prototype.getPreviousSibling=function(){return this.previousSibling_},t.tree.BaseNode.prototype.getNextSibling=function(){return this.nextSibling_},t.tree.BaseNode.prototype.isLastSibling=function(){return!this.nextSibling_},t.tree.BaseNode.prototype.isSelected=function(){return this.selected_},t.tree.BaseNode.prototype.select=function(){var t=this.getTree();t&&t.setSelectedItem(this)},t.tree.BaseNode.prototype.setSelected=function(e){if(this.selected_!=e){this.selected_=e,this.updateRow();var o=this.getElement();o&&(t.utils.aria.setState(o,t.utils.aria.State.SELECTED,e),e&&(e=this.getTree().getElement(),t.utils.aria.setState(e,t.utils.aria.State.ACTIVEDESCENDANT,this.getId())))}},t.tree.BaseNode.prototype.setExpanded=function(e){var o,i=e!=this.expanded_;this.expanded_=e;var n=this.getTree(),s=this.getElement();this.hasChildren()?(!e&&n&&this.contains(n.getSelectedItem())&&this.select(),s&&((o=this.getChildrenElement())&&(t.utils.style.setElementShown(o,e),t.utils.aria.setState(s,t.utils.aria.State.EXPANDED,e),e&&this.isInDocument()&&!o.hasChildNodes()&&(this.forEachChild((function(t){o.appendChild(t.toDom())})),this.forEachChild((function(t){t.enterDocument()})))),this.updateExpandIcon())):(o=this.getChildrenElement())&&t.utils.style.setElementShown(o,!1),s&&this.updateIcon_(),i&&(e?this.doNodeExpanded():this.doNodeCollapsed())},t.tree.BaseNode.prototype.doNodeExpanded=function(){},t.tree.BaseNode.prototype.doNodeCollapsed=function(){},t.tree.BaseNode.prototype.toggle=function(){this.setExpanded(!this.expanded_)},t.tree.BaseNode.prototype.toDom=function(){var t=this.expanded_&&this.hasChildren(),e=document.createElement("div");return e.style.backgroundPosition=this.getBackgroundPosition(),t||(e.style.display="none"),t&&this.forEachChild((function(t){e.appendChild(t.toDom())})),(t=document.createElement("div")).id=this.getId(),t.appendChild(this.getRowDom()),t.appendChild(e),t},t.tree.BaseNode.prototype.getPixelIndent_=function(){return Math.max(0,(this.getDepth()-1)*this.config_.indentWidth)},t.tree.BaseNode.prototype.getRowDom=function(){var t=document.createElement("div");return t.className=this.getRowClassName(),t.style["padding-"+(this.rightToLeft_?"right":"left")]=this.getPixelIndent_()+"px",t.appendChild(this.getIconDom()),t.appendChild(this.getLabelDom()),t},t.tree.BaseNode.prototype.getRowClassName=function(){var t="";return this.isSelected()&&(t=" "+(this.config_.cssSelectedRow||"")),this.config_.cssTreeRow+t},t.tree.BaseNode.prototype.getLabelDom=function(){var t=document.createElement("span");return t.className=this.config_.cssItemLabel||"",t.textContent=this.content,t},t.tree.BaseNode.prototype.getIconDom=function(){var t=document.createElement("span");return t.style.display="inline-block",t.className=this.getCalculatedIconClass(),t},t.tree.BaseNode.prototype.getCalculatedIconClass=function(){throw Error("unimplemented abstract method")},t.tree.BaseNode.prototype.getBackgroundPosition=function(){return(this.isLastSibling()?"-100":(this.getDepth()-1)*this.config_.indentWidth)+"px 0"},t.tree.BaseNode.prototype.getElement=function(){var e=t.tree.BaseNode.superClass_.getElement.call(this);return e||(e=document.getElementById(this.getId()),this.setElementInternal(e)),e},t.tree.BaseNode.prototype.getRowElement=function(){var t=this.getElement();return t?t.firstChild:null},t.tree.BaseNode.prototype.getIconElement=function(){var t=this.getRowElement();return t?t.firstChild:null},t.tree.BaseNode.prototype.getLabelElement=function(){var t=this.getRowElement();return t&&t.lastChild?t.lastChild.previousSibling:null},t.tree.BaseNode.prototype.getChildrenElement=function(){var t=this.getElement();return t?t.lastChild:null},t.tree.BaseNode.prototype.updateRow=function(){var t=this.getRowElement();t&&(t.className=this.getRowClassName())},t.tree.BaseNode.prototype.updateExpandIcon=function(){var t=this.getChildrenElement();t&&(t.style.backgroundPosition=this.getBackgroundPosition())},t.tree.BaseNode.prototype.updateIcon_=function(){this.getIconElement().className=this.getCalculatedIconClass()},t.tree.BaseNode.prototype.onMouseDown=function(t){"expand"==t.target.getAttribute("type")&&this.hasChildren()?this.isUserCollapsible_&&this.toggle():(this.select(),this.updateRow())},t.tree.BaseNode.prototype.onClick_=function(t){t.preventDefault()},t.tree.BaseNode.prototype.onKeyDown=function(e){var o=!0;switch(e.keyCode){case t.utils.KeyCodes.RIGHT:if(e.altKey)break;o=this.selectChild();break;case t.utils.KeyCodes.LEFT:if(e.altKey)break;o=this.selectParent();break;case t.utils.KeyCodes.DOWN:o=this.selectNext();break;case t.utils.KeyCodes.UP:o=this.selectPrevious();break;default:o=!1}return o&&e.preventDefault(),o},t.tree.BaseNode.prototype.selectNext=function(){var t=this.getNextShownNode();return t&&t.select(),!0},t.tree.BaseNode.prototype.selectPrevious=function(){var t=this.getPreviousShownNode();return t&&t.select(),!0},t.tree.BaseNode.prototype.selectParent=function(){if(this.hasChildren()&&this.expanded_&&this.isUserCollapsible_)this.setExpanded(!1);else{var t=this.getParent(),e=this.getTree();t&&t!=e&&t.select()}return!0},t.tree.BaseNode.prototype.selectChild=function(){return!!this.hasChildren()&&(this.expanded_?this.getChildAt(0).select():this.setExpanded(!0),!0)},t.tree.BaseNode.prototype.getLastShownDescendant=function(){return this.expanded_&&this.hasChildren()?this.getChildAt(this.getChildCount()-1).getLastShownDescendant():this},t.tree.BaseNode.prototype.getNextShownNode=function(){if(this.hasChildren()&&this.expanded_)return this.getChildAt(0);for(var t,e=this;e!=this.getTree();){if(null!=(t=e.getNextSibling()))return t;e=e.getParent()}return null},t.tree.BaseNode.prototype.getPreviousShownNode=function(){var t=this.getPreviousSibling();if(null!=t)return t.getLastShownDescendant();t=this.getParent();var e=this.getTree();return t==e||this==e?null:t},t.tree.BaseNode.prototype.setTreeInternal=function(t){this.tree!=t&&(this.tree=t,this.forEachChild((function(e){e.setTreeInternal(t)})))},t.tree.TreeNode=function(e,o,i){this.toolbox_=e,t.tree.BaseNode.call(this,o,i)},t.utils.object.inherits(t.tree.TreeNode,t.tree.BaseNode),t.tree.TreeNode.prototype.getTree=function(){if(this.tree)return this.tree;var t=this.getParent();return t&&(t=t.getTree())?(this.setTreeInternal(t),t):null},t.tree.TreeNode.prototype.getCalculatedIconClass=function(){var t=this.expanded_;if(t&&this.expandedIconClass)return this.expandedIconClass;var e=this.iconClass;if(!t&&e)return e;if(e=this.config_,this.hasChildren()){if(t&&e.cssExpandedFolderIcon)return e.cssTreeIcon+" "+e.cssExpandedFolderIcon;if(!t&&e.cssCollapsedFolderIcon)return e.cssTreeIcon+" "+e.cssCollapsedFolderIcon}else if(e.cssFileIcon)return e.cssTreeIcon+" "+e.cssFileIcon;return""},t.tree.TreeNode.prototype.onClick_=function(t){this.hasChildren()&&this.isUserCollapsible_?(this.toggle(),this.select()):this.isSelected()?this.getTree().setSelectedItem(null):this.select(),this.updateRow()},t.tree.TreeNode.prototype.onMouseDown=function(t){},t.tree.TreeNode.prototype.onKeyDown=function(e){if(this.tree.toolbox_.horizontalLayout_){var o={},i=t.utils.KeyCodes.DOWN,n=t.utils.KeyCodes.UP;o[t.utils.KeyCodes.RIGHT]=this.rightToLeft_?n:i,o[t.utils.KeyCodes.LEFT]=this.rightToLeft_?i:n,o[t.utils.KeyCodes.UP]=t.utils.KeyCodes.LEFT,o[t.utils.KeyCodes.DOWN]=t.utils.KeyCodes.RIGHT,Object.defineProperties(e,{keyCode:{value:o[e.keyCode]||e.keyCode}})}return t.tree.TreeNode.superClass_.onKeyDown.call(this,e)},t.tree.TreeNode.prototype.onSizeChanged=function(t){this.onSizeChanged_=t},t.tree.TreeNode.prototype.resizeToolbox_=function(){this.onSizeChanged_&&this.onSizeChanged_.call(this.toolbox_)},t.tree.TreeNode.prototype.doNodeExpanded=t.tree.TreeNode.prototype.resizeToolbox_,t.tree.TreeNode.prototype.doNodeCollapsed=t.tree.TreeNode.prototype.resizeToolbox_,t.tree.TreeControl=function(e,o){this.toolbox_=e,this.onKeydownWrapper_=this.onClickWrapper_=this.onBlurWrapper_=this.onFocusWrapper_=null,t.tree.BaseNode.call(this,"",o),this.selected_=this.expanded_=!0,this.selectedItem_=this},t.utils.object.inherits(t.tree.TreeControl,t.tree.BaseNode),t.tree.TreeControl.prototype.getTree=function(){return this},t.tree.TreeControl.prototype.getToolbox=function(){return this.toolbox_},t.tree.TreeControl.prototype.getDepth=function(){return 0},t.tree.TreeControl.prototype.handleFocus_=function(e){this.focused_=!0,e=this.getElement(),t.utils.dom.addClass(e,"focused"),this.selectedItem_&&this.selectedItem_.select()},t.tree.TreeControl.prototype.handleBlur_=function(e){this.focused_=!1,e=this.getElement(),t.utils.dom.removeClass(e,"focused")},t.tree.TreeControl.prototype.hasFocus=function(){return this.focused_},t.tree.TreeControl.prototype.setExpanded=function(t){this.expanded_=t},t.tree.TreeControl.prototype.getIconElement=function(){var t=this.getRowElement();return t?t.firstChild:null},t.tree.TreeControl.prototype.updateExpandIcon=function(){},t.tree.TreeControl.prototype.getRowClassName=function(){return t.tree.TreeControl.superClass_.getRowClassName.call(this)+" "+this.config_.cssHideRoot},t.tree.TreeControl.prototype.getCalculatedIconClass=function(){var t=this.expanded_;if(t&&this.expandedIconClass)return this.expandedIconClass;var e=this.iconClass;return!t&&e?e:t&&this.config_.cssExpandedRootIcon?this.config_.cssTreeIcon+" "+this.config_.cssExpandedRootIcon:""},t.tree.TreeControl.prototype.setSelectedItem=function(t){if(t!=this.selectedItem_&&(!this.onBeforeSelected_||this.onBeforeSelected_.call(this.toolbox_,t))){var e=this.getSelectedItem();this.selectedItem_&&this.selectedItem_.setSelected(!1),(this.selectedItem_=t)&&t.setSelected(!0),this.onAfterSelected_&&this.onAfterSelected_.call(this.toolbox_,e,t)}},t.tree.TreeControl.prototype.onBeforeSelected=function(t){this.onBeforeSelected_=t},t.tree.TreeControl.prototype.onAfterSelected=function(t){this.onAfterSelected_=t},t.tree.TreeControl.prototype.getSelectedItem=function(){return this.selectedItem_},t.tree.TreeControl.prototype.initAccessibility=function(){t.tree.TreeControl.superClass_.initAccessibility.call(this);var e=this.getElement();t.utils.aria.setRole(e,t.utils.aria.Role.TREE),t.utils.aria.setState(e,t.utils.aria.State.LABELLEDBY,this.getLabelElement().id)},t.tree.TreeControl.prototype.enterDocument=function(){t.tree.TreeControl.superClass_.enterDocument.call(this);var e=this.getElement();e.className=this.config_.cssRoot,e.setAttribute("hideFocus","true"),this.attachEvents_(),this.initAccessibility()},t.tree.TreeControl.prototype.exitDocument=function(){t.tree.TreeControl.superClass_.exitDocument.call(this),this.detachEvents_()},t.tree.TreeControl.prototype.attachEvents_=function(){var e=this.getElement();e.tabIndex=0,this.onFocusWrapper_=t.bindEvent_(e,"focus",this,this.handleFocus_),this.onBlurWrapper_=t.bindEvent_(e,"blur",this,this.handleBlur_),this.onClickWrapper_=t.bindEventWithChecks_(e,"click",this,this.handleMouseEvent_),this.onKeydownWrapper_=t.bindEvent_(e,"keydown",this,this.handleKeyEvent_)},t.tree.TreeControl.prototype.detachEvents_=function(){this.onFocusWrapper_&&(t.unbindEvent_(this.onFocusWrapper_),this.onFocusWrapper_=null),this.onBlurWrapper_&&(t.unbindEvent_(this.onBlurWrapper_),this.onBlurWrapper_=null),this.onClickWrapper_&&(t.unbindEvent_(this.onClickWrapper_),this.onClickWrapper_=null),this.onKeydownWrapper_&&(t.unbindEvent_(this.onKeydownWrapper_),this.onKeydownWrapper_=null)},t.tree.TreeControl.prototype.handleMouseEvent_=function(t){var e=this.getNodeFromEvent_(t);if(e)switch(t.type){case"mousedown":e.onMouseDown(t);break;case"click":e.onClick_(t)}},t.tree.TreeControl.prototype.handleKeyEvent_=function(e){var o=!1;return(o=this.selectedItem_&&this.selectedItem_.onKeyDown(e)||o)&&(t.utils.style.scrollIntoContainerView(this.selectedItem_.getElement(),this.getElement().parentNode),e.preventDefault()),o},t.tree.TreeControl.prototype.getNodeFromEvent_=function(e){for(var o=e.target;null!=o;){if(e=t.tree.BaseNode.allNodes[o.id])return e;if(o==this.getElement())break;if(o.getAttribute("role")==t.utils.aria.Role.GROUP)break;o=o.parentNode}return null},t.tree.TreeControl.prototype.createNode=function(e){return new t.tree.TreeNode(this.toolbox_,e||"",this.config_)},t.Toolbox=function(t){this.workspace_=t,this.RTL=t.options.RTL,this.horizontalLayout_=t.options.horizontalLayout,this.toolboxPosition=t.options.toolboxPosition,this.config_={indentWidth:19,cssRoot:"blocklyTreeRoot",cssHideRoot:"blocklyHidden",cssTreeRow:"blocklyTreeRow",cssItemLabel:"blocklyTreeLabel",cssTreeIcon:"blocklyTreeIcon",cssExpandedFolderIcon:"blocklyTreeIconOpen",cssFileIcon:"blocklyTreeIconNone",cssSelectedRow:"blocklyTreeSelected"},this.treeSeparatorConfig_={cssTreeRow:"blocklyTreeSeparator"},this.horizontalLayout_&&(this.config_.cssTreeRow+=t.RTL?" blocklyHorizontalTreeRtl":" blocklyHorizontalTree",this.treeSeparatorConfig_.cssTreeRow="blocklyTreeSeparatorHorizontal "+(t.RTL?"blocklyHorizontalTreeRtl":"blocklyHorizontalTree"),this.config_.cssTreeIcon=""),this.flyout_=null},t.Toolbox.prototype.width=0,t.Toolbox.prototype.height=0,t.Toolbox.prototype.selectedOption_=null,t.Toolbox.prototype.lastCategory_=null,t.Toolbox.prototype.init=function(){var e=this.workspace_,o=this.workspace_.getParentSvg();this.HtmlDiv=document.createElement("div"),this.HtmlDiv.className="blocklyToolboxDiv blocklyNonSelectable",this.HtmlDiv.setAttribute("dir",e.RTL?"RTL":"LTR"),o.parentNode.insertBefore(this.HtmlDiv,o);var i=e.getThemeManager();if(i.subscribe(this.HtmlDiv,"toolboxBackgroundColour","background-color"),i.subscribe(this.HtmlDiv,"toolboxForegroundColour","color"),t.bindEventWithChecks_(this.HtmlDiv,"mousedown",this,(function(e){t.utils.isRightButton(e)||e.target==this.HtmlDiv?t.hideChaff(!1):t.hideChaff(!0),t.Touch.clearTouchIdentifier()}),!1,!0),(i=new t.Options({parentWorkspace:e,rtl:e.RTL,oneBasedIndex:e.options.oneBasedIndex,horizontalLayout:e.horizontalLayout,renderer:e.options.renderer,rendererOverrides:e.options.rendererOverrides})).toolboxPosition=e.options.toolboxPosition,e.horizontalLayout){if(!t.HorizontalFlyout)throw Error("Missing require for Blockly.HorizontalFlyout");this.flyout_=new t.HorizontalFlyout(i)}else{if(!t.VerticalFlyout)throw Error("Missing require for Blockly.VerticalFlyout");this.flyout_=new t.VerticalFlyout(i)}if(!this.flyout_)throw Error("One of Blockly.VerticalFlyout or Blockly.Horizontal must berequired.");t.utils.dom.insertAfter(this.flyout_.createDom("svg"),o),this.flyout_.init(e),this.config_.cleardotPath=e.options.pathToMedia+"1x1.gif",this.config_.cssCollapsedFolderIcon="blocklyTreeIconClosed"+(e.RTL?"Rtl":"Ltr"),this.renderTree(e.options.languageTree)},t.Toolbox.prototype.renderTree=function(e){this.tree_&&(this.tree_.dispose(),this.lastCategory_=null);var o=new t.tree.TreeControl(this,this.config_);this.tree_=o,o.setSelectedItem(null),o.onBeforeSelected(this.handleBeforeTreeSelected_),o.onAfterSelected(this.handleAfterTreeSelected_);var i=null;if(e){if(this.tree_.blocks=[],this.hasColours_=!1,i=this.syncTrees_(e,this.tree_,this.workspace_.options.pathToMedia),this.tree_.blocks.length)throw Error("Toolbox cannot have both blocks and categories in the root level.");this.workspace_.resizeContents()}o.render(this.HtmlDiv),i&&o.setSelectedItem(i),this.addColour_(),this.position(),this.horizontalLayout_&&t.utils.aria.setState(this.tree_.getElement(),t.utils.aria.State.ORIENTATION,"horizontal")},t.Toolbox.prototype.handleBeforeTreeSelected_=function(t){if(t==this.tree_)return!1;if(this.lastCategory_&&(this.lastCategory_.getRowElement().style.backgroundColor=""),t){var e=t.hexColour||"#57e";t.getRowElement().style.backgroundColor=e,this.addColour_(t)}return!0},t.Toolbox.prototype.handleAfterTreeSelected_=function(e,o){o&&o.blocks&&o.blocks.length?(this.flyout_.show(o.blocks),this.lastCategory_!=o&&this.flyout_.scrollToStart(),this.workspace_.keyboardAccessibilityMode&&t.navigation.setState(t.navigation.STATE_TOOLBOX)):(this.flyout_.hide(),!this.workspace_.keyboardAccessibilityMode||o instanceof t.Toolbox.TreeSeparator||t.navigation.setState(t.navigation.STATE_WS)),e!=o&&e!=this&&((e=new t.Events.Ui(null,"category",e&&e.content,o&&o.content)).workspaceId=this.workspace_.id,t.Events.fire(e)),o&&(this.lastCategory_=o)},t.Toolbox.prototype.handleNodeSizeChanged_=function(){t.svgResize(this.workspace_)},t.Toolbox.prototype.onBlocklyAction=function(e){var o=this.tree_.getSelectedItem();if(!o)return!1;switch(e.name){case t.navigation.actionNames.PREVIOUS:return o.selectPrevious();case t.navigation.actionNames.OUT:return o.selectParent();case t.navigation.actionNames.NEXT:return o.selectNext();case t.navigation.actionNames.IN:return o.selectChild();default:return!1}},t.Toolbox.prototype.dispose=function(){this.flyout_.dispose(),this.tree_.dispose(),this.workspace_.getThemeManager().unsubscribe(this.HtmlDiv),t.utils.dom.removeNode(this.HtmlDiv),this.lastCategory_=null},t.Toolbox.prototype.getWidth=function(){return this.width},t.Toolbox.prototype.getHeight=function(){return this.height},t.Toolbox.prototype.getFlyout=function(){return this.flyout_},t.Toolbox.prototype.position=function(){var e=this.HtmlDiv;if(e){var o=t.svgSize(this.workspace_.getParentSvg());this.horizontalLayout_?(e.style.left="0",e.style.height="auto",e.style.width=o.width+"px",this.height=e.offsetHeight,this.toolboxPosition==t.TOOLBOX_AT_TOP?e.style.top="0":e.style.bottom="0"):(this.toolboxPosition==t.TOOLBOX_AT_RIGHT?e.style.right="0":e.style.left="0",e.style.height=o.height+"px",this.width=e.offsetWidth),this.flyout_.position()}},t.Toolbox.prototype.syncTrees_=function(e,o,i){for(var n,s=null,r=null,a=0;n=e.childNodes[a];a++)if(n.tagName)switch(n.tagName.toUpperCase()){case"CATEGORY":r=t.utils.replaceMessageReferences(n.getAttribute("name"));var l=this.tree_.createNode(r);l.onSizeChanged(this.handleNodeSizeChanged_),l.blocks=[],o.add(l);var c=n.getAttribute("custom");c?l.blocks=c:(c=this.syncTrees_(n,l,i))&&(s=c),c=n.getAttribute("categorystyle");var h=n.getAttribute("colour");h&&c?(l.hexColour="",console.warn('Toolbox category "'+r+'" can not have both a style and a colour')):c?this.setColourFromStyle_(c,l,r):this.setColour_(h,l,r),"true"==n.getAttribute("expanded")?(l.blocks.length&&(s=l),l.setExpanded(!0)):l.setExpanded(!1),r=n;break;case"SEP":if(r&&"CATEGORY"==r.tagName.toUpperCase()){o.add(new t.Toolbox.TreeSeparator(this.treeSeparatorConfig_));break}case"BLOCK":case"SHADOW":case"LABEL":case"BUTTON":o.blocks.push(n),r=n}return s},t.Toolbox.prototype.setColour_=function(e,o,i){if(null===(e=t.utils.replaceMessageReferences(e))||""===e)o.hexColour="";else{var n=Number(e);isNaN(n)?(n=t.utils.colour.parse(e))?(o.hexColour=n,this.hasColours_=!0):(o.hexColour="",console.warn('Toolbox category "'+i+'" has unrecognized colour attribute: '+e)):(o.hexColour=t.hueToHex(n),this.hasColours_=!0)}},t.Toolbox.prototype.setColourFromStyle_=function(t,e,o){e.styleName=t;var i=this.workspace_.getTheme();t&&i&&((i=i.categoryStyles[t])&&i.colour?this.setColour_(i.colour,e,o):console.warn('Style "'+t+'" must exist and contain a colour value'))},t.Toolbox.prototype.updateColourFromTheme_=function(t){if(t=t||this.tree_){t=t.getChildren(!1);for(var e,o=0;e=t[o];o++)e.styleName&&(this.setColourFromStyle_(e.styleName,e,""),this.addColour_()),this.updateColourFromTheme_(e)}},t.Toolbox.prototype.updateColourFromTheme=function(){var t=this.tree_;t&&(this.updateColourFromTheme_(t),this.updateSelectedItemColour_(t))},t.Toolbox.prototype.updateSelectedItemColour_=function(t){if(t=t.getSelectedItem()){var e=t.hexColour||"#57e";t.getRowElement().style.backgroundColor=e,this.addColour_(t)}},t.Toolbox.prototype.addColour_=function(t){t=(t||this.tree_).getChildren(!1);for(var e,o=0;e=t[o];o++){var i=e.getRowElement();if(i){var n=this.hasColours_?"8px solid "+(e.hexColour||"#ddd"):"none";this.workspace_.RTL?i.style.borderRight=n:i.style.borderLeft=n}this.addColour_(e)}},t.Toolbox.prototype.clearSelection=function(){this.tree_.setSelectedItem(null)},t.Toolbox.prototype.addStyle=function(e){t.utils.dom.addClass(this.HtmlDiv,e)},t.Toolbox.prototype.removeStyle=function(e){t.utils.dom.removeClass(this.HtmlDiv,e)},t.Toolbox.prototype.getClientRect=function(){if(!this.HtmlDiv)return null;var e=this.HtmlDiv.getBoundingClientRect(),o=e.top,i=o+e.height,n=e.left;return e=n+e.width,this.toolboxPosition==t.TOOLBOX_AT_TOP?new t.utils.Rect(-1e7,i,-1e7,1e7):this.toolboxPosition==t.TOOLBOX_AT_BOTTOM?new t.utils.Rect(o,1e7,-1e7,1e7):this.toolboxPosition==t.TOOLBOX_AT_LEFT?new t.utils.Rect(-1e7,1e7,-1e7,e):new t.utils.Rect(-1e7,1e7,n,1e7)},t.Toolbox.prototype.refreshSelection=function(){var t=this.tree_.getSelectedItem();t&&t.blocks&&this.flyout_.show(t.blocks)},t.Toolbox.prototype.selectFirstCategory=function(){this.tree_.getSelectedItem()||this.tree_.selectChild()},t.Toolbox.TreeSeparator=function(e){t.tree.TreeNode.call(this,null,"",e)},t.utils.object.inherits(t.Toolbox.TreeSeparator,t.tree.TreeNode),t.Css.register([".blocklyToolboxDelete {",'cursor: url("<<>>/handdelete.cur"), auto;',"}",".blocklyToolboxGrab {",'cursor: url("<<>>/handclosed.cur"), auto;',"cursor: grabbing;","cursor: -webkit-grabbing;","}",".blocklyToolboxDiv {","background-color: #ddd;","overflow-x: visible;","overflow-y: auto;","position: absolute;","z-index: 70;","-webkit-tap-highlight-color: transparent;","}",".blocklyTreeRoot {","padding: 4px 0;","}",".blocklyTreeRoot:focus {","outline: none;","}",".blocklyTreeRow {","height: 22px;","line-height: 22px;","margin-bottom: 3px;","padding-right: 8px;","white-space: nowrap;","}",".blocklyHorizontalTree {","float: left;","margin: 1px 5px 8px 0;","}",".blocklyHorizontalTreeRtl {","float: right;","margin: 1px 0 8px 5px;","}",'.blocklyToolboxDiv[dir="RTL"] .blocklyTreeRow {',"margin-left: 8px;","}",".blocklyTreeRow:not(.blocklyTreeSelected):hover {","background-color: rgba(255, 255, 255, 0.2);","}",".blocklyTreeSeparator {","border-bottom: solid #e5e5e5 1px;","height: 0;","margin: 5px 0;","}",".blocklyTreeSeparatorHorizontal {","border-right: solid #e5e5e5 1px;","width: 0;","padding: 5px 0;","margin: 0 5px;","}",".blocklyTreeIcon {","background-image: url(<<>>/sprites.png);","height: 16px;","vertical-align: middle;","width: 16px;","}",".blocklyTreeIconClosedLtr {","background-position: -32px -1px;","}",".blocklyTreeIconClosedRtl {","background-position: 0 -1px;","}",".blocklyTreeIconOpen {","background-position: -16px -1px;","}",".blocklyTreeSelected>.blocklyTreeIconClosedLtr {","background-position: -32px -17px;","}",".blocklyTreeSelected>.blocklyTreeIconClosedRtl {","background-position: 0 -17px;","}",".blocklyTreeSelected>.blocklyTreeIconOpen {","background-position: -16px -17px;","}",".blocklyTreeIconNone,",".blocklyTreeSelected>.blocklyTreeIconNone {","background-position: -48px -1px;","}",".blocklyTreeLabel {","cursor: default;","font-family: sans-serif;","font-size: 16px;","padding: 0 3px;","vertical-align: middle;","}",".blocklyToolboxDelete .blocklyTreeLabel {",'cursor: url("<<>>/handdelete.cur"), auto;',"}",".blocklyTreeSelected .blocklyTreeLabel {","color: #fff;","}"]),t.Trashcan=function(e){if(this.workspace_=e,this.contents_=[],this.flyout=null,!(0>=this.workspace_.options.maxTrashcanContents)){if(e=new t.Options({scrollbars:!0,parentWorkspace:this.workspace_,rtl:this.workspace_.RTL,oneBasedIndex:this.workspace_.options.oneBasedIndex,renderer:this.workspace_.options.renderer,rendererOverrides:this.workspace_.options.rendererOverrides}),this.workspace_.horizontalLayout){if(e.toolboxPosition=this.workspace_.toolboxPosition==t.TOOLBOX_AT_TOP?t.TOOLBOX_AT_BOTTOM:t.TOOLBOX_AT_TOP,!t.HorizontalFlyout)throw Error("Missing require for Blockly.HorizontalFlyout");this.flyout=new t.HorizontalFlyout(e)}else{if(e.toolboxPosition=this.workspace_.toolboxPosition==t.TOOLBOX_AT_RIGHT?t.TOOLBOX_AT_LEFT:t.TOOLBOX_AT_RIGHT,!t.VerticalFlyout)throw Error("Missing require for Blockly.VerticalFlyout");this.flyout=new t.VerticalFlyout(e)}this.workspace_.addChangeListener(this.onDelete_.bind(this))}},t.Trashcan.prototype.WIDTH_=47,t.Trashcan.prototype.BODY_HEIGHT_=44,t.Trashcan.prototype.LID_HEIGHT_=16,t.Trashcan.prototype.MARGIN_BOTTOM_=20,t.Trashcan.prototype.MARGIN_SIDE_=20,t.Trashcan.prototype.MARGIN_HOTSPOT_=10,t.Trashcan.prototype.SPRITE_LEFT_=0,t.Trashcan.prototype.SPRITE_TOP_=32,t.Trashcan.prototype.HAS_BLOCKS_LID_ANGLE_=.1,t.Trashcan.ANIMATION_LENGTH_=80,t.Trashcan.ANIMATION_FRAMES_=4,t.Trashcan.OPACITY_MIN_=.4,t.Trashcan.OPACITY_MAX_=.8,t.Trashcan.MAX_LID_ANGLE_=45,t.Trashcan.prototype.isOpen=!1,t.Trashcan.prototype.minOpenness_=0,t.Trashcan.prototype.svgGroup_=null,t.Trashcan.prototype.svgLid_=null,t.Trashcan.prototype.lidTask_=0,t.Trashcan.prototype.lidOpen_=0,t.Trashcan.prototype.left_=0,t.Trashcan.prototype.top_=0,t.Trashcan.prototype.createDom=function(){this.svgGroup_=t.utils.dom.createSvgElement("g",{class:"blocklyTrash"},null);var e=String(Math.random()).substring(2),o=t.utils.dom.createSvgElement("clipPath",{id:"blocklyTrashBodyClipPath"+e},this.svgGroup_);t.utils.dom.createSvgElement("rect",{width:this.WIDTH_,height:this.BODY_HEIGHT_,y:this.LID_HEIGHT_},o);var i=t.utils.dom.createSvgElement("image",{width:t.SPRITE.width,x:-this.SPRITE_LEFT_,height:t.SPRITE.height,y:-this.SPRITE_TOP_,"clip-path":"url(#blocklyTrashBodyClipPath"+e+")"},this.svgGroup_);return i.setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",this.workspace_.options.pathToMedia+t.SPRITE.url),o=t.utils.dom.createSvgElement("clipPath",{id:"blocklyTrashLidClipPath"+e},this.svgGroup_),t.utils.dom.createSvgElement("rect",{width:this.WIDTH_,height:this.LID_HEIGHT_},o),this.svgLid_=t.utils.dom.createSvgElement("image",{width:t.SPRITE.width,x:-this.SPRITE_LEFT_,height:t.SPRITE.height,y:-this.SPRITE_TOP_,"clip-path":"url(#blocklyTrashLidClipPath"+e+")"},this.svgGroup_),this.svgLid_.setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",this.workspace_.options.pathToMedia+t.SPRITE.url),t.bindEventWithChecks_(this.svgGroup_,"mouseup",this,this.click),t.bindEvent_(i,"mouseover",this,this.mouseOver_),t.bindEvent_(i,"mouseout",this,this.mouseOut_),this.animateLid_(),this.svgGroup_},t.Trashcan.prototype.init=function(e){return 0this.minOpenness_&&1>this.lidOpen_&&(this.lidTask_=setTimeout(this.animateLid_.bind(this),t.Trashcan.ANIMATION_LENGTH_/e))},t.Trashcan.prototype.setLidAngle_=function(e){var o=this.workspace_.toolboxPosition==t.TOOLBOX_AT_RIGHT||this.workspace_.horizontalLayout&&this.workspace_.RTL;this.svgLid_.setAttribute("transform","rotate("+(o?-e:e)+","+(o?4:this.WIDTH_-4)+","+(this.LID_HEIGHT_-2)+")")},t.Trashcan.prototype.setMinOpenness_=function(e){this.minOpenness_=e,this.isOpen||this.setLidAngle_(e*t.Trashcan.MAX_LID_ANGLE_)},t.Trashcan.prototype.close=function(){this.setOpen(!1)},t.Trashcan.prototype.click=function(){if(this.contents_.length){for(var e,o=[],i=0;e=this.contents_[i];i++)o[i]=t.Xml.textToDom(e);this.flyout.show(o)}},t.Trashcan.prototype.mouseOver_=function(){this.contents_.length&&this.setOpen(!0)},t.Trashcan.prototype.mouseOut_=function(){this.setOpen(!1)},t.Trashcan.prototype.onDelete_=function(e){if(!(0>=this.workspace_.options.maxTrashcanContents)&&e.type==t.Events.BLOCK_DELETE&&"shadow"!=e.oldXml.tagName.toLowerCase()&&(e=this.cleanBlockXML_(e.oldXml),-1==this.contents_.indexOf(e))){for(this.contents_.unshift(e);this.contents_.length>this.workspace_.options.maxTrashcanContents;)this.contents_.pop();this.setMinOpenness_(this.HAS_BLOCKS_LID_ANGLE_)}},t.Trashcan.prototype.cleanBlockXML_=function(e){for(var o=e=e.cloneNode(!0);o;){o.removeAttribute&&(o.removeAttribute("x"),o.removeAttribute("y"),o.removeAttribute("id"),o.removeAttribute("disabled"),"comment"==o.nodeName&&(o.removeAttribute("h"),o.removeAttribute("w"),o.removeAttribute("pinned")));var i=o.firstChild||o.nextSibling;if(!i)for(i=o.parentNode;i;){if(i.nextSibling){i=i.nextSibling;break}i=i.parentNode}o=i}return t.Xml.domToText(e)},t.VariablesDynamic={},t.VariablesDynamic.onCreateVariableButtonClick_String=function(e){t.Variables.createVariableButtonHandler(e.getTargetWorkspace(),void 0,"String")},t.VariablesDynamic.onCreateVariableButtonClick_Number=function(e){t.Variables.createVariableButtonHandler(e.getTargetWorkspace(),void 0,"Number")},t.VariablesDynamic.onCreateVariableButtonClick_Colour=function(e){t.Variables.createVariableButtonHandler(e.getTargetWorkspace(),void 0,"Colour")},t.VariablesDynamic.flyoutCategory=function(e){var o=[],i=document.createElement("button");return i.setAttribute("text",t.Msg.NEW_STRING_VARIABLE),i.setAttribute("callbackKey","CREATE_VARIABLE_STRING"),o.push(i),(i=document.createElement("button")).setAttribute("text",t.Msg.NEW_NUMBER_VARIABLE),i.setAttribute("callbackKey","CREATE_VARIABLE_NUMBER"),o.push(i),(i=document.createElement("button")).setAttribute("text",t.Msg.NEW_COLOUR_VARIABLE),i.setAttribute("callbackKey","CREATE_VARIABLE_COLOUR"),o.push(i),e.registerButtonCallback("CREATE_VARIABLE_STRING",t.VariablesDynamic.onCreateVariableButtonClick_String),e.registerButtonCallback("CREATE_VARIABLE_NUMBER",t.VariablesDynamic.onCreateVariableButtonClick_Number),e.registerButtonCallback("CREATE_VARIABLE_COLOUR",t.VariablesDynamic.onCreateVariableButtonClick_Colour),e=t.VariablesDynamic.flyoutCategoryBlocks(e),o.concat(e)},t.VariablesDynamic.flyoutCategoryBlocks=function(e){var o=[];if(0<(e=e.getAllVariables()).length){if(t.Blocks.variables_set_dynamic){var i=e[e.length-1],n=t.utils.xml.createElement("block");n.setAttribute("type","variables_set_dynamic"),n.setAttribute("gap",24),n.appendChild(t.Variables.generateVariableFieldDom(i)),o.push(n)}if(t.Blocks.variables_get_dynamic){e.sort(t.VariableModel.compareByName),i=0;for(var s;s=e[i];i++)(n=t.utils.xml.createElement("block")).setAttribute("type","variables_get_dynamic"),n.setAttribute("gap",8),n.appendChild(t.Variables.generateVariableFieldDom(s)),o.push(n)}}return o},t.ZoomControls=function(t){this.workspace_=t},t.ZoomControls.prototype.WIDTH_=32,t.ZoomControls.prototype.HEIGHT_=110,t.ZoomControls.prototype.MARGIN_BOTTOM_=20,t.ZoomControls.prototype.MARGIN_SIDE_=20,t.ZoomControls.prototype.svgGroup_=null,t.ZoomControls.prototype.left_=0,t.ZoomControls.prototype.top_=0,t.ZoomControls.prototype.createDom=function(){this.svgGroup_=t.utils.dom.createSvgElement("g",{},null);var e=String(Math.random()).substring(2);return this.createZoomOutSvg_(e),this.createZoomInSvg_(e),this.workspace_.isMovable()&&this.createZoomResetSvg_(e),this.svgGroup_},t.ZoomControls.prototype.init=function(t){return this.verticalSpacing_=this.MARGIN_BOTTOM_+t,this.verticalSpacing_+this.HEIGHT_},t.ZoomControls.prototype.dispose=function(){this.svgGroup_&&t.utils.dom.removeNode(this.svgGroup_)},t.ZoomControls.prototype.position=function(){if(this.verticalSpacing_){var e=this.workspace_.getMetrics();e&&(this.left_=e.toolboxPosition==t.TOOLBOX_AT_LEFT||this.workspace_.horizontalLayout&&!this.workspace_.RTL?e.viewWidth+e.absoluteLeft-this.WIDTH_-this.MARGIN_SIDE_-t.Scrollbar.scrollbarThickness:this.MARGIN_SIDE_+t.Scrollbar.scrollbarThickness,e.toolboxPosition==t.TOOLBOX_AT_BOTTOM?(this.top_=this.verticalSpacing_,this.zoomInGroup_.setAttribute("transform","translate(0, 34)"),this.zoomResetGroup_&&this.zoomResetGroup_.setAttribute("transform","translate(0, 77)")):(this.top_=e.viewHeight+e.absoluteTop-this.HEIGHT_-this.verticalSpacing_,this.zoomInGroup_.setAttribute("transform","translate(0, 43)"),this.zoomOutGroup_.setAttribute("transform","translate(0, 77)")),this.svgGroup_.setAttribute("transform","translate("+this.left_+","+this.top_+")"))}},t.ZoomControls.prototype.createZoomOutSvg_=function(e){var o=this.workspace_;this.zoomOutGroup_=t.utils.dom.createSvgElement("g",{class:"blocklyZoom"},this.svgGroup_);var i=t.utils.dom.createSvgElement("clipPath",{id:"blocklyZoomoutClipPath"+e},this.zoomOutGroup_);t.utils.dom.createSvgElement("rect",{width:32,height:32},i),(e=t.utils.dom.createSvgElement("image",{width:t.SPRITE.width,height:t.SPRITE.height,x:-64,y:-92,"clip-path":"url(#blocklyZoomoutClipPath"+e+")"},this.zoomOutGroup_)).setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",o.options.pathToMedia+t.SPRITE.url),t.bindEventWithChecks_(e,"mousedown",null,(function(e){o.markFocused(),o.zoomCenter(-1),t.Touch.clearTouchIdentifier(),e.stopPropagation(),e.preventDefault()}))},t.ZoomControls.prototype.createZoomInSvg_=function(e){var o=this.workspace_;this.zoomInGroup_=t.utils.dom.createSvgElement("g",{class:"blocklyZoom"},this.svgGroup_);var i=t.utils.dom.createSvgElement("clipPath",{id:"blocklyZoominClipPath"+e},this.zoomInGroup_);t.utils.dom.createSvgElement("rect",{width:32,height:32},i),(e=t.utils.dom.createSvgElement("image",{width:t.SPRITE.width,height:t.SPRITE.height,x:-32,y:-92,"clip-path":"url(#blocklyZoominClipPath"+e+")"},this.zoomInGroup_)).setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",o.options.pathToMedia+t.SPRITE.url),t.bindEventWithChecks_(e,"mousedown",null,(function(e){o.markFocused(),o.zoomCenter(1),t.Touch.clearTouchIdentifier(),e.stopPropagation(),e.preventDefault()}))},t.ZoomControls.prototype.createZoomResetSvg_=function(e){var o=this.workspace_;this.zoomResetGroup_=t.utils.dom.createSvgElement("g",{class:"blocklyZoom"},this.svgGroup_);var i=t.utils.dom.createSvgElement("clipPath",{id:"blocklyZoomresetClipPath"+e},this.zoomResetGroup_);t.utils.dom.createSvgElement("rect",{width:32,height:32},i),(e=t.utils.dom.createSvgElement("image",{width:t.SPRITE.width,height:t.SPRITE.height,y:-92,"clip-path":"url(#blocklyZoomresetClipPath"+e+")"},this.zoomResetGroup_)).setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",o.options.pathToMedia+t.SPRITE.url),t.bindEventWithChecks_(e,"mousedown",null,(function(e){o.markFocused(),o.setScale(o.options.zoomOptions.startScale),o.beginCanvasTransition(),o.scrollCenter(),setTimeout(o.endCanvasTransition.bind(o),500),t.Touch.clearTouchIdentifier(),e.stopPropagation(),e.preventDefault()}))},t.Css.register([".blocklyZoom>image, .blocklyZoom>svg>image {","opacity: .4;","}",".blocklyZoom>image:hover, .blocklyZoom>svg>image:hover {","opacity: .6;","}",".blocklyZoom>image:active, .blocklyZoom>svg>image:active {","opacity: .8;","}"]),t.Mutator=function(e){t.Mutator.superClass_.constructor.call(this,null),this.quarkNames_=e},t.utils.object.inherits(t.Mutator,t.Icon),t.Mutator.prototype.workspaceWidth_=0,t.Mutator.prototype.workspaceHeight_=0,t.Mutator.prototype.setBlock=function(t){this.block_=t},t.Mutator.prototype.getWorkspace=function(){return this.workspace_},t.Mutator.prototype.drawIcon_=function(e){t.utils.dom.createSvgElement("rect",{class:"blocklyIconShape",rx:"4",ry:"4",height:"16",width:"16"},e),t.utils.dom.createSvgElement("path",{class:"blocklyIconSymbol",d:"m4.203,7.296 0,1.368 -0.92,0.677 -0.11,0.41 0.9,1.559 0.41,0.11 1.043,-0.457 1.187,0.683 0.127,1.134 0.3,0.3 1.8,0 0.3,-0.299 0.127,-1.138 1.185,-0.682 1.046,0.458 0.409,-0.11 0.9,-1.559 -0.11,-0.41 -0.92,-0.677 0,-1.366 0.92,-0.677 0.11,-0.41 -0.9,-1.559 -0.409,-0.109 -1.046,0.458 -1.185,-0.682 -0.127,-1.138 -0.3,-0.299 -1.8,0 -0.3,0.3 -0.126,1.135 -1.187,0.682 -1.043,-0.457 -0.41,0.11 -0.899,1.559 0.108,0.409z"},e),t.utils.dom.createSvgElement("circle",{class:"blocklyIconShape",r:"2.7",cx:"8",cy:"8"},e)},t.Mutator.prototype.iconClick_=function(e){this.block_.isEditable()&&t.Icon.prototype.iconClick_.call(this,e)},t.Mutator.prototype.createEditor_=function(){if(this.svgDialog_=t.utils.dom.createSvgElement("svg",{x:t.Bubble.BORDER_WIDTH,y:t.Bubble.BORDER_WIDTH},null),this.quarkNames_.length)for(var e,o=t.utils.xml.createElement("xml"),i=0;e=this.quarkNames_[i];i++){var n=t.utils.xml.createElement("block");n.setAttribute("type",e),o.appendChild(n)}else o=null;return(i=new t.Options({disable:!1,parentWorkspace:this.block_.workspace,media:this.block_.workspace.options.pathToMedia,rtl:this.block_.RTL,horizontalLayout:!1,renderer:this.block_.workspace.options.renderer,rendererOverrides:this.block_.workspace.options.rendererOverrides})).toolboxPosition=this.block_.RTL?t.TOOLBOX_AT_RIGHT:t.TOOLBOX_AT_LEFT,i.languageTree=o,i.getMetrics=this.getFlyoutMetrics_.bind(this),this.workspace_=new t.WorkspaceSvg(i),this.workspace_.isMutator=!0,this.workspace_.addChangeListener(t.Events.disableOrphans),o=this.workspace_.addFlyout("g"),(i=this.workspace_.createDom("blocklyMutatorBackground")).insertBefore(o,this.workspace_.svgBlockCanvas_),this.svgDialog_.appendChild(i),this.svgDialog_},t.Mutator.prototype.updateEditable=function(){t.Mutator.superClass_.updateEditable.call(this),this.block_.isInFlyout||(this.block_.isEditable()?this.iconGroup_&&t.utils.dom.removeClass(this.iconGroup_,"blocklyIconGroupReadonly"):(this.setVisible(!1),this.iconGroup_&&t.utils.dom.addClass(this.iconGroup_,"blocklyIconGroupReadonly")))},t.Mutator.prototype.resizeBubble_=function(){var e=2*t.Bubble.BORDER_WIDTH,o=this.workspace_.getCanvas().getBBox(),i=this.block_.RTL?-o.x:o.width+o.x;o=o.height+3*e;var n=this.workspace_.getFlyout();n&&(n=n.getMetrics_(),o=Math.max(o,n.contentHeight+20)),i+=3*e,(Math.abs(this.workspaceWidth_-i)>e||Math.abs(this.workspaceHeight_-o)>e)&&(this.workspaceWidth_=i,this.workspaceHeight_=o,this.bubble_.setBubbleSize(i+e,o+e),this.svgDialog_.setAttribute("width",this.workspaceWidth_),this.svgDialog_.setAttribute("height",this.workspaceHeight_)),this.block_.RTL&&(e="translate("+this.workspaceWidth_+",0)",this.workspace_.getCanvas().setAttribute("transform",e)),this.workspace_.resize()},t.Mutator.prototype.onBubbleMove_=function(){this.workspace_&&this.workspace_.recordDeleteAreas()},t.Mutator.prototype.setVisible=function(e){if(e!=this.isVisible())if(t.Events.fire(new t.Events.Ui(this.block_,"mutatorOpen",!e,e)),e){this.bubble_=new t.Bubble(this.block_.workspace,this.createEditor_(),this.block_.pathObject.svgPath,this.iconXY_,null,null),this.bubble_.setSvgId(this.block_.id),this.bubble_.registerMoveEvent(this.onBubbleMove_.bind(this));var o=this.workspace_.options.languageTree;e=this.workspace_.getFlyout(),o&&(e.init(this.workspace_),e.show(o.childNodes)),this.rootBlock_=this.block_.decompose(this.workspace_),o=this.rootBlock_.getDescendants(!1);for(var i,n=0;i=o[n];n++)i.render();if(this.rootBlock_.setMovable(!1),this.rootBlock_.setDeletable(!1),e?(o=2*e.CORNER_RADIUS,e=e.getWidth()+o):e=o=16,this.block_.RTL&&(e=-e),this.rootBlock_.moveBy(e,o),this.block_.saveConnections){var s=this,r=this.block_;r.saveConnections(this.rootBlock_),this.sourceListener_=function(){r.saveConnections(s.rootBlock_)},this.block_.workspace.addChangeListener(this.sourceListener_)}this.resizeBubble_(),this.workspace_.addChangeListener(this.workspaceChanged_.bind(this)),this.applyColour()}else this.svgDialog_=null,this.workspace_.dispose(),this.rootBlock_=this.workspace_=null,this.bubble_.dispose(),this.bubble_=null,this.workspaceHeight_=this.workspaceWidth_=0,this.sourceListener_&&(this.block_.workspace.removeChangeListener(this.sourceListener_),this.sourceListener_=null)},t.Mutator.prototype.workspaceChanged_=function(e){if(e.type!=t.Events.UI&&(e.type!=t.Events.CHANGE||"disabled"!=e.element)){if(!this.workspace_.isDragging()){e=this.workspace_.getTopBlocks(!1);for(var o,i=0;o=e[i];i++){var n=o.getRelativeToSurfaceXY(),s=o.getHeightWidth();20>n.y+s.height&&o.moveBy(0,20-s.height-n.y)}}if(this.rootBlock_.workspace==this.workspace_){if(t.Events.setGroup(!0),e=(e=(o=this.block_).mutationToDom())&&t.Xml.domToText(e),o.compose(this.rootBlock_),o.initSvg(),o.render(),t.getMainWorkspace().keyboardAccessibilityMode&&t.navigation.moveCursorOnBlockMutation(o),e!=(i=(i=o.mutationToDom())&&t.Xml.domToText(i))){t.Events.fire(new t.Events.BlockChange(o,"mutation",null,e,i));var r=t.Events.getGroup();setTimeout((function(){t.Events.setGroup(r),o.bumpNeighbours(),t.Events.setGroup(!1)}),t.BUMP_DELAY)}this.workspace_.isDragging()||this.resizeBubble_(),t.Events.setGroup(!1)}}},t.Mutator.prototype.getFlyoutMetrics_=function(){return{viewHeight:this.workspaceHeight_,viewWidth:this.workspaceWidth_-this.workspace_.getFlyout().getWidth(),absoluteTop:0,absoluteLeft:this.workspace_.RTL?0:this.workspace_.getFlyout().getWidth()}},t.Mutator.prototype.dispose=function(){this.block_.mutator=null,t.Icon.prototype.dispose.call(this)},t.Mutator.prototype.updateBlockStyle=function(){var t=this.workspace_;if(t&&t.getAllBlocks(!1)){for(var e=t.getAllBlocks(!1),o=0;o=e&&this.sourceBlock_.outputConnection&&!o}else this.fullBlockClickTarget_=!1;this.fullBlockClickTarget_?this.clickTarget_=this.sourceBlock_.getSvgRoot():this.createBorderRect_(),this.createTextElement_()},t.FieldTextInput.prototype.doClassValidation_=function(t){return null==t?null:String(t)},t.FieldTextInput.prototype.doValueInvalid_=function(e){this.isBeingEdited_&&(this.isTextValid_=!1,e=this.value_,this.value_=this.htmlInput_.untypedDefaultValue_,this.sourceBlock_&&t.Events.isEnabled()&&t.Events.fire(new t.Events.BlockChange(this.sourceBlock_,"field",this.name||null,e,this.value_)))},t.FieldTextInput.prototype.doValueUpdate_=function(t){this.isTextValid_=!0,this.value_=t,this.isBeingEdited_||(this.isDirty_=!0)},t.FieldTextInput.prototype.applyColour=function(){this.sourceBlock_&&this.getConstants().FULL_BLOCK_FIELDS&&(this.borderRect_?this.borderRect_.setAttribute("stroke",this.sourceBlock_.style.colourTertiary):this.sourceBlock_.pathObject.svgPath.setAttribute("fill",this.getConstants().FIELD_BORDER_RECT_COLOUR))},t.FieldTextInput.prototype.render_=function(){if(t.FieldTextInput.superClass_.render_.call(this),this.isBeingEdited_){this.resizeEditor_();var e=this.htmlInput_;this.isTextValid_?(t.utils.dom.removeClass(e,"blocklyInvalidInput"),t.utils.aria.setState(e,t.utils.aria.State.INVALID,!1)):(t.utils.dom.addClass(e,"blocklyInvalidInput"),t.utils.aria.setState(e,t.utils.aria.State.INVALID,!0))}},t.FieldTextInput.prototype.setSpellcheck=function(t){t!=this.spellcheck_&&(this.spellcheck_=t,this.htmlInput_&&this.htmlInput_.setAttribute("spellcheck",this.spellcheck_))},t.FieldTextInput.prototype.showEditor_=function(e,o){this.workspace_=this.sourceBlock_.workspace,!(e=o||!1)&&(t.utils.userAgent.MOBILE||t.utils.userAgent.ANDROID||t.utils.userAgent.IPAD)?this.showPromptEditor_():this.showInlineEditor_(e)},t.FieldTextInput.prototype.showPromptEditor_=function(){var e=this;t.prompt(t.Msg.CHANGE_VALUE_TITLE,this.getText(),(function(t){e.setValue(t)}))},t.FieldTextInput.prototype.showInlineEditor_=function(e){t.WidgetDiv.show(this,this.sourceBlock_.RTL,this.widgetDispose_.bind(this)),this.htmlInput_=this.widgetCreate_(),this.isBeingEdited_=!0,e||(this.htmlInput_.focus({preventScroll:!0}),this.htmlInput_.select())},t.FieldTextInput.prototype.widgetCreate_=function(){var e=t.WidgetDiv.DIV;t.utils.dom.addClass(this.getClickTarget_(),"editing");var o=document.createElement("input");o.className="blocklyHtmlInput",o.setAttribute("spellcheck",this.spellcheck_);var i=this.workspace_.getScale(),n=this.getConstants().FIELD_TEXT_FONTSIZE*i+"pt";if(e.style.fontSize=n,o.style.fontSize=n,n=t.FieldTextInput.BORDERRADIUS*i+"px",this.fullBlockClickTarget_){n=((n=this.getScaledBBox()).bottom-n.top)/2+"px";var s=this.sourceBlock_.getParent()?this.sourceBlock_.getParent().style.colourTertiary:this.sourceBlock_.style.colourTertiary;o.style.border=1*i+"px solid "+s,e.style.borderRadius=n,e.style.transition="box-shadow 0.25s ease 0s",this.getConstants().FIELD_TEXTINPUT_BOX_SHADOW&&(e.style.boxShadow="rgba(255, 255, 255, 0.3) 0px 0px 0px "+4*i+"px")}return o.style.borderRadius=n,e.appendChild(o),o.value=o.defaultValue=this.getEditorText_(this.value_),o.untypedDefaultValue_=this.value_,o.oldValue_=null,this.resizeEditor_(),this.bindInputEvents_(o),o},t.FieldTextInput.prototype.widgetDispose_=function(){this.isBeingEdited_=!1,this.isTextValid_=!0,this.forceRerender(),this.onFinishEditing_&&this.onFinishEditing_(this.value_),this.unbindInputEvents_();var e=t.WidgetDiv.DIV.style;e.width="auto",e.height="auto",e.fontSize="",e.transition="",e.boxShadow="",this.htmlInput_=null,t.utils.dom.removeClass(this.getClickTarget_(),"editing")},t.FieldTextInput.prototype.bindInputEvents_=function(e){this.onKeyDownWrapper_=t.bindEventWithChecks_(e,"keydown",this,this.onHtmlInputKeyDown_),this.onKeyInputWrapper_=t.bindEventWithChecks_(e,"input",this,this.onHtmlInputChange_)},t.FieldTextInput.prototype.unbindInputEvents_=function(){this.onKeyDownWrapper_&&(t.unbindEvent_(this.onKeyDownWrapper_),this.onKeyDownWrapper_=null),this.onKeyInputWrapper_&&(t.unbindEvent_(this.onKeyInputWrapper_),this.onKeyInputWrapper_=null)},t.FieldTextInput.prototype.onHtmlInputKeyDown_=function(e){e.keyCode==t.utils.KeyCodes.ENTER?(t.WidgetDiv.hide(),t.DropDownDiv.hideWithoutAnimation()):e.keyCode==t.utils.KeyCodes.ESC?(this.htmlInput_.value=this.htmlInput_.defaultValue,t.WidgetDiv.hide(),t.DropDownDiv.hideWithoutAnimation()):e.keyCode==t.utils.KeyCodes.TAB&&(t.WidgetDiv.hide(),t.DropDownDiv.hideWithoutAnimation(),this.sourceBlock_.tab(this,!e.shiftKey),e.preventDefault())},t.FieldTextInput.prototype.onHtmlInputChange_=function(e){(e=this.htmlInput_.value)!==this.htmlInput_.oldValue_&&(this.htmlInput_.oldValue_=e,t.Events.setGroup(!0),e=this.getValueFromEditorText_(e),this.setValue(e),this.forceRerender(),this.resizeEditor_(),t.Events.setGroup(!1))},t.FieldTextInput.prototype.setEditorValue_=function(t){this.isDirty_=!0,this.isBeingEdited_&&(this.htmlInput_.value=this.getEditorText_(t)),this.setValue(t)},t.FieldTextInput.prototype.resizeEditor_=function(){var e=t.WidgetDiv.DIV,o=this.getScaledBBox();e.style.width=o.right-o.left+"px",e.style.height=o.bottom-o.top+"px",o=new t.utils.Coordinate(this.sourceBlock_.RTL?o.right-e.offsetWidth:o.left,o.top),e.style.left=o.x+"px",e.style.top=o.y+"px"},t.FieldTextInput.numberValidator=function(t){return console.warn("Blockly.FieldTextInput.numberValidator is deprecated. Use Blockly.FieldNumber instead."),null===t?null:(t=(t=(t=String(t)).replace(/O/gi,"0")).replace(/,/g,""),t=Number(t||0),isNaN(t)?null:String(t))},t.FieldTextInput.nonnegativeIntegerValidator=function(e){return(e=t.FieldTextInput.numberValidator(e))&&(e=String(Math.max(0,Math.floor(e)))),e},t.FieldTextInput.prototype.isTabNavigable=function(){return!0},t.FieldTextInput.prototype.getText_=function(){return this.isBeingEdited_&&this.htmlInput_?this.htmlInput_.value:null},t.FieldTextInput.prototype.getEditorText_=function(t){return String(t)},t.FieldTextInput.prototype.getValueFromEditorText_=function(t){return t},t.fieldRegistry.register("field_input",t.FieldTextInput),t.FieldAngle=function(e,o,i){this.clockwise_=t.FieldAngle.CLOCKWISE,this.offset_=t.FieldAngle.OFFSET,this.wrap_=t.FieldAngle.WRAP,this.round_=t.FieldAngle.ROUND,t.FieldAngle.superClass_.constructor.call(this,e||0,o,i),this.moveSurfaceWrapper_=this.clickSurfaceWrapper_=this.clickWrapper_=this.line_=this.gauge_=null},t.utils.object.inherits(t.FieldAngle,t.FieldTextInput),t.FieldAngle.fromJson=function(e){return new t.FieldAngle(e.angle,void 0,e)},t.FieldAngle.prototype.SERIALIZABLE=!0,t.FieldAngle.ROUND=15,t.FieldAngle.HALF=50,t.FieldAngle.CLOCKWISE=!1,t.FieldAngle.OFFSET=0,t.FieldAngle.WRAP=360,t.FieldAngle.RADIUS=t.FieldAngle.HALF-1,t.FieldAngle.prototype.configure_=function(e){switch(t.FieldAngle.superClass_.configure_.call(this,e),e.mode){case"compass":this.clockwise_=!0,this.offset_=90;break;case"protractor":this.clockwise_=!1,this.offset_=0}var o=e.clockwise;"boolean"==typeof o&&(this.clockwise_=o),null!=(o=e.offset)&&(o=Number(o),isNaN(o)||(this.offset_=o)),null!=(o=e.wrap)&&(o=Number(o),isNaN(o)||(this.wrap_=o)),null!=(e=e.round)&&(e=Number(e),isNaN(e)||(this.round_=e))},t.FieldAngle.prototype.initView=function(){t.FieldAngle.superClass_.initView.call(this),this.symbol_=t.utils.dom.createSvgElement("tspan",{},null),this.symbol_.appendChild(document.createTextNode("°")),this.textElement_.appendChild(this.symbol_)},t.FieldAngle.prototype.render_=function(){t.FieldAngle.superClass_.render_.call(this),this.updateGraph_()},t.FieldAngle.prototype.showEditor_=function(e){t.FieldAngle.superClass_.showEditor_.call(this,e,t.utils.userAgent.MOBILE||t.utils.userAgent.ANDROID||t.utils.userAgent.IPAD),e=this.dropdownCreate_(),t.DropDownDiv.getContentDiv().appendChild(e),t.DropDownDiv.setColour(this.sourceBlock_.style.colourPrimary,this.sourceBlock_.style.colourTertiary),t.DropDownDiv.showPositionedByField(this,this.dropdownDispose_.bind(this)),this.updateGraph_()},t.FieldAngle.prototype.dropdownCreate_=function(){var e=t.utils.dom.createSvgElement("svg",{xmlns:t.utils.dom.SVG_NS,"xmlns:html":t.utils.dom.HTML_NS,"xmlns:xlink":t.utils.dom.XLINK_NS,version:"1.1",height:2*t.FieldAngle.HALF+"px",width:2*t.FieldAngle.HALF+"px",style:"touch-action: none"},null),o=t.utils.dom.createSvgElement("circle",{cx:t.FieldAngle.HALF,cy:t.FieldAngle.HALF,r:t.FieldAngle.RADIUS,class:"blocklyAngleCircle"},e);this.gauge_=t.utils.dom.createSvgElement("path",{class:"blocklyAngleGauge"},e),this.line_=t.utils.dom.createSvgElement("line",{x1:t.FieldAngle.HALF,y1:t.FieldAngle.HALF,class:"blocklyAngleLine"},e);for(var i=0;360>i;i+=15)t.utils.dom.createSvgElement("line",{x1:t.FieldAngle.HALF+t.FieldAngle.RADIUS,y1:t.FieldAngle.HALF,x2:t.FieldAngle.HALF+t.FieldAngle.RADIUS-(0==i%45?10:5),y2:t.FieldAngle.HALF,class:"blocklyAngleMarks",transform:"rotate("+i+","+t.FieldAngle.HALF+","+t.FieldAngle.HALF+")"},e);return this.clickWrapper_=t.bindEventWithChecks_(e,"click",this,this.hide_),this.clickSurfaceWrapper_=t.bindEventWithChecks_(o,"click",this,this.onMouseMove_,!0,!0),this.moveSurfaceWrapper_=t.bindEventWithChecks_(o,"mousemove",this,this.onMouseMove_,!0,!0),e},t.FieldAngle.prototype.dropdownDispose_=function(){this.clickWrapper_&&(t.unbindEvent_(this.clickWrapper_),this.clickWrapper_=null),this.clickSurfaceWrapper_&&(t.unbindEvent_(this.clickSurfaceWrapper_),this.clickSurfaceWrapper_=null),this.moveSurfaceWrapper_&&(t.unbindEvent_(this.moveSurfaceWrapper_),this.moveSurfaceWrapper_=null),this.line_=this.gauge_=null},t.FieldAngle.prototype.hide_=function(){t.DropDownDiv.hideIfOwner(this),t.WidgetDiv.hide()},t.FieldAngle.prototype.onMouseMove_=function(e){var o=this.gauge_.ownerSVGElement.getBoundingClientRect(),i=e.clientX-o.left-t.FieldAngle.HALF;e=e.clientY-o.top-t.FieldAngle.HALF,o=Math.atan(-e/i),isNaN(o)||(o=t.utils.math.toDegrees(o),0>i?o+=180:0(t%=360)&&(t+=360),t>this.wrap_&&(t-=360),t},t.Css.register(".blocklyAngleCircle {,stroke: #444;,stroke-width: 1;,fill: #ddd;,fill-opacity: .8;,},.blocklyAngleMarks {,stroke: #444;,stroke-width: 1;,},.blocklyAngleGauge {,fill: #f88;,fill-opacity: .8;,pointer-events: none;,},.blocklyAngleLine {,stroke: #f00;,stroke-width: 2;,stroke-linecap: round;,pointer-events: none;,}".split(",")),t.fieldRegistry.register("field_angle",t.FieldAngle),t.FieldCheckbox=function(e,o,i){this.checkChar_=null,null==e&&(e="FALSE"),t.FieldCheckbox.superClass_.constructor.call(this,e,o,i)},t.utils.object.inherits(t.FieldCheckbox,t.Field),t.FieldCheckbox.fromJson=function(e){return new t.FieldCheckbox(e.checked,void 0,e)},t.FieldCheckbox.CHECK_CHAR="✓",t.FieldCheckbox.prototype.SERIALIZABLE=!0,t.FieldCheckbox.prototype.CURSOR="default",t.FieldCheckbox.prototype.configure_=function(e){t.FieldCheckbox.superClass_.configure_.call(this,e),e.checkCharacter&&(this.checkChar_=e.checkCharacter)},t.FieldCheckbox.prototype.initView=function(){t.FieldCheckbox.superClass_.initView.call(this),t.utils.dom.addClass(this.textElement_,"blocklyCheckbox"),this.textElement_.style.display=this.value_?"block":"none"},t.FieldCheckbox.prototype.render_=function(){this.textContent_&&(this.textContent_.nodeValue=this.getDisplayText_()),this.updateSize_(this.getConstants().FIELD_CHECKBOX_X_OFFSET)},t.FieldCheckbox.prototype.getDisplayText_=function(){return this.checkChar_||t.FieldCheckbox.CHECK_CHAR},t.FieldCheckbox.prototype.setCheckCharacter=function(t){this.checkChar_=t,this.forceRerender()},t.FieldCheckbox.prototype.showEditor_=function(){this.setValue(!this.value_)},t.FieldCheckbox.prototype.doClassValidation_=function(t){return!0===t||"TRUE"===t?"TRUE":!1===t||"FALSE"===t?"FALSE":null},t.FieldCheckbox.prototype.doValueUpdate_=function(t){this.value_=this.convertValueToBool_(t),this.textElement_&&(this.textElement_.style.display=this.value_?"block":"none")},t.FieldCheckbox.prototype.getValue=function(){return this.value_?"TRUE":"FALSE"},t.FieldCheckbox.prototype.getValueBoolean=function(){return this.value_},t.FieldCheckbox.prototype.getText=function(){return String(this.convertValueToBool_(this.value_))},t.FieldCheckbox.prototype.convertValueToBool_=function(t){return"string"==typeof t?"TRUE"==t:!!t},t.fieldRegistry.register("field_checkbox",t.FieldCheckbox),t.FieldColour=function(e,o,i){t.FieldColour.superClass_.constructor.call(this,e||t.FieldColour.COLOURS[0],o,i),this.onKeyDownWrapper_=this.onMouseLeaveWrapper_=this.onMouseEnterWrapper_=this.onMouseMoveWrapper_=this.onClickWrapper_=this.highlightedIndex_=this.picker_=null},t.utils.object.inherits(t.FieldColour,t.Field),t.FieldColour.fromJson=function(e){return new t.FieldColour(e.colour,void 0,e)},t.FieldColour.prototype.SERIALIZABLE=!0,t.FieldColour.prototype.CURSOR="default",t.FieldColour.prototype.isDirty_=!1,t.FieldColour.prototype.colours_=null,t.FieldColour.prototype.titles_=null,t.FieldColour.prototype.columns_=0,t.FieldColour.prototype.configure_=function(e){t.FieldColour.superClass_.configure_.call(this,e),e.colourOptions&&(this.colours_=e.colourOptions,this.titles_=e.colourTitles),e.columns&&(this.columns_=e.columns)},t.FieldColour.prototype.initView=function(){this.size_=new t.utils.Size(this.getConstants().FIELD_COLOUR_DEFAULT_WIDTH,this.getConstants().FIELD_COLOUR_DEFAULT_HEIGHT),this.getConstants().FIELD_COLOUR_FULL_BLOCK?this.clickTarget_=this.sourceBlock_.getSvgRoot():(this.createBorderRect_(),this.borderRect_.style.fillOpacity="1")},t.FieldColour.prototype.applyColour=function(){this.getConstants().FIELD_COLOUR_FULL_BLOCK?(this.sourceBlock_.pathObject.svgPath.setAttribute("fill",this.getValue()),this.sourceBlock_.pathObject.svgPath.setAttribute("stroke","#fff")):this.borderRect_&&(this.borderRect_.style.fill=this.getValue())},t.FieldColour.prototype.doClassValidation_=function(e){return"string"!=typeof e?null:t.utils.colour.parse(e)},t.FieldColour.prototype.doValueUpdate_=function(t){this.value_=t,this.borderRect_?this.borderRect_.style.fill=t:this.sourceBlock_&&this.sourceBlock_.rendered&&(this.sourceBlock_.pathObject.svgPath.setAttribute("fill",t),this.sourceBlock_.pathObject.svgPath.setAttribute("stroke","#fff"))},t.FieldColour.prototype.getText=function(){var t=this.value_;return/^#(.)\1(.)\2(.)\3$/.test(t)&&(t="#"+t[1]+t[3]+t[5]),t},t.FieldColour.COLOURS="#ffffff #cccccc #c0c0c0 #999999 #666666 #333333 #000000 #ffcccc #ff6666 #ff0000 #cc0000 #990000 #660000 #330000 #ffcc99 #ff9966 #ff9900 #ff6600 #cc6600 #993300 #663300 #ffff99 #ffff66 #ffcc66 #ffcc33 #cc9933 #996633 #663333 #ffffcc #ffff33 #ffff00 #ffcc00 #999900 #666600 #333300 #99ff99 #66ff99 #33ff33 #33cc00 #009900 #006600 #003300 #99ffff #33ffff #66cccc #00cccc #339999 #336666 #003333 #ccffff #66ffff #33ccff #3366ff #3333ff #000099 #000066 #ccccff #9999ff #6666cc #6633ff #6600cc #333399 #330099 #ffccff #ff99ff #cc66cc #cc33cc #993399 #663366 #330033".split(" "),t.FieldColour.TITLES=[],t.FieldColour.COLUMNS=7,t.FieldColour.prototype.setColours=function(t,e){return this.colours_=t,e&&(this.titles_=e),this},t.FieldColour.prototype.setColumns=function(t){return this.columns_=t,this},t.FieldColour.prototype.showEditor_=function(){this.picker_=this.dropdownCreate_(),t.DropDownDiv.getContentDiv().appendChild(this.picker_),t.DropDownDiv.showPositionedByField(this,this.dropdownDispose_.bind(this)),this.picker_.focus({preventScroll:!0})},t.FieldColour.prototype.onClick_=function(e){null!==(e=(e=e.target)&&e.label)&&(this.setValue(e),t.DropDownDiv.hideIfOwner(this))},t.FieldColour.prototype.onKeyDown_=function(e){var o=!1;e.keyCode===t.utils.KeyCodes.UP?(this.moveHighlightBy_(0,-1),o=!0):e.keyCode===t.utils.KeyCodes.DOWN?(this.moveHighlightBy_(0,1),o=!0):e.keyCode===t.utils.KeyCodes.LEFT?(this.moveHighlightBy_(-1,0),o=!0):e.keyCode===t.utils.KeyCodes.RIGHT?(this.moveHighlightBy_(1,0),o=!0):e.keyCode===t.utils.KeyCodes.ENTER&&((o=this.getHighlighted_())&&null!==(o=o&&o.label)&&this.setValue(o),t.DropDownDiv.hideWithoutAnimation(),o=!0),o&&e.stopPropagation()},t.FieldColour.prototype.onBlocklyAction=function(e){if(this.picker_){if(e===t.navigation.ACTION_PREVIOUS)return this.moveHighlightBy_(0,-1),!0;if(e===t.navigation.ACTION_NEXT)return this.moveHighlightBy_(0,1),!0;if(e===t.navigation.ACTION_OUT)return this.moveHighlightBy_(-1,0),!0;if(e===t.navigation.ACTION_IN)return this.moveHighlightBy_(1,0),!0}return t.FieldColour.superClass_.onBlocklyAction.call(this,e)},t.FieldColour.prototype.moveHighlightBy_=function(e,o){var i=this.colours_||t.FieldColour.COLOURS,n=this.columns_||t.FieldColour.COLUMNS,s=this.highlightedIndex_%n,r=Math.floor(this.highlightedIndex_/n);s+=e,r+=o,0>e?0>s&&0s&&(s=0):0n-1&&rn-1&&s--:0>o?0>r&&(r=0):0Math.floor(i.length/n)-1&&(r=Math.floor(i.length/n)-1),this.setHighlightedCell_(this.picker_.childNodes[r].childNodes[s],r*n+s)},t.FieldColour.prototype.onMouseMove_=function(t){var e=(t=t.target)&&Number(t.getAttribute("data-index"));null!==e&&e!==this.highlightedIndex_&&this.setHighlightedCell_(t,e)},t.FieldColour.prototype.onMouseEnter_=function(){this.picker_.focus({preventScroll:!0})},t.FieldColour.prototype.onMouseLeave_=function(){this.picker_.blur();var e=this.getHighlighted_();e&&t.utils.dom.removeClass(e,"blocklyColourHighlighted")},t.FieldColour.prototype.getHighlighted_=function(){var e=this.columns_||t.FieldColour.COLUMNS,o=this.picker_.childNodes[Math.floor(this.highlightedIndex_/e)];return o?o.childNodes[this.highlightedIndex_%e]:null},t.FieldColour.prototype.setHighlightedCell_=function(e,o){var i=this.getHighlighted_();i&&t.utils.dom.removeClass(i,"blocklyColourHighlighted"),t.utils.dom.addClass(e,"blocklyColourHighlighted"),this.highlightedIndex_=o,t.utils.aria.setState(this.picker_,t.utils.aria.State.ACTIVEDESCENDANT,e.getAttribute("id"))},t.FieldColour.prototype.dropdownCreate_=function(){var e=this.columns_||t.FieldColour.COLUMNS,o=this.colours_||t.FieldColour.COLOURS,i=this.titles_||t.FieldColour.TITLES,n=this.getValue(),s=document.createElement("table");s.className="blocklyColourTable",s.tabIndex=0,s.dir="ltr",t.utils.aria.setRole(s,t.utils.aria.Role.GRID),t.utils.aria.setState(s,t.utils.aria.State.EXPANDED,!0),t.utils.aria.setState(s,t.utils.aria.State.ROWCOUNT,Math.floor(o.length/e)),t.utils.aria.setState(s,t.utils.aria.State.COLCOUNT,e);for(var r,a=0;atr>td {","border: .5px solid #888;","box-sizing: border-box;","cursor: pointer;","display: inline-block;","height: 20px;","padding: 0;","width: 20px;","}",".blocklyColourTable>tr>td.blocklyColourHighlighted {","border-color: #eee;","box-shadow: 2px 2px 7px 2px rgba(0,0,0,.3);","position: relative;","}",".blocklyColourSelected, .blocklyColourSelected:hover {","border-color: #eee !important;","outline: 1px solid #333;","position: relative;","}"]),t.fieldRegistry.register("field_colour",t.FieldColour),t.FieldDropdown=function(e,o,i){"function"!=typeof e&&t.FieldDropdown.validateOptions_(e),this.menuGenerator_=e,this.generatedOptions_=null,this.trimOptions_(),this.selectedOption_=this.getOptions(!1)[0],t.FieldDropdown.superClass_.constructor.call(this,this.selectedOption_[1],o,i),this.svgArrow_=this.arrow_=this.imageElement_=this.menu_=this.selectedMenuItem_=null},t.utils.object.inherits(t.FieldDropdown,t.Field),t.FieldDropdown.fromJson=function(e){return new t.FieldDropdown(e.options,void 0,e)},t.FieldDropdown.prototype.SERIALIZABLE=!0,t.FieldDropdown.CHECKMARK_OVERHANG=25,t.FieldDropdown.MAX_MENU_HEIGHT_VH=.45,t.FieldDropdown.IMAGE_Y_OFFSET=5,t.FieldDropdown.IMAGE_Y_PADDING=2*t.FieldDropdown.IMAGE_Y_OFFSET,t.FieldDropdown.ARROW_CHAR=t.utils.userAgent.ANDROID?"▼":"▾",t.FieldDropdown.prototype.CURSOR="default",t.FieldDropdown.prototype.initView=function(){this.shouldAddBorderRect_()?this.createBorderRect_():this.clickTarget_=this.sourceBlock_.getSvgRoot(),this.createTextElement_(),this.imageElement_=t.utils.dom.createSvgElement("image",{},this.fieldGroup_),this.getConstants().FIELD_DROPDOWN_SVG_ARROW?this.createSVGArrow_():this.createTextArrow_(),this.borderRect_&&t.utils.dom.addClass(this.borderRect_,"blocklyDropdownRect")},t.FieldDropdown.prototype.shouldAddBorderRect_=function(){return!this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW||this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW&&!this.sourceBlock_.isShadow()},t.FieldDropdown.prototype.createTextArrow_=function(){this.arrow_=t.utils.dom.createSvgElement("tspan",{},this.textElement_),this.arrow_.appendChild(document.createTextNode(this.sourceBlock_.RTL?t.FieldDropdown.ARROW_CHAR+" ":" "+t.FieldDropdown.ARROW_CHAR)),this.sourceBlock_.RTL?this.textElement_.insertBefore(this.arrow_,this.textContent_):this.textElement_.appendChild(this.arrow_)},t.FieldDropdown.prototype.createSVGArrow_=function(){this.svgArrow_=t.utils.dom.createSvgElement("image",{height:this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE+"px",width:this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE+"px"},this.fieldGroup_),this.svgArrow_.setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",this.getConstants().FIELD_DROPDOWN_SVG_ARROW_DATAURI)},t.FieldDropdown.prototype.showEditor_=function(e){if(this.menu_=this.dropdownCreate_(),this.menu_.openingCoords=e&&"number"==typeof e.clientX?new t.utils.Coordinate(e.clientX,e.clientY):null,this.menu_.render(t.DropDownDiv.getContentDiv()),t.utils.dom.addClass(this.menu_.getElement(),"blocklyDropdownMenu"),this.getConstants().FIELD_DROPDOWN_COLOURED_DIV){e=this.sourceBlock_.isShadow()?this.sourceBlock_.getParent().getColour():this.sourceBlock_.getColour();var o=this.sourceBlock_.isShadow()?this.sourceBlock_.getParent().style.colourTertiary:this.sourceBlock_.style.colourTertiary;t.DropDownDiv.setColour(e,o)}t.DropDownDiv.showPositionedByField(this,this.dropdownDispose_.bind(this)),this.menu_.focus(),this.selectedMenuItem_&&t.utils.style.scrollIntoContainerView(this.selectedMenuItem_.getElement(),this.menu_.getElement()),this.applyColour()},t.FieldDropdown.prototype.dropdownCreate_=function(){var e=new t.Menu;e.setRightToLeft(this.sourceBlock_.RTL),e.setRole(t.utils.aria.Role.LISTBOX);var o=this.getOptions(!1);this.selectedMenuItem_=null;for(var i=0;ie.length)){for(o=[],i=0;i=i||0>=o)throw Error("Height and width values of an image field must be greater than 0.");this.flipRtl_=!1,this.altText_="",t.FieldImage.superClass_.constructor.call(this,e||"",null,a),a||(this.flipRtl_=!!r,this.altText_=t.utils.replaceMessageReferences(n)||""),this.size_=new t.utils.Size(o,i+t.FieldImage.Y_PADDING),this.imageHeight_=i,this.clickHandler_=null,"function"==typeof s&&(this.clickHandler_=s),this.imageElement_=null},t.utils.object.inherits(t.FieldImage,t.Field),t.FieldImage.fromJson=function(e){return new t.FieldImage(e.src,e.width,e.height,void 0,void 0,void 0,e)},t.FieldImage.Y_PADDING=1,t.FieldImage.prototype.EDITABLE=!1,t.FieldImage.prototype.isDirty_=!1,t.FieldImage.prototype.configure_=function(e){t.FieldImage.superClass_.configure_.call(this,e),this.flipRtl_=!!e.flipRtl,this.altText_=t.utils.replaceMessageReferences(e.alt)||""},t.FieldImage.prototype.initView=function(){this.imageElement_=t.utils.dom.createSvgElement("image",{height:this.imageHeight_+"px",width:this.size_.width+"px",alt:this.altText_},this.fieldGroup_),this.imageElement_.setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",this.value_),this.clickHandler_&&(this.imageElement_.style.cursor="pointer")},t.FieldImage.prototype.updateSize_=function(){},t.FieldImage.prototype.doClassValidation_=function(t){return"string"!=typeof t?null:t},t.FieldImage.prototype.doValueUpdate_=function(e){this.value_=e,this.imageElement_&&this.imageElement_.setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",String(this.value_))},t.FieldImage.prototype.getFlipRtl=function(){return this.flipRtl_},t.FieldImage.prototype.setAlt=function(t){t!=this.altText_&&(this.altText_=t||"",this.imageElement_&&this.imageElement_.setAttribute("alt",this.altText_))},t.FieldImage.prototype.showEditor_=function(){this.clickHandler_&&this.clickHandler_(this)},t.FieldImage.prototype.setOnClickHandler=function(t){this.clickHandler_=t},t.FieldImage.prototype.getText_=function(){return this.altText_},t.fieldRegistry.register("field_image",t.FieldImage),t.FieldMultilineInput=function(e,o,i){null==e&&(e=""),t.FieldMultilineInput.superClass_.constructor.call(this,e,o,i),this.textGroup_=null},t.utils.object.inherits(t.FieldMultilineInput,t.FieldTextInput),t.FieldMultilineInput.fromJson=function(e){var o=t.utils.replaceMessageReferences(e.text);return new t.FieldMultilineInput(o,void 0,e)},t.FieldMultilineInput.prototype.initView=function(){this.createBorderRect_(),this.textGroup_=t.utils.dom.createSvgElement("g",{class:"blocklyEditableText"},this.fieldGroup_)},t.FieldMultilineInput.prototype.getDisplayText_=function(){var e=this.value_;if(!e)return t.Field.NBSP;var o=e.split("\n");e="";for(var i=0;ithis.maxDisplayLength&&(n=n.substring(0,this.maxDisplayLength-4)+"..."),e+=n=n.replace(/\s/g,t.Field.NBSP),i!==o.length-1&&(e+="\n")}return this.sourceBlock_.RTL&&(e+="‏"),e},t.FieldMultilineInput.prototype.render_=function(){for(var e;e=this.textGroup_.firstChild;)this.textGroup_.removeChild(e);e=this.getDisplayText_().split("\n");for(var o=0,i=0;io&&(o=s),i+=this.getConstants().FIELD_TEXT_HEIGHT+(0this.max_&&t.utils.aria.setState(e,t.utils.aria.State.VALUEMAX,this.max_),e},t.fieldRegistry.register("field_number",t.FieldNumber),t.FieldVariable=function(e,o,i,n,s){this.menuGenerator_=t.FieldVariable.dropdownCreate,this.defaultVariableName=e||"",this.size_=new t.utils.Size(0,0),s&&this.configure_(s),o&&this.setValidator(o),s||this.setTypes_(i,n)},t.utils.object.inherits(t.FieldVariable,t.FieldDropdown),t.FieldVariable.fromJson=function(e){var o=t.utils.replaceMessageReferences(e.variable);return new t.FieldVariable(o,void 0,void 0,void 0,e)},t.FieldVariable.prototype.workspace_=null,t.FieldVariable.prototype.SERIALIZABLE=!0,t.FieldVariable.prototype.configure_=function(e){t.FieldVariable.superClass_.configure_.call(this,e),this.setTypes_(e.variableTypes,e.defaultType)},t.FieldVariable.prototype.initModel=function(){if(!this.variable_){var e=t.Variables.getOrCreateVariablePackage(this.sourceBlock_.workspace,null,this.defaultVariableName,this.defaultType_);this.doValueUpdate_(e.getId())}},t.FieldVariable.prototype.shouldAddBorderRect_=function(){return t.FieldVariable.superClass_.shouldAddBorderRect_.call(this)&&(!this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW||"variables_get"!=this.sourceBlock_.type)},t.FieldVariable.prototype.fromXml=function(e){var o=e.getAttribute("id"),i=e.textContent,n=e.getAttribute("variabletype")||e.getAttribute("variableType")||"";if(o=t.Variables.getOrCreateVariablePackage(this.sourceBlock_.workspace,o,i,n),null!=n&&n!==o.type)throw Error("Serialized variable type with id '"+o.getId()+"' had type "+o.type+", and does not match variable field that references it: "+t.Xml.domToText(e)+".");this.setValue(o.getId())},t.FieldVariable.prototype.toXml=function(t){return this.initModel(),t.id=this.variable_.getId(),t.textContent=this.variable_.name,this.variable_.type&&t.setAttribute("variabletype",this.variable_.type),t},t.FieldVariable.prototype.setSourceBlock=function(e){if(e.isShadow())throw Error("Variable fields are not allowed to exist on shadow blocks.");t.FieldVariable.superClass_.setSourceBlock.call(this,e)},t.FieldVariable.prototype.getValue=function(){return this.variable_?this.variable_.getId():null},t.FieldVariable.prototype.getText=function(){return this.variable_?this.variable_.name:""},t.FieldVariable.prototype.getVariable=function(){return this.variable_},t.FieldVariable.prototype.getValidator=function(){return this.variable_?this.validator_:null},t.FieldVariable.prototype.doClassValidation_=function(e){if(null===e)return null;var o=t.Variables.getVariable(this.sourceBlock_.workspace,e);return o?(o=o.type,this.typeIsAllowed_(o)?e:(console.warn("Variable type doesn't match this field! Type was "+o),null)):(console.warn("Variable id doesn't point to a real variable! ID was "+e),null)},t.FieldVariable.prototype.doValueUpdate_=function(e){this.variable_=t.Variables.getVariable(this.sourceBlock_.workspace,e),t.FieldVariable.superClass_.doValueUpdate_.call(this,e)},t.FieldVariable.prototype.typeIsAllowed_=function(t){var e=this.getVariableTypes_();if(!e)return!0;for(var o=0;orect,",t+" .blocklyEditableText>rect {","fill: "+this.FIELD_BORDER_RECT_COLOUR+";","fill-opacity: .6;","stroke: none;","}",t+" .blocklyNonEditableText>text,",t+" .blocklyEditableText>text {","fill: #000;","}",t+" .blocklyFlyoutLabelText {","fill: #000;","}",t+" .blocklyText.blocklyBubbleText {","fill: #000;","}",t+" .blocklyEditableText:not(.editing):hover>rect {","stroke: #fff;","stroke-width: 2;","}",t+" .blocklyHtmlInput {","font-family: "+this.FIELD_TEXT_FONTFAMILY+";","font-weight: "+this.FIELD_TEXT_FONTWEIGHT+";","}",t+" .blocklySelected>.blocklyPath {","stroke: #fc3;","stroke-width: 3px;","}",t+" .blocklyHighlightedConnectionPath {","stroke: #fc3;","}",t+" .blocklyReplaceable .blocklyPath {","fill-opacity: .5;","}",t+" .blocklyReplaceable .blocklyPathLight,",t+" .blocklyReplaceable .blocklyPathDark {","display: none;","}",t+" .blocklyInsertionMarker>.blocklyPath {","fill-opacity: "+this.INSERTION_MARKER_OPACITY+";","stroke: none","}"]},t.blockRendering.MarkerSvg=function(t,e,o){this.workspace_=t,this.marker_=o,this.parent_=null,this.constants_=e,this.currentMarkerSvg=null,t=this.isCursor()?this.constants_.CURSOR_COLOUR:this.constants_.MARKER_COLOUR,this.colour_=o.colour||t},t.blockRendering.MarkerSvg.CURSOR_CLASS="blocklyCursor",t.blockRendering.MarkerSvg.MARKER_CLASS="blocklyMarker",t.blockRendering.MarkerSvg.HEIGHT_MULTIPLIER=.75,t.blockRendering.MarkerSvg.prototype.getSvgRoot=function(){return this.svgGroup_},t.blockRendering.MarkerSvg.prototype.isCursor=function(){return"cursor"==this.marker_.type},t.blockRendering.MarkerSvg.prototype.createDom=function(){var e=this.isCursor()?t.blockRendering.MarkerSvg.CURSOR_CLASS:t.blockRendering.MarkerSvg.MARKER_CLASS;return this.svgGroup_=t.utils.dom.createSvgElement("g",{class:e},null),this.createDomInternal_(),this.applyColour_(),this.svgGroup_},t.blockRendering.MarkerSvg.prototype.setParent_=function(t){this.isCursor()?(this.parent_&&this.parent_.setCursorSvg(null),t.setCursorSvg(this.getSvgRoot())):(this.parent_&&this.parent_.setMarkerSvg(null),t.setMarkerSvg(this.getSvgRoot())),this.parent_=t},t.blockRendering.MarkerSvg.prototype.showWithBlockPrevOutput_=function(e){if(e){var o=e.width,i=e.height,n=i*t.blockRendering.MarkerSvg.HEIGHT_MULTIPLIER,s=this.constants_.CURSOR_BLOCK_PADDING;if(e.previousConnection){var r=this.constants_.shapeFor(e.previousConnection);this.positionPrevious_(o,s,n,r)}else e.outputConnection?(r=this.constants_.shapeFor(e.outputConnection),this.positionOutput_(o,i,r)):this.positionBlock_(o,s,n);this.setParent_(e),this.showCurrent_()}},t.blockRendering.MarkerSvg.prototype.showWithCoordinates_=function(t){var e=t.getWsCoordinate();t=e.x,e=e.y,this.workspace_.RTL&&(t-=this.constants_.CURSOR_WS_WIDTH),this.positionLine_(t,e,this.constants_.CURSOR_WS_WIDTH),this.setParent_(this.workspace_),this.showCurrent_()},t.blockRendering.MarkerSvg.prototype.showWithField_=function(t){var e=(t=t.getLocation()).getSize().width,o=t.getSize().height;this.positionRect_(0,0,e,o),this.setParent_(t),this.showCurrent_()},t.blockRendering.MarkerSvg.prototype.showWithInput_=function(t){var e=(t=t.getLocation()).getSourceBlock();this.positionInput_(t),this.setParent_(e),this.showCurrent_()},t.blockRendering.MarkerSvg.prototype.showWithNext_=function(t){var e=t.getLocation();t=e.getSourceBlock();var o=0;e=e.getOffsetInBlock().y;var i=t.getHeightWidth().width;this.workspace_.RTL&&(o=-i),this.positionLine_(o,e,i),this.setParent_(t),this.showCurrent_()},t.blockRendering.MarkerSvg.prototype.showWithStack_=function(t){var e=(t=t.getLocation()).getHeightWidth(),o=e.width+this.constants_.CURSOR_STACK_PADDING;e=e.height+this.constants_.CURSOR_STACK_PADDING;var i=-this.constants_.CURSOR_STACK_PADDING/2,n=-this.constants_.CURSOR_STACK_PADDING/2,s=i;this.workspace_.RTL&&(s=-(o+i)),this.positionRect_(s,n,o,e),this.setParent_(t),this.showCurrent_()},t.blockRendering.MarkerSvg.prototype.showCurrent_=function(){this.hide(),this.currentMarkerSvg.style.display=""},t.blockRendering.MarkerSvg.prototype.positionBlock_=function(e,o,i){e=t.utils.svgPaths.moveBy(-o,i)+t.utils.svgPaths.lineOnAxis("V",-o)+t.utils.svgPaths.lineOnAxis("H",e+2*o)+t.utils.svgPaths.lineOnAxis("V",i),this.markerBlock_.setAttribute("d",e),this.workspace_.RTL&&this.flipRtl_(this.markerBlock_),this.currentMarkerSvg=this.markerBlock_},t.blockRendering.MarkerSvg.prototype.positionInput_=function(e){var o=e.getOffsetInBlock().x,i=e.getOffsetInBlock().y;e=t.utils.svgPaths.moveTo(0,0)+this.constants_.shapeFor(e).pathDown,this.markerInput_.setAttribute("d",e),this.markerInput_.setAttribute("transform","translate("+o+","+i+")"+(this.workspace_.RTL?" scale(-1 1)":"")),this.currentMarkerSvg=this.markerInput_},t.blockRendering.MarkerSvg.prototype.positionLine_=function(t,e,o){this.markerSvgLine_.setAttribute("x",t),this.markerSvgLine_.setAttribute("y",e),this.markerSvgLine_.setAttribute("width",o),this.currentMarkerSvg=this.markerSvgLine_},t.blockRendering.MarkerSvg.prototype.positionOutput_=function(e,o,i){e=t.utils.svgPaths.moveBy(e,0)+t.utils.svgPaths.lineOnAxis("h",-(e-i.width))+t.utils.svgPaths.lineOnAxis("v",this.constants_.TAB_OFFSET_FROM_TOP)+i.pathDown+t.utils.svgPaths.lineOnAxis("V",o)+t.utils.svgPaths.lineOnAxis("H",e),this.markerBlock_.setAttribute("d",e),this.workspace_.RTL&&this.flipRtl_(this.markerBlock_),this.currentMarkerSvg=this.markerBlock_},t.blockRendering.MarkerSvg.prototype.positionPrevious_=function(e,o,i,n){e=t.utils.svgPaths.moveBy(-o,i)+t.utils.svgPaths.lineOnAxis("V",-o)+t.utils.svgPaths.lineOnAxis("H",this.constants_.NOTCH_OFFSET_LEFT)+n.pathLeft+t.utils.svgPaths.lineOnAxis("H",e+2*o)+t.utils.svgPaths.lineOnAxis("V",i),this.markerBlock_.setAttribute("d",e),this.workspace_.RTL&&this.flipRtl_(this.markerBlock_),this.currentMarkerSvg=this.markerBlock_},t.blockRendering.MarkerSvg.prototype.positionRect_=function(t,e,o,i){this.markerSvgRect_.setAttribute("x",t),this.markerSvgRect_.setAttribute("y",e),this.markerSvgRect_.setAttribute("width",o),this.markerSvgRect_.setAttribute("height",i),this.currentMarkerSvg=this.markerSvgRect_},t.blockRendering.MarkerSvg.prototype.flipRtl_=function(t){t.setAttribute("transform","scale(-1 1)")},t.blockRendering.MarkerSvg.prototype.hide=function(){this.markerSvgLine_.style.display="none",this.markerSvgRect_.style.display="none",this.markerInput_.style.display="none",this.markerBlock_.style.display="none"},t.blockRendering.MarkerSvg.prototype.draw=function(t,e){if(e){this.constants_=this.workspace_.getRenderer().getConstants();var o=this.isCursor()?this.constants_.CURSOR_COLOUR:this.constants_.MARKER_COLOUR;this.colour_=this.marker_.colour||o,this.applyColour_(),this.showAtLocation_(e),this.firemarkerEvent_(t,e),void 0!==(t=this.currentMarkerSvg.childNodes[0])&&t.beginElement&&t.beginElement()}else this.hide()},t.blockRendering.MarkerSvg.prototype.showAtLocation_=function(e){e.getType()==t.ASTNode.types.BLOCK?(e=e.getLocation(),this.showWithBlockPrevOutput_(e)):e.getType()==t.ASTNode.types.OUTPUT?(e=e.getLocation().getSourceBlock(),this.showWithBlockPrevOutput_(e)):e.getLocation().type==t.INPUT_VALUE?this.showWithInput_(e):e.getLocation().type==t.NEXT_STATEMENT?this.showWithNext_(e):e.getType()==t.ASTNode.types.PREVIOUS?(e=e.getLocation().getSourceBlock(),this.showWithBlockPrevOutput_(e)):e.getType()==t.ASTNode.types.FIELD?this.showWithField_(e):e.getType()==t.ASTNode.types.WORKSPACE?this.showWithCoordinates_(e):e.getType()==t.ASTNode.types.STACK&&this.showWithStack_(e)},t.blockRendering.MarkerSvg.prototype.firemarkerEvent_=function(e,o){var i=o.getSourceBlock(),n=this.isCursor()?"cursorMove":"markerMove";e=new t.Events.Ui(i,n,e,o),o.getType()==t.ASTNode.types.WORKSPACE&&(e.workspaceId=o.getLocation().id),t.Events.fire(e)},t.blockRendering.MarkerSvg.prototype.getBlinkProperties_=function(){return{attributeType:"XML",attributeName:"fill",dur:"1s",values:this.colour_+";transparent;transparent;",repeatCount:"indefinite"}},t.blockRendering.MarkerSvg.prototype.createDomInternal_=function(){if(this.markerSvg_=t.utils.dom.createSvgElement("g",{width:this.constants_.CURSOR_WS_WIDTH,height:this.constants_.WS_CURSOR_HEIGHT},this.svgGroup_),this.markerSvgLine_=t.utils.dom.createSvgElement("rect",{width:this.constants_.CURSOR_WS_WIDTH,height:this.constants_.WS_CURSOR_HEIGHT,style:"display: none"},this.markerSvg_),this.markerSvgRect_=t.utils.dom.createSvgElement("rect",{class:"blocklyVerticalMarker",rx:10,ry:10,style:"display: none"},this.markerSvg_),this.markerInput_=t.utils.dom.createSvgElement("path",{transform:"",style:"display: none"},this.markerSvg_),this.markerBlock_=t.utils.dom.createSvgElement("path",{transform:"",style:"display: none",fill:"none","stroke-width":this.constants_.CURSOR_STROKE_WIDTH},this.markerSvg_),this.isCursor()){var e=this.getBlinkProperties_();t.utils.dom.createSvgElement("animate",e,this.markerSvgLine_),t.utils.dom.createSvgElement("animate",e,this.markerInput_),e.attributeName="stroke",t.utils.dom.createSvgElement("animate",e,this.markerBlock_)}return this.markerSvg_},t.blockRendering.MarkerSvg.prototype.applyColour_=function(){if(this.markerSvgLine_.setAttribute("fill",this.colour_),this.markerSvgRect_.setAttribute("stroke",this.colour_),this.markerInput_.setAttribute("fill",this.colour_),this.markerBlock_.setAttribute("stroke",this.colour_),this.isCursor()){var t=this.colour_+";transparent;transparent;";this.markerSvgLine_.firstChild.setAttribute("values",t),this.markerInput_.firstChild.setAttribute("values",t),this.markerBlock_.firstChild.setAttribute("values",t)}},t.blockRendering.MarkerSvg.prototype.dispose=function(){this.svgGroup_&&t.utils.dom.removeNode(this.svgGroup_)},t.blockRendering.Types={NONE:0,FIELD:1,HAT:2,ICON:4,SPACER:8,BETWEEN_ROW_SPACER:16,IN_ROW_SPACER:32,EXTERNAL_VALUE_INPUT:64,INPUT:128,INLINE_INPUT:256,STATEMENT_INPUT:512,CONNECTION:1024,PREVIOUS_CONNECTION:2048,NEXT_CONNECTION:4096,OUTPUT_CONNECTION:8192,CORNER:16384,LEFT_SQUARE_CORNER:32768,LEFT_ROUND_CORNER:65536,RIGHT_SQUARE_CORNER:131072,RIGHT_ROUND_CORNER:262144,JAGGED_EDGE:524288,ROW:1048576,TOP_ROW:2097152,BOTTOM_ROW:4194304,INPUT_ROW:8388608},t.blockRendering.Types.LEFT_CORNER=t.blockRendering.Types.LEFT_SQUARE_CORNER|t.blockRendering.Types.LEFT_ROUND_CORNER,t.blockRendering.Types.RIGHT_CORNER=t.blockRendering.Types.RIGHT_SQUARE_CORNER|t.blockRendering.Types.RIGHT_ROUND_CORNER,t.blockRendering.Types.nextTypeValue_=16777216,t.blockRendering.Types.getType=function(e){return t.blockRendering.Types.hasOwnProperty(e)||(t.blockRendering.Types[e]=t.blockRendering.Types.nextTypeValue_,t.blockRendering.Types.nextTypeValue_<<=1),t.blockRendering.Types[e]},t.blockRendering.Types.isField=function(e){return e.type&t.blockRendering.Types.FIELD},t.blockRendering.Types.isHat=function(e){return e.type&t.blockRendering.Types.HAT},t.blockRendering.Types.isIcon=function(e){return e.type&t.blockRendering.Types.ICON},t.blockRendering.Types.isSpacer=function(e){return e.type&t.blockRendering.Types.SPACER},t.blockRendering.Types.isInRowSpacer=function(e){return e.type&t.blockRendering.Types.IN_ROW_SPACER},t.blockRendering.Types.isInput=function(e){return e.type&t.blockRendering.Types.INPUT},t.blockRendering.Types.isExternalInput=function(e){return e.type&t.blockRendering.Types.EXTERNAL_VALUE_INPUT},t.blockRendering.Types.isInlineInput=function(e){return e.type&t.blockRendering.Types.INLINE_INPUT},t.blockRendering.Types.isStatementInput=function(e){return e.type&t.blockRendering.Types.STATEMENT_INPUT},t.blockRendering.Types.isPreviousConnection=function(e){return e.type&t.blockRendering.Types.PREVIOUS_CONNECTION},t.blockRendering.Types.isNextConnection=function(e){return e.type&t.blockRendering.Types.NEXT_CONNECTION},t.blockRendering.Types.isPreviousOrNextConnection=function(e){return e.type&(t.blockRendering.Types.PREVIOUS_CONNECTION|t.blockRendering.Types.NEXT_CONNECTION)},t.blockRendering.Types.isLeftRoundedCorner=function(e){return e.type&t.blockRendering.Types.LEFT_ROUND_CORNER},t.blockRendering.Types.isRightRoundedCorner=function(e){return e.type&t.blockRendering.Types.RIGHT_ROUND_CORNER},t.blockRendering.Types.isLeftSquareCorner=function(e){return e.type&t.blockRendering.Types.LEFT_SQUARE_CORNER},t.blockRendering.Types.isRightSquareCorner=function(e){return e.type&t.blockRendering.Types.RIGHT_SQUARE_CORNER},t.blockRendering.Types.isCorner=function(e){return e.type&t.blockRendering.Types.CORNER},t.blockRendering.Types.isJaggedEdge=function(e){return e.type&t.blockRendering.Types.JAGGED_EDGE},t.blockRendering.Types.isRow=function(e){return e.type&t.blockRendering.Types.ROW},t.blockRendering.Types.isBetweenRowSpacer=function(e){return e.type&t.blockRendering.Types.BETWEEN_ROW_SPACER},t.blockRendering.Types.isTopRow=function(e){return e.type&t.blockRendering.Types.TOP_ROW},t.blockRendering.Types.isBottomRow=function(e){return e.type&t.blockRendering.Types.BOTTOM_ROW},t.blockRendering.Types.isTopOrBottomRow=function(e){return e.type&(t.blockRendering.Types.TOP_ROW|t.blockRendering.Types.BOTTOM_ROW)},t.blockRendering.Types.isInputRow=function(e){return e.type&t.blockRendering.Types.INPUT_ROW},t.blockRendering.Measurable=function(e){this.height=this.width=0,this.type=t.blockRendering.Types.NONE,this.centerline=this.xPos=0,this.constants_=e,this.notchOffset=this.constants_.NOTCH_OFFSET_LEFT},t.blockRendering.Connection=function(e,o){t.blockRendering.Connection.superClass_.constructor.call(this,e),this.connectionModel=o,this.shape=this.constants_.shapeFor(o),this.isDynamicShape=!!this.shape.isDynamic,this.type|=t.blockRendering.Types.CONNECTION},t.utils.object.inherits(t.blockRendering.Connection,t.blockRendering.Measurable),t.blockRendering.OutputConnection=function(e,o){t.blockRendering.OutputConnection.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.OUTPUT_CONNECTION,this.height=this.isDynamicShape?0:this.shape.height,this.startX=this.width=this.isDynamicShape?0:this.shape.width,this.connectionOffsetY=this.constants_.TAB_OFFSET_FROM_TOP,this.connectionOffsetX=0},t.utils.object.inherits(t.blockRendering.OutputConnection,t.blockRendering.Connection),t.blockRendering.PreviousConnection=function(e,o){t.blockRendering.PreviousConnection.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.PREVIOUS_CONNECTION,this.height=this.shape.height,this.width=this.shape.width},t.utils.object.inherits(t.blockRendering.PreviousConnection,t.blockRendering.Connection),t.blockRendering.NextConnection=function(e,o){t.blockRendering.NextConnection.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.NEXT_CONNECTION,this.height=this.shape.height,this.width=this.shape.width},t.utils.object.inherits(t.blockRendering.NextConnection,t.blockRendering.Connection),t.blockRendering.InputConnection=function(e,o){t.blockRendering.InputConnection.superClass_.constructor.call(this,e,o.connection),this.type|=t.blockRendering.Types.INPUT,this.input=o,this.align=o.align,(this.connectedBlock=o.connection&&o.connection.targetBlock()?o.connection.targetBlock():null)?(e=this.connectedBlock.getHeightWidth(),this.connectedBlockWidth=e.width,this.connectedBlockHeight=e.height):this.connectedBlockHeight=this.connectedBlockWidth=0,this.connectionOffsetY=this.connectionOffsetX=0},t.utils.object.inherits(t.blockRendering.InputConnection,t.blockRendering.Connection),t.blockRendering.InlineInput=function(e,o){t.blockRendering.InlineInput.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.INLINE_INPUT,this.connectedBlock?(this.width=this.connectedBlockWidth,this.height=this.connectedBlockHeight):(this.height=this.constants_.EMPTY_INLINE_INPUT_HEIGHT,this.width=this.constants_.EMPTY_INLINE_INPUT_PADDING),this.connectionHeight=this.isDynamicShape?this.shape.height(this.height):this.shape.height,this.connectionWidth=this.isDynamicShape?this.shape.width(this.height):this.shape.width,this.connectedBlock||(this.width+=this.connectionWidth*(this.isDynamicShape?2:1)),this.connectionOffsetY=this.isDynamicShape?this.shape.connectionOffsetY(this.connectionHeight):this.constants_.TAB_OFFSET_FROM_TOP,this.connectionOffsetX=this.isDynamicShape?this.shape.connectionOffsetX(this.connectionWidth):0},t.utils.object.inherits(t.blockRendering.InlineInput,t.blockRendering.InputConnection),t.blockRendering.StatementInput=function(e,o){t.blockRendering.StatementInput.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.STATEMENT_INPUT,this.height=this.connectedBlock?this.connectedBlockHeight+this.constants_.STATEMENT_BOTTOM_SPACER:this.constants_.EMPTY_STATEMENT_INPUT_HEIGHT,this.width=this.constants_.STATEMENT_INPUT_NOTCH_OFFSET+this.shape.width},t.utils.object.inherits(t.blockRendering.StatementInput,t.blockRendering.InputConnection),t.blockRendering.ExternalValueInput=function(e,o){t.blockRendering.ExternalValueInput.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.EXTERNAL_VALUE_INPUT,this.height=this.connectedBlock?this.connectedBlockHeight-this.constants_.TAB_OFFSET_FROM_TOP-this.constants_.MEDIUM_PADDING:this.shape.height,this.width=this.shape.width+this.constants_.EXTERNAL_VALUE_INPUT_PADDING,this.connectionOffsetY=this.constants_.TAB_OFFSET_FROM_TOP,this.connectionHeight=this.shape.height,this.connectionWidth=this.shape.width},t.utils.object.inherits(t.blockRendering.ExternalValueInput,t.blockRendering.InputConnection),t.blockRendering.Icon=function(e,o){t.blockRendering.Icon.superClass_.constructor.call(this,e),this.icon=o,this.isVisible=o.isVisible(),this.type|=t.blockRendering.Types.ICON,e=o.getCorrectedSize(),this.height=e.height,this.width=e.width},t.utils.object.inherits(t.blockRendering.Icon,t.blockRendering.Measurable),t.blockRendering.JaggedEdge=function(e){t.blockRendering.JaggedEdge.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.JAGGED_EDGE,this.height=this.constants_.JAGGED_TEETH.height,this.width=this.constants_.JAGGED_TEETH.width},t.utils.object.inherits(t.blockRendering.JaggedEdge,t.blockRendering.Measurable),t.blockRendering.Field=function(e,o,i){t.blockRendering.Field.superClass_.constructor.call(this,e),this.field=o,this.isEditable=o.EDITABLE,this.flipRtl=o.getFlipRtl(),this.type|=t.blockRendering.Types.FIELD,e=this.field.getSize(),this.height=e.height,this.width=e.width,this.parentInput=i},t.utils.object.inherits(t.blockRendering.Field,t.blockRendering.Measurable),t.blockRendering.Hat=function(e){t.blockRendering.Hat.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.HAT,this.height=this.constants_.START_HAT.height,this.width=this.constants_.START_HAT.width,this.ascenderHeight=this.height},t.utils.object.inherits(t.blockRendering.Hat,t.blockRendering.Measurable),t.blockRendering.SquareCorner=function(e,o){t.blockRendering.SquareCorner.superClass_.constructor.call(this,e),this.type=(o&&"left"!=o?t.blockRendering.Types.RIGHT_SQUARE_CORNER:t.blockRendering.Types.LEFT_SQUARE_CORNER)|t.blockRendering.Types.CORNER,this.width=this.height=this.constants_.NO_PADDING},t.utils.object.inherits(t.blockRendering.SquareCorner,t.blockRendering.Measurable),t.blockRendering.RoundCorner=function(e,o){t.blockRendering.RoundCorner.superClass_.constructor.call(this,e),this.type=(o&&"left"!=o?t.blockRendering.Types.RIGHT_ROUND_CORNER:t.blockRendering.Types.LEFT_ROUND_CORNER)|t.blockRendering.Types.CORNER,this.width=this.constants_.CORNER_RADIUS,this.height=this.constants_.CORNER_RADIUS/2},t.utils.object.inherits(t.blockRendering.RoundCorner,t.blockRendering.Measurable),t.blockRendering.InRowSpacer=function(e,o){t.blockRendering.InRowSpacer.superClass_.constructor.call(this,e),this.type=this.type|t.blockRendering.Types.SPACER|t.blockRendering.Types.IN_ROW_SPACER,this.width=o,this.height=this.constants_.SPACER_DEFAULT_HEIGHT},t.utils.object.inherits(t.blockRendering.InRowSpacer,t.blockRendering.Measurable),t.blockRendering.Row=function(e){this.type=t.blockRendering.Types.ROW,this.elements=[],this.xPos=this.yPos=this.widthWithConnectedBlocks=this.minWidth=this.minHeight=this.width=this.height=0,this.hasJaggedEdge=this.hasDummyInput=this.hasInlineInput=this.hasStatement=this.hasExternalInput=!1,this.constants_=e,this.notchOffset=this.constants_.NOTCH_OFFSET_LEFT,this.align=null},t.blockRendering.Row.prototype.measure=function(){throw Error("Unexpected attempt to measure a base Row.")},t.blockRendering.Row.prototype.getLastInput=function(){for(var e,o=this.elements.length-1;e=this.elements[o];o--)if(t.blockRendering.Types.isInput(e))return e;return null},t.blockRendering.Row.prototype.startsWithElemSpacer=function(){return!0},t.blockRendering.Row.prototype.endsWithElemSpacer=function(){return!0},t.blockRendering.Row.prototype.getFirstSpacer=function(){for(var e,o=0;e=this.elements[o];o++)if(t.blockRendering.Types.isSpacer(e))return e;return null},t.blockRendering.Row.prototype.getLastSpacer=function(){for(var e,o=this.elements.length-1;e=this.elements[o];o--)if(t.blockRendering.Types.isSpacer(e))return e;return null},t.blockRendering.TopRow=function(e){t.blockRendering.TopRow.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.TOP_ROW,this.ascenderHeight=this.capline=0,this.hasPreviousConnection=!1,this.connection=null},t.utils.object.inherits(t.blockRendering.TopRow,t.blockRendering.Row),t.blockRendering.TopRow.prototype.hasLeftSquareCorner=function(t){var e=(t.hat?"cap"===t.hat:this.constants_.ADD_START_HATS)&&!t.outputConnection&&!t.previousConnection,o=t.getPreviousBlock();return!!t.outputConnection||e||!!o&&o.getNextBlock()==t},t.blockRendering.TopRow.prototype.hasRightSquareCorner=function(t){return!0},t.blockRendering.TopRow.prototype.measure=function(){for(var e,o=0,i=0,n=0,s=0;e=this.elements[s];s++)i+=e.width,t.blockRendering.Types.isSpacer(e)||(t.blockRendering.Types.isHat(e)?n=Math.max(n,e.ascenderHeight):o=Math.max(o,e.height));this.width=Math.max(this.minWidth,i),this.height=Math.max(this.minHeight,o)+n,this.capline=this.ascenderHeight=n,this.widthWithConnectedBlocks=this.width},t.blockRendering.TopRow.prototype.startsWithElemSpacer=function(){return!1},t.blockRendering.TopRow.prototype.endsWithElemSpacer=function(){return!1},t.blockRendering.BottomRow=function(e){t.blockRendering.BottomRow.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.BOTTOM_ROW,this.hasNextConnection=!1,this.connection=null,this.baseline=this.descenderHeight=0},t.utils.object.inherits(t.blockRendering.BottomRow,t.blockRendering.Row),t.blockRendering.BottomRow.prototype.hasLeftSquareCorner=function(t){return!!t.outputConnection||!!t.getNextBlock()},t.blockRendering.BottomRow.prototype.hasRightSquareCorner=function(t){return!0},t.blockRendering.BottomRow.prototype.measure=function(){for(var e,o=0,i=0,n=0,s=0;e=this.elements[s];s++)i+=e.width,t.blockRendering.Types.isSpacer(e)||(t.blockRendering.Types.isNextConnection(e)?n=Math.max(n,e.height):o=Math.max(o,e.height));this.width=Math.max(this.minWidth,i),this.height=Math.max(this.minHeight,o)+n,this.descenderHeight=n,this.widthWithConnectedBlocks=this.width},t.blockRendering.BottomRow.prototype.startsWithElemSpacer=function(){return!1},t.blockRendering.BottomRow.prototype.endsWithElemSpacer=function(){return!1},t.blockRendering.SpacerRow=function(e,o,i){t.blockRendering.SpacerRow.superClass_.constructor.call(this,e),this.type=this.type|t.blockRendering.Types.SPACER|t.blockRendering.Types.BETWEEN_ROW_SPACER,this.width=i,this.height=o,this.followsStatement=!1,this.widthWithConnectedBlocks=0,this.elements=[new t.blockRendering.InRowSpacer(this.constants_,i)]},t.utils.object.inherits(t.blockRendering.SpacerRow,t.blockRendering.Row),t.blockRendering.SpacerRow.prototype.measure=function(){},t.blockRendering.InputRow=function(e){t.blockRendering.InputRow.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.INPUT_ROW,this.connectedBlockWidths=0},t.utils.object.inherits(t.blockRendering.InputRow,t.blockRendering.Row),t.blockRendering.InputRow.prototype.measure=function(){this.width=this.minWidth,this.height=this.minHeight;for(var e,o=0,i=0;e=this.elements[i];i++)this.width+=e.width,t.blockRendering.Types.isInput(e)&&(t.blockRendering.Types.isStatementInput(e)?o+=e.connectedBlockWidth:t.blockRendering.Types.isExternalInput(e)&&0!=e.connectedBlockWidth&&(o+=e.connectedBlockWidth-e.connectionWidth)),t.blockRendering.Types.isSpacer(e)||(this.height=Math.max(this.height,e.height));this.connectedBlockWidths=o,this.widthWithConnectedBlocks=this.width+o},t.blockRendering.InputRow.prototype.endsWithElemSpacer=function(){return!this.hasExternalInput&&!this.hasStatement},t.blockRendering.RenderInfo=function(e,o){this.block_=o,this.renderer_=e,this.constants_=this.renderer_.getConstants(),this.outputConnection=o.outputConnection?new t.blockRendering.OutputConnection(this.constants_,o.outputConnection):null,this.isInline=o.getInputsInline()&&!o.isCollapsed(),this.isCollapsed=o.isCollapsed(),this.isInsertionMarker=o.isInsertionMarker(),this.RTL=o.RTL,this.statementEdge=this.width=this.widthWithChildren=this.height=0,this.rows=[],this.inputRows=[],this.hiddenIcons=[],this.topRow=new t.blockRendering.TopRow(this.constants_),this.bottomRow=new t.blockRendering.BottomRow(this.constants_),this.startY=this.startX=0},t.blockRendering.RenderInfo.prototype.getRenderer=function(){return this.renderer_},t.blockRendering.RenderInfo.prototype.measure=function(){this.createRows_(),this.addElemSpacing_(),this.addRowSpacing_(),this.computeBounds_(),this.alignRowElements_(),this.finalize_()},t.blockRendering.RenderInfo.prototype.createRows_=function(){this.populateTopRow_(),this.rows.push(this.topRow);var e=new t.blockRendering.InputRow(this.constants_);this.inputRows.push(e);var o=this.block_.getIcons();if(o.length)for(var i,n=0;i=o[n];n++){var s=new t.blockRendering.Icon(this.constants_,i);this.isCollapsed&&i.collapseHidden?this.hiddenIcons.push(s):e.elements.push(s)}for(i=null,n=0;o=this.block_.inputList[n];n++)if(o.isVisible()){for(this.shouldStartNewRow_(o,i)&&(this.rows.push(e),e=new t.blockRendering.InputRow(this.constants_),this.inputRows.push(e)),i=0;s=o.fieldRow[i];i++)e.elements.push(new t.blockRendering.Field(this.constants_,s,o));this.addInput_(o,e),i=o}this.isCollapsed&&(e.hasJaggedEdge=!0,e.elements.push(new t.blockRendering.JaggedEdge(this.constants_))),(e.elements.length||e.hasDummyInput)&&this.rows.push(e),this.populateBottomRow_(),this.rows.push(this.bottomRow)},t.blockRendering.RenderInfo.prototype.populateTopRow_=function(){var e=!!this.block_.previousConnection,o=(this.block_.hat?"cap"===this.block_.hat:this.constants_.ADD_START_HATS)&&!this.outputConnection&&!e;this.topRow.hasLeftSquareCorner(this.block_)?this.topRow.elements.push(new t.blockRendering.SquareCorner(this.constants_)):this.topRow.elements.push(new t.blockRendering.RoundCorner(this.constants_)),o?(e=new t.blockRendering.Hat(this.constants_),this.topRow.elements.push(e),this.topRow.capline=e.ascenderHeight):e&&(this.topRow.hasPreviousConnection=!0,this.topRow.connection=new t.blockRendering.PreviousConnection(this.constants_,this.block_.previousConnection),this.topRow.elements.push(this.topRow.connection)),this.block_.inputList.length&&this.block_.inputList[0].type==t.NEXT_STATEMENT&&!this.block_.isCollapsed()?this.topRow.minHeight=this.constants_.TOP_ROW_PRECEDES_STATEMENT_MIN_HEIGHT:this.topRow.minHeight=this.constants_.TOP_ROW_MIN_HEIGHT,this.topRow.hasRightSquareCorner(this.block_)?this.topRow.elements.push(new t.blockRendering.SquareCorner(this.constants_,"right")):this.topRow.elements.push(new t.blockRendering.RoundCorner(this.constants_,"right"))},t.blockRendering.RenderInfo.prototype.populateBottomRow_=function(){this.bottomRow.hasNextConnection=!!this.block_.nextConnection,this.bottomRow.minHeight=this.block_.inputList.length&&this.block_.inputList[this.block_.inputList.length-1].type==t.NEXT_STATEMENT?this.constants_.BOTTOM_ROW_AFTER_STATEMENT_MIN_HEIGHT:this.constants_.BOTTOM_ROW_MIN_HEIGHT,this.bottomRow.hasLeftSquareCorner(this.block_)?this.bottomRow.elements.push(new t.blockRendering.SquareCorner(this.constants_)):this.bottomRow.elements.push(new t.blockRendering.RoundCorner(this.constants_)),this.bottomRow.hasNextConnection&&(this.bottomRow.connection=new t.blockRendering.NextConnection(this.constants_,this.block_.nextConnection),this.bottomRow.elements.push(this.bottomRow.connection)),this.bottomRow.hasRightSquareCorner(this.block_)?this.bottomRow.elements.push(new t.blockRendering.SquareCorner(this.constants_,"right")):this.bottomRow.elements.push(new t.blockRendering.RoundCorner(this.constants_,"right"))},t.blockRendering.RenderInfo.prototype.addInput_=function(e,o){this.isInline&&e.type==t.INPUT_VALUE?(o.elements.push(new t.blockRendering.InlineInput(this.constants_,e)),o.hasInlineInput=!0):e.type==t.NEXT_STATEMENT?(o.elements.push(new t.blockRendering.StatementInput(this.constants_,e)),o.hasStatement=!0):e.type==t.INPUT_VALUE?(o.elements.push(new t.blockRendering.ExternalValueInput(this.constants_,e)),o.hasExternalInput=!0):e.type==t.DUMMY_INPUT&&(o.minHeight=Math.max(o.minHeight,e.getSourceBlock()&&e.getSourceBlock().isShadow()?this.constants_.DUMMY_INPUT_SHADOW_MIN_HEIGHT:this.constants_.DUMMY_INPUT_MIN_HEIGHT),o.hasDummyInput=!0),null==o.align&&(o.align=e.align)},t.blockRendering.RenderInfo.prototype.shouldStartNewRow_=function(e,o){return!(!o||e.type!=t.NEXT_STATEMENT&&o.type!=t.NEXT_STATEMENT&&(e.type!=t.INPUT_VALUE&&e.type!=t.DUMMY_INPUT||this.isInline))},t.blockRendering.RenderInfo.prototype.addElemSpacing_=function(){for(var e,o=0;e=this.rows[o];o++){var i=e.elements;if(e.elements=[],e.startsWithElemSpacer()&&e.elements.push(new t.blockRendering.InRowSpacer(this.constants_,this.getInRowSpacing_(null,i[0]))),i.length){for(var n=0;n.blocklyPathLight,",e+" .blocklyInsertionMarker>.blocklyPathDark {","fill-opacity: "+this.INSERTION_MARKER_OPACITY+";","stroke: none","}"])},t.geras.Highlighter=function(t){this.info_=t,this.inlineSteps_=this.steps_="",this.RTL_=this.info_.RTL,t=t.getRenderer(),this.constants_=t.getConstants(),this.highlightConstants_=t.getHighlightConstants(),this.highlightOffset_=this.highlightConstants_.OFFSET,this.outsideCornerPaths_=this.highlightConstants_.OUTSIDE_CORNER,this.insideCornerPaths_=this.highlightConstants_.INSIDE_CORNER,this.puzzleTabPaths_=this.highlightConstants_.PUZZLE_TAB,this.notchPaths_=this.highlightConstants_.NOTCH,this.startPaths_=this.highlightConstants_.START_HAT,this.jaggedTeethPaths_=this.highlightConstants_.JAGGED_TEETH},t.geras.Highlighter.prototype.getPath=function(){return this.steps_+"\n"+this.inlineSteps_},t.geras.Highlighter.prototype.drawTopCorner=function(e){this.steps_+=t.utils.svgPaths.moveBy(e.xPos,this.info_.startY);for(var o,i=0;o=e.elements[i];i++)t.blockRendering.Types.isLeftSquareCorner(o)?this.steps_+=this.highlightConstants_.START_POINT:t.blockRendering.Types.isLeftRoundedCorner(o)?this.steps_+=this.outsideCornerPaths_.topLeft(this.RTL_):t.blockRendering.Types.isPreviousConnection(o)?this.steps_+=this.notchPaths_.pathLeft:t.blockRendering.Types.isHat(o)?this.steps_+=this.startPaths_.path(this.RTL_):t.blockRendering.Types.isSpacer(o)&&0!=o.width&&(this.steps_+=t.utils.svgPaths.lineOnAxis("H",o.xPos+o.width-this.highlightOffset_));this.steps_+=t.utils.svgPaths.lineOnAxis("H",e.xPos+e.width-this.highlightOffset_)},t.geras.Highlighter.prototype.drawJaggedEdge_=function(e){this.info_.RTL&&(this.steps_+=this.jaggedTeethPaths_.pathLeft+t.utils.svgPaths.lineOnAxis("v",e.height-this.jaggedTeethPaths_.height-this.highlightOffset_))},t.geras.Highlighter.prototype.drawValueInput=function(e){var o=e.getLastInput();if(this.RTL_){var i=e.height-o.connectionHeight;this.steps_+=t.utils.svgPaths.moveTo(o.xPos+o.width-this.highlightOffset_,e.yPos)+this.puzzleTabPaths_.pathDown(this.RTL_)+t.utils.svgPaths.lineOnAxis("v",i)}else this.steps_+=t.utils.svgPaths.moveTo(o.xPos+o.width,e.yPos)+this.puzzleTabPaths_.pathDown(this.RTL_)},t.geras.Highlighter.prototype.drawStatementInput=function(e){var o=e.getLastInput();if(this.RTL_){var i=e.height-2*this.insideCornerPaths_.height;this.steps_+=t.utils.svgPaths.moveTo(o.xPos,e.yPos)+this.insideCornerPaths_.pathTop(this.RTL_)+t.utils.svgPaths.lineOnAxis("v",i)+this.insideCornerPaths_.pathBottom(this.RTL_)+t.utils.svgPaths.lineTo(e.width-o.xPos-this.insideCornerPaths_.width,0)}else this.steps_+=t.utils.svgPaths.moveTo(o.xPos,e.yPos+e.height)+this.insideCornerPaths_.pathBottom(this.RTL_)+t.utils.svgPaths.lineTo(e.width-o.xPos-this.insideCornerPaths_.width,0)},t.geras.Highlighter.prototype.drawRightSideRow=function(e){var o=e.xPos+e.width-this.highlightOffset_;e.followsStatement&&(this.steps_+=t.utils.svgPaths.lineOnAxis("H",o)),this.RTL_&&(this.steps_+=t.utils.svgPaths.lineOnAxis("H",o),e.height>this.highlightOffset_&&(this.steps_+=t.utils.svgPaths.lineOnAxis("V",e.yPos+e.height-this.highlightOffset_)))},t.geras.Highlighter.prototype.drawBottomRow=function(e){if(this.RTL_)this.steps_+=t.utils.svgPaths.lineOnAxis("V",e.baseline-this.highlightOffset_);else{var o=this.info_.bottomRow.elements[0];t.blockRendering.Types.isLeftSquareCorner(o)?this.steps_+=t.utils.svgPaths.moveTo(e.xPos+this.highlightOffset_,e.baseline-this.highlightOffset_):t.blockRendering.Types.isLeftRoundedCorner(o)&&(this.steps_+=t.utils.svgPaths.moveTo(e.xPos,e.baseline),this.steps_+=this.outsideCornerPaths_.bottomLeft())}},t.geras.Highlighter.prototype.drawLeft=function(){var e=this.info_.outputConnection;e&&(e=e.connectionOffsetY+e.height,this.RTL_?this.steps_+=t.utils.svgPaths.moveTo(this.info_.startX,e):(this.steps_+=t.utils.svgPaths.moveTo(this.info_.startX+this.highlightOffset_,this.info_.bottomRow.baseline-this.highlightOffset_),this.steps_+=t.utils.svgPaths.lineOnAxis("V",e)),this.steps_+=this.puzzleTabPaths_.pathUp(this.RTL_)),this.RTL_||(e=this.info_.topRow,t.blockRendering.Types.isLeftRoundedCorner(e.elements[0])?this.steps_+=t.utils.svgPaths.lineOnAxis("V",this.outsideCornerPaths_.height):this.steps_+=t.utils.svgPaths.lineOnAxis("V",e.capline+this.highlightOffset_))},t.geras.Highlighter.prototype.drawInlineInput=function(e){var o=this.highlightOffset_,i=e.xPos+e.connectionWidth,n=e.centerline-e.height/2,s=e.width-e.connectionWidth,r=n+o;this.RTL_?(n=e.connectionOffsetY-o,e=e.height-(e.connectionOffsetY+e.connectionHeight)+o,this.inlineSteps_+=t.utils.svgPaths.moveTo(i-o,r)+t.utils.svgPaths.lineOnAxis("v",n)+this.puzzleTabPaths_.pathDown(this.RTL_)+t.utils.svgPaths.lineOnAxis("v",e)+t.utils.svgPaths.lineOnAxis("h",s)):this.inlineSteps_+=t.utils.svgPaths.moveTo(e.xPos+e.width+o,r)+t.utils.svgPaths.lineOnAxis("v",e.height)+t.utils.svgPaths.lineOnAxis("h",-s)+t.utils.svgPaths.moveTo(i,n+e.connectionOffsetY)+this.puzzleTabPaths_.pathDown(this.RTL_)},t.geras.InlineInput=function(e,o){t.geras.InlineInput.superClass_.constructor.call(this,e,o),this.connectedBlock&&(this.width+=this.constants_.DARK_PATH_OFFSET,this.height+=this.constants_.DARK_PATH_OFFSET)},t.utils.object.inherits(t.geras.InlineInput,t.blockRendering.InlineInput),t.geras.StatementInput=function(e,o){t.geras.StatementInput.superClass_.constructor.call(this,e,o),this.connectedBlock&&(this.height+=this.constants_.DARK_PATH_OFFSET)},t.utils.object.inherits(t.geras.StatementInput,t.blockRendering.StatementInput),t.geras.RenderInfo=function(e,o){t.geras.RenderInfo.superClass_.constructor.call(this,e,o)},t.utils.object.inherits(t.geras.RenderInfo,t.blockRendering.RenderInfo),t.geras.RenderInfo.prototype.getRenderer=function(){return this.renderer_},t.geras.RenderInfo.prototype.populateBottomRow_=function(){t.geras.RenderInfo.superClass_.populateBottomRow_.call(this),this.block_.inputList.length&&this.block_.inputList[this.block_.inputList.length-1].type==t.NEXT_STATEMENT||(this.bottomRow.minHeight=this.constants_.MEDIUM_PADDING-this.constants_.DARK_PATH_OFFSET)},t.geras.RenderInfo.prototype.addInput_=function(e,o){this.isInline&&e.type==t.INPUT_VALUE?(o.elements.push(new t.geras.InlineInput(this.constants_,e)),o.hasInlineInput=!0):e.type==t.NEXT_STATEMENT?(o.elements.push(new t.geras.StatementInput(this.constants_,e)),o.hasStatement=!0):e.type==t.INPUT_VALUE?(o.elements.push(new t.blockRendering.ExternalValueInput(this.constants_,e)),o.hasExternalInput=!0):e.type==t.DUMMY_INPUT&&(o.minHeight=Math.max(o.minHeight,this.constants_.DUMMY_INPUT_MIN_HEIGHT),o.hasDummyInput=!0),this.isInline||null!=o.align||(o.align=e.align)},t.geras.RenderInfo.prototype.addElemSpacing_=function(){for(var e,o=!1,i=0;e=this.rows[i];i++)e.hasExternalInput&&(o=!0);for(i=0;e=this.rows[i];i++){var n=e.elements;if(e.elements=[],e.startsWithElemSpacer()&&e.elements.push(new t.blockRendering.InRowSpacer(this.constants_,this.getInRowSpacing_(null,n[0]))),n.length){for(var s=0;so?o:s,n=n?-1:1,e=(i?-1:1)*e/2,t.utils.svgPaths.lineTo(-n*s,e)+t.utils.svgPaths.lineTo(n*s,e)}var o=this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH;return{type:this.SHAPES.HEXAGONAL,isDynamic:!0,width:function(t){return(t/=2)>o?o:t},height:function(t){return t},connectionOffsetY:function(t){return t/2},connectionOffsetX:function(t){return-t},pathDown:function(t){return e(t,!1,!1)},pathUp:function(t){return e(t,!0,!1)},pathRightDown:function(t){return e(t,!1,!0)},pathRightUp:function(t){return e(t,!1,!0)}}},t.zelos.ConstantProvider.prototype.makeRounded=function(){function e(e,o,n){var s=e>i?e-i:0;return e=(e>i?i:e)/2,t.utils.svgPaths.arc("a","0 0,1",e,t.utils.svgPaths.point((o?-1:1)*e,(o?-1:1)*e))+t.utils.svgPaths.lineOnAxis("v",(n?1:-1)*s)+t.utils.svgPaths.arc("a","0 0,1",e,t.utils.svgPaths.point((o?1:-1)*e,(o?-1:1)*e))}var o=this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH,i=2*o;return{type:this.SHAPES.ROUND,isDynamic:!0,width:function(t){return(t/=2)>o?o:t},height:function(t){return t},connectionOffsetY:function(t){return t/2},connectionOffsetX:function(t){return-t},pathDown:function(t){return e(t,!1,!1)},pathUp:function(t){return e(t,!0,!1)},pathRightDown:function(t){return e(t,!1,!0)},pathRightUp:function(t){return e(t,!1,!0)}}},t.zelos.ConstantProvider.prototype.makeSquared=function(){function e(e,i,n){return e-=2*o,t.utils.svgPaths.arc("a","0 0,1",o,t.utils.svgPaths.point((i?-1:1)*o,(i?-1:1)*o))+t.utils.svgPaths.lineOnAxis("v",(n?1:-1)*e)+t.utils.svgPaths.arc("a","0 0,1",o,t.utils.svgPaths.point((i?1:-1)*o,(i?-1:1)*o))}var o=this.CORNER_RADIUS;return{type:this.SHAPES.SQUARE,isDynamic:!0,width:function(t){return o},height:function(t){return t},connectionOffsetY:function(t){return t/2},connectionOffsetX:function(t){return-t},pathDown:function(t){return e(t,!1,!1)},pathUp:function(t){return e(t,!0,!1)},pathRightDown:function(t){return e(t,!1,!0)},pathRightUp:function(t){return e(t,!1,!0)}}},t.zelos.ConstantProvider.prototype.shapeFor=function(e){var o=e.getCheck();switch(!o&&e.targetConnection&&(o=e.targetConnection.getCheck()),e.type){case t.INPUT_VALUE:case t.OUTPUT_VALUE:if(null!=(e=e.getSourceBlock().getOutputShape()))switch(e){case this.SHAPES.HEXAGONAL:return this.HEXAGONAL;case this.SHAPES.ROUND:return this.ROUNDED;case this.SHAPES.SQUARE:return this.SQUARED}return o&&-1!=o.indexOf("Boolean")?this.HEXAGONAL:(o&&-1!=o.indexOf("Number")||o&&o.indexOf("String"),this.ROUNDED);case t.PREVIOUS_STATEMENT:case t.NEXT_STATEMENT:return this.NOTCH;default:throw Error("Unknown type")}},t.zelos.ConstantProvider.prototype.makeNotch=function(){function e(e){return t.utils.svgPaths.curve("c",[t.utils.svgPaths.point(e*s/2,0),t.utils.svgPaths.point(e*s*3/4,a/2),t.utils.svgPaths.point(e*s,a)])+t.utils.svgPaths.line([t.utils.svgPaths.point(e*s,r)])+t.utils.svgPaths.curve("c",[t.utils.svgPaths.point(e*s/4,a/2),t.utils.svgPaths.point(e*s/2,a),t.utils.svgPaths.point(e*s,a)])+t.utils.svgPaths.lineOnAxis("h",e*n)+t.utils.svgPaths.curve("c",[t.utils.svgPaths.point(e*s/2,0),t.utils.svgPaths.point(e*s*3/4,-a/2),t.utils.svgPaths.point(e*s,-a)])+t.utils.svgPaths.line([t.utils.svgPaths.point(e*s,-r)])+t.utils.svgPaths.curve("c",[t.utils.svgPaths.point(e*s/4,-a/2),t.utils.svgPaths.point(e*s/2,-a),t.utils.svgPaths.point(e*s,-a)])}var o=this.NOTCH_WIDTH,i=this.NOTCH_HEIGHT,n=o/3,s=n/3,r=i/2,a=r/2,l=e(1),c=e(-1);return{type:this.SHAPES.NOTCH,width:o,height:i,pathLeft:l,pathRight:c}},t.zelos.ConstantProvider.prototype.makeInsideCorners=function(){var e=this.CORNER_RADIUS,o=t.utils.svgPaths.arc("a","0 0,0",e,t.utils.svgPaths.point(-e,e)),i=t.utils.svgPaths.arc("a","0 0,1",e,t.utils.svgPaths.point(-e,e));return{width:e,height:e,pathTop:o,pathBottom:t.utils.svgPaths.arc("a","0 0,0",e,t.utils.svgPaths.point(e,e)),rightWidth:e,rightHeight:e,pathTopRight:i,pathBottomRight:t.utils.svgPaths.arc("a","0 0,1",e,t.utils.svgPaths.point(e,e))}},t.zelos.ConstantProvider.prototype.generateSecondaryColour_=function(e){return t.utils.colour.blend("#000",e,.15)||e},t.zelos.ConstantProvider.prototype.generateTertiaryColour_=function(e){return t.utils.colour.blend("#000",e,.25)||e},t.zelos.ConstantProvider.prototype.createDom=function(e,o,i){t.zelos.ConstantProvider.superClass_.createDom.call(this,e,o,i),e=t.utils.dom.createSvgElement("defs",{},e),o=t.utils.dom.createSvgElement("filter",{id:"blocklySelectedGlowFilter"+this.randomIdentifier,height:"160%",width:"180%",y:"-30%",x:"-40%"},e),t.utils.dom.createSvgElement("feGaussianBlur",{in:"SourceGraphic",stdDeviation:this.SELECTED_GLOW_SIZE},o),i=t.utils.dom.createSvgElement("feComponentTransfer",{result:"outBlur"},o),t.utils.dom.createSvgElement("feFuncA",{type:"table",tableValues:"0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"},i),t.utils.dom.createSvgElement("feFlood",{"flood-color":this.SELECTED_GLOW_COLOUR,"flood-opacity":1,result:"outColor"},o),t.utils.dom.createSvgElement("feComposite",{in:"outColor",in2:"outBlur",operator:"in",result:"outGlow"},o),this.selectedGlowFilterId=o.id,this.selectedGlowFilter_=o,e=t.utils.dom.createSvgElement("filter",{id:"blocklyReplacementGlowFilter"+this.randomIdentifier,height:"160%",width:"180%",y:"-30%",x:"-40%"},e),t.utils.dom.createSvgElement("feGaussianBlur",{in:"SourceGraphic",stdDeviation:this.REPLACEMENT_GLOW_SIZE},e),o=t.utils.dom.createSvgElement("feComponentTransfer",{result:"outBlur"},e),t.utils.dom.createSvgElement("feFuncA",{type:"table",tableValues:"0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"},o),t.utils.dom.createSvgElement("feFlood",{"flood-color":this.REPLACEMENT_GLOW_COLOUR,"flood-opacity":1,result:"outColor"},e),t.utils.dom.createSvgElement("feComposite",{in:"outColor",in2:"outBlur",operator:"in",result:"outGlow"},e),t.utils.dom.createSvgElement("feComposite",{in:"SourceGraphic",in2:"outGlow",operator:"over"},e),this.replacementGlowFilterId=e.id,this.replacementGlowFilter_=e},t.zelos.ConstantProvider.prototype.getCSS_=function(t){return[t+" .blocklyText, ",t+" .blocklyFlyoutLabelText {","font-family: "+this.FIELD_TEXT_FONTFAMILY+";","font-size: "+this.FIELD_TEXT_FONTSIZE+"pt;","font-weight: "+this.FIELD_TEXT_FONTWEIGHT+";","}",t+" .blocklyText {","fill: #fff;","}",t+" .blocklyNonEditableText>rect:not(.blocklyDropdownRect),",t+" .blocklyEditableText>rect:not(.blocklyDropdownRect) {","fill: "+this.FIELD_BORDER_RECT_COLOUR+";","}",t+" .blocklyNonEditableText>text,",t+" .blocklyEditableText>text,",t+" .blocklyNonEditableText>g>text,",t+" .blocklyEditableText>g>text {","fill: #575E75;","}",t+" .blocklyFlyoutLabelText {","fill: #575E75;","}",t+" .blocklyText.blocklyBubbleText {","fill: #575E75;","}",t+" .blocklyDraggable:not(.blocklyDisabled)"," .blocklyEditableText:not(.editing):hover>rect ,",t+" .blocklyDraggable:not(.blocklyDisabled)"," .blocklyEditableText:not(.editing):hover>.blocklyPath {","stroke: #fff;","stroke-width: 2;","}",t+" .blocklyHtmlInput {","font-family: "+this.FIELD_TEXT_FONTFAMILY+";","font-weight: "+this.FIELD_TEXT_FONTWEIGHT+";","color: #575E75;","}",t+" .blocklyDropdownText {","fill: #fff !important;","}",t+".blocklyWidgetDiv .goog-menuitem,",t+".blocklyDropDownDiv .goog-menuitem {","font-family: "+this.FIELD_TEXT_FONTFAMILY+";","}",t+".blocklyDropDownDiv .goog-menuitem-content {","color: #fff;","}",t+" .blocklyHighlightedConnectionPath {","stroke: "+this.SELECTED_GLOW_COLOUR+";","}",t+" .blocklyDisabled > .blocklyOutlinePath {","fill: url(#blocklyDisabledPattern"+this.randomIdentifier+")","}",t+" .blocklyInsertionMarker>.blocklyPath {","fill-opacity: "+this.INSERTION_MARKER_OPACITY+";","stroke: none","}"]},t.zelos.TopRow=function(e){t.zelos.TopRow.superClass_.constructor.call(this,e)},t.utils.object.inherits(t.zelos.TopRow,t.blockRendering.TopRow),t.zelos.TopRow.prototype.endsWithElemSpacer=function(){return!1},t.zelos.TopRow.prototype.hasLeftSquareCorner=function(t){var e=(t.hat?"cap"===t.hat:this.constants_.ADD_START_HATS)&&!t.outputConnection&&!t.previousConnection;return!!t.outputConnection||e},t.zelos.TopRow.prototype.hasRightSquareCorner=function(t){return!!t.outputConnection&&!t.statementInputCount&&!t.nextConnection},t.zelos.BottomRow=function(e){t.zelos.BottomRow.superClass_.constructor.call(this,e)},t.utils.object.inherits(t.zelos.BottomRow,t.blockRendering.BottomRow),t.zelos.BottomRow.prototype.endsWithElemSpacer=function(){return!1},t.zelos.BottomRow.prototype.hasLeftSquareCorner=function(t){return!!t.outputConnection},t.zelos.BottomRow.prototype.hasRightSquareCorner=function(t){return!!t.outputConnection&&!t.statementInputCount&&!t.nextConnection},t.zelos.RightConnectionShape=function(e){t.zelos.RightConnectionShape.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.getType("RIGHT_CONNECTION"),this.width=this.height=0},t.utils.object.inherits(t.zelos.RightConnectionShape,t.blockRendering.Measurable),t.zelos.StatementInput=function(e,o){if(t.zelos.StatementInput.superClass_.constructor.call(this,e,o),this.connectedBlock){for(e=this.connectedBlock;e.getNextBlock();)e=e.getNextBlock();e.nextConnection||(this.height=this.connectedBlockHeight,this.connectedBottomNextConnection=!0)}},t.utils.object.inherits(t.zelos.StatementInput,t.blockRendering.StatementInput),t.zelos.RenderInfo=function(e,o){t.zelos.RenderInfo.superClass_.constructor.call(this,e,o),this.topRow=new t.zelos.TopRow(this.constants_),this.bottomRow=new t.zelos.BottomRow(this.constants_),this.isInline=!0,this.isMultiRow=!o.getInputsInline()||o.isCollapsed(),this.hasStatementInput=0=this.rows.length-1?!!this.bottomRow.hasNextConnection:!!r.precedesStatement,t.blockRendering.Types.isInputRow(s)&&s.hasStatement)s.measure(),o=s.width-s.getLastInput().width+e;else if(n&&(2==i||r)&&t.blockRendering.Types.isInputRow(s)&&!s.hasStatement){r=s.xPos,n=null;for(var a,l=0;a=s.elements[l];l++)t.blockRendering.Types.isSpacer(a)&&(n=a),!(n&&(t.blockRendering.Types.isField(a)||t.blockRendering.Types.isInput(a))&&ri?i:this.height/2)*(1-Math.sin(Math.acos((i-this.constants_.SMALL_PADDING)/i)));default:return 0}if(t.blockRendering.Types.isInlineInput(e)){var s=e.connectedBlock;return e=s?s.pathObject.outputShapeType:e.shape.type,s&&s.outputConnection&&(s.statementInputCount||s.nextConnection)||i==n.SHAPES.HEXAGONAL&&i!=e?0:o-this.constants_.SHAPE_IN_SHAPE_PADDING[i][e]}return t.blockRendering.Types.isField(e)?i==n.SHAPES.ROUND&&e.field instanceof t.FieldTextInput?o-2.75*n.GRID_UNIT:o-this.constants_.SHAPE_IN_SHAPE_PADDING[i][0]:t.blockRendering.Types.isIcon(e)?this.constants_.SMALL_PADDING:0},t.zelos.RenderInfo.prototype.finalizeVerticalAlignment_=function(){if(!this.outputConnection)for(var e=2;e=this.rows.length-1?!!this.bottomRow.hasNextConnection:!!n.precedesStatement;if(s?this.topRow.hasPreviousConnection:o.followsStatement){var a=3==i.elements.length&&(i.elements[1].field instanceof t.FieldLabel||i.elements[1].field instanceof t.FieldImage);if(!s&&a)o.height-=this.constants_.SMALL_PADDING,n.height-=this.constants_.SMALL_PADDING,i.height-=this.constants_.MEDIUM_PADDING;else if(s||r){if(r){for(s=!1,r=0;a=i.elements[r];r++)if(t.blockRendering.Types.isInlineInput(a)&&a.connectedBlock&&!a.connectedBlock.isShadow()&&40<=a.connectedBlock.getHeightWidth().height){s=!0;break}s&&(o.height-=this.constants_.SMALL_PADDING,n.height-=this.constants_.SMALL_PADDING)}}else o.height+=this.constants_.SMALL_PADDING}}},t.zelos.RenderInfo.prototype.finalize_=function(){this.finalizeOutputConnection_(),this.finalizeHorizontalAlignment_(),this.finalizeVerticalAlignment_(),t.zelos.RenderInfo.superClass_.finalize_.call(this),this.rightSide&&(this.widthWithChildren+=this.rightSide.width)},t.zelos.Drawer=function(e,o){t.zelos.Drawer.superClass_.constructor.call(this,e,o)},t.utils.object.inherits(t.zelos.Drawer,t.blockRendering.Drawer),t.zelos.Drawer.prototype.draw=function(){var e=this.block_.pathObject;e.beginDrawing(),this.hideHiddenIcons_(),this.drawOutline_(),this.drawInternals_(),e.setPath(this.outlinePath_+"\n"+this.inlinePath_),this.info_.RTL&&e.flipRTL(),t.blockRendering.useDebugger&&this.block_.renderingDebugger.drawDebug(this.block_,this.info_),this.recordSizeOnBlock_(),this.info_.outputConnection&&(e.outputShapeType=this.info_.outputConnection.shape.type),e.endDrawing()},t.zelos.Drawer.prototype.drawOutline_=function(){this.info_.outputConnection&&this.info_.outputConnection.isDynamicShape&&!this.info_.hasStatementInput&&!this.info_.bottomRow.hasNextConnection?(this.drawFlatTop_(),this.drawRightDynamicConnection_(),this.drawFlatBottom_(),this.drawLeftDynamicConnection_()):t.zelos.Drawer.superClass_.drawOutline_.call(this)},t.zelos.Drawer.prototype.drawLeft_=function(){this.info_.outputConnection&&this.info_.outputConnection.isDynamicShape?this.drawLeftDynamicConnection_():t.zelos.Drawer.superClass_.drawLeft_.call(this)},t.zelos.Drawer.prototype.drawRightSideRow_=function(e){if(!(0>=e.height))if(e.precedesStatement||e.followsStatement){var o=this.constants_.INSIDE_CORNERS.rightHeight;o=e.height-(e.precedesStatement?o:0),this.outlinePath_+=(e.followsStatement?this.constants_.INSIDE_CORNERS.pathBottomRight:"")+(0","GT"],["‏≥","GTE"]]},{type:"input_value",name:"B"}],inputsInline:!0,output:"Boolean",style:"logic_blocks",helpUrl:"%{BKY_LOGIC_COMPARE_HELPURL}",extensions:["logic_compare","logic_op_tooltip"]},{type:"logic_operation",message0:"%1 %2 %3",args0:[{type:"input_value",name:"A",check:"Boolean"},{type:"field_dropdown",name:"OP",options:[["%{BKY_LOGIC_OPERATION_AND}","AND"],["%{BKY_LOGIC_OPERATION_OR}","OR"]]},{type:"input_value",name:"B",check:"Boolean"}],inputsInline:!0,output:"Boolean",style:"logic_blocks",helpUrl:"%{BKY_LOGIC_OPERATION_HELPURL}",extensions:["logic_op_tooltip"]},{type:"logic_negate",message0:"%{BKY_LOGIC_NEGATE_TITLE}",args0:[{type:"input_value",name:"BOOL",check:"Boolean"}],output:"Boolean",style:"logic_blocks",tooltip:"%{BKY_LOGIC_NEGATE_TOOLTIP}",helpUrl:"%{BKY_LOGIC_NEGATE_HELPURL}"},{type:"logic_null",message0:"%{BKY_LOGIC_NULL}",output:null,style:"logic_blocks",tooltip:"%{BKY_LOGIC_NULL_TOOLTIP}",helpUrl:"%{BKY_LOGIC_NULL_HELPURL}"},{type:"logic_ternary",message0:"%{BKY_LOGIC_TERNARY_CONDITION} %1",args0:[{type:"input_value",name:"IF",check:"Boolean"}],message1:"%{BKY_LOGIC_TERNARY_IF_TRUE} %1",args1:[{type:"input_value",name:"THEN"}],message2:"%{BKY_LOGIC_TERNARY_IF_FALSE} %1",args2:[{type:"input_value",name:"ELSE"}],output:null,style:"logic_blocks",tooltip:"%{BKY_LOGIC_TERNARY_TOOLTIP}",helpUrl:"%{BKY_LOGIC_TERNARY_HELPURL}",extensions:["logic_ternary"]}]),t.defineBlocksWithJsonArray([{type:"controls_if_if",message0:"%{BKY_CONTROLS_IF_IF_TITLE_IF}",nextStatement:null,enableContextMenu:!1,style:"logic_blocks",tooltip:"%{BKY_CONTROLS_IF_IF_TOOLTIP}"},{type:"controls_if_elseif",message0:"%{BKY_CONTROLS_IF_ELSEIF_TITLE_ELSEIF}",previousStatement:null,nextStatement:null,enableContextMenu:!1,style:"logic_blocks",tooltip:"%{BKY_CONTROLS_IF_ELSEIF_TOOLTIP}"},{type:"controls_if_else",message0:"%{BKY_CONTROLS_IF_ELSE_TITLE_ELSE}",previousStatement:null,enableContextMenu:!1,style:"logic_blocks",tooltip:"%{BKY_CONTROLS_IF_ELSE_TOOLTIP}"}]),t.Constants.Logic.TOOLTIPS_BY_OP={EQ:"%{BKY_LOGIC_COMPARE_TOOLTIP_EQ}",NEQ:"%{BKY_LOGIC_COMPARE_TOOLTIP_NEQ}",LT:"%{BKY_LOGIC_COMPARE_TOOLTIP_LT}",LTE:"%{BKY_LOGIC_COMPARE_TOOLTIP_LTE}",GT:"%{BKY_LOGIC_COMPARE_TOOLTIP_GT}",GTE:"%{BKY_LOGIC_COMPARE_TOOLTIP_GTE}",AND:"%{BKY_LOGIC_OPERATION_TOOLTIP_AND}",OR:"%{BKY_LOGIC_OPERATION_TOOLTIP_OR}"},t.Extensions.register("logic_op_tooltip",t.Extensions.buildTooltipForDropdown("OP",t.Constants.Logic.TOOLTIPS_BY_OP)),t.Constants.Logic.CONTROLS_IF_MUTATOR_MIXIN={elseifCount_:0,elseCount_:0,suppressPrefixSuffix:!0,mutationToDom:function(){if(!this.elseifCount_&&!this.elseCount_)return null;var e=t.utils.xml.createElement("mutation");return this.elseifCount_&&e.setAttribute("elseif",this.elseifCount_),this.elseCount_&&e.setAttribute("else",1),e},domToMutation:function(t){this.elseifCount_=parseInt(t.getAttribute("elseif"),10)||0,this.elseCount_=parseInt(t.getAttribute("else"),10)||0,this.rebuildShape_()},decompose:function(t){var e=t.newBlock("controls_if_if");e.initSvg();for(var o=e.nextConnection,i=1;i<=this.elseifCount_;i++){var n=t.newBlock("controls_if_elseif");n.initSvg(),o.connect(n.previousConnection),o=n.nextConnection}return this.elseCount_&&((t=t.newBlock("controls_if_else")).initSvg(),o.connect(t.previousConnection)),e},compose:function(t){t=t.nextConnection.targetBlock(),this.elseCount_=this.elseifCount_=0;for(var e=[null],o=[null],i=null;t;){switch(t.type){case"controls_if_elseif":this.elseifCount_++,e.push(t.valueConnection_),o.push(t.statementConnection_);break;case"controls_if_else":this.elseCount_++,i=t.statementConnection_;break;default:throw TypeError("Unknown block type: "+t.type)}t=t.nextConnection&&t.nextConnection.targetBlock()}this.updateShape_(),this.reconnectChildBlocks_(e,o,i)},saveConnections:function(t){t=t.nextConnection.targetBlock();for(var e=1;t;){switch(t.type){case"controls_if_elseif":var o=this.getInput("IF"+e),i=this.getInput("DO"+e);t.valueConnection_=o&&o.connection.targetConnection,t.statementConnection_=i&&i.connection.targetConnection,e++;break;case"controls_if_else":i=this.getInput("ELSE"),t.statementConnection_=i&&i.connection.targetConnection;break;default:throw TypeError("Unknown block type: "+t.type)}t=t.nextConnection&&t.nextConnection.targetBlock()}},rebuildShape_:function(){var t=[null],e=[null],o=null;this.getInput("ELSE")&&(o=this.getInput("ELSE").connection.targetConnection);for(var i=1;this.getInput("IF"+i);){var n=this.getInput("IF"+i),s=this.getInput("DO"+i);t.push(n.connection.targetConnection),e.push(s.connection.targetConnection),i++}this.updateShape_(),this.reconnectChildBlocks_(t,e,o)},updateShape_:function(){this.getInput("ELSE")&&this.removeInput("ELSE");for(var e=1;this.getInput("IF"+e);)this.removeInput("IF"+e),this.removeInput("DO"+e),e++;for(e=1;e<=this.elseifCount_;e++)this.appendValueInput("IF"+e).setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_ELSEIF),this.appendStatementInput("DO"+e).appendField(t.Msg.CONTROLS_IF_MSG_THEN);this.elseCount_&&this.appendStatementInput("ELSE").appendField(t.Msg.CONTROLS_IF_MSG_ELSE)},reconnectChildBlocks_:function(e,o,i){for(var n=1;n<=this.elseifCount_;n++)t.Mutator.reconnect(e[n],this,"IF"+n),t.Mutator.reconnect(o[n],this,"DO"+n);t.Mutator.reconnect(i,this,"ELSE")}},t.Extensions.registerMutator("controls_if_mutator",t.Constants.Logic.CONTROLS_IF_MUTATOR_MIXIN,null,["controls_if_elseif","controls_if_else"]),t.Constants.Logic.CONTROLS_IF_TOOLTIP_EXTENSION=function(){this.setTooltip(function(){return this.elseifCount_||this.elseCount_?!this.elseifCount_&&this.elseCount_?t.Msg.CONTROLS_IF_TOOLTIP_2:this.elseifCount_&&!this.elseCount_?t.Msg.CONTROLS_IF_TOOLTIP_3:this.elseifCount_&&this.elseCount_?t.Msg.CONTROLS_IF_TOOLTIP_4:"":t.Msg.CONTROLS_IF_TOOLTIP_1}.bind(this))},t.Extensions.register("controls_if_tooltip",t.Constants.Logic.CONTROLS_IF_TOOLTIP_EXTENSION),t.Constants.Logic.LOGIC_COMPARE_ONCHANGE_MIXIN={onchange:function(e){this.prevBlocks_||(this.prevBlocks_=[null,null]);var o=this.getInputTargetBlock("A"),i=this.getInputTargetBlock("B");o&&i&&!o.outputConnection.checkType(i.outputConnection)&&(t.Events.setGroup(e.group),(e=this.prevBlocks_[0])!==o&&(o.unplug(),!e||e.isDisposed()||e.isShadow()||this.getInput("A").connection.connect(e.outputConnection)),(o=this.prevBlocks_[1])!==i&&(i.unplug(),!o||o.isDisposed()||o.isShadow()||this.getInput("B").connection.connect(o.outputConnection)),this.bumpNeighbours(),t.Events.setGroup(!1)),this.prevBlocks_[0]=this.getInputTargetBlock("A"),this.prevBlocks_[1]=this.getInputTargetBlock("B")}},t.Constants.Logic.LOGIC_COMPARE_EXTENSION=function(){this.mixin(t.Constants.Logic.LOGIC_COMPARE_ONCHANGE_MIXIN)},t.Extensions.register("logic_compare",t.Constants.Logic.LOGIC_COMPARE_EXTENSION),t.Constants.Logic.LOGIC_TERNARY_ONCHANGE_MIXIN={prevParentConnection_:null,onchange:function(e){var o=this.getInputTargetBlock("THEN"),i=this.getInputTargetBlock("ELSE"),n=this.outputConnection.targetConnection;if((o||i)&&n)for(var s=0;2>s;s++){var r=1==s?o:i;r&&!r.outputConnection.checkType(n)&&(t.Events.setGroup(e.group),n===this.prevParentConnection_?(this.unplug(),n.getSourceBlock().bumpNeighbours()):(r.unplug(),r.bumpNeighbours()),t.Events.setGroup(!1))}this.prevParentConnection_=n}},t.Extensions.registerMixin("logic_ternary",t.Constants.Logic.LOGIC_TERNARY_ONCHANGE_MIXIN),t.Blocks.loops={},t.Constants.Loops={},t.Constants.Loops.HUE=120,t.defineBlocksWithJsonArray([{type:"controls_repeat_ext",message0:"%{BKY_CONTROLS_REPEAT_TITLE}",args0:[{type:"input_value",name:"TIMES",check:"Number"}],message1:"%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",args1:[{type:"input_statement",name:"DO"}],previousStatement:null,nextStatement:null,style:"loop_blocks",tooltip:"%{BKY_CONTROLS_REPEAT_TOOLTIP}",helpUrl:"%{BKY_CONTROLS_REPEAT_HELPURL}"},{type:"controls_repeat",message0:"%{BKY_CONTROLS_REPEAT_TITLE}",args0:[{type:"field_number",name:"TIMES",value:10,min:0,precision:1}],message1:"%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",args1:[{type:"input_statement",name:"DO"}],previousStatement:null,nextStatement:null,style:"loop_blocks",tooltip:"%{BKY_CONTROLS_REPEAT_TOOLTIP}",helpUrl:"%{BKY_CONTROLS_REPEAT_HELPURL}"},{type:"controls_whileUntil",message0:"%1 %2",args0:[{type:"field_dropdown",name:"MODE",options:[["%{BKY_CONTROLS_WHILEUNTIL_OPERATOR_WHILE}","WHILE"],["%{BKY_CONTROLS_WHILEUNTIL_OPERATOR_UNTIL}","UNTIL"]]},{type:"input_value",name:"BOOL",check:"Boolean"}],message1:"%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",args1:[{type:"input_statement",name:"DO"}],previousStatement:null,nextStatement:null,style:"loop_blocks",helpUrl:"%{BKY_CONTROLS_WHILEUNTIL_HELPURL}",extensions:["controls_whileUntil_tooltip"]},{type:"controls_for",message0:"%{BKY_CONTROLS_FOR_TITLE}",args0:[{type:"field_variable",name:"VAR",variable:null},{type:"input_value",name:"FROM",check:"Number",align:"RIGHT"},{type:"input_value",name:"TO",check:"Number",align:"RIGHT"},{type:"input_value",name:"BY",check:"Number",align:"RIGHT"}],message1:"%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",args1:[{type:"input_statement",name:"DO"}],inputsInline:!0,previousStatement:null,nextStatement:null,style:"loop_blocks",helpUrl:"%{BKY_CONTROLS_FOR_HELPURL}",extensions:["contextMenu_newGetVariableBlock","controls_for_tooltip"]},{type:"controls_forEach",message0:"%{BKY_CONTROLS_FOREACH_TITLE}",args0:[{type:"field_variable",name:"VAR",variable:null},{type:"input_value",name:"LIST",check:"Array"}],message1:"%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",args1:[{type:"input_statement",name:"DO"}],previousStatement:null,nextStatement:null,style:"loop_blocks",helpUrl:"%{BKY_CONTROLS_FOREACH_HELPURL}",extensions:["contextMenu_newGetVariableBlock","controls_forEach_tooltip"]},{type:"controls_flow_statements",message0:"%1",args0:[{type:"field_dropdown",name:"FLOW",options:[["%{BKY_CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK}","BREAK"],["%{BKY_CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE}","CONTINUE"]]}],previousStatement:null,style:"loop_blocks",helpUrl:"%{BKY_CONTROLS_FLOW_STATEMENTS_HELPURL}",extensions:["controls_flow_tooltip","controls_flow_in_loop_check"]}]),t.Constants.Loops.WHILE_UNTIL_TOOLTIPS={WHILE:"%{BKY_CONTROLS_WHILEUNTIL_TOOLTIP_WHILE}",UNTIL:"%{BKY_CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL}"},t.Extensions.register("controls_whileUntil_tooltip",t.Extensions.buildTooltipForDropdown("MODE",t.Constants.Loops.WHILE_UNTIL_TOOLTIPS)),t.Constants.Loops.BREAK_CONTINUE_TOOLTIPS={BREAK:"%{BKY_CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK}",CONTINUE:"%{BKY_CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE}"},t.Extensions.register("controls_flow_tooltip",t.Extensions.buildTooltipForDropdown("FLOW",t.Constants.Loops.BREAK_CONTINUE_TOOLTIPS)),t.Constants.Loops.CUSTOM_CONTEXT_MENU_CREATE_VARIABLES_GET_MIXIN={customContextMenu:function(e){if(!this.isInFlyout){var o=this.getField("VAR").getVariable(),i=o.name;if(!this.isCollapsed()&&null!=i){var n={enabled:!0};n.text=t.Msg.VARIABLES_SET_CREATE_GET.replace("%1",i),o=t.Variables.generateVariableFieldDom(o),(i=t.utils.xml.createElement("block")).setAttribute("type","variables_get"),i.appendChild(o),n.callback=t.ContextMenu.callbackFactory(this,i),e.push(n)}}}},t.Extensions.registerMixin("contextMenu_newGetVariableBlock",t.Constants.Loops.CUSTOM_CONTEXT_MENU_CREATE_VARIABLES_GET_MIXIN),t.Extensions.register("controls_for_tooltip",t.Extensions.buildTooltipWithFieldText("%{BKY_CONTROLS_FOR_TOOLTIP}","VAR")),t.Extensions.register("controls_forEach_tooltip",t.Extensions.buildTooltipWithFieldText("%{BKY_CONTROLS_FOREACH_TOOLTIP}","VAR")),t.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN={LOOP_TYPES:["controls_repeat","controls_repeat_ext","controls_forEach","controls_for","controls_whileUntil"],suppressPrefixSuffix:!0,getSurroundLoop:function(e){do{if(-1!=t.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN.LOOP_TYPES.indexOf(e.type))return e;e=e.getSurroundParent()}while(e);return null},onchange:function(e){if(this.workspace.isDragging&&!this.workspace.isDragging()&&e.type==t.Events.BLOCK_MOVE&&e.blockId==this.id){var o=t.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN.getSurroundLoop(this);if(this.setWarningText(o?null:t.Msg.CONTROLS_FLOW_STATEMENTS_WARNING),!this.isInFlyout){var i=t.Events.getGroup();t.Events.setGroup(e.group),this.setEnabled(o),t.Events.setGroup(i)}}}},t.Extensions.registerMixin("controls_flow_in_loop_check",t.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN),t.Blocks.math={},t.Constants.Math={},t.Constants.Math.HUE=230,t.defineBlocksWithJsonArray([{type:"math_number",message0:"%1",args0:[{type:"field_number",name:"NUM",value:0}],output:"Number",helpUrl:"%{BKY_MATH_NUMBER_HELPURL}",style:"math_blocks",tooltip:"%{BKY_MATH_NUMBER_TOOLTIP}",extensions:["parent_tooltip_when_inline"]},{type:"math_arithmetic",message0:"%1 %2 %3",args0:[{type:"input_value",name:"A",check:"Number"},{type:"field_dropdown",name:"OP",options:[["%{BKY_MATH_ADDITION_SYMBOL}","ADD"],["%{BKY_MATH_SUBTRACTION_SYMBOL}","MINUS"],["%{BKY_MATH_MULTIPLICATION_SYMBOL}","MULTIPLY"],["%{BKY_MATH_DIVISION_SYMBOL}","DIVIDE"],["%{BKY_MATH_POWER_SYMBOL}","POWER"]]},{type:"input_value",name:"B",check:"Number"}],inputsInline:!0,output:"Number",style:"math_blocks",helpUrl:"%{BKY_MATH_ARITHMETIC_HELPURL}",extensions:["math_op_tooltip"]},{type:"math_single",message0:"%1 %2",args0:[{type:"field_dropdown",name:"OP",options:[["%{BKY_MATH_SINGLE_OP_ROOT}","ROOT"],["%{BKY_MATH_SINGLE_OP_ABSOLUTE}","ABS"],["-","NEG"],["ln","LN"],["log10","LOG10"],["e^","EXP"],["10^","POW10"]]},{type:"input_value",name:"NUM",check:"Number"}],output:"Number",style:"math_blocks",helpUrl:"%{BKY_MATH_SINGLE_HELPURL}",extensions:["math_op_tooltip"]},{type:"math_trig",message0:"%1 %2",args0:[{type:"field_dropdown",name:"OP",options:[["%{BKY_MATH_TRIG_SIN}","SIN"],["%{BKY_MATH_TRIG_COS}","COS"],["%{BKY_MATH_TRIG_TAN}","TAN"],["%{BKY_MATH_TRIG_ASIN}","ASIN"],["%{BKY_MATH_TRIG_ACOS}","ACOS"],["%{BKY_MATH_TRIG_ATAN}","ATAN"]]},{type:"input_value",name:"NUM",check:"Number"}],output:"Number",style:"math_blocks",helpUrl:"%{BKY_MATH_TRIG_HELPURL}",extensions:["math_op_tooltip"]},{type:"math_constant",message0:"%1",args0:[{type:"field_dropdown",name:"CONSTANT",options:[["π","PI"],["e","E"],["φ","GOLDEN_RATIO"],["sqrt(2)","SQRT2"],["sqrt(½)","SQRT1_2"],["∞","INFINITY"]]}],output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_CONSTANT_TOOLTIP}",helpUrl:"%{BKY_MATH_CONSTANT_HELPURL}"},{type:"math_number_property",message0:"%1 %2",args0:[{type:"input_value",name:"NUMBER_TO_CHECK",check:"Number"},{type:"field_dropdown",name:"PROPERTY",options:[["%{BKY_MATH_IS_EVEN}","EVEN"],["%{BKY_MATH_IS_ODD}","ODD"],["%{BKY_MATH_IS_PRIME}","PRIME"],["%{BKY_MATH_IS_WHOLE}","WHOLE"],["%{BKY_MATH_IS_POSITIVE}","POSITIVE"],["%{BKY_MATH_IS_NEGATIVE}","NEGATIVE"],["%{BKY_MATH_IS_DIVISIBLE_BY}","DIVISIBLE_BY"]]}],inputsInline:!0,output:"Boolean",style:"math_blocks",tooltip:"%{BKY_MATH_IS_TOOLTIP}",mutator:"math_is_divisibleby_mutator"},{type:"math_change",message0:"%{BKY_MATH_CHANGE_TITLE}",args0:[{type:"field_variable",name:"VAR",variable:"%{BKY_MATH_CHANGE_TITLE_ITEM}"},{type:"input_value",name:"DELTA",check:"Number"}],previousStatement:null,nextStatement:null,style:"variable_blocks",helpUrl:"%{BKY_MATH_CHANGE_HELPURL}",extensions:["math_change_tooltip"]},{type:"math_round",message0:"%1 %2",args0:[{type:"field_dropdown",name:"OP",options:[["%{BKY_MATH_ROUND_OPERATOR_ROUND}","ROUND"],["%{BKY_MATH_ROUND_OPERATOR_ROUNDUP}","ROUNDUP"],["%{BKY_MATH_ROUND_OPERATOR_ROUNDDOWN}","ROUNDDOWN"]]},{type:"input_value",name:"NUM",check:"Number"}],output:"Number",style:"math_blocks",helpUrl:"%{BKY_MATH_ROUND_HELPURL}",tooltip:"%{BKY_MATH_ROUND_TOOLTIP}"},{type:"math_on_list",message0:"%1 %2",args0:[{type:"field_dropdown",name:"OP",options:[["%{BKY_MATH_ONLIST_OPERATOR_SUM}","SUM"],["%{BKY_MATH_ONLIST_OPERATOR_MIN}","MIN"],["%{BKY_MATH_ONLIST_OPERATOR_MAX}","MAX"],["%{BKY_MATH_ONLIST_OPERATOR_AVERAGE}","AVERAGE"],["%{BKY_MATH_ONLIST_OPERATOR_MEDIAN}","MEDIAN"],["%{BKY_MATH_ONLIST_OPERATOR_MODE}","MODE"],["%{BKY_MATH_ONLIST_OPERATOR_STD_DEV}","STD_DEV"],["%{BKY_MATH_ONLIST_OPERATOR_RANDOM}","RANDOM"]]},{type:"input_value",name:"LIST",check:"Array"}],output:"Number",style:"math_blocks",helpUrl:"%{BKY_MATH_ONLIST_HELPURL}",mutator:"math_modes_of_list_mutator",extensions:["math_op_tooltip"]},{type:"math_modulo",message0:"%{BKY_MATH_MODULO_TITLE}",args0:[{type:"input_value",name:"DIVIDEND",check:"Number"},{type:"input_value",name:"DIVISOR",check:"Number"}],inputsInline:!0,output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_MODULO_TOOLTIP}",helpUrl:"%{BKY_MATH_MODULO_HELPURL}"},{type:"math_constrain",message0:"%{BKY_MATH_CONSTRAIN_TITLE}",args0:[{type:"input_value",name:"VALUE",check:"Number"},{type:"input_value",name:"LOW",check:"Number"},{type:"input_value",name:"HIGH",check:"Number"}],inputsInline:!0,output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_CONSTRAIN_TOOLTIP}",helpUrl:"%{BKY_MATH_CONSTRAIN_HELPURL}"},{type:"math_random_int",message0:"%{BKY_MATH_RANDOM_INT_TITLE}",args0:[{type:"input_value",name:"FROM",check:"Number"},{type:"input_value",name:"TO",check:"Number"}],inputsInline:!0,output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_RANDOM_INT_TOOLTIP}",helpUrl:"%{BKY_MATH_RANDOM_INT_HELPURL}"},{type:"math_random_float",message0:"%{BKY_MATH_RANDOM_FLOAT_TITLE_RANDOM}",output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_RANDOM_FLOAT_TOOLTIP}",helpUrl:"%{BKY_MATH_RANDOM_FLOAT_HELPURL}"},{type:"math_atan2",message0:"%{BKY_MATH_ATAN2_TITLE}",args0:[{type:"input_value",name:"X",check:"Number"},{type:"input_value",name:"Y",check:"Number"}],inputsInline:!0,output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_ATAN2_TOOLTIP}",helpUrl:"%{BKY_MATH_ATAN2_HELPURL}"}]),t.Constants.Math.TOOLTIPS_BY_OP={ADD:"%{BKY_MATH_ARITHMETIC_TOOLTIP_ADD}",MINUS:"%{BKY_MATH_ARITHMETIC_TOOLTIP_MINUS}",MULTIPLY:"%{BKY_MATH_ARITHMETIC_TOOLTIP_MULTIPLY}",DIVIDE:"%{BKY_MATH_ARITHMETIC_TOOLTIP_DIVIDE}",POWER:"%{BKY_MATH_ARITHMETIC_TOOLTIP_POWER}",ROOT:"%{BKY_MATH_SINGLE_TOOLTIP_ROOT}",ABS:"%{BKY_MATH_SINGLE_TOOLTIP_ABS}",NEG:"%{BKY_MATH_SINGLE_TOOLTIP_NEG}",LN:"%{BKY_MATH_SINGLE_TOOLTIP_LN}",LOG10:"%{BKY_MATH_SINGLE_TOOLTIP_LOG10}",EXP:"%{BKY_MATH_SINGLE_TOOLTIP_EXP}",POW10:"%{BKY_MATH_SINGLE_TOOLTIP_POW10}",SIN:"%{BKY_MATH_TRIG_TOOLTIP_SIN}",COS:"%{BKY_MATH_TRIG_TOOLTIP_COS}",TAN:"%{BKY_MATH_TRIG_TOOLTIP_TAN}",ASIN:"%{BKY_MATH_TRIG_TOOLTIP_ASIN}",ACOS:"%{BKY_MATH_TRIG_TOOLTIP_ACOS}",ATAN:"%{BKY_MATH_TRIG_TOOLTIP_ATAN}",SUM:"%{BKY_MATH_ONLIST_TOOLTIP_SUM}",MIN:"%{BKY_MATH_ONLIST_TOOLTIP_MIN}",MAX:"%{BKY_MATH_ONLIST_TOOLTIP_MAX}",AVERAGE:"%{BKY_MATH_ONLIST_TOOLTIP_AVERAGE}",MEDIAN:"%{BKY_MATH_ONLIST_TOOLTIP_MEDIAN}",MODE:"%{BKY_MATH_ONLIST_TOOLTIP_MODE}",STD_DEV:"%{BKY_MATH_ONLIST_TOOLTIP_STD_DEV}",RANDOM:"%{BKY_MATH_ONLIST_TOOLTIP_RANDOM}"},t.Extensions.register("math_op_tooltip",t.Extensions.buildTooltipForDropdown("OP",t.Constants.Math.TOOLTIPS_BY_OP)),t.Constants.Math.IS_DIVISIBLEBY_MUTATOR_MIXIN={mutationToDom:function(){var e=t.utils.xml.createElement("mutation"),o="DIVISIBLE_BY"==this.getFieldValue("PROPERTY");return e.setAttribute("divisor_input",o),e},domToMutation:function(t){t="true"==t.getAttribute("divisor_input"),this.updateShape_(t)},updateShape_:function(t){var e=this.getInput("DIVISOR");t?e||this.appendValueInput("DIVISOR").setCheck("Number"):e&&this.removeInput("DIVISOR")}},t.Constants.Math.IS_DIVISIBLE_MUTATOR_EXTENSION=function(){this.getField("PROPERTY").setValidator((function(t){t="DIVISIBLE_BY"==t,this.getSourceBlock().updateShape_(t)}))},t.Extensions.registerMutator("math_is_divisibleby_mutator",t.Constants.Math.IS_DIVISIBLEBY_MUTATOR_MIXIN,t.Constants.Math.IS_DIVISIBLE_MUTATOR_EXTENSION),t.Extensions.register("math_change_tooltip",t.Extensions.buildTooltipWithFieldText("%{BKY_MATH_CHANGE_TOOLTIP}","VAR")),t.Constants.Math.LIST_MODES_MUTATOR_MIXIN={updateType_:function(t){"MODE"==t?this.outputConnection.setCheck("Array"):this.outputConnection.setCheck("Number")},mutationToDom:function(){var e=t.utils.xml.createElement("mutation");return e.setAttribute("op",this.getFieldValue("OP")),e},domToMutation:function(t){this.updateType_(t.getAttribute("op"))}},t.Constants.Math.LIST_MODES_MUTATOR_EXTENSION=function(){this.getField("OP").setValidator(function(t){this.updateType_(t)}.bind(this))},t.Extensions.registerMutator("math_modes_of_list_mutator",t.Constants.Math.LIST_MODES_MUTATOR_MIXIN,t.Constants.Math.LIST_MODES_MUTATOR_EXTENSION),t.Blocks.procedures={},t.Blocks.procedures_defnoreturn={init:function(){var e=new t.FieldTextInput("",t.Procedures.rename);e.setSpellcheck(!1),this.appendDummyInput().appendField(t.Msg.PROCEDURES_DEFNORETURN_TITLE).appendField(e,"NAME").appendField("","PARAMS"),this.setMutator(new t.Mutator(["procedures_mutatorarg"])),(this.workspace.options.comments||this.workspace.options.parentWorkspace&&this.workspace.options.parentWorkspace.options.comments)&&t.Msg.PROCEDURES_DEFNORETURN_COMMENT&&this.setCommentText(t.Msg.PROCEDURES_DEFNORETURN_COMMENT),this.setStyle("procedure_blocks"),this.setTooltip(t.Msg.PROCEDURES_DEFNORETURN_TOOLTIP),this.setHelpUrl(t.Msg.PROCEDURES_DEFNORETURN_HELPURL),this.arguments_=[],this.argumentVarModels_=[],this.setStatements_(!0),this.statementConnection_=null},setStatements_:function(e){this.hasStatements_!==e&&(e?(this.appendStatementInput("STACK").appendField(t.Msg.PROCEDURES_DEFNORETURN_DO),this.getInput("RETURN")&&this.moveInputBefore("STACK","RETURN")):this.removeInput("STACK",!0),this.hasStatements_=e)},updateParams_:function(){var e="";this.arguments_.length&&(e=t.Msg.PROCEDURES_BEFORE_PARAMS+" "+this.arguments_.join(", ")),t.Events.disable();try{this.setFieldValue(e,"PARAMS")}finally{t.Events.enable()}},mutationToDom:function(e){var o=t.utils.xml.createElement("mutation");e&&o.setAttribute("name",this.getFieldValue("NAME"));for(var i=0;ii?t.JavaScript.valueToCode(e,o,t.JavaScript.ORDER_SUBTRACTION)||r:n?t.JavaScript.valueToCode(e,o,t.JavaScript.ORDER_UNARY_NEGATION)||r:t.JavaScript.valueToCode(e,o,s)||r,t.isNumber(e))e=Number(e)+i,n&&(e=-e);else{if(0i&&(e=e+" - "+-i,a=t.JavaScript.ORDER_SUBTRACTION);n&&(e=i?"-("+e+")":"-"+e,a=t.JavaScript.ORDER_UNARY_NEGATION),a=Math.floor(a),s=Math.floor(s),a&&s>=a&&(e="("+e+")")}return e},t.JavaScript.colour={},t.JavaScript.colour_picker=function(e){return[t.JavaScript.quote_(e.getFieldValue("COLOUR")),t.JavaScript.ORDER_ATOMIC]},t.JavaScript.colour_random=function(e){return[t.JavaScript.provideFunction_("colourRandom",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"() {"," var num = Math.floor(Math.random() * Math.pow(2, 24));"," return '#' + ('00000' + num.toString(16)).substr(-6);","}"])+"()",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.colour_rgb=function(e){var o=t.JavaScript.valueToCode(e,"RED",t.JavaScript.ORDER_COMMA)||0,i=t.JavaScript.valueToCode(e,"GREEN",t.JavaScript.ORDER_COMMA)||0;return e=t.JavaScript.valueToCode(e,"BLUE",t.JavaScript.ORDER_COMMA)||0,[t.JavaScript.provideFunction_("colourRgb",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(r, g, b) {"," r = Math.max(Math.min(Number(r), 100), 0) * 2.55;"," g = Math.max(Math.min(Number(g), 100), 0) * 2.55;"," b = Math.max(Math.min(Number(b), 100), 0) * 2.55;"," r = ('0' + (Math.round(r) || 0).toString(16)).slice(-2);"," g = ('0' + (Math.round(g) || 0).toString(16)).slice(-2);"," b = ('0' + (Math.round(b) || 0).toString(16)).slice(-2);"," return '#' + r + g + b;","}"])+"("+o+", "+i+", "+e+")",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.colour_blend=function(e){var o=t.JavaScript.valueToCode(e,"COLOUR1",t.JavaScript.ORDER_COMMA)||"'#000000'",i=t.JavaScript.valueToCode(e,"COLOUR2",t.JavaScript.ORDER_COMMA)||"'#000000'";return e=t.JavaScript.valueToCode(e,"RATIO",t.JavaScript.ORDER_COMMA)||.5,[t.JavaScript.provideFunction_("colourBlend",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(c1, c2, ratio) {"," ratio = Math.max(Math.min(Number(ratio), 1), 0);"," var r1 = parseInt(c1.substring(1, 3), 16);"," var g1 = parseInt(c1.substring(3, 5), 16);"," var b1 = parseInt(c1.substring(5, 7), 16);"," var r2 = parseInt(c2.substring(1, 3), 16);"," var g2 = parseInt(c2.substring(3, 5), 16);"," var b2 = parseInt(c2.substring(5, 7), 16);"," var r = Math.round(r1 * (1 - ratio) + r2 * ratio);"," var g = Math.round(g1 * (1 - ratio) + g2 * ratio);"," var b = Math.round(b1 * (1 - ratio) + b2 * ratio);"," r = ('0' + (r || 0).toString(16)).slice(-2);"," g = ('0' + (g || 0).toString(16)).slice(-2);"," b = ('0' + (b || 0).toString(16)).slice(-2);"," return '#' + r + g + b;","}"])+"("+o+", "+i+", "+e+")",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.lists={},t.JavaScript.lists_create_empty=function(e){return["[]",t.JavaScript.ORDER_ATOMIC]},t.JavaScript.lists_create_with=function(e){for(var o=Array(e.itemCount_),i=0;i b.toString() ? 1 : -1; },",' "IGNORE_CASE": function(a, b) {'," return a.toString().toLowerCase() > b.toString().toLowerCase() ? 1 : -1; },"," };"," var compare = compareFuncs[type];"," return function(a, b) { return compare(a, b) * direction; }","}"])+'("'+e+'", '+i+"))",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.lists_split=function(e){var o=t.JavaScript.valueToCode(e,"INPUT",t.JavaScript.ORDER_MEMBER),i=t.JavaScript.valueToCode(e,"DELIM",t.JavaScript.ORDER_NONE)||"''";if("SPLIT"==(e=e.getFieldValue("MODE")))o||(o="''"),e="split";else{if("JOIN"!=e)throw Error("Unknown mode: "+e);o||(o="[]"),e="join"}return[o+"."+e+"("+i+")",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.lists_reverse=function(e){return[(t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_FUNCTION_CALL)||"[]")+".slice().reverse()",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.logic={},t.JavaScript.controls_if=function(e){var o=0,i="";t.JavaScript.STATEMENT_PREFIX&&(i+=t.JavaScript.injectId(t.JavaScript.STATEMENT_PREFIX,e));do{var n=t.JavaScript.valueToCode(e,"IF"+o,t.JavaScript.ORDER_NONE)||"false",s=t.JavaScript.statementToCode(e,"DO"+o);t.JavaScript.STATEMENT_SUFFIX&&(s=t.JavaScript.prefixLines(t.JavaScript.injectId(t.JavaScript.STATEMENT_SUFFIX,e),t.JavaScript.INDENT)+s),i+=(0",GTE:">="}[e.getFieldValue("OP")],i="=="==o||"!="==o?t.JavaScript.ORDER_EQUALITY:t.JavaScript.ORDER_RELATIONAL;return[(t.JavaScript.valueToCode(e,"A",i)||"0")+" "+o+" "+(e=t.JavaScript.valueToCode(e,"B",i)||"0"),i]},t.JavaScript.logic_operation=function(e){var o="AND"==e.getFieldValue("OP")?"&&":"||",i="&&"==o?t.JavaScript.ORDER_LOGICAL_AND:t.JavaScript.ORDER_LOGICAL_OR,n=t.JavaScript.valueToCode(e,"A",i);if(e=t.JavaScript.valueToCode(e,"B",i),n||e){var s="&&"==o?"true":"false";n||(n=s),e||(e=s)}else e=n="false";return[n+" "+o+" "+e,i]},t.JavaScript.logic_negate=function(e){var o=t.JavaScript.ORDER_LOGICAL_NOT;return["!"+(t.JavaScript.valueToCode(e,"BOOL",o)||"true"),o]},t.JavaScript.logic_boolean=function(e){return["TRUE"==e.getFieldValue("BOOL")?"true":"false",t.JavaScript.ORDER_ATOMIC]},t.JavaScript.logic_null=function(e){return["null",t.JavaScript.ORDER_ATOMIC]},t.JavaScript.logic_ternary=function(e){return[(t.JavaScript.valueToCode(e,"IF",t.JavaScript.ORDER_CONDITIONAL)||"false")+" ? "+(t.JavaScript.valueToCode(e,"THEN",t.JavaScript.ORDER_CONDITIONAL)||"null")+" : "+(e=t.JavaScript.valueToCode(e,"ELSE",t.JavaScript.ORDER_CONDITIONAL)||"null"),t.JavaScript.ORDER_CONDITIONAL]},t.JavaScript.loops={},t.JavaScript.controls_repeat_ext=function(e){var o=e.getField("TIMES")?String(Number(e.getFieldValue("TIMES"))):t.JavaScript.valueToCode(e,"TIMES",t.JavaScript.ORDER_ASSIGNMENT)||"0",i=t.JavaScript.statementToCode(e,"DO");i=t.JavaScript.addLoopTrap(i,e),e="";var n=t.JavaScript.variableDB_.getDistinctName("count",t.VARIABLE_CATEGORY_NAME),s=o;return o.match(/^\w+$/)||t.isNumber(o)||(e+="var "+(s=t.JavaScript.variableDB_.getDistinctName("repeat_end",t.VARIABLE_CATEGORY_NAME))+" = "+o+";\n"),e+"for (var "+n+" = 0; "+n+" < "+s+"; "+n+"++) {\n"+i+"}\n"},t.JavaScript.controls_repeat=t.JavaScript.controls_repeat_ext,t.JavaScript.controls_whileUntil=function(e){var o="UNTIL"==e.getFieldValue("MODE"),i=t.JavaScript.valueToCode(e,"BOOL",o?t.JavaScript.ORDER_LOGICAL_NOT:t.JavaScript.ORDER_NONE)||"false",n=t.JavaScript.statementToCode(e,"DO");return o&&(i="!"+i),"while ("+i+") {\n"+(n=t.JavaScript.addLoopTrap(n,e))+"}\n"},t.JavaScript.controls_for=function(e){var o=t.JavaScript.variableDB_.getName(e.getFieldValue("VAR"),t.VARIABLE_CATEGORY_NAME),i=t.JavaScript.valueToCode(e,"FROM",t.JavaScript.ORDER_ASSIGNMENT)||"0",n=t.JavaScript.valueToCode(e,"TO",t.JavaScript.ORDER_ASSIGNMENT)||"0",s=t.JavaScript.valueToCode(e,"BY",t.JavaScript.ORDER_ASSIGNMENT)||"1",r=t.JavaScript.statementToCode(e,"DO");if(r=t.JavaScript.addLoopTrap(r,e),t.isNumber(i)&&t.isNumber(n)&&t.isNumber(s)){var a=Number(i)<=Number(n);e="for ("+o+" = "+i+"; "+o+(a?" <= ":" >= ")+n+"; "+o,e=(1==(o=Math.abs(Number(s)))?e+(a?"++":"--"):e+(a?" += ":" -= ")+o)+") {\n"+r+"}\n"}else e="",a=i,i.match(/^\w+$/)||t.isNumber(i)||(e+="var "+(a=t.JavaScript.variableDB_.getDistinctName(o+"_start",t.VARIABLE_CATEGORY_NAME))+" = "+i+";\n"),i=n,n.match(/^\w+$/)||t.isNumber(n)||(e+="var "+(i=t.JavaScript.variableDB_.getDistinctName(o+"_end",t.VARIABLE_CATEGORY_NAME))+" = "+n+";\n"),e+="var "+(n=t.JavaScript.variableDB_.getDistinctName(o+"_inc",t.VARIABLE_CATEGORY_NAME))+" = ",e=(e=t.isNumber(s)?e+(Math.abs(s)+";\n"):e+"Math.abs("+s+");\n")+"if ("+a+" > "+i+") {\n"+(t.JavaScript.INDENT+n)+" = -"+n+";\n",e+="}\n",e+="for ("+o+" = "+a+"; "+n+" >= 0 ? "+o+" <= "+i+" : "+o+" >= "+i+"; "+o+" += "+n+") {\n"+r+"}\n";return e},t.JavaScript.controls_forEach=function(e){var o=t.JavaScript.variableDB_.getName(e.getFieldValue("VAR"),t.VARIABLE_CATEGORY_NAME),i=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_ASSIGNMENT)||"[]",n=t.JavaScript.statementToCode(e,"DO");n=t.JavaScript.addLoopTrap(n,e),e="";var s=i;return i.match(/^\w+$/)||(e+="var "+(s=t.JavaScript.variableDB_.getDistinctName(o+"_list",t.VARIABLE_CATEGORY_NAME))+" = "+i+";\n"),e+"for (var "+(i=t.JavaScript.variableDB_.getDistinctName(o+"_index",t.VARIABLE_CATEGORY_NAME))+" in "+s+") {\n"+(n=t.JavaScript.INDENT+o+" = "+s+"["+i+"];\n"+n)+"}\n"},t.JavaScript.controls_flow_statements=function(e){var o="";if(t.JavaScript.STATEMENT_PREFIX&&(o+=t.JavaScript.injectId(t.JavaScript.STATEMENT_PREFIX,e)),t.JavaScript.STATEMENT_SUFFIX&&(o+=t.JavaScript.injectId(t.JavaScript.STATEMENT_SUFFIX,e)),t.JavaScript.STATEMENT_PREFIX){var i=t.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN.getSurroundLoop(e);i&&!i.suppressPrefixSuffix&&(o+=t.JavaScript.injectId(t.JavaScript.STATEMENT_PREFIX,i))}switch(e.getFieldValue("FLOW")){case"BREAK":return o+"break;\n";case"CONTINUE":return o+"continue;\n"}throw Error("Unknown flow statement.")},t.JavaScript.math={},t.JavaScript.math_number=function(e){return[e=Number(e.getFieldValue("NUM")),0<=e?t.JavaScript.ORDER_ATOMIC:t.JavaScript.ORDER_UNARY_NEGATION]},t.JavaScript.math_arithmetic=function(e){var o={ADD:[" + ",t.JavaScript.ORDER_ADDITION],MINUS:[" - ",t.JavaScript.ORDER_SUBTRACTION],MULTIPLY:[" * ",t.JavaScript.ORDER_MULTIPLICATION],DIVIDE:[" / ",t.JavaScript.ORDER_DIVISION],POWER:[null,t.JavaScript.ORDER_COMMA]}[e.getFieldValue("OP")],i=o[0];o=o[1];var n=t.JavaScript.valueToCode(e,"A",o)||"0";return e=t.JavaScript.valueToCode(e,"B",o)||"0",i?[n+i+e,o]:["Math.pow("+n+", "+e+")",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.math_single=function(e){var o=e.getFieldValue("OP");if("NEG"==o)return"-"==(e=t.JavaScript.valueToCode(e,"NUM",t.JavaScript.ORDER_UNARY_NEGATION)||"0")[0]&&(e=" "+e),["-"+e,t.JavaScript.ORDER_UNARY_NEGATION];switch(e="SIN"==o||"COS"==o||"TAN"==o?t.JavaScript.valueToCode(e,"NUM",t.JavaScript.ORDER_DIVISION)||"0":t.JavaScript.valueToCode(e,"NUM",t.JavaScript.ORDER_NONE)||"0",o){case"ABS":var i="Math.abs("+e+")";break;case"ROOT":i="Math.sqrt("+e+")";break;case"LN":i="Math.log("+e+")";break;case"EXP":i="Math.exp("+e+")";break;case"POW10":i="Math.pow(10,"+e+")";break;case"ROUND":i="Math.round("+e+")";break;case"ROUNDUP":i="Math.ceil("+e+")";break;case"ROUNDDOWN":i="Math.floor("+e+")";break;case"SIN":i="Math.sin("+e+" / 180 * Math.PI)";break;case"COS":i="Math.cos("+e+" / 180 * Math.PI)";break;case"TAN":i="Math.tan("+e+" / 180 * Math.PI)"}if(i)return[i,t.JavaScript.ORDER_FUNCTION_CALL];switch(o){case"LOG10":i="Math.log("+e+") / Math.log(10)";break;case"ASIN":i="Math.asin("+e+") / Math.PI * 180";break;case"ACOS":i="Math.acos("+e+") / Math.PI * 180";break;case"ATAN":i="Math.atan("+e+") / Math.PI * 180";break;default:throw Error("Unknown math operator: "+o)}return[i,t.JavaScript.ORDER_DIVISION]},t.JavaScript.math_constant=function(e){return{PI:["Math.PI",t.JavaScript.ORDER_MEMBER],E:["Math.E",t.JavaScript.ORDER_MEMBER],GOLDEN_RATIO:["(1 + Math.sqrt(5)) / 2",t.JavaScript.ORDER_DIVISION],SQRT2:["Math.SQRT2",t.JavaScript.ORDER_MEMBER],SQRT1_2:["Math.SQRT1_2",t.JavaScript.ORDER_MEMBER],INFINITY:["Infinity",t.JavaScript.ORDER_ATOMIC]}[e.getFieldValue("CONSTANT")]},t.JavaScript.math_number_property=function(e){var o=t.JavaScript.valueToCode(e,"NUMBER_TO_CHECK",t.JavaScript.ORDER_MODULUS)||"0",i=e.getFieldValue("PROPERTY");if("PRIME"==i)return[t.JavaScript.provideFunction_("mathIsPrime",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(n) {"," // https://en.wikipedia.org/wiki/Primality_test#Naive_methods"," if (n == 2 || n == 3) {"," return true;"," }"," // False if n is NaN, negative, is 1, or not whole."," // And false if n is divisible by 2 or 3."," if (isNaN(n) || n <= 1 || n % 1 != 0 || n % 2 == 0 || n % 3 == 0) {"," return false;"," }"," // Check all the numbers of form 6k +/- 1, up to sqrt(n)."," for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {"," if (n % (x - 1) == 0 || n % (x + 1) == 0) {"," return false;"," }"," }"," return true;","}"])+"("+o+")",t.JavaScript.ORDER_FUNCTION_CALL];switch(i){case"EVEN":var n=o+" % 2 == 0";break;case"ODD":n=o+" % 2 == 1";break;case"WHOLE":n=o+" % 1 == 0";break;case"POSITIVE":n=o+" > 0";break;case"NEGATIVE":n=o+" < 0";break;case"DIVISIBLE_BY":n=o+" % "+(e=t.JavaScript.valueToCode(e,"DIVISOR",t.JavaScript.ORDER_MODULUS)||"0")+" == 0"}return[n,t.JavaScript.ORDER_EQUALITY]},t.JavaScript.math_change=function(e){var o=t.JavaScript.valueToCode(e,"DELTA",t.JavaScript.ORDER_ADDITION)||"0";return(e=t.JavaScript.variableDB_.getName(e.getFieldValue("VAR"),t.VARIABLE_CATEGORY_NAME))+" = (typeof "+e+" == 'number' ? "+e+" : 0) + "+o+";\n"},t.JavaScript.math_round=t.JavaScript.math_single,t.JavaScript.math_trig=t.JavaScript.math_single,t.JavaScript.math_on_list=function(e){var o=e.getFieldValue("OP");switch(o){case"SUM":e=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_MEMBER)||"[]",e+=".reduce(function(x, y) {return x + y;})";break;case"MIN":e="Math.min.apply(null, "+(e=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_COMMA)||"[]")+")";break;case"MAX":e="Math.max.apply(null, "+(e=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_COMMA)||"[]")+")";break;case"AVERAGE":e=(o=t.JavaScript.provideFunction_("mathMean",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(myList) {"," return myList.reduce(function(x, y) {return x + y;}) / myList.length;","}"]))+"("+(e=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_NONE)||"[]")+")";break;case"MEDIAN":e=(o=t.JavaScript.provideFunction_("mathMedian",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(myList) {"," var localList = myList.filter(function (x) {return typeof x == 'number';});"," if (!localList.length) return null;"," localList.sort(function(a, b) {return b - a;});"," if (localList.length % 2 == 0) {"," return (localList[localList.length / 2 - 1] + localList[localList.length / 2]) / 2;"," } else {"," return localList[(localList.length - 1) / 2];"," }","}"]))+"("+(e=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_NONE)||"[]")+")";break;case"MODE":e=(o=t.JavaScript.provideFunction_("mathModes",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(values) {"," var modes = [];"," var counts = [];"," var maxCount = 0;"," for (var i = 0; i < values.length; i++) {"," var value = values[i];"," var found = false;"," var thisCount;"," for (var j = 0; j < counts.length; j++) {"," if (counts[j][0] === value) {"," thisCount = ++counts[j][1];"," found = true;"," break;"," }"," }"," if (!found) {"," counts.push([value, 1]);"," thisCount = 1;"," }"," maxCount = Math.max(thisCount, maxCount);"," }"," for (var j = 0; j < counts.length; j++) {"," if (counts[j][1] == maxCount) {"," modes.push(counts[j][0]);"," }"," }"," return modes;","}"]))+"("+(e=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_NONE)||"[]")+")";break;case"STD_DEV":e=(o=t.JavaScript.provideFunction_("mathStandardDeviation",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(numbers) {"," var n = numbers.length;"," if (!n) return null;"," var mean = numbers.reduce(function(x, y) {return x + y;}) / n;"," var variance = 0;"," for (var j = 0; j < n; j++) {"," variance += Math.pow(numbers[j] - mean, 2);"," }"," variance = variance / n;"," return Math.sqrt(variance);","}"]))+"("+(e=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_NONE)||"[]")+")";break;case"RANDOM":e=(o=t.JavaScript.provideFunction_("mathRandomList",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(list) {"," var x = Math.floor(Math.random() * list.length);"," return list[x];","}"]))+"("+(e=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_NONE)||"[]")+")";break;default:throw Error("Unknown operator: "+o)}return[e,t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.math_modulo=function(e){return[(t.JavaScript.valueToCode(e,"DIVIDEND",t.JavaScript.ORDER_MODULUS)||"0")+" % "+(e=t.JavaScript.valueToCode(e,"DIVISOR",t.JavaScript.ORDER_MODULUS)||"0"),t.JavaScript.ORDER_MODULUS]},t.JavaScript.math_constrain=function(e){return["Math.min(Math.max("+(t.JavaScript.valueToCode(e,"VALUE",t.JavaScript.ORDER_COMMA)||"0")+", "+(t.JavaScript.valueToCode(e,"LOW",t.JavaScript.ORDER_COMMA)||"0")+"), "+(e=t.JavaScript.valueToCode(e,"HIGH",t.JavaScript.ORDER_COMMA)||"Infinity")+")",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.math_random_int=function(e){var o=t.JavaScript.valueToCode(e,"FROM",t.JavaScript.ORDER_COMMA)||"0";return e=t.JavaScript.valueToCode(e,"TO",t.JavaScript.ORDER_COMMA)||"0",[t.JavaScript.provideFunction_("mathRandomInt",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(a, b) {"," if (a > b) {"," // Swap a and b to ensure a is smaller."," var c = a;"," a = b;"," b = c;"," }"," return Math.floor(Math.random() * (b - a + 1) + a);","}"])+"("+o+", "+e+")",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.math_random_float=function(e){return["Math.random()",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.math_atan2=function(e){var o=t.JavaScript.valueToCode(e,"X",t.JavaScript.ORDER_COMMA)||"0";return["Math.atan2("+(t.JavaScript.valueToCode(e,"Y",t.JavaScript.ORDER_COMMA)||"0")+", "+o+") / Math.PI * 180",t.JavaScript.ORDER_DIVISION]},t.JavaScript.procedures={},t.JavaScript.procedures_defreturn=function(e){var o=t.JavaScript.variableDB_.getName(e.getFieldValue("NAME"),t.PROCEDURE_CATEGORY_NAME),i="";t.JavaScript.STATEMENT_PREFIX&&(i+=t.JavaScript.injectId(t.JavaScript.STATEMENT_PREFIX,e)),t.JavaScript.STATEMENT_SUFFIX&&(i+=t.JavaScript.injectId(t.JavaScript.STATEMENT_SUFFIX,e)),i&&(i=t.JavaScript.prefixLines(i,t.JavaScript.INDENT));var n="";t.JavaScript.INFINITE_LOOP_TRAP&&(n=t.JavaScript.prefixLines(t.JavaScript.injectId(t.JavaScript.INFINITE_LOOP_TRAP,e),t.JavaScript.INDENT));var s=t.JavaScript.statementToCode(e,"STACK"),r=t.JavaScript.valueToCode(e,"RETURN",t.JavaScript.ORDER_NONE)||"",a="";s&&r&&(a=i),r&&(r=t.JavaScript.INDENT+"return "+r+";\n");for(var l=[],c=0;c\n \n \n \n 1\n 1\n \n \n 1\n \n \n 1\n \n \n \n \n 1\n \n \n Alias\n name\n \n \n Existing Key\n tpub, WIF, hex...\n \n \n \n \n \n \n Alias\n Alice\n \n \n \n \n 1\n 1\n \n \n \n \n Alias\n Alice\n \n \n \n \n \n \n \n \n Alias\n Bob\n \n \n \n \n \n \n 99\n 1\n \n \n \n \n Alias\n KeyLikely\n \n \n \n \n \n \n \n \n Alias\n Likely\n \n \n \n \n \n \n \n \n \n \n Alias\n User\n \n \n \n \n \n \n 99\n 1\n \n \n \n \n Alias\n Service\n \n \n \n \n \n \n 12960\n \n \n \n \n \n \n 3\n \n \n \n \n \n \n Alias\n Alice\n \n \n \n \n \n \n \n \n \n \n Alias\n Bob\n \n \n \n \n \n \n \n \n \n \n Alias\n Carol\n \n \n \n \n \n \n \n \n 12960\n \n \n \n \n \n \n \n \n \n \n \n \n',collapse:!0,comments:!0,disable:!0,maxBlocks:1/0,trashcan:!0,horizontalLayout:!0,toolboxPosition:"start",css:!0,media:"https://blockly-demo.appspot.com/static/media/",rtl:!1,scrollbars:!0,sounds:!0,oneBasedIndex:!0,grid:{spacing:20,length:1,colour:"#888",snap:!0}};i.a.Blocks.pk={init:function(){this.appendValueInput("pk").setCheck("key").appendField("Key"),this.setPreviousStatement(!0,"policy"),this.setColour(260),this.setTooltip("Requires a signature with a given public key"),this.setHelpUrl("")}},i.a.Blocks.begin={init:function(){this.appendDummyInput().appendField("Begin"),this.setNextStatement(!0,"policy"),this.setColour(160),this.setTooltip("Sets the beginning of the policy"),this.setHelpUrl("")}},i.a.Blocks.existing_key={init:function(){this.appendDummyInput().appendField(new i.a.FieldLabelSerializable("Existing Key"),"NAME").appendField(new i.a.FieldTextInput("tpub, WIF, hex..."),"key"),this.setOutput(!0,"key"),this.setColour(120),this.setTooltip("Sets the value of a key to an existing WIF key, xpub or hex public key"),this.setHelpUrl("")}},i.a.Blocks.alias_key={init:function(){this.appendDummyInput().appendField(new i.a.FieldLabelSerializable("Alias"),"label").appendField(new i.a.FieldTextInput("name"),"name"),this.setOutput(!0,"key"),this.setColour(120),this.setTooltip("Sets the value of a key to an alias"),this.setHelpUrl("")}},i.a.Blocks.thresh={init:function(){this.appendDummyInput().appendField("Threshold").appendField(new i.a.FieldNumber(1,1,1/0,1),"Threshold"),this.appendStatementInput("A").setCheck("thresh").appendField("Policies"),this.setPreviousStatement(!0,"policy"),this.setColour(230),this.setTooltip("Creates a threshold element (m-of-n), where the 'm' field is manually set and 'n' is implied by the number of sub-policies added. Requies all of its children to be wrapped in the 'Entry' block"),this.setHelpUrl("")}},i.a.Blocks.older={init:function(){this.appendDummyInput().appendField("Older").appendField(new i.a.FieldNumber(1,1,1/0,1),"NAME"),this.setPreviousStatement(!0,"policy"),this.setColour(20),this.setTooltip("Requires waiting a number of blocks from the confirmation height of a UTXO before it becomes spendable"),this.setHelpUrl("")}},i.a.Blocks.after={init:function(){this.appendDummyInput().appendField("After").appendField(new i.a.FieldNumber(1,1,1/0,1),"NAME"),this.setPreviousStatement(!0,"policy"),this.setColour(20),this.setTooltip("Requires the blockchain to reach a specific block height before the UTXO becomes spendable"),this.setHelpUrl("")}},i.a.Blocks.adapter={init:function(){this.appendStatementInput("NAME").setCheck("policy").appendField("Entry"),this.setPreviousStatement(!0,"thresh"),this.setNextStatement(!0,"thresh"),this.setColour(290),this.setTooltip("Adapter used to stack policies into 'Threshold' blocks"),this.setHelpUrl("")}},i.a.Blocks.and={init:function(){this.appendStatementInput("A").setCheck("policy"),this.appendDummyInput().appendField("AND"),this.appendStatementInput("B").setCheck("policy"),this.setPreviousStatement(!0,"policy"),this.setColour(230),this.setTooltip("Requires both sub-policies to be satisfied"),this.setHelpUrl("")}},i.a.Blocks.or={init:function(){this.appendStatementInput("A").setCheck("policy").appendField("Weight").appendField(new i.a.FieldNumber(1,1),"A_weight"),this.appendDummyInput().appendField("OR"),this.appendStatementInput("B").setCheck("policy").appendField("Weight").appendField(new i.a.FieldNumber(1,1),"B_weight"),this.setPreviousStatement(!0,"policy"),this.setColour(230),this.setTooltip("Requires either one of the two sub-policies to be satisfied. Weights can be used to indicate the relative probability of each sub-policy"),this.setHelpUrl("")}},i.a.JavaScript.begin=function(e){return""},i.a.JavaScript.pk=function(e){if(!e.getParent())return"";var n=i.a.JavaScript.valueToCode(e,"pk",i.a.JavaScript.ORDER_ATOMIC);return""==n&&(n="()"),"pk"+n},i.a.JavaScript.existing_key=function(e){return e.getParent()?[e.getFieldValue("key"),i.a.JavaScript.ORDER_NONE]:["",i.a.JavaScript.ORDER_NONE]},i.a.JavaScript.alias_key=function(e){return e.getParent()?[e.getFieldValue("name"),i.a.JavaScript.ORDER_NONE]:["",i.a.JavaScript.ORDER_NONE]},i.a.JavaScript.thresh=function(e){return"thresh("+e.getFieldValue("Threshold")+","+i.a.JavaScript.statementToCode(e,"A")+")"},i.a.JavaScript.older=function(e){return e.getParent()?"older("+e.getFieldValue("NAME")+")":""},i.a.JavaScript.after=function(e){return e.getParent()?"after("+e.getFieldValue("NAME")+")":""},i.a.JavaScript.adapter=function(e){return e.getParent()?i.a.JavaScript.statementToCode(e,"NAME")+(e.getNextBlock()?",":""):""},i.a.JavaScript.and=function(e){return e.getParent()?"and("+i.a.JavaScript.statementToCode(e,"A")+","+i.a.JavaScript.statementToCode(e,"B")+")":""},i.a.JavaScript.or=function(e){if(!e.getParent())return"";var n=e.getFieldValue("A_weight");"1"==n?n="":n+="@";var t=i.a.JavaScript.statementToCode(e,"A"),r=e.getFieldValue("B_weight");return"1"==r?r="":r+="@","or("+n+t+","+r+i.a.JavaScript.statementToCode(e,"B")+")"};var o=i.a.inject(e,r);o.addChangeListener((function(e){t.value=i.a.JavaScript.workspaceToCode(o)})),o.addChangeListener(i.a.Events.disableOrphans),setTimeout(()=>{if(l.restoreBlocks(),0==o.getTopBlocks().length){var e=o.newBlock("begin");e.setDeletable(!1),e.setEditable(!1),e.moveBy(20,20),e.initSvg(),e.render()}const n=document.createElement("span");n.innerHTML='',n.style.float="right",n.style["margin-right"]="10px";let t=!1;n.onclick=function(){t?document.exitFullscreen():document.getElementById("blocklyDiv").requestFullscreen(),t=!t},document.getElementsByClassName("blocklyToolboxDiv")[0].appendChild(n)},0),l.backupOnUnload()}("blocklyDiv","policy");let e=null;document.getElementById("stdin").disabled=!0;const n=document.getElementById("start_button"),t=document.getElementById("stop_button"),o=document.getElementById("start_message");n.disabled=!1,t.disabled=!0;const a=document.getElementById("descriptor"),u=document.getElementById("change_descriptor");n.onclick=i=>{0!=a.value.length&&(i.preventDefault(),async function(e,n){const t=document.getElementById("stdout"),o=document.getElementById("stdin");o.disabled=!1;const i=[];let a=0,l=null;try{l=await new r.a("testnet",e,n,"https://blockstream.info/testnet/api")}catch(e){console.error(e)}const u=e=>{if("clear"!=e)return o.disabled=!0,t.innerHTML.length>0&&(t.innerHTML+="\n"),t.innerHTML+=`> ${e}\n`,a=i.push(e),l.run(e).then(e=>{e&&(t.innerHTML+=`${e}\n`)}).catch(e=>t.innerHTML+=`${e}\n`).finally(()=>{o.disabled=!1,t.scrollTop=t.scrollHeight-t.clientHeight});t.innerHTML=""};return o.onkeydown=e=>{if("Enter"==e.key){if(0==o.value.length)return;u(o.value),o.value="",e.preventDefault()}else"ArrowUp"==e.key?a>0&&(o.value=i[--a]):"ArrowDown"==e.key&&a0?u.value:null).then(r=>{n.disabled=!0,a.disabled=!0,u.disabled=!0,o.innerHTML="Wallet created, running `sync`...",r.run("sync").then(()=>o.innerHTML="Ready!"),e=r,t.disabled=!1}).catch(e=>o.innerHTML=`${e}`))},t.onclick=r=>{null!=e&&(r.preventDefault(),e.free(),o.innerHTML="Wallet instance destroyed",n.disabled=!1,t.disabled=!0,a.disabled=!1,u.disabled=!1)};const c=document.getElementById("policy"),s=document.getElementById("compiler_script_type"),d=document.getElementById("compiler_output");document.getElementById("compile_button").onclick=e=>{if(0==c.value.length)return;e.preventDefault();const n=!e.target.form.elements.namedItem("alias").length;let t=e.target.form.elements.namedItem("alias"),o=e.target.form.elements.namedItem("type"),i=e.target.form.elements.namedItem("extra");n?(t=[t],o=[o],i=[i]):(t=Array.from(t),o=Array.from(o),i=Array.from(i));const a={};t.forEach(e=>{const n=o.filter(n=>n.attributes["data-index"].value==e.attributes["data-index"].value)[0].value,t=i.filter(n=>n.attributes["data-index"].value==e.attributes["data-index"].value)[0].value,r=e.value;a[r]={type:n,extra:t}}),Object(r.ub)(c.value,JSON.stringify(a),s.value).then(e=>d.innerHTML=e).catch(e=>d.innerHTML=`${e}`)}}()},12:function(e,n,t){"use strict";var r=t.w[e.i];e.exports=r;t(2);r.n()},2:function(e,n,t){"use strict";(function(e,r){t.d(n,"vb",(function(){return T})),t.d(n,"ub",(function(){return _})),t.d(n,"a",(function(){return E})),t.d(n,"qb",(function(){return R})),t.d(n,"eb",(function(){return x})),t.d(n,"sb",(function(){return B})),t.d(n,"E",(function(){return I})),t.d(n,"W",(function(){return F})),t.d(n,"l",(function(){return q})),t.d(n,"nb",(function(){return C})),t.d(n,"q",(function(){return N})),t.d(n,"P",(function(){return M})),t.d(n,"T",(function(){return D})),t.d(n,"Q",(function(){return O})),t.d(n,"i",(function(){return H})),t.d(n,"B",(function(){return J})),t.d(n,"mb",(function(){return L})),t.d(n,"p",(function(){return P})),t.d(n,"X",(function(){return U})),t.d(n,"pb",(function(){return X})),t.d(n,"n",(function(){return j})),t.d(n,"j",(function(){return W})),t.d(n,"m",(function(){return V})),t.d(n,"w",(function(){return $})),t.d(n,"A",(function(){return K})),t.d(n,"fb",(function(){return z})),t.d(n,"F",(function(){return Q})),t.d(n,"b",(function(){return G})),t.d(n,"o",(function(){return Y})),t.d(n,"L",(function(){return Z})),t.d(n,"x",(function(){return ee})),t.d(n,"cb",(function(){return ne})),t.d(n,"Y",(function(){return te})),t.d(n,"v",(function(){return re})),t.d(n,"e",(function(){return oe})),t.d(n,"Z",(function(){return ie})),t.d(n,"K",(function(){return ae})),t.d(n,"D",(function(){return le})),t.d(n,"d",(function(){return ue})),t.d(n,"c",(function(){return ce})),t.d(n,"hb",(function(){return se})),t.d(n,"kb",(function(){return de})),t.d(n,"lb",(function(){return fe})),t.d(n,"N",(function(){return pe})),t.d(n,"k",(function(){return me})),t.d(n,"db",(function(){return be})),t.d(n,"y",(function(){return he})),t.d(n,"I",(function(){return ke})),t.d(n,"g",(function(){return ye})),t.d(n,"h",(function(){return ge})),t.d(n,"M",(function(){return ve})),t.d(n,"O",(function(){return we})),t.d(n,"C",(function(){return Te})),t.d(n,"H",(function(){return _e})),t.d(n,"R",(function(){return Ae})),t.d(n,"bb",(function(){return Se})),t.d(n,"ab",(function(){return Ee})),t.d(n,"S",(function(){return Re})),t.d(n,"gb",(function(){return xe})),t.d(n,"s",(function(){return Be})),t.d(n,"t",(function(){return Ie})),t.d(n,"f",(function(){return Fe})),t.d(n,"J",(function(){return qe})),t.d(n,"G",(function(){return Ce})),t.d(n,"V",(function(){return Ne})),t.d(n,"z",(function(){return Me})),t.d(n,"r",(function(){return De})),t.d(n,"u",(function(){return Oe})),t.d(n,"U",(function(){return He})),t.d(n,"rb",(function(){return Je})),t.d(n,"jb",(function(){return Le})),t.d(n,"tb",(function(){return Pe})),t.d(n,"ob",(function(){return Ue})),t.d(n,"ib",(function(){return Xe}));var o=t(12);const i=new Array(32).fill(void 0);function a(e){return i[e]}i.push(void 0,null,!0,!1);let l=i.length;function u(e){const n=a(e);return function(e){e<36||(i[e]=l,l=e)}(e),n}let c=new("undefined"==typeof TextDecoder?(0,e.require)("util").TextDecoder:TextDecoder)("utf-8",{ignoreBOM:!0,fatal:!0});c.decode();let s=null;function d(){return null!==s&&s.buffer===o.j.buffer||(s=new Uint8Array(o.j.buffer)),s}function f(e,n){return c.decode(d().subarray(e,e+n))}function p(e){l===i.length&&i.push(i.length+1);const n=l;return l=i[n],i[n]=e,n}let m=0;let b=new("undefined"==typeof TextEncoder?(0,e.require)("util").TextEncoder:TextEncoder)("utf-8");const h="function"==typeof b.encodeInto?function(e,n){return b.encodeInto(e,n)}:function(e,n){const t=b.encode(e);return n.set(t),{read:e.length,written:t.length}};function k(e,n,t){if(void 0===t){const t=b.encode(e),r=n(t.length);return d().subarray(r,r+t.length).set(t),m=t.length,r}let r=e.length,o=n(r);const i=d();let a=0;for(;a127)break;i[o+a]=n}if(a!==r){0!==a&&(e=e.slice(a)),o=t(o,r,r=a+3*e.length);const n=d().subarray(o+a,o+r);a+=h(e,n).written}return m=a,o}let y=null;function g(){return null!==y&&y.buffer===o.j.buffer||(y=new Int32Array(o.j.buffer)),y}function v(e){return null==e}function w(e,n,t){o.g(e,n,p(t))}function T(){o.i()}function _(e,n,t){var r=k(e,o.e,o.f),i=m,a=k(n,o.e,o.f),l=m,c=k(t,o.e,o.f),s=m;return u(o.h(r,i,a,l,c,s))}function A(e){return function(){try{return e.apply(this,arguments)}catch(e){o.b(p(e))}}}function S(e,n){return d().subarray(e/1,e/1+n)}class E{static __wrap(e){const n=Object.create(E.prototype);return n.ptr=e,n}free(){const e=this.ptr;this.ptr=0,o.a(e)}constructor(e,n,t,r){var i=k(e,o.e,o.f),a=m,l=k(n,o.e,o.f),c=m,s=v(t)?0:k(t,o.e,o.f),d=m,f=k(r,o.e,o.f),p=m;return u(o.k(i,a,l,c,s,d,f,p))}run(e){var n=k(e,o.e,o.f),t=m;return u(o.l(this.ptr,n,t))}}const R=function(e){u(e)},x=function(e){return p(E.__wrap(e))},B=function(e,n){return p(f(e,n))},I=function(){return p(new Error)},F=function(e,n){var t=k(a(n).stack,o.e,o.f),r=m;g()[e/4+1]=r,g()[e/4+0]=t},q=function(e,n){try{console.error(f(e,n))}finally{o.d(e,n)}},C=function(e,n){const t=a(n);var r=k(JSON.stringify(void 0===t?null:t),o.e,o.f),i=m;g()[e/4+1]=i,g()[e/4+0]=r},N=function(e,n,t){a(e).getRandomValues(S(n,t))},M=function(e,n,t){a(e).randomFillSync(S(n,t))},D=A((function(){return p(self.self)})),O=function(e,n,t){return p(a(e).require(f(n,t)))},H=function(e){return p(a(e).crypto)},J=function(e){return p(a(e).msCrypto)},L=function(e){return void 0===a(e)},P=function(e){return p(a(e).getRandomValues)},U=function(){return p(e)},X=function(e){return p(a(e))},j=function(e){return p(fetch(a(e)))},W=function(e){console.debug(a(e))},V=function(e){console.error(a(e))},$=function(e){console.info(a(e))},K=function(e){console.log(a(e))},z=function(e){console.warn(a(e))},Q=A((function(){return p(new Headers)})),G=A((function(e,n,t,r,o){a(e).append(f(n,t),f(r,o))})),Y=function(e,n){return p(a(e).fetch(a(n)))},Z=A((function(e,n){return p(new Blob(a(e),a(n)))})),ee=function(e){return a(e)instanceof Response},ne=function(e,n){var t=k(a(n).url,o.e,o.f),r=m;g()[e/4+1]=r,g()[e/4+0]=t},te=function(e){return a(e).status},re=function(e){return p(a(e).headers)},oe=A((function(e){return p(a(e).arrayBuffer())})),ie=A((function(e){return p(a(e).text())})),ae=A((function(e,n,t){return p(new Request(f(e,n),a(t)))})),le=A((function(){return p(new FormData)})),ue=A((function(e,n,t,r){a(e).append(f(n,t),a(r))})),ce=A((function(e,n,t,r,o,i){a(e).append(f(n,t),a(r),f(o,i))})),se=function(e){const n=u(e).original;if(1==n.cnt--)return n.a=0,!0;return!1},de=function(e){return"function"==typeof a(e)},fe=function(e){const n=a(e);return"object"==typeof n&&null!==n},pe=function(e){return p(a(e).next)},me=function(e){return a(e).done},be=function(e){return p(a(e).value)},he=function(){return p(Symbol.iterator)},ke=function(e,n){return p(new Function(f(e,n)))},ye=A((function(e,n){return p(a(e).call(a(n)))})),ge=A((function(e,n,t){return p(a(e).call(a(n),a(t)))})),ve=A((function(e){return p(a(e).next())})),we=function(){return Date.now()},Te=function(){return p(new Object)},_e=function(e,n){try{var t={a:e,b:n},r=new Promise((e,n)=>{const r=t.a;t.a=0;try{return function(e,n,t,r){o.m(e,n,p(t),p(r))}(r,t.b,e,n)}finally{t.a=r}});return p(r)}finally{t.a=t.b=0}},Ae=function(e){return p(Promise.resolve(a(e)))},Se=function(e,n){return p(a(e).then(a(n)))},Ee=function(e,n,t){return p(a(e).then(a(n),a(t)))},Re=A((function(){return p(self.self)})),xe=A((function(){return p(window.window)})),Be=A((function(){return p(globalThis.globalThis)})),Ie=A((function(){return p(r.global)})),Fe=function(e){return p(a(e).buffer)},qe=function(e,n,t){return p(new Uint8Array(a(e),n>>>0,t>>>0))},Ce=function(e){return p(new Uint8Array(a(e)))},Ne=function(e,n,t){a(e).set(a(n),t>>>0)},Me=function(e){return a(e).length},De=A((function(e,n){return p(Reflect.get(a(e),a(n)))})),Oe=A((function(e,n){return Reflect.has(a(e),a(n))})),He=A((function(e,n,t){return Reflect.set(a(e),a(n),a(t))})),Je=function(e,n){const t=a(n);var r="string"==typeof t?t:void 0,i=v(r)?0:k(r,o.e,o.f),l=m;g()[e/4+1]=l,g()[e/4+0]=i},Le=function(e,n){var t=k(function e(n){const t=typeof n;if("number"==t||"boolean"==t||null==n)return""+n;if("string"==t)return`"${n}"`;if("symbol"==t){const e=n.description;return null==e?"Symbol":`Symbol(${e})`}if("function"==t){const e=n.name;return"string"==typeof e&&e.length>0?`Function(${e})`:"Function"}if(Array.isArray(n)){const t=n.length;let r="[";t>0&&(r+=e(n[0]));for(let o=1;o1))return toString.call(n);if(o=r[1],"Object"==o)try{return"Object("+JSON.stringify(n)+")"}catch(e){return"Object"}return n instanceof Error?`${n.name}: ${n.message}\n${n.stack}`:o}(a(n)),o.e,o.f),r=m;g()[e/4+1]=r,g()[e/4+0]=t},Pe=function(e,n){throw new Error(f(e,n))},Ue=function(){return p(o.j)},Xe=function(e,n,t){return p(function(e,n,t,r){const i={a:e,b:n,cnt:1,dtor:t},a=(...e)=>{i.cnt++;const n=i.a;i.a=0;try{return r(n,i.b,...e)}finally{0==--i.cnt?o.c.get(i.dtor)(n,i.b):i.a=n}};return a.original=i,a}(e,n,1126,w))}}).call(this,t(11)(e),t(5))}}]); \ No newline at end of file diff --git a/docs/.vuepress/public/bdk-cli/playground/2715004f10f13ece5ea4.module.wasm b/docs/.vuepress/public/bdk-cli/playground/2715004f10f13ece5ea4.module.wasm new file mode 100644 index 0000000000..c1b7ba6a6e Binary files /dev/null and b/docs/.vuepress/public/bdk-cli/playground/2715004f10f13ece5ea4.module.wasm differ diff --git a/docs/.vuepress/public/bdk-cli/playground/playground.html b/docs/.vuepress/public/bdk-cli/playground/playground.html new file mode 100644 index 0000000000..14c6a89cea --- /dev/null +++ b/docs/.vuepress/public/bdk-cli/playground/playground.html @@ -0,0 +1,137 @@ + + +
+
+ +

Policy Compiler

+
+
+
+ +
+
+
+ + +
+
+ + Map every alias to an existing key or generate a new one. You can also specify known keys directly in the + visual editor or the policy input field. +
+
+ + + +

+    
+
+
+ +
+
+ +

Wallet

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

+
+    
+ > + +
+
+
+ + + + diff --git a/docs/.vuepress/public/bdk-cli/playground/playground.js b/docs/.vuepress/public/bdk-cli/playground/playground.js new file mode 100644 index 0000000000..a74dfb7e8c --- /dev/null +++ b/docs/.vuepress/public/bdk-cli/playground/playground.js @@ -0,0 +1 @@ +!function(e){function n(n){for(var t,_,o=n[0],u=n[1],c=0,f=[];cconsole.error("Error importing `index.js`:",e))}]); \ No newline at end of file diff --git a/docs/.vuepress/public/browserconfig.xml b/docs/.vuepress/public/browserconfig.xml new file mode 100644 index 0000000000..76dea925c1 --- /dev/null +++ b/docs/.vuepress/public/browserconfig.xml @@ -0,0 +1,9 @@ + + + + + + #ffffff + + + diff --git a/docs/.vuepress/public/card.png b/docs/.vuepress/public/card.png new file mode 100644 index 0000000000..83cbb13a82 Binary files /dev/null and b/docs/.vuepress/public/card.png differ diff --git a/docs/.vuepress/public/css/blog.css b/docs/.vuepress/public/css/blog.css new file mode 100644 index 0000000000..678e85fdee --- /dev/null +++ b/docs/.vuepress/public/css/blog.css @@ -0,0 +1,44 @@ +h1.blog-title { + margin-top: 0; + margin-bottom: 0; +} + +span.blog-author { + font-weight: bolder; + font-size: 1.2em; +} + +div.tags { + display: flex; + justify-content: center; +} + +h3.blog-post { + display: flex; + align-items: center; + margin-bottom: 0; +} + +h3.blog-post span.anchor { + position: initial; +} + +h3.blog-post > span.date { + font-weight: lighter; + width: 10vh; + display: inline-block; + margin-left: 2vh; +} + +span.blog-post-tags { + margin-left: 12vh; +} + +a.tag-link::before { + width: 1em !important; + height: 2em !important; +} + +a.tag-link { + border-radius: 1px 3px 3px 1px !important; +} diff --git a/docs/.vuepress/public/css/jsonview.css b/docs/.vuepress/public/css/jsonview.css new file mode 100644 index 0000000000..72419b32d1 --- /dev/null +++ b/docs/.vuepress/public/css/jsonview.css @@ -0,0 +1,88 @@ +.json { + padding: 16px; + background-color: #272822; + color: #FFF; + font-family: "Consolas", menlo, monospace; +} + +.line { + margin: 4px 0; + display: flex; + justify-content: flex-start; +} + +.caret-icon { + width: 28px; + text-align: center; + cursor: pointer; +} + +.json .caret-icon > i { + border: 0; +} + +.empty-icon { + width: 20px; +} + +.json-type { + margin-right: 4px; + margin-left: 4px; +} + +.json-key { + color: #EEE; + margin-right: 4px; + margin-left: 4px; +} + +.json-index { + margin-right: 4px; + margin-left: 4px; +} + +.json-separator { + +} + +.json-value { + margin-left: 8px; +} + +.json-number { + color: #f9ae58; +} + +.json-boolean { + color: #ec5f66; +} + +.json-string { + color: #86b25c; +} + +.json-size { + margin-right: 4px; + margin-left: 4px; +} + +.hide { + display: none; +} + +.json .fas { + display: inline-block; + width: 0; + height: 0; + border-style: solid; +} + +.json .fa-caret-down { + border-width: 6px 5px 0 5px; + border-color: #808080 transparent +} + +.json .fa-caret-right { + border-width: 5px 0 5px 6px; + border-color: transparent transparent transparent #808080; +} diff --git a/docs/.vuepress/public/css/variables.css b/docs/.vuepress/public/css/variables.css new file mode 100644 index 0000000000..5748722a51 --- /dev/null +++ b/docs/.vuepress/public/css/variables.css @@ -0,0 +1,78 @@ +:root { + --docs-primary-light: #F7931A; + --docs-primary-dark: #FFC774; + --docs-dark: #40382D; + + --docs-note-text: var(--docs-body-text) !important; + --docs-note-bg: #FEF3E6 !important; + --docs-code-text: var(--docs-black) !important; + --docs-code-bg: #FCDCB5; + --docs-pre-bg: #271601; +} + +:root[data-theme="dark"] { + --docs-note-text: var(--docs-white) !important; + --docs-note-bg: var(--docs-pre-bg) !important; + --docs-code-text: var(--docs-white) !important; + --docs-code-bg: #704400; + --docs-pre-bg: #211D17; +} + +@media (prefers-color-scheme: dark) { + :root:not([data-theme]) { + --docs-note-text: var(--docs-white) !important; + --docs-note-bg: var(--docs-pre-bg) !important; + --docs-code-text: var(--docs-white) !important; + --docs-code-bg: #704400; + --docs-pre-bg: #211D17; + } +} + + +iframe.example { + width: 100%; + height: 800px; + border: 0; +} + +iframe.playground { + width: 100%; + height: 888px; + border: 0; +} + +.supporters a { + display: inline-block; + margin: 1.5rem 1.5rem 1.5rem 0; + text-align: center; +} + +.supporters img { + display: block; + width: 75px; + height: 75px; + margin-bottom: .5rem; +} + +.descriptor-support-table > table { + width: 100%; +} + +.descriptor-support-table > table > thead > tr > th { + width: 25%; +} + +.descriptor-examples-table > table > thead > tr > th:nth-child(2) { + width: 45%; +} + +.descriptor-examples-table code, +.descriptor-examples-table td:not(:first-child) { + overflow-x: auto; + white-space: pre-wrap; + white-space: -moz-pre-wrap; + white-space: -pre-wrap; + white-space: -o-pre-wrap; + word-wrap: break-word; + overflow-wrap: anywhere; +} diff --git a/docs/.vuepress/public/descriptor-based-paper-wallets/Bitcoin_Paper_Wallet.html b/docs/.vuepress/public/descriptor-based-paper-wallets/Bitcoin_Paper_Wallet.html new file mode 100644 index 0000000000..bc68433046 --- /dev/null +++ b/docs/.vuepress/public/descriptor-based-paper-wallets/Bitcoin_Paper_Wallet.html @@ -0,0 +1,2 @@ + +Bitcoin Paper Wallet
Alice
tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw
wsh(multi(2,Grandma,Alice,Barbara))#em3q73l5
Alice: cSSKRHDmQEEutp5LD14tAcixu2ehSNPDTqNek1zMa9Pet98qxHq3
Barbara: 02a3f3f2658b9812ddeabfbde2fde03f8a65369e4ed621f29fa8ba0cc519b789fb
Grandma: 03f1bd2bff8e9c61f58a8d46d18fd8f3149b1f2d76b3c423a7874a5d5811d67cee
Barbara
tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw
wsh(multi(2,Grandma,Alice,Barbara))#nxfa5n0z
Alice: 02e486e32f0f87136fa042cb53219ace8537ea1d036deb2f4293570b94325d11cb
Barbara: cSfMLzSZ9NjWUTqL3sFpgWJssnu2qgmE2cm5N1jPDRRJuDcrsPEB
Grandma: 03f1bd2bff8e9c61f58a8d46d18fd8f3149b1f2d76b3c423a7874a5d5811d67cee
Grandma
tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw
wsh(multi(2,Grandma,Alice,Barbara))#5m0qdehe
Alice: 02e486e32f0f87136fa042cb53219ace8537ea1d036deb2f4293570b94325d11cb
Barbara: 02a3f3f2658b9812ddeabfbde2fde03f8a65369e4ed621f29fa8ba0cc519b789fb
Grandma: cS2XH31JtmbxXUxt1yxVgFzy69zq4b5jx6zFok3B4HzBEwQ5D2Kq
diff --git a/docs/.vuepress/public/descriptor-based-paper-wallets/data-url.txt b/docs/.vuepress/public/descriptor-based-paper-wallets/data-url.txt new file mode 100644 index 0000000000..4eb7f23658 --- /dev/null +++ b/docs/.vuepress/public/descriptor-based-paper-wallets/data-url.txt @@ -0,0 +1 @@ +data:text/html;base64,PCFET0NUWVBFIGh0bWw+PGh0bWw+PGhlYWQ+PG1ldGEgY2hhcnNldD0iVVRGLTgiPjwvbWV0YT48dGl0bGU+Qml0Y29pbiBQYXBlciBXYWxsZXQ8L3RpdGxlPjxzdHlsZT46cm9vdCB7IC0td2FsbGV0LXdpZHRoOiAyMDBweDsgLS1wYWdlLW1hcmdpbjogMWVtO31odG1sLCBib2R5IHsgaGVpZ2h0OiAxMDAlOyB3aWR0aDogMTAwJTsgbWFyZ2luOiAwOyBhbGlnbi1pdGVtczogY2VudGVyOyBmb250LWZhbWlseTogbW9ub3NwYWNlOyBkaXNwbGF5OiBmbGV4OyBmbGV4LXdyYXA6IHdyYXA7IGp1c3RpZnktY29udGVudDogc3BhY2UtZXZlbmx5O30uc2luZ2xlIHsgd2lkdGg6IDIwMHB4OyB3aWR0aDogdmFyKC0td2FsbGV0LXdpZHRoKTsgYm9yZGVyOiBkYXNoZWQ7IGJvcmRlci13aWR0aDogdGhpbjsgZGlzcGxheTogZmxleDsgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuOyBoZWlnaHQ6IGNhbGMoMTAwJSAtIDIgKiB2YXIoLS1wYWdlLW1hcmdpbikpOyBtYXJnaW46IHZhcigtLXBhZ2UtbWFyZ2luKSAwOyBwb3NpdGlvbjogcmVsYXRpdmU7fS5zaW5nbGU6YWZ0ZXIgeyBjb250ZW50OiB1cmwoJ2RhdGE6aW1hZ2Uvc3ZnK3htbDtiYXNlNjQsUEQ5NGJXd2dkbVZ5YzJsdmJqMGlNUzR3SWlCbGJtTnZaR2x1WnowaVZWUkdMVGdpUHo0OGMzWm5JSFpsY25OcGIyNDlJakV1TVNJZ2RtbGxkMEp2ZUQwaU1DQXdJREV3TUNBMk1DSWdlRzFzYm5NOUltaDBkSEE2THk5M2QzY3Vkek11YjNKbkx6SXdNREF2YzNabklqNDhaeUIwY21GdWMyWnZjbTA5SW5SeVlXNXpiR0YwWlNnd0lDMDVPVEl1TXpZcElqNDhaeUIwY21GdWMyWnZjbTA5SW0xaGRISnBlQ2cwTGpJMk1URWdMVEV1TWpNMU1TQXhMakl6TlRFZ05DNHlOakV4SUMweE16TTNMamdnTFRJNU9UVXBJajQ4Y0dGMGFDQm1hV3hzUFNJalpETmtNMlF6SWlCa1BTSnROVGt1TnpNeUlEazFOaTQwWXkwd0xqWXdPVGM0TFRFdU16a3lPUzB5TGpNd016VXRNUzQ0TXpVMkxUTXVOams0T1MweExqY3hNak5zTFRndU56UXlOaUF3TGpZNU5UWTJZeTB4TGprek5UY3RNUzQ1TVRReUxUUXVNekEzTlMweUxqSXdORGt0TkM0eE16SXhMVEl1T0RFMk5TQXdMakV6TnpBMExUQXVORGM0TURZZ01DNDFORFU1T1Mwd0xqSTBOelExSURBdU9ETTNNUzB4TGpVeE1TQXdMakkzT1RVeExURXVNakV6TWkwd0xqY3hORGN4TFRJdU5EVTFNUzB4TGpreE5qVXRNaTQzTVRRNUxURXVNVGMzTnkwd0xqTTBOVEkyTFRJdU5qVTVPQ0F3TGpJd09ESTNMVE11TURJM055QXhMalExTWkwd0xqUTBOemc0SURFdU1qTXdOaUF3TGpJM016ZzNJREl1TmprNU55QXhMalE1T1RVZ015NHhOQ0F4TGpRd01Ea2dNQzQyTXpjMElEUXVNalEyTmlBd0xqUTVNemM1SURRdU9ETTNPQ0F6TGpBeU1TMHhMak00TkRnZ01TNDBNVEV6TFRJdU9Ua3pNU0F3TGprMU5USTFMVFF1TkRJeU1TQXdMalExTlRFdE1TNHhPRFkwTFRBdU5ERTFNalF0TWk0M016UXpMVEF1TkRnME9EY3RNeTQyTkRrMklEQXVOVE0xT0RrdE1DNDRPREUzTWlBd0xqazNOamswTFRBdU9EQXdNVFlnTWk0M05UQTJJREF1TXpjMk5qZ2dNeTQwTmpReklERXVNVFV5T0NBd0xqZzBNakVnTXk0d09UTXpJREF1TnpVeE9DQXpMamd5TkRNdE1DNDJOREUzTWlBd0xqVTJNelEzTFRFdU1EYzBNUzB3TGpBNU1URTVMVEV1T0RReU5DQXdMak16T0MweUxqRTJPQ0F3TGpNeU16ZzBMVEF1TWpRMU5qTWdNUzQzTlRreUlEQXVNell4T1RRZ05DNDNORGs1TFRBdU1EWTRObXczTGpZNE5EY2dOUzQwTmpSak1DNDVPVE0zTWlBd0xqWXhNVEU1SURJdU16RTJOU0F3TGprM09UUTNJRE11TlRjM09DQXdMakU1TVRZMGJDMDNMamt3TWpjdE5TNDRPVEE1SURrdU56WTJOUzB3TGpnNU5UYzBlbTB0TVRjdU1EYzFMVFl1T0RjeE9XTXhMakEwTlRNZ01TNHdOVEUySURBdU5EQXpNekVnTWk0NU1EY3pMVEF1T1RrME5URWdNaTQ1TURFMkxURXVNamcyTWlBd0xqQTNNaTB5TGpRMU5EWXRNUzQwT1RNeUxURXVOekU0TkMweUxqWTFNemdnTUM0MU1UWTBPQzB3TGprM056TTNJREV1T1RrM05DMHdMamsyTnpZNUlESXVOekV5T1Mwd0xqSTBOemd5ZW0wdE1pNHhOVFV5SURjdU56SXlOR014TGpFMk1URWdNQzQ0TlRFM09TQXdMak14TURjeUlESXVPVGcxTnkweExqQTVORFFnTWk0NU1ESTBMVEF1T1RZeU9UWWdNQzR3TlRNdE1pNHdPRGsyTFRBdU56UXpOQzB4TGpnNE1qUXRNUzQ0TURBMklEQXVNVGc0T1MweExqTXdNelVnTVM0NU9EZ3hMVEl1TURFME15QXlMamszTmpndE1TNHhNREU0ZWlJdlBqd3ZaejQ4TDJjK1BDOXpkbWMrQ2c9PScpOyB3aWR0aDogM2VtOyBwb3NpdGlvbjogYWJzb2x1dGU7IGJvdHRvbTogLTFlbTsgcmlnaHQ6IC0xLjY2ZW07IHRyYW5zZm9ybTogcm90YXRlKC05MGRlZyk7fS5icmVhay13b3JkIHsgd29yZC1icmVhazogYnJlYWstYWxsOyBwYWRkaW5nOiAwLjM1ZW07IC13ZWJraXQtcHJpbnQtY29sb3ItYWRqdXN0OiBleGFjdDsgcG9zaXRpb246IHJlbGF0aXZlOyBvdmVyZmxvdzogaGlkZGVuO30uYnJlYWstd29yZDo6YmVmb3JlIHsgY29udGVudDogJyc7IGJvcmRlcjogMTAwMDBweCBzb2xpZCBsaWdodGdyYXk7IHBvc2l0aW9uOiBhYnNvbHV0ZTsgdG9wOiAwOyBsZWZ0OiAwOyB6LWluZGV4OiAtMTsgYm94LXNpemluZzogYm9yZGVyLWJveDt9LnBhZCB7IHBhZGRpbmctdG9wOiAwLjFlbTsgcGFkZGluZy1ib3R0b206IDAuMWVtOyBmb250LXNpemU6IHgtc21hbGw7fS5jZW50ZXIgeyB0ZXh0LWFsaWduOiBjZW50ZXI7IGhlaWdodDogMjAwcHg7IGhlaWdodDogdmFyKC0td2FsbGV0LXdpZHRoKTt9LmJsYWNrIHsgcG9zaXRpb246IHJlbGF0aXZlOyBvdmVyZmxvdzogaGlkZGVuOyBmbGV4LWdyb3c6IDI7fS5ibGFjazo6YmVmb3JlIHsgY29udGVudDogJyc7IGJvcmRlcjogMTAwMDBweCBzb2xpZCBibGFjazsgcG9zaXRpb246IGFic29sdXRlOyB6LWluZGV4OiAtMTsgYm94LXNpemluZzogYm9yZGVyLWJveDt9LnFyIHsgaGVpZ2h0OiA4MCU7IG1hcmdpbjogMTAlOyBpbWFnZS1yZW5kZXJpbmc6IHBpeGVsYXRlZDsgaW1hZ2UtcmVuZGVyaW5nOiBjcmlzcC1lZGdlczt9LmJvbGQgeyB3aWR0aDogMTAwJTsgZGlzcGxheTogaW5saW5lLWJsb2NrOyB0ZXh0LWFsaWduOiBjZW50ZXI7IGZvbnQtd2VpZ2h0OiA4MDA7fUBtZWRpYSBwcmludCB7IEBwYWdlIHsgbWFyZ2luOiAwOyB9IDpyb290IHsgIC0td2FsbGV0LXdpZHRoOiA1Y207ICAtLXBhZ2UtbWFyZ2luOiAxY207IH19PC9zdHlsZT48L2hlYWQ+PGJvZHk+PGRpdiBjbGFzcz0ic2luZ2xlIj48ZGl2PjxkaXYgY2xhc3M9ImJyZWFrLXdvcmQiPjxzcGFuIGNsYXNzPSJib2xkIj5BbGljZTwvc3Bhbj48YnI+dGIxcXU2bGN1YTl3MnprYXJqajV4d3hoM2wzcXRjeGg4NGhzcmEzanJ2cHN6aDY5ajJlNTR4N3EzdGh5Y3c8L2Rpdj48ZGl2IGNsYXNzPSJjZW50ZXIiPjxpbWcgY2xhc3M9InFyIiBzcmM9ImRhdGE6aW1hZ2UvYm1wO2Jhc2U2NCxRazF1QmdBQUFBQUFBRDRBQUFBb0FBQUFZd0FBQUdNQUFBQUJBQUVBQUFBQUFEQUdBQUFBQWdBQUFBSUFBQUlBQUFBQ0FBQUEvLy8vQUFBQUFBRC8vL2pnQWNELzhBY0FmOGZnQUFBQS8vLzQ0QUhBLy9BSEFIL0g0QUFBQVAvLytPQUJ3UC93QndCL3grQUFBQURnQURnQUFjZi9nRC9nRDhEZ0FBQUE0QUE0QUFISC80QS80QS9BNEFBQUFPQUFPQUFCeC8rQVArQVB3T0FBQUFEai9qZ0FELzhBRC9nZmdmZ0FBQUFBNC80NEFBLy9BQS80SDRINEFBQUFBT1ArT0FBUC93QVArQitCK0FBQUFBRGovamdjY0FBRC9nZmdEL2pnQUFBQTQvNDRISEFBQS80SDRBLzQ0QUFBQU9QK09CeHdBQVArQitBUCtPQUFBQURqL2pqOGNEamdBRC8vLy84QUFBQUE0LzQ0L0hBNDRBQS8vLy8vQUFBQUFPUCtPUHh3T09BQVAvLy8vd0FBQUFEZ0FEZ2ZnZmpnRGpqZ0Q4QUFBQUFBNEFBNEg0SDQ0QTQ0NEEvQUFBQUFBT0FBT0IrQitPQU9PT0FQd0FBQUFBRC8vL2pqZ2YvamdBZmpqai9nQUFBQS8vLzQ0NEgvNDRBSDQ0NC80QUFBQVAvLytPT0IvK09BQitPT1ArQUFBQUFBQUFEOERnRDhmL2pnRGo4QUFBQUFBQUFBL0E0QS9ILzQ0QTQvQUFBQUFBQUFBUHdPQVB4LytPQU9Qd0FBQUFEL2dmZ2NEOGNmZ2YvLy84QUFBQUFBLzRINEhBL0hINEgvLy8vQUFBQUFBUCtCK0J3UHh4K0IvLy8vd0FBQUFBQUQ4Y0FjZmdBY2ZqOGNEai9nQUFBQUEvSEFISDRBSEg0L0hBNC80QUFBQUFQeHdCeCtBQngrUHh3T1ArQUFBQUFEOGYvZ0Q4RGo4QUFBRDhjQUFBQUFBL0gvNEEvQTQvQUFBQS9IQUFBQUFBUHgvK0FQd09Qd0FBQVB4d0FBQUFELy9nRGpnY0RnY2Y4Y2NmamdBQUFBLy80QTQ0SEE0SEgvSEhINDRBQUFBUC8rQU9PQndPQngveHh4K09BQUFBRGo4RDhjZmdBRC9nQURnZi9nQUFBQTQvQS9ISDRBQS80QUE0SC80QUFBQU9Qd1B4eCtBQVArQUFPQi8rQUFBQUQvajhjZjhBY2ZqOERnQUFBQUFBQUEvNC9ISC9BSEg0L0E0QUFBQUFBQUFQK1B4eC93QngrUHdPQUFBQUFBQUFEOEFEZ0FBQUQ4QWYvOERqamdBQUFBL0FBNEFBQUEvQUgvL0E0NDRBQUFBUHdBT0FBQUFQd0IvL3dPT09BQUFBQWNBY0RnRGdEampnQWNjY2ZnQUFBQUhBSEE0QTRBNDQ0QUhISEg0QUFBQUJ3QndPQU9BT09PQUJ4eHgrQUFBQURnQUQ4QUFjRGdjZmo4Y2YvZ0FBQUE0QUEvQUFIQTRISDQvSEgvNEFBQUFPQUFQd0FCd09CeCtQeHgvK0FBQUFBY2Y4Y2YvOGZnQWNjRDhmamdBQUFBSEgvSEgvL0g0QUhIQS9INDRBQUFBQngveHgvL3grQUJ4d1B4K09BQUFBQURqL2dBZmdjRGpqOGNjQWNBQUFBQUE0LzRBSDRIQTQ0L0hIQUhBQUFBQUFPUCtBQitCd09PUHh4d0J3QUFBQUQ4Y0FELzhmZ0QvOEQ4RC8vZ0FBQUEvSEFBLy9INEEvL0EvQS8vNEFBQUFQeHdBUC94K0FQL3dQd1AvK0FBQUFBRGpqLy9qOERnY0QvOERqOEFBQUFBQTQ0Ly80L0E0SEEvL0E0L0FBQUFBQU9PUC8rUHdPQndQL3dPUHdBQUFBRC8vZ0QvOGNjQURqL2dmLy9nQUFBQS8vNEEvL0hIQUE0LzRILy80QUFBQVAvK0FQL3h4d0FPUCtCLy8rQUFBQUQ4ZmpnZjhmamo4QWZqLzhEZ0FBQUEvSDQ0SC9INDQvQUg0Ly9BNEFBQUFQeCtPQi94K09Qd0IrUC93T0FBQUFELy84RDhEZ0Q4Zi8vZ0FEZ0FBQUFBLy8vQS9BNEEvSC8vNEFBNEFBQUFBUC8vd1B3T0FQeC8vK0FBT0FBQUFBRGdEai9nY0QvamdmLy8vOERnQUFBQTRBNC80SEEvNDRILy8vL0E0QUFBQU9BT1ArQndQK09CLy8vL3dPQUFBQUFBQUFEZ0FBQWYvOERnQUFBQUFBQUFBQUFBNEFBQUgvL0E0QUFBQUFBQUFBQUFBT0FBQUIvL3dPQUFBQUFBQUFELy8vampqampqampqai8vL2dBQUFBLy8vNDQ0NDQ0NDQ0NC8vLzRBQUFBUC8vK09PT09PT09PT1AvLytBQUFBRGdBRGovai84Y0RnZmpnQURnQUFBQTRBQTQvNC8vSEE0SDQ0QUE0QUFBQU9BQU9QK1AveHdPQitPQUFPQUFBQURqL2pqLzhjRDhjZmdEai9qZ0FBQUE0LzQ0Ly9IQS9ISDRBNC80NEFBQUFPUCtPUC94d1B4eCtBT1ArT0FBQUFEai9qai84QUQ4QWY4RGovamdBQUFBNC80NC8vQUEvQUgvQTQvNDRBQUFBT1ArT1Avd0FQd0Ivd09QK09BQUFBRGovamdEL2pnZi84RGpqL2pnQUFBQTQvNDRBLzQ0SC8vQTQ0LzQ0QUFBQU9QK09BUCtPQi8vd09PUCtPQUFBQURnQURnRC8vOERqZ2ZqZ0FEZ0FBQUE0QUE0QS8vL0E0NEg0NEFBNEFBQUFPQUFPQVAvL3dPT0IrT0FBT0FBQUFELy8vamdEOEFEZ0Qvai8vL2dBQUFBLy8vNDRBL0FBNEEvNC8vLzRBQUFBUC8vK09BUHdBT0FQK1AvLytBQUFBQT0iPjwvaW1nPjwvZGl2PjwvZGl2PjxkaXYgY2xhc3M9ImJsYWNrIj48L2Rpdj48ZGl2PjxkaXYgY2xhc3M9ImJyZWFrLXdvcmQiPjxkaXYgY2xhc3M9InBhZCI+d3NoKG11bHRpKDIsR3JhbmRtYSxBbGljZSxCYXJiYXJhKSkjZW0zcTczbDU8L2Rpdj48ZGl2IGNsYXNzPSJwYWQiPkFsaWNlOiBjU1NLUkhEbVFFRXV0cDVMRDE0dEFjaXh1MmVoU05QRFRxTmVrMXpNYTlQZXQ5OHF4SHEzPC9kaXY+PGRpdiBjbGFzcz0icGFkIj5CYXJiYXJhOiAwMmEzZjNmMjY1OGI5ODEyZGRlYWJmYmRlMmZkZTAzZjhhNjUzNjllNGVkNjIxZjI5ZmE4YmEwY2M1MTliNzg5ZmI8L2Rpdj48ZGl2IGNsYXNzPSJwYWQiPkdyYW5kbWE6IDAzZjFiZDJiZmY4ZTljNjFmNThhOGQ0NmQxOGZkOGYzMTQ5YjFmMmQ3NmIzYzQyM2E3ODc0YTVkNTgxMWQ2N2NlZTwvZGl2PjwvZGl2PjxkaXYgY2xhc3M9ImNlbnRlciI+PGltZyBjbGFzcz0icXIiIHNyYz0iZGF0YTppbWFnZS9ibXA7YmFzZTY0LFFrMW1FUUFBQUFBQUFENEFBQUFvQUFBQXR3QUFBTGNBQUFBQkFBRUFBQUFBQUNnUkFBQUFBZ0FBQUFJQUFBSUFBQUFDQUFBQS8vLy9BQUFBQUFELy8vamdEL2dEZ0FmZ2Zqai8vLy84Y0Q4ZmdmZ2NEZ0QvLy9qZ0QvZ0RnQWZnZmpqLy8vLzhjRDhmZ2ZnY0RnRC8vL2pnRC9nRGdBZmdmamovLy8vOGNEOGZnZmdjRGdEZ0FEZ2NjRGovOGZqamdjRGdmai9nY0FEai84QUQvZ0RnQURnY2NEai84ZmpqZ2NEZ2ZqL2djQURqLzhBRC9nRGdBRGdjY0RqLzhmampnY0RnZmovZ2NBRGovOEFEL2dEai9qZ0FBY0Q4Y0FEOEFBY2NBQURnQWNjQWYvZ2NmZ0RqL2pnQUFjRDhjQUQ4QUFjY0FBRGdBY2NBZi9nY2ZnRGovamdBQWNEOGNBRDhBQWNjQUFEZ0FjY0FmL2djZmdEai9qai8vOERnRGdEampqZ2NBY0FEajhBQUFBZmdEZ0RqL2pqLy84RGdEZ0RqampnY0FjQURqOEFBQUFmZ0RnRGovamovLzhEZ0RnRGpqamdjQWNBRGo4QUFBQWZnRGdEai9qajhEamovLy9qamovLy84Y0FmZ0Q4QWYvLy9qZ0RqL2pqOERqai8vL2pqai8vLzhjQWZnRDhBZi8vL2pnRGovamo4RGpqLy8vampqLy8vOGNBZmdEOEFmLy8vamdEZ0FEamdjY0FBQUFmLy9nRDhEL2dBY0Fmai9nRC9qZ0RnQURqZ2NjQUFBQWYvL2dEOEQvZ0FjQWZqL2dEL2pnRGdBRGpnY2NBQUFBZi8vZ0Q4RC9nQWNBZmovZ0QvamdELy8vampnZmpqLzhEai9qai84RDhmLy8vai9qajhmZ0QvLy9qamdmamovOERqL2pqLzhEOGYvLy9qL2pqOGZnRC8vL2pqZ2Zqai84RGovamovOEQ4Zi8vL2ovamo4ZmdBQUFBRGpqamovai9nY0RnRGdmLy9qamovL2pnRGovZ0FBQUFEampqai9qL2djRGdEZ2YvL2pqai8vamdEai9nQUFBQURqampqL2ovZ2NEZ0RnZi8vampqLy9qZ0RqL2dELzhEZ2YvamdBY0FEai8vL2dEamdmLzhmamovLzhmZ0QvOERnZi9qZ0FjQURqLy8vZ0RqZ2YvOGZqai8vOGZnRC84RGdmL2pnQWNBRGovLy9nRGpnZi84ZmpqLy84ZmdEL2pnZi9qOERqampqamdEOERnRGdEZ0Q4Y0Q4ZmovZ0QvamdmL2o4RGpqampqZ0Q4RGdEZ0RnRDhjRDhmai9nRC9qZ2YvajhEampqampnRDhEZ0RnRGdEOGNEOGZqL2dBRC8vOEFmOEFEajhmOGYvOGNBRDhjY0FBRGdmOGY4QUFELy84QWY4QURqOGY4Zi84Y0FEOGNjQUFEZ2Y4ZjhBQUQvLzhBZjhBRGo4ZjhmLzhjQUQ4Y2NBQURnZjhmOEFEOGNBZmpnZmdjRGpqai9qajhELzhEL2dEL2pqZ0FEZ0Q4Y0FmamdmZ2NEampqL2pqOEQvOEQvZ0QvampnQURnRDhjQWZqZ2ZnY0Rqamovamo4RC84RC9nRC9qamdBRGdBQURqOGNmZ0FEajhmLzhBZjhBRC9qLy9qL2pnRC9qZ0FBRGo4Y2ZnQURqOGYvOEFmOEFEL2ovL2ovamdEL2pnQUFEajhjZmdBRGo4Zi84QWY4QUQvai8vai9qZ0QvamdBRC9nRDhEL2dBZmdmOEQ4QWZqOGZqLy8vL2dmOGNmZ0FEL2dEOEQvZ0FmZ2Y4RDhBZmo4ZmovLy8vZ2Y4Y2ZnQUQvZ0Q4RC9nQWZnZjhEOEFmajhmai8vLy9nZjhjZmdEajhmOGNBY0FEamo4Zi9nY0FEL2dEL2dmajhBRDhmZ0RqOGY4Y0FjQURqajhmL2djQUQvZ0QvZ2ZqOEFEOGZnRGo4ZjhjQWNBRGpqOGYvZ2NBRC9nRC9nZmo4QUQ4ZmdBY2NjRGpnY2Y4Y2NmZ0RnY0Rqai9qLzhmOEFBY0RqZ0FjY2NEamdjZjhjY2ZnRGdjRGpqL2ovOGY4QUFjRGpnQWNjY0RqZ2NmOGNjZmdEZ2NEamovai84ZjhBQWNEamdBRGpqLy9nQUFjQUFBZmdmZ0Q4QWNmOGNmLy9qai8vZ0FEamovL2dBQWNBQUFmZ2ZnRDhBY2Y4Y2YvL2pqLy9nQURqai8vZ0FBY0FBQWZnZmdEOEFjZjhjZi8vamovL2dBY2NBY0FBZmo4QWZqOEFEamdBZmdEZ2NEai9qampnQUFjY0FjQUFmajhBZmo4QURqZ0FmZ0RnY0RqL2pqamdBQWNjQWNBQWZqOEFmajhBRGpnQWZnRGdjRGovampqZ0FBQUQvOEFmOGNjZmpqZ2ZnZi8vOGNmOEQ4RGovL2pnQUFBRC84QWY4Y2NmampnZmdmLy84Y2Y4RDhEai8vamdBQUFELzhBZjhjY2ZqamdmZ2YvLzhjZjhEOERqLy9qZ0FBY2NjRDhmZ2Y4Y2NmOGNmLzhmamo4Y0FEOEFmOEFmZ0FjY2NEOGZnZjhjY2Y4Y2YvOGZqajhjQUQ4QWY4QWZnQWNjY0Q4ZmdmOGNjZjhjZi84ZmpqOGNBRDhBZjhBZmdBY0RqL2pqLy9nZmdEajhjRC9qamdEajhjRGdmZ2YvZ0FjRGovamovL2dmZ0RqOGNEL2pqZ0RqOGNEZ2ZnZi9nQWNEai9qai8vZ2ZnRGo4Y0QvampnRGo4Y0RnZmdmL2dBZmo4Zmo4Y0RqZ2YvL2ovZ0FEZ0RnZjhmZ0FEZ2ZqZ0FmajhmajhjRGpnZi8vai9nQURnRGdmOGZnQURnZmpnQWZqOGZqOGNEamdmLy9qL2dBRGdEZ2Y4ZmdBRGdmamdBZmdmOGNjQURnRC8vOGNBRC9qZ2ZnZmpnQWNBY0FEZ0FmZ2Y4Y2NBRGdELy84Y0FEL2pnZmdmamdBY0FjQURnQWZnZjhjY0FEZ0QvLzhjQUQvamdmZ2ZqZ0FjQWNBRGdEZ2NBY0FEZ2NBY2NjZmdEZ2YvZ2NjY2NBY0QvamdBQURnY0FjQURnY0FjY2NmZ0RnZi9nY2NjY0FjRC9qZ0FBRGdjQWNBRGdjQWNjY2ZnRGdmL2djY2NjQWNEL2pnQUFBY2ZqamdELy9qOERqZ0FEL2ovai9qL2pqamdEOEFmZ0FjZmpqZ0QvL2o4RGpnQUQvai9qL2ovampqZ0Q4QWZnQWNmampnRC8vajhEamdBRC9qL2ovai9qampnRDhBZmdEai9nRGdjQURqamo4QUFEOERqOGZqZ0Q4RDhEai9nQURqL2dEZ2NBRGpqajhBQUQ4RGo4ZmpnRDhEOERqL2dBRGovZ0RnY0FEampqOEFBRDhEajhmamdEOEQ4RGovZ0FEOGZqOEFEamdmampqampnQUQvLzhmajhmamdjZi84QUQ4Zmo4QURqZ2ZqampqamdBRC8vOGZqOGZqZ2NmLzhBRDhmajhBRGpnZmpqampqZ0FELy84Zmo4ZmpnY2YvOEFEL2djQWYvOGZnRGdBRGpnRGdmZ2NEZ2Y4QUQvamovZ0QvZ2NBZi84ZmdEZ0FEamdEZ2ZnY0RnZjhBRC9qai9nRC9nY0FmLzhmZ0RnQURqZ0RnZmdjRGdmOEFEL2pqL2dBQUQvLy8vZ2NmOGZqZ0QvLy9qZ2YvZ2YvOEQvL2pqZ0FBRC8vLy9nY2Y4ZmpnRC8vL2pnZi9nZi84RC8vampnQUFELy8vL2djZjhmamdELy8vamdmL2dmLzhELy9qamdBQURnRGdmZ0FBZi9qL2pnRDhjQWZqOGNBQURnRGdEZ0FBRGdEZ2ZnQUFmL2ovamdEOGNBZmo4Y0FBRGdEZ0RnQUFEZ0RnZmdBQWYvai9qZ0Q4Y0FmajhjQUFEZ0RnRGdEZ0RqamdjQWNEL2ovOGZqamdBQUQ4RDhEOGZqajhBQURnRGpqZ2NBY0Qvai84ZmpqZ0FBRDhEOEQ4ZmpqOEFBRGdEampnY0FjRC9qLzhmampnQUFEOEQ4RDhmamo4QUFEZ2ZnRC84ZmovL2pnY2ZnRGpqZ0Rqai8vZ0RnRGpqZ0RnZmdELzhmai8vamdjZmdEampnRGpqLy9nRGdEampnRGdmZ0QvOGZqLy9qZ2NmZ0RqamdEamovL2dEZ0RqamdEOGYvL2o4RDhmamovai8vLzhjQUFmai8vZ0QvL2dmZ0Q4Zi8vajhEOGZqai9qLy8vOGNBQWZqLy9nRC8vZ2ZnRDhmLy9qOEQ4ZmpqL2ovLy84Y0FBZmovL2dELy9nZmdBRC84QWNEZ0QvamdjZjhmLy9qLy9nZmpqai84RGpqZ0FELzhBY0RnRC9qZ2NmOGYvL2ovL2dmampqLzhEampnQUQvOEFjRGdEL2pnY2Y4Zi8vai8vZ2ZqamovOERqamdEOGYvOGNBQUFjY2ZnQWZnY2ZqOERqLzhjY2ZnY0RqZ0Q4Zi84Y0FBQWNjZmdBZmdjZmo4RGovOGNjZmdjRGpnRDhmLzhjQUFBY2NmZ0FmZ2NmajhEai84Y2NmZ2NEamdEZ2Y4RGdjY0FBZi84Zi8vai8vZ0FjRDhmajhmamdEZ0RnZjhEZ2NjQUFmLzhmLy9qLy9nQWNEOGZqOGZqZ0RnRGdmOERnY2NBQWYvOGYvL2ovL2dBY0Q4Zmo4ZmpnRGdEai9qLy8vLzhmL2dmajhELzhBY0FjY2NmOERqZ0RqZ0RqL2ovLy8vOGYvZ2ZqOEQvOEFjQWNjY2Y4RGpnRGpnRGovai8vLy84Zi9nZmo4RC84QWNBY2NjZjhEamdEamdBY0Q4Y0FEZ0RqOEQ4QWNmOGNmL2dBY2NBQUFEOGY4QUFjRDhjQURnRGo4RDhBY2Y4Y2YvZ0FjY0FBQUQ4ZjhBQWNEOGNBRGdEajhEOEFjZjhjZi9nQWNjQUFBRDhmOEFEamovZ0RnQUQvL2djZjhEajhBZmdEZ2NjZmdBZjhEZ0Rqai9nRGdBRC8vZ2NmOERqOEFmZ0RnY2NmZ0FmOERnRGpqL2dEZ0FELy9nY2Y4RGo4QWZnRGdjY2ZnQWY4RGdEOEFjQWNBY2NmOEQ4RC9qOGNEOEQ4Zi9qL2ovLzhBQUQ4QWNBY0FjY2Y4RDhEL2o4Y0Q4RDhmL2ovai8vOEFBRDhBY0FjQWNjZjhEOEQvajhjRDhEOGYvai9qLy84QUFEajhmOEFEai8vZ2YvajhEai84Y2ZqZ0RnQWNEZ0FBQURqOGY4QURqLy9nZi9qOERqLzhjZmpnRGdBY0RnQUFBRGo4ZjhBRGovL2dmL2o4RGovOGNmamdEZ0FjRGdBQUFEamdjY0Q4RC84RGpqOEFjRGpqOEFjZmovOERqLzhjQURqZ2NjRDhELzhEamo4QWNEamo4QWNmai84RGovOGNBRGpnY2NEOEQvOERqajhBY0RqajhBY2ZqLzhEai84Y0FELzhmLzhmL2dEamovZ0Q4RDhBRGdmZ0RqLy8vZ0FEZ0QvOGYvOGYvZ0Rqai9nRDhEOEFEZ2ZnRGovLy9nQURnRC84Zi84Zi9nRGpqL2dEOEQ4QURnZmdEai8vL2dBRGdBQUFjZmo4QUFBQUFmL2ovZ0Q4RGdBRGo4Zjhmai9nQUFBQWNmajhBQUFBQWYvai9nRDhEZ0FEajhmOGZqL2dBQUFBY2ZqOEFBQUFBZi9qL2dEOERnQURqOGY4ZmovZ0FBY2YvamdEZ2NjZi9qL2dmamdBZmovOEFBRDhELy84QUFjZi9qZ0RnY2NmL2ovZ2ZqZ0Fmai84QUFEOEQvLzhBQWNmL2pnRGdjY2Yvai9nZmpnQWZqLzhBQUQ4RC8vOEFBQWNjQURqai9qL2pnQUFjRGpqamo4RGpnZmpnY2ZqZ0FBY2NBRGpqL2ovamdBQWNEampqajhEamdmamdjZmpnQUFjY0FEamovai9qZ0FBY0RqampqOERqZ2ZqZ2NmamdBZmdEOERnQUQ4ZmdBY0FEampnY0RqZ0FmOERqajhBQUFmZ0Q4RGdBRDhmZ0FjQURqamdjRGpnQWY4RGpqOEFBQWZnRDhEZ0FEOGZnQWNBRGpqZ2NEamdBZjhEamo4QUFBQUQ4QUFjQWNmL2dmampqL2pqL2ovOEFBZi9qampqZ0FBRDhBQWNBY2YvZ2Zqamovamovai84QUFmL2pqampnQUFEOEFBY0FjZi9nZmpqai9qai9qLzhBQWYvampqamdBQWNmOERnY0FjQUFEOGY4RGpqai84RGovampqajhEZ0FBY2Y4RGdjQWNBQUQ4ZjhEampqLzhEai9qampqOERnQUFjZjhEZ2NBY0FBRDhmOERqamovOERqL2pqamo4RGdBY0Q4Y2NEamdEampnY2NmZ2Y4QWNEampnZmdmLy9qZ0FjRDhjY0RqZ0RqamdjY2ZnZjhBY0RqamdmZ2YvL2pnQWNEOGNjRGpnRGpqZ2NjZmdmOEFjRGpqZ2ZnZi8vamdBRC9qZ2NjRGdmL2djY2NEL2pnQWNBRC8vOEFmOEFmZ0FEL2pnY2NEZ2YvZ2NjY0QvamdBY0FELy84QWY4QWZnQUQvamdjY0RnZi9nY2NjRC9qZ0FjQUQvLzhBZjhBZmdBQURnRGdmOERnRGdmajhjQUQvL2pqOGYvamo4Zmo4QUFBRGdEZ2Y4RGdEZ2ZqOGNBRC8vamo4Zi9qajhmajhBQUFEZ0RnZjhEZ0RnZmo4Y0FELy9qajhmL2pqOGZqOEFEZ2YvL2djQWZnRGpqZ2YvLy9nQWZnQURqOEQ4RGovZ0RnZi8vZ2NBZmdEampnZi8vL2dBZmdBRGo4RDhEai9nRGdmLy9nY0FmZ0RqamdmLy8vZ0FmZ0FEajhEOERqL2dBQUFBQUQ4Zi9nY0FjRGpnRDhmL2dmamdjY0FBQUFBQUFBQUFBRDhmL2djQWNEamdEOGYvZ2ZqZ2NjQUFBQUFBQUFBQUFEOGYvZ2NBY0RqZ0Q4Zi9nZmpnY2NBQUFBQUFELy8vampqampqampqampqampqampqampqampqLy8vZ0QvLy9qampqampqampqampqampqampqampqamovLy9nRC8vL2pqampqampqampqampqampqampqampqai8vL2dEZ0FEZ0FBQUQvai9nY2ZnRC9qOGZqOEFjZmdEZ0FEZ0RnQURnQUFBRC9qL2djZmdEL2o4Zmo4QWNmZ0RnQURnRGdBRGdBQUFEL2ovZ2NmZ0QvajhmajhBY2ZnRGdBRGdEai9qamdmZ2ZqOEFjRGovLzhEamdmL2dEajhEai9qZ0RqL2pqZ2ZnZmo4QWNEai8vOERqZ2YvZ0RqOERqL2pnRGovampnZmdmajhBY0RqLy84RGpnZi9nRGo4RGovamdEai9qZ2NBRDhjZmo4RGpnY2Y4Zi8vZ0FmL2pqai9qZ0RqL2pnY0FEOGNmajhEamdjZjhmLy9nQWYvampqL2pnRGovamdjQUQ4Y2ZqOERqZ2NmOGYvL2dBZi9qamovamdEai9qamo4QURnZi9qOGYvLy9nY2ZqLy9qLy9qai9qZ0RqL2pqajhBRGdmL2o4Zi8vL2djZmovL2ovL2pqL2pnRGovampqOEFEZ2YvajhmLy8vZ2Nmai8vai8vamovamdEZ0FEai84RDhEZ2NELzhEZ0RnY0FEZ2NBY2ZqZ0FEZ0RnQURqLzhEOERnY0QvOERnRGdjQURnY0FjZmpnQURnRGdBRGovOEQ4RGdjRC84RGdEZ2NBRGdjQWNmamdBRGdELy8vai84Y2NmOEFmai84Zmo4RGovLy9qZ2ZqLy8vZ0QvLy9qLzhjY2Y4QWZqLzhmajhEai8vL2pnZmovLy9nRC8vL2ovOGNjZjhBZmovOGZqOERqLy8vamdmai8vL2dBPSI+PC9pbWc+PC9kaXY+PC9kaXY+PC9kaXY+PGRpdiBjbGFzcz0ic2luZ2xlIj48ZGl2PjxkaXYgY2xhc3M9ImJyZWFrLXdvcmQiPjxzcGFuIGNsYXNzPSJib2xkIj5CYXJiYXJhPC9zcGFuPjxicj50YjFxdTZsY3VhOXcyemthcmpqNXh3eGgzbDNxdGN4aDg0aHNyYTNqcnZwc3poNjlqMmU1NHg3cTN0aHljdzwvZGl2PjxkaXYgY2xhc3M9ImNlbnRlciI+PGltZyBjbGFzcz0icXIiIHNyYz0iZGF0YTppbWFnZS9ibXA7YmFzZTY0LFFrMXVCZ0FBQUFBQUFENEFBQUFvQUFBQVl3QUFBR01BQUFBQkFBRUFBQUFBQURBR0FBQUFBZ0FBQUFJQUFBSUFBQUFDQUFBQS8vLy9BQUFBQUFELy8vamdBY0QvOEFjQWY4ZmdBQUFBLy8vNDRBSEEvL0FIQUgvSDRBQUFBUC8vK09BQndQL3dCd0IveCtBQUFBRGdBRGdBQWNmL2dEL2dEOERnQUFBQTRBQTRBQUhILzRBLzRBL0E0QUFBQU9BQU9BQUJ4LytBUCtBUHdPQUFBQURqL2pnQUQvOEFEL2dmZ2ZnQUFBQUE0LzQ0QUEvL0FBLzRINEg0QUFBQUFPUCtPQUFQL3dBUCtCK0IrQUFBQUFEai9qZ2NjQUFEL2dmZ0QvamdBQUFBNC80NEhIQUFBLzRINEEvNDRBQUFBT1ArT0J4d0FBUCtCK0FQK09BQUFBRGovamo4Y0RqZ0FELy8vLzhBQUFBQTQvNDQvSEE0NEFBLy8vLy9BQUFBQU9QK09QeHdPT0FBUC8vLy93QUFBQURnQURnZmdmamdEampnRDhBQUFBQUE0QUE0SDRINDRBNDQ0QS9BQUFBQUFPQUFPQitCK09BT09PQVB3QUFBQUFELy8vampnZi9qZ0FmampqL2dBQUFBLy8vNDQ0SC80NEFINDQ0LzRBQUFBUC8vK09PQi8rT0FCK09PUCtBQUFBQUFBQUQ4RGdEOGYvamdEajhBQUFBQUFBQUEvQTRBL0gvNDRBNC9BQUFBQUFBQUFQd09BUHgvK09BT1B3QUFBQUQvZ2ZnY0Q4Y2ZnZi8vLzhBQUFBQUEvNEg0SEEvSEg0SC8vLy9BQUFBQUFQK0IrQndQeHgrQi8vLy93QUFBQUFBRDhjQWNmZ0FjZmo4Y0RqL2dBQUFBQS9IQUhINEFISDQvSEE0LzRBQUFBQVB4d0J4K0FCeCtQeHdPUCtBQUFBQUQ4Zi9nRDhEajhBQUFEOGNBQUFBQUEvSC80QS9BNC9BQUFBL0hBQUFBQUFQeC8rQVB3T1B3QUFBUHh3QUFBQUQvL2dEamdjRGdjZjhjY2ZqZ0FBQUEvLzRBNDRIQTRISC9ISEg0NEFBQUFQLytBT09Cd09CeC94eHgrT0FBQUFEajhEOGNmZ0FEL2dBRGdmL2dBQUFBNC9BL0hINEFBLzRBQTRILzRBQUFBT1B3UHh4K0FBUCtBQU9CLytBQUFBRC9qOGNmOEFjZmo4RGdBQUFBQUFBQS80L0hIL0FISDQvQTRBQUFBQUFBQVArUHh4L3dCeCtQd09BQUFBQUFBQUQ4QURnQUFBRDhBZi84RGpqZ0FBQUEvQUE0QUFBQS9BSC8vQTQ0NEFBQUFQd0FPQUFBQVB3Qi8vd09PT0FBQUFBY0FjRGdEZ0RqamdBY2NjZmdBQUFBSEFIQTRBNEE0NDRBSEhISDRBQUFBQndCd09BT0FPT09BQnh4eCtBQUFBRGdBRDhBQWNEZ2NmajhjZi9nQUFBQTRBQS9BQUhBNEhINC9ISC80QUFBQU9BQVB3QUJ3T0J4K1B4eC8rQUFBQUFjZjhjZi84ZmdBY2NEOGZqZ0FBQUFISC9ISC8vSDRBSEhBL0g0NEFBQUFCeC94eC8veCtBQnh3UHgrT0FBQUFBRGovZ0FmZ2NEamo4Y2NBY0FBQUFBQTQvNEFINEhBNDQvSEhBSEFBQUFBQU9QK0FCK0J3T09QeHh3QndBQUFBRDhjQUQvOGZnRC84RDhELy9nQUFBQS9IQUEvL0g0QS8vQS9BLy80QUFBQVB4d0FQL3grQVAvd1B3UC8rQUFBQUFEamovL2o4RGdjRC84RGo4QUFBQUFBNDQvLzQvQTRIQS8vQTQvQUFBQUFBT09QLytQd09Cd1Avd09Qd0FBQUFELy9nRC84Y2NBRGovZ2YvL2dBQUFBLy80QS8vSEhBQTQvNEgvLzRBQUFBUC8rQVAveHh3QU9QK0IvLytBQUFBRDhmamdmOGZqajhBZmovOERnQUFBQS9INDRIL0g0NC9BSDQvL0E0QUFBQVB4K09CL3grT1B3QitQL3dPQUFBQUQvLzhEOERnRDhmLy9nQURnQUFBQUEvLy9BL0E0QS9ILy80QUE0QUFBQUFQLy93UHdPQVB4Ly8rQUFPQUFBQUFEZ0RqL2djRC9qZ2YvLy84RGdBQUFBNEE0LzRIQS80NEgvLy8vQTRBQUFBT0FPUCtCd1ArT0IvLy8vd09BQUFBQUFBQURnQUFBZi84RGdBQUFBQUFBQUFBQUE0QUFBSC8vQTRBQUFBQUFBQUFBQUFPQUFBQi8vd09BQUFBQUFBQUQvLy9qampqampqampqLy8vZ0FBQUEvLy80NDQ0NDQ0NDQ0Ly8vNEFBQUFQLy8rT09PT09PT09PUC8vK0FBQUFEZ0FEai9qLzhjRGdmamdBRGdBQUFBNEFBNC80Ly9IQTRINDRBQTRBQUFBT0FBT1ArUC94d09CK09BQU9BQUFBRGovamovOGNEOGNmZ0RqL2pnQUFBQTQvNDQvL0hBL0hINEE0LzQ0QUFBQU9QK09QL3h3UHh4K0FPUCtPQUFBQURqL2pqLzhBRDhBZjhEai9qZ0FBQUE0LzQ0Ly9BQS9BSC9BNC80NEFBQUFPUCtPUC93QVB3Qi93T1ArT0FBQUFEai9qZ0QvamdmLzhEamovamdBQUFBNC80NEEvNDRILy9BNDQvNDRBQUFBT1ArT0FQK09CLy93T09QK09BQUFBRGdBRGdELy84RGpnZmpnQURnQUFBQTRBQTRBLy8vQTQ0SDQ0QUE0QUFBQU9BQU9BUC8vd09PQitPQUFPQUFBQUQvLy9qZ0Q4QURnRC9qLy8vZ0FBQUEvLy80NEEvQUE0QS80Ly8vNEFBQUFQLy8rT0FQd0FPQVArUC8vK0FBQUFBPSI+PC9pbWc+PC9kaXY+PC9kaXY+PGRpdiBjbGFzcz0iYmxhY2siPjwvZGl2PjxkaXY+PGRpdiBjbGFzcz0iYnJlYWstd29yZCI+PGRpdiBjbGFzcz0icGFkIj53c2gobXVsdGkoMixHcmFuZG1hLEFsaWNlLEJhcmJhcmEpKSNueGZhNW4wejwvZGl2PjxkaXYgY2xhc3M9InBhZCI+QWxpY2U6IDAyZTQ4NmUzMmYwZjg3MTM2ZmEwNDJjYjUzMjE5YWNlODUzN2VhMWQwMzZkZWIyZjQyOTM1NzBiOTQzMjVkMTFjYjwvZGl2PjxkaXYgY2xhc3M9InBhZCI+QmFyYmFyYTogY1NmTUx6U1o5TmpXVVRxTDNzRnBnV0pzc251MnFnbUUyY201TjFqUERSUkp1RGNyc1BFQjwvZGl2PjxkaXYgY2xhc3M9InBhZCI+R3JhbmRtYTogMDNmMWJkMmJmZjhlOWM2MWY1OGE4ZDQ2ZDE4ZmQ4ZjMxNDliMWYyZDc2YjNjNDIzYTc4NzRhNWQ1ODExZDY3Y2VlPC9kaXY+PC9kaXY+PGRpdiBjbGFzcz0iY2VudGVyIj48aW1nIGNsYXNzPSJxciIgc3JjPSJkYXRhOmltYWdlL2JtcDtiYXNlNjQsUWsxbUVRQUFBQUFBQUQ0QUFBQW9BQUFBdHdBQUFMY0FBQUFCQUFFQUFBQUFBQ2dSQUFBQUFnQUFBQUlBQUFJQUFBQUNBQUFBLy8vL0FBQUFBQUQvLy9qOGZqOGY4Y0Q4Y0QvZ2NBQWY4ZmdmL2o4QWZnRC8vL2o4Zmo4ZjhjRDhjRC9nY0FBZjhmZ2YvajhBZmdELy8vajhmajhmOGNEOGNEL2djQUFmOGZnZi9qOEFmZ0RnQURnRDhjZmdBQWNjQUFmZ0Q4Y0QvL2o4ZmovOEFBRGdBRGdEOGNmZ0FBY2NBQWZnRDhjRC8vajhmai84QUFEZ0FEZ0Q4Y2ZnQUFjY0FBZmdEOGNELy9qOGZqLzhBQURqL2pnY0FBY0FBY2ZnRDhBQWNmL2pnRC9nRGo4QURnRGovamdjQUFjQUFjZmdEOEFBY2YvamdEL2dEajhBRGdEai9qZ2NBQWNBQWNmZ0Q4QUFjZi9qZ0QvZ0RqOEFEZ0RqL2pqOEQ4QUQvLzhmLzhmLy84ZjhBQWNmOGZnZjhBRGovamo4RDhBRC8vOGYvOGYvLzhmOEFBY2Y4ZmdmOEFEai9qajhEOEFELy84Zi84Zi8vOGY4QUFjZjhmZ2Y4QURqL2pnY0FEOGZnQWZnZi8vamdjY0QvL2pnZi8vZ2ZnRGovamdjQUQ4ZmdBZmdmLy9qZ2NjRC8vamdmLy9nZmdEai9qZ2NBRDhmZ0FmZ2YvL2pnY2NELy9qZ2YvL2dmZ0RnQURqL2djRGdmZ2NEamdEOGNEL2pnZi9nRGdEOGNBRGdBRGovZ2NEZ2ZnY0RqZ0Q4Y0QvamdmL2dEZ0Q4Y0FEZ0FEai9nY0RnZmdjRGpnRDhjRC9qZ2YvZ0RnRDhjQUQvLy9nY0QvamdEZ2YvampqamdmZ0RqamovampqZ0RnRC8vL2djRC9qZ0RnZi9qampqZ2ZnRGpqai9qampnRGdELy8vZ2NEL2pnRGdmL2pqampnZmdEampqL2pqamdEZ0FBQUFEZ2ZqLy9qZ0QvamdEamdBQWNjY0FBZmdEamdBQUFBQURnZmovL2pnRC9qZ0RqZ0FBY2NjQUFmZ0RqZ0FBQUFBRGdmai8vamdEL2pnRGpnQUFjY2NBQWZnRGpnQUQvOEQ4RGdEZ0Q4QWY4RC8vZ2YvOERqZ0Qvai8vampnRC84RDhEZ0RnRDhBZjhELy9nZi84RGpnRC9qLy9qamdELzhEOERnRGdEOEFmOEQvL2dmLzhEamdEL2ovL2pqZ0QvamdjY0FBZi9nRC9nRDhEOGY4ZjhmOERqL2o4ZjhBRC9qZ2NjQUFmL2dEL2dEOEQ4ZjhmOGY4RGovajhmOEFEL2pnY2NBQWYvZ0QvZ0Q4RDhmOGY4ZjhEai9qOGY4QUFELy9qajhmL2dBY2Y4RGpnQWNmZ0FBY2NmL2pnRC9nQUQvL2pqOGYvZ0FjZjhEamdBY2ZnQUFjY2YvamdEL2dBRC8vamo4Zi9nQWNmOERqZ0FjZmdBQWNjZi9qZ0QvZ0FjQUFELy84Y0FjZmdBY2NjRDhBRDhBZjhBRDhmOEFBQWNBQUQvLzhjQWNmZ0FjY2NEOEFEOEFmOEFEOGY4QUFBY0FBRC8vOGNBY2ZnQWNjY0Q4QUQ4QWY4QUQ4ZjhBQUFBZmpqLy9nY0FEOEQ4RDhEZ2Nmai9qai9qajhBRC9nQUFmamovL2djQUQ4RDhEOERnY2ZqL2pqL2pqOEFEL2dBQWZqai8vZ2NBRDhEOEQ4RGdjZmovamovamo4QUQvZ0FjRGdjQUFELy9nY2YvOEQvZ2NEZ2NBQUFBY0RnY2ZnQWNEZ2NBQUQvL2djZi84RC9nY0RnY0FBQUFjRGdjZmdBY0RnY0FBRC8vZ2NmLzhEL2djRGdjQUFBQWNEZ2NmZ0Qvai8vampnZi9nRC84RDhBY2NEZ2Yvamo4QWYvZ0FBRC9qLy9qamdmL2dELzhEOEFjY0RnZi9qajhBZi9nQUFEL2ovL2pqZ2YvZ0QvOEQ4QWNjRGdmL2pqOEFmL2dBQURqajhjY0FBY0FBRGdmOGY4Y2NjY2NELzhjZi8vOGZnRGpqOGNjQUFjQUFEZ2Y4ZjhjY2NjY0QvOGNmLy84ZmdEamo4Y2NBQWNBQURnZjhmOGNjY2NjRC84Y2YvLzhmZ0FEL2ovZ2NjQUQvai9qOGNBZi84RGo4QWNjRGdBRDhBQUQvai9nY2NBRC9qL2o4Y0FmLzhEajhBY2NEZ0FEOEFBRC9qL2djY0FEL2ovajhjQWYvOERqOEFjY0RnQUQ4QUFBRGdBY2ZqOEFmajhELzhmLzhBZjhEai84QWZqOGNBQUFEZ0FjZmo4QWZqOEQvOGYvOEFmOERqLzhBZmo4Y0FBQURnQWNmajhBZmo4RC84Zi84QWY4RGovOEFmajhjQUQ4RGo4QUQ4QURqOGY4RGdEZ0FBZmdjQUFELy9qL2dBRDhEajhBRDhBRGo4ZjhEZ0RnQUFmZ2NBQUQvL2ovZ0FEOERqOEFEOEFEajhmOERnRGdBQWZnY0FBRC8vai9nQUFEZ2NjRGdmZ0RqamdEajhBZjhBZmdEOGNBZmdjZmdBQURnY2NEZ2ZnRGpqZ0RqOEFmOEFmZ0Q4Y0FmZ2NmZ0FBRGdjY0RnZmdEampnRGo4QWY4QWZnRDhjQWZnY2ZnQUFmOERnZi9qajhEOGYvOGNmai8vOEFEL2dmOGNmampnQWY4RGdmL2pqOEQ4Zi84Y2ZqLy84QUQvZ2Y4Y2ZqamdBZjhEZ2Yvamo4RDhmLzhjZmovLzhBRC9nZjhjZmpqZ0QvZ2NjY2ZqZ2NjQWZnY0FmajhEL2o4QWNELzhmZ2NBRC9nY2NjZmpnY2NBZmdjQWZqOEQvajhBY0QvOGZnY0FEL2djY2NmamdjY0FmZ2NBZmo4RC9qOEFjRC84ZmdjQUQvZ0RnQWNjRDhmai9nY2Y4Zi84RGo4QUFBQWZnY2ZnRC9nRGdBY2NEOGZqL2djZjhmLzhEajhBQUFBZmdjZmdEL2dEZ0FjY0Q4ZmovZ2NmOGYvOERqOEFBQUFmZ2NmZ0FEZ2Nmai9qajhjQUFBZi8vamdjRGdEamdBQWY4Zi9nQURnY2ZqL2pqOGNBQUFmLy9qZ2NEZ0RqZ0FBZjhmL2dBRGdjZmovamo4Y0FBQWYvL2pnY0RnRGpnQUFmOGYvZ0FjRGovampqZ0Rqamo4QWNBZmpqai9qOGNBRC9nRGpnQWNEai9qampnRGpqajhBY0FmampqL2o4Y0FEL2dEamdBY0RqL2pqamdEampqOEFjQWZqamovajhjQUQvZ0RqZ0QvZ2NjQUQvL2ovOEFEL2dmLzhBQWNmOEFmLzhjQWZnRC9nY2NBRC8vai84QUQvZ2YvOEFBY2Y4QWYvOGNBZmdEL2djY0FELy9qLzhBRC9nZi84QUFjZjhBZi84Y0FmZ0RnRC9nRDhBZi8vL2o4Zmo4ZmpqZ0QvZ0QvZ0FEOEFBRGdEL2dEOEFmLy8vajhmajhmampnRC9nRC9nQUQ4QUFEZ0QvZ0Q4QWYvLy9qOGZqOGZqamdEL2dEL2dBRDhBQUFEamdmOGNEai8vLzhjY2Y4ZmdmajhmZ0QvL2djZmdBQURqZ2Y4Y0RqLy8vOGNjZjhmZ2ZqOGZnRC8vZ2NmZ0FBRGpnZjhjRGovLy84Y2NmOGZnZmo4ZmdELy9nY2ZnQUFmai8vZ2YvOEQvOERnZi8vai84RGo4RGpnZi8vampnQWZqLy9nZi84RC84RGdmLy9qLzhEajhEamdmLy9qamdBZmovL2dmLzhELzhEZ2YvL2ovOERqOERqZ2YvL2pqZ0Q4ZmdELy9nQUQvZ2ZnRGdEamovZ2NEai8vamdEL2pnRDhmZ0QvL2dBRC9nZmdEZ0Rqai9nY0RqLy9qZ0QvamdEOGZnRC8vZ0FEL2dmZ0RnRGpqL2djRGovL2pnRC9qZ0Q4ZmpqOGZqLy84ZmdEL2pqOGNjZmdmZ2ZnRGpqai9nRDhmamo4ZmovLzhmZ0Qvamo4Y2NmZ2ZnZmdEampqL2dEOGZqajhmai8vOGZnRC9qajhjY2ZnZmdmZ0RqamovZ0Q4RGdEOEFjY0RnZmdEL2dEOGNmOGNjQUFmL2dEOERnRDhEZ0Q4QWNjRGdmZ0QvZ0Q4Y2Y4Y2NBQWYvZ0Q4RGdEOERnRDhBY2NEZ2ZnRC9nRDhjZjhjY0FBZi9nRDhEZ0QvLy8vZ0Q4Zmo4Y0Q4RC8vZ0FjY0Qvamo4RC8vZ2NBRC8vLy9nRDhmajhjRDhELy9nQWNjRC9qajhELy9nY0FELy8vL2dEOGZqOGNEOEQvL2dBY2NEL2pqOEQvL2djQUQ4QUFmOGNELy9nY0RnQUFBQWNBQWZnY2NjZmo4ZmpnRDhBQWY4Y0QvL2djRGdBQUFBY0FBZmdjY2NmajhmamdEOEFBZjhjRC8vZ2NEZ0FBQUFjQUFmZ2NjY2ZqOGZqZ0Q4RGovZ2ZqamdjZjhEZ2NBRGdBRC84QWZqajhmai9nRDhEai9nZmpqZ2NmOERnY0FEZ0FELzhBZmpqOGZqL2dEOERqL2dmampnY2Y4RGdjQURnQUQvOEFmamo4ZmovZ0QvajhmL2dBRGdEOERnQUFjQWNmZ0Q4ZmdBY0FBY0RnRC9qOGYvZ0FEZ0Q4RGdBQWNBY2ZnRDhmZ0FjQUFjRGdEL2o4Zi9nQURnRDhEZ0FBY0FjZmdEOGZnQWNBQWNEZ0FmZ2Yvai8vamdmOEQvZ2ZqZ2NBRGdEamovZ2Y4ZmdBQWZnZi9qLy9qZ2Y4RC9nZmpnY0FEZ0Rqai9nZjhmZ0FBZmdmL2ovL2pnZjhEL2dmamdjQURnRGpqL2dmOGZnQURqZ2NmOGNEOERqL2ovamdEamdBQWZqai9qLzhmZ0RnRGpnY2Y4Y0Q4RGovai9qZ0RqZ0FBZmpqL2ovOGZnRGdEamdjZjhjRDhEai9qL2pnRGpnQUFmamovai84ZmdEZ0FBRC9nQWNjZmpqL2dEZ2YvZ2NmL2o4QWNjY0RqZ2ZnQUFEL2dBY2NmamovZ0RnZi9nY2YvajhBY2NjRGpnZmdBQUQvZ0FjY2Zqai9nRGdmL2djZi9qOEFjY2NEamdmZ0FjQWNmai9qamdEOEQ4QWNEai84Zi8vZ0RnY0FmajhBQWNBY2ZqL2pqZ0Q4RDhBY0RqLzhmLy9nRGdjQWZqOEFBY0FjZmovampnRDhEOEFjRGovOGYvL2dEZ2NBZmo4QUFjRC8vOGYvamo4RGovZ2NEL2pqLzhmOERqZ2NBY2NBQWNELy84Zi9qajhEai9nY0QvamovOGY4RGpnY0FjY0FBY0QvLzhmL2pqOERqL2djRC9qai84ZjhEamdjQWNjQUQvL2djY0FjRGpqOGNELy84QWYvOGZqOGNEOERqampnRC8vZ2NjQWNEamo4Y0QvLzhBZi84Zmo4Y0Q4RGpqamdELy9nY2NBY0RqajhjRC8vOEFmLzhmajhjRDhEampqZ0FBQWYvZ0RqLy8vL2o4Zi9nZjhEOGY4RDhEamdjY2ZnQUFBZi9nRGovLy8vajhmL2dmOEQ4ZjhEOERqZ2NjZmdBQUFmL2dEai8vLy9qOGYvZ2Y4RDhmOEQ4RGpnY2NmZ0FEamdjQUQ4Y2NjY2NjQWZqOERqLy9nY2ZqamdmZ2ZnQURqZ2NBRDhjY2NjY2NBZmo4RGovL2djZmpqZ2ZnZmdBRGpnY0FEOGNjY2NjY0FmajhEai8vZ2NmampnZmdmZ0RqZ0Q4QWZqampnZmo4QUQ4Y2NmL2pqZ0QvZ0FEZ0FBRGpnRDhBZmpqamdmajhBRDhjY2YvampnRC9nQURnQUFEamdEOEFmampqZ2ZqOEFEOGNjZi9qamdEL2dBRGdBQURnZmdjY2Y4Y0Q4Zi8vajhBZjhmOEFjY2NEamdmZ2NBRGdmZ2NjZjhjRDhmLy9qOEFmOGY4QWNjY0RqZ2ZnY0FEZ2ZnY2NmOGNEOGYvL2o4QWY4ZjhBY2NjRGpnZmdjQUQ4QUQvajhBQUFmOGY4RC9qLzhBZi84Y0RnRDhmZ2NBRDhBRC9qOEFBQWY4ZjhEL2ovOEFmLzhjRGdEOGZnY0FEOEFEL2o4QUFBZjhmOEQvai84QWYvOGNEZ0Q4ZmdjQUQ4RDhmamovZ0FEai9nRGdBY2NjY0FELy9nRDhjY2NBRDhEOGZqai9nQURqL2dEZ0FjY2NjQUQvL2dEOGNjY0FEOEQ4ZmpqL2dBRGovZ0RnQWNjY2NBRC8vZ0Q4Y2NjQUFjQURnY0FEai9nZjhEai84Zi9qamdmL2ovZ0Qvai9nQWNBRGdjQURqL2dmOERqLzhmL2pqZ2Yvai9nRC9qL2dBY0FEZ2NBRGovZ2Y4RGovOGYvampnZi9qL2dEL2ovZ0RnY2NELzhEZ2NBY2YvOGYvZ0QvajhjY2ZnRC9nZi9nRGdjY0QvOERnY0FjZi84Zi9nRC9qOGNjZmdEL2dmL2dEZ2NjRC84RGdjQWNmLzhmL2dEL2o4Y2NmZ0QvZ2YvZ0FmLy84Zi9nRGdBRDhmOERnZjhjQWNmampnQURnRC9nQWYvLzhmL2dEZ0FEOGY4RGdmOGNBY2ZqamdBRGdEL2dBZi8vOGYvZ0RnQUQ4ZjhEZ2Y4Y0FjZmpqZ0FEZ0QvZ0RqOGNjZjhEOEFmZ0Q4RGdmOEFBY2NEZ0FjQURnY2NBRGo4Y2NmOEQ4QWZnRDhEZ2Y4QUFjY0RnQWNBRGdjY0FEajhjY2Y4RDhBZmdEOERnZjhBQWNjRGdBY0FEZ2NjQURnY2ZqajhjY0RnZmdmai8vajhjRDhjZi9nQWNjQUFBRGdjZmpqOGNjRGdmZ2ZqLy9qOGNEOGNmL2dBY2NBQUFEZ2Nmamo4Y2NEZ2ZnZmovL2o4Y0Q4Y2YvZ0FjY0FBQUFBQUFBZmo4Zi84RC9nRGdEamdBZmdjZmpqOEFBQUFBQUFBQUFmajhmLzhEL2dEZ0RqZ0FmZ2Nmamo4QUFBQUFBQUFBQWZqOGYvOEQvZ0RnRGpnQWZnY2ZqajhBQUFBQUQvLy9qampqampqampqampqampqampqampqamovLy9nRC8vL2pqampqampqampqampqampqampqampqai8vL2dELy8vampqampqampqampqampqampqampqampqLy8vZ0RnQURqOGNELzhjQURnRGdEZ2ZqL2dmOGNmZ0RnQURnRGdBRGo4Y0QvOGNBRGdEZ0RnZmovZ2Y4Y2ZnRGdBRGdEZ0FEajhjRC84Y0FEZ0RnRGdmai9nZjhjZmdEZ0FEZ0RqL2pnZi9nZmpqamovai8vZ2YvOEQvL2ovOERqL2pnRGovamdmL2dmampqai9qLy9nZi84RC8vai84RGovamdEai9qZ2YvZ2ZqampqL2ovL2dmLzhELy9qLzhEai9qZ0RqL2pnY2YvL2pnY0FjZi9qZ2ZnQWNjY2NEampqL2pnRGovamdjZi8vamdjQWNmL2pnZmdBY2NjY0RqamovamdEai9qZ2NmLy9qZ2NBY2YvamdmZ0FjY2NjRGpqai9qZ0RqL2pnRGdBZmdELy9nRGpqampnZi9nY2ZqL2pqL2pnRGovamdEZ0FmZ0QvL2dEampqamdmL2djZmovamovamdEai9qZ0RnQWZnRC8vZ0RqampqZ2YvZ2Nmai9qai9qZ0RnQURnQUQvamdmajhBRDhmOERnY2ZqOGZnZmpnQURnRGdBRGdBRC9qZ2ZqOEFEOGY4RGdjZmo4ZmdmamdBRGdEZ0FEZ0FEL2pnZmo4QUQ4ZjhEZ2NmajhmZ2ZqZ0FEZ0QvLy9nRGdBQURnY0QvamdEL2djRGdBZmdBZmovLy9nRC8vL2dEZ0FBRGdjRC9qZ0QvZ2NEZ0FmZ0Fmai8vL2dELy8vZ0RnQUFEZ2NEL2pnRC9nY0RnQWZnQWZqLy8vZ0E9Ij48L2ltZz48L2Rpdj48L2Rpdj48L2Rpdj48ZGl2IGNsYXNzPSJzaW5nbGUiPjxkaXY+PGRpdiBjbGFzcz0iYnJlYWstd29yZCI+PHNwYW4gY2xhc3M9ImJvbGQiPkdyYW5kbWE8L3NwYW4+PGJyPnRiMXF1NmxjdWE5dzJ6a2Fyamo1eHd4aDNsM3F0Y3hoODRoc3JhM2pydnBzemg2OWoyZTU0eDdxM3RoeWN3PC9kaXY+PGRpdiBjbGFzcz0iY2VudGVyIj48aW1nIGNsYXNzPSJxciIgc3JjPSJkYXRhOmltYWdlL2JtcDtiYXNlNjQsUWsxdUJnQUFBQUFBQUQ0QUFBQW9BQUFBWXdBQUFHTUFBQUFCQUFFQUFBQUFBREFHQUFBQUFnQUFBQUlBQUFJQUFBQUNBQUFBLy8vL0FBQUFBQUQvLy9qZ0FjRC84QWNBZjhmZ0FBQUEvLy80NEFIQS8vQUhBSC9INEFBQUFQLy8rT0FCd1Avd0J3Qi94K0FBQUFEZ0FEZ0FBY2YvZ0QvZ0Q4RGdBQUFBNEFBNEFBSEgvNEEvNEEvQTRBQUFBT0FBT0FBQngvK0FQK0FQd09BQUFBRGovamdBRC84QUQvZ2ZnZmdBQUFBQTQvNDRBQS8vQUEvNEg0SDRBQUFBQU9QK09BQVAvd0FQK0IrQitBQUFBQURqL2pnY2NBQUQvZ2ZnRC9qZ0FBQUE0LzQ0SEhBQUEvNEg0QS80NEFBQUFPUCtPQnh3QUFQK0IrQVArT0FBQUFEai9qajhjRGpnQUQvLy8vOEFBQUFBNC80NC9IQTQ0QUEvLy8vL0FBQUFBT1ArT1B4d09PQUFQLy8vL3dBQUFBRGdBRGdmZ2ZqZ0RqamdEOEFBQUFBQTRBQTRINEg0NEE0NDRBL0FBQUFBQU9BQU9CK0IrT0FPT09BUHdBQUFBQUQvLy9qamdmL2pnQWZqamovZ0FBQUEvLy80NDRILzQ0QUg0NDQvNEFBQUFQLy8rT09CLytPQUIrT09QK0FBQUFBQUFBRDhEZ0Q4Zi9qZ0RqOEFBQUFBQUFBQS9BNEEvSC80NEE0L0FBQUFBQUFBQVB3T0FQeC8rT0FPUHdBQUFBRC9nZmdjRDhjZmdmLy8vOEFBQUFBQS80SDRIQS9ISDRILy8vL0FBQUFBQVArQitCd1B4eCtCLy8vL3dBQUFBQUFEOGNBY2ZnQWNmajhjRGovZ0FBQUFBL0hBSEg0QUhINC9IQTQvNEFBQUFBUHh3QngrQUJ4K1B4d09QK0FBQUFBRDhmL2dEOERqOEFBQUQ4Y0FBQUFBQS9ILzRBL0E0L0FBQUEvSEFBQUFBQVB4LytBUHdPUHdBQUFQeHdBQUFBRC8vZ0RqZ2NEZ2NmOGNjZmpnQUFBQS8vNEE0NEhBNEhIL0hISDQ0QUFBQVAvK0FPT0J3T0J4L3h4eCtPQUFBQURqOEQ4Y2ZnQUQvZ0FEZ2YvZ0FBQUE0L0EvSEg0QUEvNEFBNEgvNEFBQUFPUHdQeHgrQUFQK0FBT0IvK0FBQUFEL2o4Y2Y4QWNmajhEZ0FBQUFBQUFBLzQvSEgvQUhINC9BNEFBQUFBQUFBUCtQeHgvd0J4K1B3T0FBQUFBQUFBRDhBRGdBQUFEOEFmLzhEampnQUFBQS9BQTRBQUFBL0FILy9BNDQ0QUFBQVB3QU9BQUFBUHdCLy93T09PQUFBQUFjQWNEZ0RnRGpqZ0FjY2NmZ0FBQUFIQUhBNEE0QTQ0NEFISEhINEFBQUFCd0J3T0FPQU9PT0FCeHh4K0FBQUFEZ0FEOEFBY0RnY2ZqOGNmL2dBQUFBNEFBL0FBSEE0SEg0L0hILzRBQUFBT0FBUHdBQndPQngrUHh4LytBQUFBQWNmOGNmLzhmZ0FjY0Q4ZmpnQUFBQUhIL0hILy9INEFISEEvSDQ0QUFBQUJ4L3h4Ly94K0FCeHdQeCtPQUFBQUFEai9nQWZnY0RqajhjY0FjQUFBQUFBNC80QUg0SEE0NC9ISEFIQUFBQUFBT1ArQUIrQndPT1B4eHdCd0FBQUFEOGNBRC84ZmdELzhEOEQvL2dBQUFBL0hBQS8vSDRBLy9BL0EvLzRBQUFBUHh3QVAveCtBUC93UHdQLytBQUFBQURqai8vajhEZ2NELzhEajhBQUFBQUE0NC8vNC9BNEhBLy9BNC9BQUFBQUFPT1AvK1B3T0J3UC93T1B3QUFBQUQvL2dELzhjY0FEai9nZi8vZ0FBQUEvLzRBLy9ISEFBNC80SC8vNEFBQUFQLytBUC94eHdBT1ArQi8vK0FBQUFEOGZqZ2Y4ZmpqOEFmai84RGdBQUFBL0g0NEgvSDQ0L0FINC8vQTRBQUFBUHgrT0IveCtPUHdCK1Avd09BQUFBRC8vOEQ4RGdEOGYvL2dBRGdBQUFBQS8vL0EvQTRBL0gvLzRBQTRBQUFBQVAvL3dQd09BUHgvLytBQU9BQUFBQURnRGovZ2NEL2pnZi8vLzhEZ0FBQUE0QTQvNEhBLzQ0SC8vLy9BNEFBQUFPQU9QK0J3UCtPQi8vLy93T0FBQUFBQUFBRGdBQUFmLzhEZ0FBQUFBQUFBQUFBQTRBQUFILy9BNEFBQUFBQUFBQUFBQU9BQUFCLy93T0FBQUFBQUFBRC8vL2pqampqampqamovLy9nQUFBQS8vLzQ0NDQ0NDQ0NDQvLy80QUFBQVAvLytPT09PT09PT09QLy8rQUFBQURnQURqL2ovOGNEZ2ZqZ0FEZ0FBQUE0QUE0LzQvL0hBNEg0NEFBNEFBQUFPQUFPUCtQL3h3T0IrT0FBT0FBQUFEai9qai84Y0Q4Y2ZnRGovamdBQUFBNC80NC8vSEEvSEg0QTQvNDRBQUFBT1ArT1AveHdQeHgrQU9QK09BQUFBRGovamovOEFEOEFmOERqL2pnQUFBQTQvNDQvL0FBL0FIL0E0LzQ0QUFBQU9QK09QL3dBUHdCL3dPUCtPQUFBQURqL2pnRC9qZ2YvOERqai9qZ0FBQUE0LzQ0QS80NEgvL0E0NC80NEFBQUFPUCtPQVArT0IvL3dPT1ArT0FBQUFEZ0FEZ0QvLzhEamdmamdBRGdBQUFBNEFBNEEvLy9BNDRINDRBQTRBQUFBT0FBT0FQLy93T09CK09BQU9BQUFBRC8vL2pnRDhBRGdEL2ovLy9nQUFBQS8vLzQ0QS9BQTRBLzQvLy80QUFBQVAvLytPQVB3QU9BUCtQLy8rQUFBQUE9Ij48L2ltZz48L2Rpdj48L2Rpdj48ZGl2IGNsYXNzPSJibGFjayI+PC9kaXY+PGRpdj48ZGl2IGNsYXNzPSJicmVhay13b3JkIj48ZGl2IGNsYXNzPSJwYWQiPndzaChtdWx0aSgyLEdyYW5kbWEsQWxpY2UsQmFyYmFyYSkpIzVtMHFkZWhlPC9kaXY+PGRpdiBjbGFzcz0icGFkIj5BbGljZTogMDJlNDg2ZTMyZjBmODcxMzZmYTA0MmNiNTMyMTlhY2U4NTM3ZWExZDAzNmRlYjJmNDI5MzU3MGI5NDMyNWQxMWNiPC9kaXY+PGRpdiBjbGFzcz0icGFkIj5CYXJiYXJhOiAwMmEzZjNmMjY1OGI5ODEyZGRlYWJmYmRlMmZkZTAzZjhhNjUzNjllNGVkNjIxZjI5ZmE4YmEwY2M1MTliNzg5ZmI8L2Rpdj48ZGl2IGNsYXNzPSJwYWQiPkdyYW5kbWE6IGNTMlhIMzFKdG1ieFhVeHQxeXhWZ0Z6eTY5enE0YjVqeDZ6Rm9rM0I0SHpCRXdRNUQyS3E8L2Rpdj48L2Rpdj48ZGl2IGNsYXNzPSJjZW50ZXIiPjxpbWcgY2xhc3M9InFyIiBzcmM9ImRhdGE6aW1hZ2UvYm1wO2Jhc2U2NCxRazFtRVFBQUFBQUFBRDRBQUFBb0FBQUF0d0FBQUxjQUFBQUJBQUVBQUFBQUFDZ1JBQUFBQWdBQUFBSUFBQUlBQUFBQ0FBQUEvLy8vQUFBQUFBRC8vL2o4ZmdjZmpnZmpnRGdmLy9qOEQvZ0QvOGZnZmdELy8vajhmZ2NmamdmamdEZ2YvL2o4RC9nRC84ZmdmZ0QvLy9qOGZnY2ZqZ2ZqZ0RnZi8vajhEL2dELzhmZ2ZnRGdBRGdmOEFBY2NjRGo4QURnY2ZnQUFmLy8vOGY4QUFEZ0FEZ2Y4QUFjY2NEajhBRGdjZmdBQWYvLy84ZjhBQURnQURnZjhBQWNjY0RqOEFEZ2NmZ0FBZi8vLzhmOEFBRGovamdjRGdBY0Q4QWZnQWY4RDhBRGpnY2NBZmpnRGdEai9qZ2NEZ0FjRDhBZmdBZjhEOEFEamdjY0FmamdEZ0RqL2pnY0RnQWNEOEFmZ0FmOEQ4QURqZ2NjQWZqZ0RnRGovampnZmpnY0RnQWNEZ0FjQWZnY0FjY0FBQWNmOEFEai9qamdmamdjRGdBY0RnQWNBZmdjQWNjQUFBY2Y4QURqL2pqZ2ZqZ2NEZ0FjRGdBY0FmZ2NBY2NBQUFjZjhBRGovamdjY0FEOEFmL2pqLy84ZmdEL2ovZ2ZqLy9nRGdEai9qZ2NjQUQ4QWYvamovLzhmZ0Qvai9nZmovL2dEZ0RqL2pnY2NBRDhBZi9qai8vOGZnRC9qL2dmai8vZ0RnRGdBRGovai9qamdjY2NmZ0Q4QWZqOEQvZ0FmZ0RnZmdEZ0FEai9qL2pqZ2NjY2ZnRDhBZmo4RC9nQWZnRGdmZ0RnQURqL2ovampnY2NjZmdEOEFmajhEL2dBZmdEZ2ZnRC8vL2dmL2ovL2pqampqampqZ2ZnQUQ4RGpqampqL2dELy8vZ2Yvai8vampqampqampnZmdBRDhEampqamovZ0QvLy9nZi9qLy9qampqampqamdmZ0FEOERqampqai9nQUFBQUQ4RGpnRGdmLy8vZ0QvZ0FjY0Q4ZmovZ0RnRGdBQUFBRDhEamdEZ2YvLy9nRC9nQWNjRDhmai9nRGdEZ0FBQUFEOERqZ0RnZi8vL2dEL2dBY2NEOGZqL2dEZ0RnRC84RGdmZ2NEL2djZjhmLy84Zmo4QUQ4ZjhELy9qZ0FELzhEZ2ZnY0QvZ2NmOGYvLzhmajhBRDhmOEQvL2pnQUQvOERnZmdjRC9nY2Y4Zi8vOGZqOEFEOGY4RC8vamdBRC9qZ0Q4Y0FEZ2YvOGNjY2NmZ2ZnY2NBQWNjRGdjY0FEL2pnRDhjQURnZi84Y2NjY2ZnZmdjY0FBY2NEZ2NjQUQvamdEOGNBRGdmLzhjY2NjZmdmZ2NjQUFjY0RnY2NBQUQvLzhEZ2NjRGdBZmdmajhjZi8vajhjY0Rqai9qZ0FBRC8vOERnY2NEZ0FmZ2ZqOGNmLy9qOGNjRGpqL2pnQUFELy84RGdjY0RnQWZnZmo4Y2YvL2o4Y2NEamovamdBRGdmOGYvamo4RGdmOEFjQWNmLzhjQUFmajhjY2NEZ0FEZ2Y4Zi9qajhEZ2Y4QWNBY2YvOGNBQWZqOGNjY0RnQURnZjhmL2pqOERnZjhBY0FjZi84Y0FBZmo4Y2NjRGdBQUQ4ZjhjZmovLy8vZ0Qvamdmai9qamo4Zmo4Y0QvamdBRDhmOGNmai8vLy9nRC9qZ2ZqL2pqajhmajhjRC9qZ0FEOGY4Y2ZqLy8vL2dEL2pnZmovampqOGZqOGNEL2pnQURnY2YvajhjY2Zqai9qOGYvajhEamdjZmdjRC9nZmdBRGdjZi9qOGNjZmpqL2o4Zi9qOERqZ2NmZ2NEL2dmZ0FEZ2NmL2o4Y2NmamovajhmL2o4RGpnY2ZnY0QvZ2ZnRGdjZjhmOGZnY0Q4Zi84RGdBRC9nRC84Zi9qOGY4RGdEZ2NmOGY4ZmdjRDhmLzhEZ0FEL2dELzhmL2o4ZjhEZ0RnY2Y4ZjhmZ2NEOGYvOERnQUQvZ0QvOGYvajhmOERnRGdBY0RqLy84Zi84ZmovZ2NEOERnRDhmLy8vOGNBY0FEZ0FjRGovLzhmLzhmai9nY0Q4RGdEOGYvLy84Y0FjQURnQWNEai8vOGYvOGZqL2djRDhEZ0Q4Zi8vLzhjQWNBQUFmamovZ2NmZ2NjZjhEOGNBZmovOGNmamdEL2djZmdBQWZqai9nY2ZnY2NmOEQ4Y0Fmai84Y2ZqZ0QvZ2NmZ0FBZmpqL2djZmdjY2Y4RDhjQWZqLzhjZmpnRC9nY2ZnRGo4Y0RnRGdELzhmampqZ0RnY2Y4RC8vOGNBY2NmZ0FEajhjRGdEZ0QvOGZqampnRGdjZjhELy84Y0FjY2ZnQURqOGNEZ0RnRC84ZmpqamdEZ2NmOEQvLzhjQWNjZmdBQWNmL2pqZ0Q4RDhBQWZqL2dmajhjY0QvajhEai9nQUFBY2YvampnRDhEOEFBZmovZ2ZqOGNjRC9qOERqL2dBQUFjZi9qamdEOEQ4QUFmai9nZmo4Y2NEL2o4RGovZ0FBQWZqZ2NmZ2NjQUQ4Zi9nY2NmZ2NjRGdmOGNEajhjQUFBZmpnY2ZnY2NBRDhmL2djY2ZnY2NEZ2Y4Y0RqOGNBQUFmamdjZmdjY0FEOGYvZ2NjZmdjY0RnZjhjRGo4Y0FBRGo4Zi8vamo4RC9qamdEZ0FjRGpnZi9qajhEai9qamdEajhmLy9qajhEL2pqZ0RnQWNEamdmL2pqOERqL2pqZ0RqOGYvL2pqOEQvampnRGdBY0RqZ2Yvamo4RGovampnQUFjQWNBRDhmL2dmLy84QWNjY2NEL2o4RDhmZ2ZnY0FBQWNBY0FEOGYvZ2YvLzhBY2NjY0QvajhEOGZnZmdjQUFBY0FjQUQ4Zi9nZi8vOEFjY2NjRC9qOEQ4ZmdmZ2NBQWNBRGdjY2ZnZmovLy9qLzhEZ0FjZmdBRC9nRGdjRGdBY0FEZ2NjZmdmai8vL2ovOERnQWNmZ0FEL2dEZ2NEZ0FjQURnY2NmZ2ZqLy8vai84RGdBY2ZnQUQvZ0RnY0RnQWZnY0FmZ2NjY2NjQURqZ0FjZi84Y2NEZ0FELzhmOEFBZmdjQWZnY2NjY2NBRGpnQWNmLzhjY0RnQUQvOGY4QUFmZ2NBZmdjY2NjY0FEamdBY2YvOGNjRGdBRC84ZjhBQWNEai9nY0FjZjhELzhmamovOGNjRGdBQWNBZmdEOEFBY0RqL2djQWNmOEQvOGZqai84Y2NEZ0FBY0FmZ0Q4QUFjRGovZ2NBY2Y4RC84ZmpqLzhjY0RnQUFjQWZnRDhBQUFjY2NjRDhjZmdjQWY4ZmdmZ2NjY0RnZi84QWNEL2dBQWNjY2NEOGNmZ2NBZjhmZ2ZnY2NjRGdmLzhBY0QvZ0FBY2NjY0Q4Y2ZnY0FmOGZnZmdjY2NEZ2YvOEFjRC9nQUFBRC84Y0FBY2NjQUQvZ0RnZmo4Y2NEamdmLy9nZmdBQUFELzhjQUFjY2NBRC9nRGdmajhjY0RqZ2YvL2dmZ0FBQUQvOGNBQWNjY0FEL2dEZ2ZqOGNjRGpnZi8vZ2ZnRGdEZ0FELy84Y0RqOEQ4RGo4ZmpnY2ZnRDhjZmdBZmdEZ0RnQUQvLzhjRGo4RDhEajhmamdjZmdEOGNmZ0FmZ0RnRGdBRC8vOGNEajhEOERqOGZqZ2NmZ0Q4Y2ZnQWZnRC8vLy9nQWZqOGNEamdmLy84RDhmZ2NBZmdmLy9qOEFELy8vL2dBZmo4Y0RqZ2YvLzhEOGZnY0FmZ2YvL2o4QUQvLy8vZ0FmajhjRGpnZi8vOEQ4ZmdjQWZnZi8vajhBRGdEZ0QvOGZnQURnQWZqZ0QvLzhBY2YvajhmZ0RnQUFEZ0RnRC84ZmdBRGdBZmpnRC8vOEFjZi9qOGZnRGdBQURnRGdELzhmZ0FEZ0FmamdELy84QWNmL2o4ZmdEZ0FBRGdEampnY2ZqamovamdEamo4RDhEOEFjRGdEampnZmdEZ0RqamdjZmpqai9qZ0RqajhEOEQ4QWNEZ0RqamdmZ0RnRGpqZ2NmampqL2pnRGpqOEQ4RDhBY0RnRGpqZ2ZnRGdEZ0Q4ZmdmZ0FBZi8vZ0RnQUQ4Y2Y4Y2ZqZ0Q4QUFEZ0RnRDhmZ2ZnQUFmLy9nRGdBRDhjZjhjZmpnRDhBQURnRGdEOGZnZmdBQWYvL2dEZ0FEOGNmOGNmamdEOEFBQWNELy9nY2Y4RDhmai9qLy9qamo4QWZnRDhmLy8vZ0FBY0QvL2djZjhEOGZqL2ovL2pqajhBZmdEOGYvLy9nQUFjRC8vZ2NmOEQ4Zmovai8vampqOEFmZ0Q4Zi8vL2dBRGpqZ2NBQUFEZ0RnY0FEOGYvOGNmOEQvLzhmOEQ4Y0FEampnY0FBQURnRGdjQUQ4Zi84Y2Y4RC8vOGY4RDhjQURqamdjQUFBRGdEZ2NBRDhmLzhjZjhELy84ZjhEOGNBQWZnZjhEajhBZmdEai9nRC8vLzhEajhmamovOEFmL2dBZmdmOERqOEFmZ0RqL2dELy8vOERqOGZqai84QWYvZ0FmZ2Y4RGo4QWZnRGovZ0QvLy84RGo4ZmpqLzhBZi9nRC9nQURnY2NEZ2Y4Y2YvOEFmOEFjY0Q4Zmo4QUFmOEFEL2dBRGdjY0RnZjhjZi84QWY4QWNjRDhmajhBQWY4QUQvZ0FEZ2NjRGdmOGNmLzhBZjhBY2NEOGZqOEFBZjhBRGdmL2pqZ2ZnRGo4ZmovamdmLy9qL2dmL2pqL2pqOEFEZ2YvampnZmdEajhmai9qZ2YvL2ovZ2Yvamovamo4QURnZi9qamdmZ0RqOGZqL2pnZi8vai9nZi9qai9qajhBRC9nQUFBQWNBQUFjY2Y4Zmo4RC9nQUFBY0QvOGZnY0FEL2dBQUFBY0FBQWNjZjhmajhEL2dBQUFjRC84ZmdjQUQvZ0FBQUFjQUFBY2NmOGZqOEQvZ0FBQWNELzhmZ2NBQWNjRGo4Y2ZqOGNjY2NjQUQ4RGpnZi8vamdjQWNmZ0FBY2NEajhjZmo4Y2NjY2NBRDhEamdmLy9qZ2NBY2ZnQUFjY0RqOGNmajhjY2NjY0FEOERqZ2YvL2pnY0FjZmdBQWNjY0FEOGNEOERqOEFBRGpqOEQ4Y2Y4RDhjRGdjY0FBY2NjQUQ4Y0Q4RGo4QUFEamo4RDhjZjhEOGNEZ2NjQUFjY2NBRDhjRDhEajhBQURqajhEOGNmOEQ4Y0RnY2NBQWY4RGo4Zi9nY0RqamdmL2dEOERnZmdBZmpnZi84QUFBZjhEajhmL2djRGpqZ2YvZ0Q4RGdmZ0FmamdmLzhBQUFmOERqOGYvZ2NEampnZi9nRDhEZ2ZnQWZqZ2YvOEFBQWNEZ2ZnQWNjZi9nRDhEajhEZ0FmLy8vamdmampqZ0FBY0RnZmdBY2NmL2dEOERqOERnQWYvLy9qZ2ZqampnQUFjRGdmZ0FjY2YvZ0Q4RGo4RGdBZi8vL2pnZmpqamdBQWY4ZmdmOGNBY2NmL2pnRGdEamdEai9nZmovL2djZmdBZjhmZ2Y4Y0FjY2YvamdEZ0RqZ0RqL2dmai8vZ2NmZ0FmOGZnZjhjQWNjZi9qZ0RnRGpnRGovZ2ZqLy9nY2ZnRGdEZ0FEZ2NmajhmLy9qamovOEFBQWY4QWY4RC9nZmdEZ0RnQURnY2ZqOGYvL2pqai84QUFBZjhBZjhEL2dmZ0RnRGdBRGdjZmo4Zi8vampqLzhBQUFmOEFmOEQvZ2ZnQWNmajhmOGZnRC9nZjhBRC84RGpnZi8vOEFmZ0FjQUFBY2ZqOGY4ZmdEL2dmOEFELzhEamdmLy84QWZnQWNBQUFjZmo4ZjhmZ0QvZ2Y4QUQvOERqZ2YvLzhBZmdBY0FBRGpqZ2NjRC84QUFmZ0FjZmdjQUFBQWNjY2NBZmdEamdEampnY2NELzhBQWZnQWNmZ2NBQUFBY2NjY0FmZ0RqZ0RqamdjY0QvOEFBZmdBY2ZnY0FBQUFjY2NjQWZnRGpnQWYvLzhjRGdjZjhjZmpnRDhjRGdBQWNjZmdBZi9qL2dBZi8vOGNEZ2NmOGNmamdEOGNEZ0FBY2NmZ0FmL2ovZ0FmLy84Y0RnY2Y4Y2ZqZ0Q4Y0RnQUFjY2ZnQWYvai9nRGo4QWZnQWNmL2o4Y2NjY0QvamdmOEFmLzhEajhBRGdEajhBZmdBY2YvajhjY2NjRC9qZ2Y4QWYvOERqOEFEZ0RqOEFmZ0FjZi9qOGNjY2NEL2pnZjhBZi84RGo4QURnRGovamdmL2dBRGdBZmdjZmdjZmovLy9qLy9qai9qL2dEai9qZ2YvZ0FEZ0FmZ2NmZ2Nmai8vL2ovL2pqL2ovZ0RqL2pnZi9nQURnQWZnY2ZnY2ZqLy8vai8vamovai9nQWNBQWNBQWNjZi9qOEQ4QWYvZ2ZqOGNjY0Q4QUFjQUFBY0FBY0FBY2NmL2o4RDhBZi9nZmo4Y2NjRDhBQWNBQUFjQUFjQUFjY2YvajhEOEFmL2dmajhjY2NEOEFBY0FBRGpqLy9qZ2NmOERqOGYvOEFmamdjQURnY0FEajhBRGdEamovL2pnY2Y4RGo4Zi84QWZqZ2NBRGdjQURqOEFEZ0Rqai8vamdjZjhEajhmLzhBZmpnY0FEZ2NBRGo4QURnQWNBQWNjZmdjRGo4QWNBY2NBY2NmZ2ZnY2NjQWY4Y0FBY0FBY2NmZ2NEajhBY0FjY0FjY2ZnZmdjY2NBZjhjQUFjQUFjY2ZnY0RqOEFjQWNjQWNjZmdmZ2NjY0FmOGNBRGdjZmpnY2Zqamo4RDhELy9nZmdEajhEL2djY2NBQUFEZ2NmamdjZmpqajhEOEQvL2dmZ0RqOEQvZ2NjY0FBQURnY2ZqZ2NmampqOEQ4RC8vZ2ZnRGo4RC9nY2NjQUFBQUFBQUFmamdEZ2NjQUFEZ0RqajhEamo4RGo4QUFBQUFBQUFBQWZqZ0RnY2NBQURnRGpqOERqajhEajhBQUFBQUFBQUFBZmpnRGdjY0FBRGdEamo4RGpqOERqOEFBQUFBRC8vL2pqampqampqampqampqampqampqampqai8vL2dELy8vampqampqampqampqampqampqampqampqLy8vZ0QvLy9qampqampqampqampqampqampqampqamovLy9nRGdBRGpnZjhBY0FmajhEZ0Q4RC84QUQ4Y2ZnRGdBRGdEZ0FEamdmOEFjQWZqOERnRDhELzhBRDhjZmdEZ0FEZ0RnQURqZ2Y4QWNBZmo4RGdEOEQvOEFEOGNmZ0RnQURnRGovamdmOEFEZ0FjY0FELy8vOEFBY0QvZ0Q4RGovamdEai9qZ2Y4QURnQWNjQUQvLy84QUFjRC9nRDhEai9qZ0RqL2pnZjhBRGdBY2NBRC8vLzhBQWNEL2dEOERqL2pnRGovamdELzhBRGdEZ0FBRDhmOGY4ZmdBY2ZqamovamdEai9qZ0QvOEFEZ0RnQUFEOGY4ZjhmZ0FjZmpqai9qZ0RqL2pnRC84QURnRGdBQUQ4ZjhmOGZnQWNmampqL2pnRGovamdmZ0Qvai8vZ0Q4RDhjY2ZqZ0RqOGYvamovamdEai9qZ2ZnRC9qLy9nRDhEOGNjZmpnRGo4Zi9qai9qZ0RqL2pnZmdEL2ovL2dEOEQ4Y2NmamdEajhmL2pqL2pnRGdBRGdEOGZnY0FmOEQ4ZmdEL2djQUFBY0FmamdBRGdEZ0FEZ0Q4ZmdjQWY4RDhmZ0QvZ2NBQUFjQWZqZ0FEZ0RnQURnRDhmZ2NBZjhEOGZnRC9nY0FBQWNBZmpnQURnRC8vL2djRDhmZ0RnRGo4QWZnZmpqZ0FEL2dmai8vL2dELy8vZ2NEOGZnRGdEajhBZmdmampnQUQvZ2ZqLy8vZ0QvLy9nY0Q4ZmdEZ0RqOEFmZ2ZqamdBRC9nZmovLy9nQT0iPjwvaW1nPjwvZGl2PjwvZGl2PjwvZGl2PjwvYm9keT48L2h0bWw+ diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/COPYRIGHT.txt b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/COPYRIGHT.txt new file mode 100644 index 0000000000..af77776cca --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/COPYRIGHT.txt @@ -0,0 +1,45 @@ +These documentation pages include resources by third parties. This copyright +file applies only to those resources. The following third party resources are +included, and carry their own copyright notices and license terms: + +* Fira Sans (FiraSans-Regular.woff, FiraSans-Medium.woff): + + Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ + with Reserved Font Name Fira Sans. + + Copyright (c) 2014, Telefonica S.A. + + Licensed under the SIL Open Font License, Version 1.1. + See FiraSans-LICENSE.txt. + +* rustdoc.css, main.js, and playpen.js: + + Copyright 2015 The Rust Developers. + Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or + the MIT license (LICENSE-MIT.txt) at your option. + +* normalize.css: + + Copyright (c) Nicolas Gallagher and Jonathan Neal. + Licensed under the MIT license (see LICENSE-MIT.txt). + +* Source Code Pro (SourceCodePro-Regular.woff, SourceCodePro-Semibold.woff): + + Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), + with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark + of Adobe Systems Incorporated in the United States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceCodePro-LICENSE.txt. + +* Source Serif Pro (SourceSerifPro-Regular.ttf.woff, + SourceSerifPro-Bold.ttf.woff, SourceSerifPro-It.ttf.woff): + + Copyright 2014 Adobe Systems Incorporated (http://www.adobe.com/), with + Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of + Adobe Systems Incorporated in the United States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceSerifPro-LICENSE.txt. + +This copyright file is intended to be distributed with rustdoc output. diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/FiraSans-LICENSE.txt b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/FiraSans-LICENSE.txt new file mode 100644 index 0000000000..d444ea92b6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/FiraSans-LICENSE.txt @@ -0,0 +1,94 @@ +Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. +with Reserved Font Name < Fira >, + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/FiraSans-Medium.woff b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/FiraSans-Medium.woff new file mode 100644 index 0000000000..7d742c5fb7 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/FiraSans-Medium.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/FiraSans-Regular.woff b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/FiraSans-Regular.woff new file mode 100644 index 0000000000..d8e0363f4e Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/FiraSans-Regular.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/LICENSE-APACHE.txt b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/LICENSE-APACHE.txt new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/LICENSE-APACHE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/LICENSE-MIT.txt b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/LICENSE-MIT.txt new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/LICENSE-MIT.txt @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-LICENSE.txt b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-LICENSE.txt new file mode 100644 index 0000000000..07542572e3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-LICENSE.txt @@ -0,0 +1,93 @@ +Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Regular.woff b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Regular.woff new file mode 100644 index 0000000000..5576670903 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Regular.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Semibold.woff b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Semibold.woff new file mode 100644 index 0000000000..ca972a11dc Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Semibold.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Bold.ttf.woff b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Bold.ttf.woff new file mode 100644 index 0000000000..ca254318fe Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Bold.ttf.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-It.ttf.woff b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-It.ttf.woff new file mode 100644 index 0000000000..a287bbe6ed Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-It.ttf.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-LICENSE.md b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-LICENSE.md new file mode 100644 index 0000000000..22cb755f2f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-LICENSE.md @@ -0,0 +1,93 @@ +Copyright 2014-2018 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Regular.ttf.woff b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Regular.ttf.woff new file mode 100644 index 0000000000..a3d55cfdf2 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Regular.ttf.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/all.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/all.html new file mode 100644 index 0000000000..3a505a083c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/all.html @@ -0,0 +1,3 @@ +List of all items in this crate

[] + + List of all items

Structs

Enums

Traits

Functions

Typedefs

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/enum.CompactFiltersError.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/enum.CompactFiltersError.html new file mode 100644 index 0000000000..03e77e6d1f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/enum.CompactFiltersError.html @@ -0,0 +1,56 @@ +bdk::blockchain::compact_filters::CompactFiltersError - Rust

[][src]Enum bdk::blockchain::compact_filters::CompactFiltersError

pub enum CompactFiltersError {
+    InvalidResponse,
+    InvalidHeaders,
+    InvalidFilterHeader,
+    InvalidFilter,
+    MissingBlock,
+    DataCorruption,
+    NotConnected,
+    Timeout,
+    NoPeers,
+    DB(Error),
+    IO(Error),
+    BIP158(Error),
+    Time(SystemTimeError),
+    Global(Box<Error>),
+}
This is supported on feature="compact_filters" only.

An error that can occur during sync with a CompactFiltersBlockchain

+

+ Variants

+
InvalidResponse
This is supported on feature="compact_filters" only.

A peer sent an invalid or unexpected response

+
InvalidHeaders
This is supported on feature="compact_filters" only.

The headers returned are invalid

+
InvalidFilterHeader
This is supported on feature="compact_filters" only.

The compact filter headers returned are invalid

+
InvalidFilter
This is supported on feature="compact_filters" only.

The compact filter returned is invalid

+
MissingBlock
This is supported on feature="compact_filters" only.

The peer is missing a block in the valid chain

+
DataCorruption
This is supported on feature="compact_filters" only.

The data stored in the block filters storage are corrupted

+
NotConnected
This is supported on feature="compact_filters" only.

A peer is not connected

+
Timeout
This is supported on feature="compact_filters" only.

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

+
NoPeers
This is supported on feature="compact_filters" only.

No peers have been specified

+
DB(Error)
This is supported on feature="compact_filters" only.

Internal database error

+
IO(Error)
This is supported on feature="compact_filters" only.

Internal I/O error

+
BIP158(Error)
This is supported on feature="compact_filters" only.

Invalid BIP158 filter

+
This is supported on feature="compact_filters" only.

Internal system time error

+
Global(Box<Error>)
This is supported on feature="compact_filters" only.

Wrapper for crate::error::Error

+

Trait Implementations

impl Debug for CompactFiltersError[src]

impl Display for CompactFiltersError[src]

impl Error for CompactFiltersError[src]

impl From<CompactFiltersError> for Error[src]

impl From<Error> for CompactFiltersError[src]

impl From<Error> for CompactFiltersError[src]

impl From<Error> for CompactFiltersError[src]

impl From<Error> for CompactFiltersError[src]

impl From<SystemTimeError> for CompactFiltersError[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/index.html new file mode 100644 index 0000000000..9a0f04a20e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/index.html @@ -0,0 +1,31 @@ +bdk::blockchain::compact_filters - Rust

[][src]Module bdk::blockchain::compact_filters

This is supported on feature="compact_filters" only.

Compact Filters

+

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

+

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

+

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

+

Example

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

Structs

+
CompactFiltersBlockchainfeature="compact_filters"

Structure implementing the required blockchain traits

+
Mempoolfeature="compact_filters"

Container for unconfirmed, but valid Bitcoin transactions

+
Peerfeature="compact_filters"

A Bitcoin peer

+

Enums

+
CompactFiltersErrorfeature="compact_filters"

An error that can occur during sync with a CompactFiltersBlockchain

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Mempool.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Mempool.html new file mode 100644 index 0000000000..cd04378cbe --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Mempool.html @@ -0,0 +1,10 @@ + + + + + + +

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

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Peer.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Peer.html new file mode 100644 index 0000000000..11332c3bdb --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Peer.html @@ -0,0 +1,10 @@ + + + + + + +

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

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/sidebar-items.js new file mode 100644 index 0000000000..22c61151d6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["CompactFiltersError","An error that can occur during sync with a [`CompactFiltersBlockchain`]"]],"struct":[["CompactFiltersBlockchain","Structure implementing the required blockchain traits"],["Mempool","Container for unconfirmed, but valid Bitcoin transactions"],["Peer","A Bitcoin peer"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html new file mode 100644 index 0000000000..e66ceef644 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html @@ -0,0 +1,28 @@ +bdk::blockchain::compact_filters::CompactFiltersBlockchain - Rust

[][src]Struct bdk::blockchain::compact_filters::CompactFiltersBlockchain

pub struct CompactFiltersBlockchain { /* fields omitted */ }
This is supported on feature="compact_filters" only.

Structure implementing the required blockchain traits

+

Example

+

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

+

Implementations

impl CompactFiltersBlockchain[src]

pub fn new<P: AsRef<Path>>(
    peers: Vec<Peer>,
    storage_dir: P,
    skip_blocks: Option<usize>
) -> Result<Self, CompactFiltersError>
[src]

This is supported on feature="compact_filters" only.

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

+

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

+

Trait Implementations

impl Blockchain for CompactFiltersBlockchain[src]

impl Debug for CompactFiltersBlockchain[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> BlockchainMarker for T where
    T: Blockchain
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Mempool.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Mempool.html new file mode 100644 index 0000000000..d7cf23d992 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Mempool.html @@ -0,0 +1,21 @@ +bdk::blockchain::compact_filters::Mempool - Rust

[][src]Struct bdk::blockchain::compact_filters::Mempool

pub struct Mempool { /* fields omitted */ }
This is supported on feature="compact_filters" only.

Container for unconfirmed, but valid Bitcoin transactions

+

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

+

Implementations

impl Mempool[src]

pub fn add_tx(&self, tx: Transaction)[src]

This is supported on feature="compact_filters" only.

Add a transaction to the mempool

+

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

+

pub fn get_tx(&self, inventory: &Inventory) -> Option<Transaction>[src]

This is supported on feature="compact_filters" only.

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

+

pub fn has_tx(&self, txid: &Txid) -> bool[src]

This is supported on feature="compact_filters" only.

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

+

pub fn iter_txs(&self) -> Vec<Transaction>[src]

This is supported on feature="compact_filters" only.

Return the list of transactions contained in the mempool

+

Trait Implementations

impl Debug for Mempool[src]

impl Default for Mempool[src]

Auto Trait Implementations

impl RefUnwindSafe for Mempool

impl Send for Mempool

impl Sync for Mempool

impl Unpin for Mempool

impl UnwindSafe for Mempool

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Peer.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Peer.html new file mode 100644 index 0000000000..e870e68138 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Peer.html @@ -0,0 +1,25 @@ +bdk::blockchain::compact_filters::Peer - Rust

[][src]Struct bdk::blockchain::compact_filters::Peer

pub struct Peer { /* fields omitted */ }
This is supported on feature="compact_filters" only.

A Bitcoin peer

+

Implementations

impl Peer[src]

pub fn connect<A: ToSocketAddrs>(
    address: A,
    mempool: Arc<Mempool>,
    network: Network
) -> Result<Self, CompactFiltersError>
[src]

This is supported on feature="compact_filters" only.

Connect to a peer over a plaintext TCP connection

+

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

+

pub fn connect_proxy<T: ToTargetAddr, P: ToSocketAddrs>(
    target: T,
    proxy: P,
    credentials: Option<(&str, &str)>,
    mempool: Arc<Mempool>,
    network: Network
) -> Result<Self, CompactFiltersError>
[src]

This is supported on feature="compact_filters" only.

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

+

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

+

pub fn get_version(&self) -> &VersionMessage[src]

This is supported on feature="compact_filters" only.

Return the [VersionMessage] sent by the peer

+

pub fn get_network(&self) -> Network[src]

This is supported on feature="compact_filters" only.

Return the Bitcoin [Network] in use

+

pub fn get_mempool(&self) -> Arc<Mempool>[src]

This is supported on feature="compact_filters" only.

Return the mempool used by this peer

+

pub fn is_connected(&self) -> bool[src]

This is supported on feature="compact_filters" only.

Return whether or not the peer is still connected

+

pub fn send(&self, payload: NetworkMessage) -> Result<(), CompactFiltersError>[src]

This is supported on feature="compact_filters" only.

Send a raw Bitcoin message to the peer

+

pub fn recv(
    &self,
    wait_for: &'static str,
    timeout: Option<Duration>
) -> Result<Option<NetworkMessage>, CompactFiltersError>
[src]

This is supported on feature="compact_filters" only.

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

+

Trait Implementations

impl Debug for Peer[src]

Auto Trait Implementations

impl !RefUnwindSafe for Peer

impl Send for Peer

impl Sync for Peer

impl Unpin for Peer

impl !UnwindSafe for Peer

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/index.html new file mode 100644 index 0000000000..6284002c9b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/index.html @@ -0,0 +1,11 @@ +bdk::blockchain::electrum - Rust

[][src]Module bdk::blockchain::electrum

This is supported on feature="electrum" only.

Electrum

+

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

+

Example

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

Structs

+
ElectrumBlockchainfeature="electrum"

Wrapper over an Electrum Client that implements the required blockchain traits

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/sidebar-items.js new file mode 100644 index 0000000000..ca94a34fb0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["ElectrumBlockchain","Wrapper over an Electrum Client that implements the required blockchain traits"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/struct.ElectrumBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/struct.ElectrumBlockchain.html new file mode 100644 index 0000000000..44ca3ba179 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/struct.ElectrumBlockchain.html @@ -0,0 +1,21 @@ +bdk::blockchain::electrum::ElectrumBlockchain - Rust

[][src]Struct bdk::blockchain::electrum::ElectrumBlockchain

pub struct ElectrumBlockchain(_);
This is supported on feature="electrum" only.

Wrapper over an Electrum Client that implements the required blockchain traits

+

Example

+

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

+

Trait Implementations

impl Blockchain for ElectrumBlockchain[src]

impl From<Client> for ElectrumBlockchain[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> BlockchainMarker for T where
    T: Blockchain
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/enum.Capability.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/enum.Capability.html new file mode 100644 index 0000000000..2fc3bbd7d1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/enum.Capability.html @@ -0,0 +1,32 @@ +bdk::blockchain::Capability - Rust

[][src]Enum bdk::blockchain::Capability

pub enum Capability {
+    FullHistory,
+    GetAnyTx,
+    AccurateFees,
+}

Capabilities that can be supported by a Blockchain backend

+

+ Variants

+
FullHistory

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

+
GetAnyTx

Can fetch any historical transaction given its txid

+
AccurateFees

Can compute accurate fees for the transactions found during sync

+

Trait Implementations

impl Clone for Capability[src]

impl Copy for Capability[src]

impl Debug for Capability[src]

impl Eq for Capability[src]

impl Hash for Capability[src]

impl PartialEq<Capability> for Capability[src]

impl StructuralEq for Capability[src]

impl StructuralPartialEq for Capability[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/enum.EsploraError.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/enum.EsploraError.html new file mode 100644 index 0000000000..f4e7f9664c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/enum.EsploraError.html @@ -0,0 +1,34 @@ +bdk::blockchain::esplora::EsploraError - Rust

[][src]Enum bdk::blockchain::esplora::EsploraError

pub enum EsploraError {
+    Reqwest(Error),
+    Parsing(ParseIntError),
+    BitcoinEncoding(Error),
+    TransactionNotFound(Txid),
+}
This is supported on feature="esplora" only.

Errors that can happen during a sync with EsploraBlockchain

+

+ Variants

+
Reqwest(Error)
This is supported on feature="esplora" only.

Error with the HTTP call

+
Parsing(ParseIntError)
This is supported on feature="esplora" only.

Invalid number returned

+
BitcoinEncoding(Error)
This is supported on feature="esplora" only.

Invalid Bitcoin data returned

+
TransactionNotFound(Txid)
This is supported on feature="esplora" only.

Transaction not found

+

Trait Implementations

impl Debug for EsploraError[src]

impl Display for EsploraError[src]

impl Error for EsploraError[src]

impl From<Error> for EsploraError[src]

impl From<Error> for EsploraError[src]

impl From<EsploraError> for Error[src]

impl From<ParseIntError> for EsploraError[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/index.html new file mode 100644 index 0000000000..abb4d4d08a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/index.html @@ -0,0 +1,11 @@ +bdk::blockchain::esplora - Rust

[][src]Module bdk::blockchain::esplora

This is supported on feature="esplora" only.

Esplora

+

This module defines a Blockchain struct that can query an Esplora backend +populate the wallet's database by

+

Example

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

Structs

+
EsploraBlockchainfeature="esplora"

Structure that implements the logic to sync with Esplora

+

Enums

+
EsploraErrorfeature="esplora"

Errors that can happen during a sync with EsploraBlockchain

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/sidebar-items.js new file mode 100644 index 0000000000..fc6ecf6be6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["EsploraError","Errors that can happen during a sync with [`EsploraBlockchain`]"]],"struct":[["EsploraBlockchain","Structure that implements the logic to sync with Esplora"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/struct.EsploraBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/struct.EsploraBlockchain.html new file mode 100644 index 0000000000..e2a5d3c475 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/struct.EsploraBlockchain.html @@ -0,0 +1,22 @@ +bdk::blockchain::esplora::EsploraBlockchain - Rust

[][src]Struct bdk::blockchain::esplora::EsploraBlockchain

pub struct EsploraBlockchain(_);
This is supported on feature="esplora" only.

Structure that implements the logic to sync with Esplora

+

Example

+

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

+

Implementations

impl EsploraBlockchain[src]

pub fn new(base_url: &str) -> Self[src]

This is supported on feature="esplora" only.

Create a new instance of the client from a base URL

+

Trait Implementations

impl Blockchain for EsploraBlockchain[src]

impl Debug for EsploraBlockchain[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> BlockchainMarker for T where
    T: Blockchain
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.log_progress.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.log_progress.html new file mode 100644 index 0000000000..c9bf15bd7a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.log_progress.html @@ -0,0 +1,2 @@ +bdk::blockchain::log_progress - Rust

[][src]Function bdk::blockchain::log_progress

pub fn log_progress() -> LogProgress

Create a nwe instance of LogProgress

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.noop_progress.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.noop_progress.html new file mode 100644 index 0000000000..046b7d470f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.noop_progress.html @@ -0,0 +1,2 @@ +bdk::blockchain::noop_progress - Rust

[][src]Function bdk::blockchain::noop_progress

pub fn noop_progress() -> NoopProgress

Create a new instance of NoopProgress

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.progress.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.progress.html new file mode 100644 index 0000000000..5070df1d52 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.progress.html @@ -0,0 +1,2 @@ +bdk::blockchain::progress - Rust

[][src]Function bdk::blockchain::progress

pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>)

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

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/index.html new file mode 100644 index 0000000000..0d1ede0175 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/index.html @@ -0,0 +1,28 @@ +bdk::blockchain - Rust

[][src]Module bdk::blockchain

Blockchain backends

+

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

+

Re-exports

+
pub use self::electrum::ElectrumBlockchain;
pub use self::esplora::EsploraBlockchain;
pub use self::compact_filters::CompactFiltersBlockchain;

Modules

+
compact_filtersfeature="compact_filters"

Compact Filters

+
electrumfeature="electrum"

Electrum

+
esplorafeature="esplora"

Esplora

+

Structs

+
LogProgress

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

+
NoopProgress

Type that implements Progress and drops every update received

+
OfflineBlockchain

Type that only implements Blockchain and is always "offline"

+

Enums

+
Capability

Capabilities that can be supported by a Blockchain backend

+

Traits

+
Blockchain

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

+
BlockchainMarker

Marker trait for a blockchain backend

+
Progress

Trait for types that can receive and process progress updates during Blockchain::sync and +Blockchain::setup

+

Functions

+
log_progress

Create a nwe instance of LogProgress

+
noop_progress

Create a new instance of NoopProgress

+
progress

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

+

Type Definitions

+
ProgressData

Data sent with a progress update over a channel

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/sidebar-items.js new file mode 100644 index 0000000000..caf2b0fe29 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["Capability","Capabilities that can be supported by a [`Blockchain`] backend"]],"fn":[["log_progress","Create a nwe instance of [`LogProgress`]"],["noop_progress","Create a new instance of [`NoopProgress`]"],["progress","Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]"]],"mod":[["compact_filters","Compact Filters"],["electrum","Electrum"],["esplora","Esplora"]],"struct":[["LogProgress","Type that implements [`Progress`] and logs at level `INFO` every update received"],["NoopProgress","Type that implements [`Progress`] and drops every update received"],["OfflineBlockchain","Type that only implements [`Blockchain`] and is always \"offline\""]],"trait":[["Blockchain","Trait that defines the actions that must be supported by a blockchain backend"],["BlockchainMarker","Marker trait for a blockchain backend"],["Progress","Trait for types that can receive and process progress updates during [`Blockchain::sync`] and [`Blockchain::setup`]"]],"type":[["ProgressData","Data sent with a progress update over a [`channel`]"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.LogProgress.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.LogProgress.html new file mode 100644 index 0000000000..90c9026c8b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.LogProgress.html @@ -0,0 +1,18 @@ +bdk::blockchain::LogProgress - Rust

[][src]Struct bdk::blockchain::LogProgress

pub struct LogProgress;

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

+

Trait Implementations

impl Clone for LogProgress[src]

impl Progress for LogProgress[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.NoopProgress.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.NoopProgress.html new file mode 100644 index 0000000000..14ff942c13 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.NoopProgress.html @@ -0,0 +1,18 @@ +bdk::blockchain::NoopProgress - Rust

[][src]Struct bdk::blockchain::NoopProgress

pub struct NoopProgress;

Type that implements Progress and drops every update received

+

Trait Implementations

impl Clone for NoopProgress[src]

impl Progress for NoopProgress[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.OfflineBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.OfflineBlockchain.html new file mode 100644 index 0000000000..8a5fcd5f92 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.OfflineBlockchain.html @@ -0,0 +1,11 @@ +bdk::blockchain::OfflineBlockchain - Rust

[][src]Struct bdk::blockchain::OfflineBlockchain

pub struct OfflineBlockchain;

Type that only implements Blockchain and is always "offline"

+

Trait Implementations

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> BlockchainMarker for T where
    T: Blockchain
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Blockchain.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Blockchain.html new file mode 100644 index 0000000000..37b5fa8bce --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Blockchain.html @@ -0,0 +1,37 @@ +bdk::blockchain::Blockchain - Rust

[][src]Trait bdk::blockchain::Blockchain

pub trait Blockchain: BlockchainMarker {
+    fn get_capabilities(&self) -> HashSet<Capability>;
+
fn setup<D: BatchDatabase, P: 'static + Progress>(
        &self,
        stop_gap: Option<usize>,
        database: &mut D,
        progress_update: P
    ) -> Result<(), Error>; +
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>; +
fn broadcast(&self, tx: &Transaction) -> Result<(), Error>; +
fn get_height(&self) -> Result<u32, Error>; +
fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>; + + fn sync<D: BatchDatabase, P: 'static + Progress>(
        &self,
        stop_gap: Option<usize>,
        database: &mut D,
        progress_update: P
    ) -> Result<(), Error> { ... } +}

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

+
+

Required methods

fn get_capabilities(&self) -> HashSet<Capability>

Return the set of Capability supported by this backend

+

fn setup<D: BatchDatabase, P: 'static + Progress>(
    &self,
    stop_gap: Option<usize>,
    database: &mut D,
    progress_update: P
) -> Result<(), Error>

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

+

This method is the equivalent of Blockchain::sync, but it's guaranteed to only be +called once, at the first Wallet::sync.

+

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

+

For types that do not have that distinction, only this method can be implemented, since +Blockchain::sync defaults to calling this internally if not overridden.

+

fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>

Fetch a transaction from the blockchain given its txid

+

fn broadcast(&self, tx: &Transaction) -> Result<(), Error>

Broadcast a transaction

+

fn get_height(&self) -> Result<u32, Error>

Return the current height

+

fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>

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

+
Loading content... +

Provided methods

fn sync<D: BatchDatabase, P: 'static + Progress>(
    &self,
    stop_gap: Option<usize>,
    database: &mut D,
    progress_update: P
) -> Result<(), Error>

Populate the internal database with transactions and UTXOs

+

If not overridden, it defaults to calling Blockchain::setup internally.

+

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

+

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

+

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

+
Loading content... +

Implementations on Foreign Types

impl<T: Blockchain> Blockchain for Arc<T>[src]

Loading content... +

Implementors

impl Blockchain for CompactFiltersBlockchain[src]

impl Blockchain for ElectrumBlockchain[src]

impl Blockchain for EsploraBlockchain[src]

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.BlockchainMarker.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.BlockchainMarker.html new file mode 100644 index 0000000000..abd1997c9f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.BlockchainMarker.html @@ -0,0 +1,12 @@ +bdk::blockchain::BlockchainMarker - Rust

[][src]Trait bdk::blockchain::BlockchainMarker

pub trait BlockchainMarker { }

Marker trait for a blockchain backend

+

This is a marker trait for blockchain types. It is automatically implemented for types that +implement Blockchain, so as a user of the library you won't have to implement this +manually.

+

Users of the library will probably never have to implement this trait manually, but they +could still need to import it to define types and structs with generics; +Implementing only the marker trait is pointless, since OfflineBlockchain +already does that, and whenever Blockchain is implemented, the marker trait is also +automatically implemented by the library.

+
+

Implementors

impl BlockchainMarker for OfflineBlockchain[src]

impl<T: Blockchain> BlockchainMarker for T[src]

The BlockchainMarker marker trait is automatically implemented for Blockchain types

+
Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Progress.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Progress.html new file mode 100644 index 0000000000..c5b883f49e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Progress.html @@ -0,0 +1,11 @@ +bdk::blockchain::Progress - Rust

[][src]Trait bdk::blockchain::Progress

pub trait Progress: Send {
+    fn update(
        &self,
        progress: f32,
        message: Option<String>
    ) -> Result<(), Error>; +}

Trait for types that can receive and process progress updates during Blockchain::sync and +Blockchain::setup

+
+

Required methods

fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error>

Send a new progress update

+

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

+
Loading content... +

Implementations on Foreign Types

impl Progress for Sender<ProgressData>[src]

Loading content... +

Implementors

impl Progress for LogProgress[src]

impl Progress for NoopProgress[src]

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/type.ProgressData.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/type.ProgressData.html new file mode 100644 index 0000000000..ec3f541cb7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/type.ProgressData.html @@ -0,0 +1,2 @@ +bdk::blockchain::ProgressData - Rust

[][src]Type Definition bdk::blockchain::ProgressData

type ProgressData = (f32, Option<String>);

Data sent with a progress update over a channel

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/index.html new file mode 100644 index 0000000000..7d69c1a943 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/index.html @@ -0,0 +1,17 @@ +bdk::database - Rust

[][src]Module bdk::database

Database types

+

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

+

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

+

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

+

Re-exports

+
pub use memory::MemoryDatabase;

Modules

+
memory

In-memory ephemeral database

+

Traits

+
BatchDatabase

Trait for a database that supports batch operations

+
BatchOperations

Trait for operations that can be batched

+
Database

Trait for reading data from a database

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/index.html new file mode 100644 index 0000000000..c30317bfb8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/index.html @@ -0,0 +1,6 @@ +bdk::database::memory - Rust

[][src]Module bdk::database::memory

In-memory ephemeral database

+

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

+

Structs

+
MemoryDatabase

In-memory ephemeral database

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/sidebar-items.js new file mode 100644 index 0000000000..665f6718d0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["MemoryDatabase","In-memory ephemeral database"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/struct.MemoryDatabase.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/struct.MemoryDatabase.html new file mode 100644 index 0000000000..f06b045d39 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/struct.MemoryDatabase.html @@ -0,0 +1,45 @@ +bdk::database::memory::MemoryDatabase - Rust

[][src]Struct bdk::database::memory::MemoryDatabase

pub struct MemoryDatabase { /* fields omitted */ }

In-memory ephemeral database

+

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

+

Once it's dropped its content will be lost.

+

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

+

Implementations

impl MemoryDatabase[src]

pub fn new() -> Self[src]

Create a new empty database

+

Trait Implementations

impl BatchDatabase for MemoryDatabase[src]

type Batch = Self

Container for the operations

+

impl BatchOperations for MemoryDatabase[src]

impl Database for MemoryDatabase[src]

impl Debug for MemoryDatabase[src]

impl Default for MemoryDatabase[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/sidebar-items.js new file mode 100644 index 0000000000..1d5816196c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"mod":[["memory","In-memory ephemeral database"]],"trait":[["BatchDatabase","Trait for a database that supports batch operations"],["BatchOperations","Trait for operations that can be batched"],["Database","Trait for reading data from a database"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchDatabase.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchDatabase.html new file mode 100644 index 0000000000..051a61e18b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchDatabase.html @@ -0,0 +1,14 @@ +bdk::database::BatchDatabase - Rust

[][src]Trait bdk::database::BatchDatabase

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

Trait for a database that supports batch operations

+

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

+
+

Associated Types

type Batch: BatchOperations

Container for the operations

+
Loading content... +

Required methods

fn begin_batch(&self) -> Self::Batch

Create a new batch container

+

fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>

Consume and apply a batch of operations

+
Loading content... +

Implementations on Foreign Types

impl BatchDatabase for Tree[src]

type Batch = Batch

Loading content... +

Implementors

impl BatchDatabase for MemoryDatabase[src]

type Batch = Self

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchOperations.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchOperations.html new file mode 100644 index 0000000000..4fc52b7d3b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchOperations.html @@ -0,0 +1,31 @@ +bdk::database::BatchOperations - Rust

[][src]Trait bdk::database::BatchOperations

pub trait BatchOperations {
+    fn set_script_pubkey(
        &mut self,
        script: &Script,
        script_type: ScriptType,
        child: u32
    ) -> Result<(), Error>; +
fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>; +
fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>; +
fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>; +
fn set_last_index(
        &mut self,
        script_type: ScriptType,
        value: u32
    ) -> Result<(), Error>; +
fn del_script_pubkey_from_path(
        &mut self,
        script_type: ScriptType,
        child: u32
    ) -> Result<Option<Script>, Error>; +
fn del_path_from_script_pubkey(
        &mut self,
        script: &Script
    ) -> Result<Option<(ScriptType, u32)>, Error>; +
fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>; +
fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>; +
fn del_tx(
        &mut self,
        txid: &Txid,
        include_raw: bool
    ) -> Result<Option<TransactionDetails>, Error>; +
fn del_last_index(
        &mut self,
        script_type: ScriptType
    ) -> Result<Option<u32>, Error>; +}

Trait for operations that can be batched

+

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

+
+

Required methods

fn set_script_pubkey(
    &mut self,
    script: &Script,
    script_type: ScriptType,
    child: u32
) -> Result<(), Error>

Store a script_pubkey along with its script type and child number

+

fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>

Store a UTXO

+

fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>

Store a raw transaction

+

fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>

Store the metadata of a transaction

+

fn set_last_index(
    &mut self,
    script_type: ScriptType,
    value: u32
) -> Result<(), Error>

Store the last derivation index for a given script type

+

fn del_script_pubkey_from_path(
    &mut self,
    script_type: ScriptType,
    child: u32
) -> Result<Option<Script>, Error>

Delete a script_pubkey given the script type and its child number

+

fn del_path_from_script_pubkey(
    &mut self,
    script: &Script
) -> Result<Option<(ScriptType, u32)>, Error>

Delete the data related to a specific script_pubkey, meaning the script type and the child +number

+

fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>

Delete a UTXO given its [OutPoint]

+

fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>

Delete a raw transaction given its [Txid]

+

fn del_tx(
    &mut self,
    txid: &Txid,
    include_raw: bool
) -> Result<Option<TransactionDetails>, Error>

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

+

fn del_last_index(
    &mut self,
    script_type: ScriptType
) -> Result<Option<u32>, Error>

Delete the last derivation index for a script type

+
Loading content... +

Implementations on Foreign Types

impl BatchOperations for Tree[src]

impl BatchOperations for Batch[src]

Loading content... +

Implementors

impl BatchOperations for MemoryDatabase[src]

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.Database.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.Database.html new file mode 100644 index 0000000000..05be68c384 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.Database.html @@ -0,0 +1,35 @@ +bdk::database::Database - Rust

[][src]Trait bdk::database::Database

pub trait Database: BatchOperations {
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
        &mut self,
        script_type: ScriptType,
        bytes: B
    ) -> Result<(), Error>; +
fn iter_script_pubkeys(
        &self,
        script_type: Option<ScriptType>
    ) -> Result<Vec<Script>, Error>; +
fn iter_utxos(&self) -> Result<Vec<UTXO>, Error>; +
fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>; +
fn iter_txs(
        &self,
        include_raw: bool
    ) -> Result<Vec<TransactionDetails>, Error>; +
fn get_script_pubkey_from_path(
        &self,
        script_type: ScriptType,
        child: u32
    ) -> Result<Option<Script>, Error>; +
fn get_path_from_script_pubkey(
        &self,
        script: &Script
    ) -> Result<Option<(ScriptType, u32)>, Error>; +
fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>; +
fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>; +
fn get_tx(
        &self,
        txid: &Txid,
        include_raw: bool
    ) -> Result<Option<TransactionDetails>, Error>; +
fn get_last_index(
        &self,
        script_type: ScriptType
    ) -> Result<Option<u32>, Error>; +
fn increment_last_index(
        &mut self,
        script_type: ScriptType
    ) -> Result<u32, Error>; +}

Trait for reading data from a database

+

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

+
+

Required methods

fn check_descriptor_checksum<B: AsRef<[u8]>>(
    &mut self,
    script_type: ScriptType,
    bytes: B
) -> Result<(), Error>

Read and checks the descriptor checksum for a given script type

+

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

+

fn iter_script_pubkeys(
    &self,
    script_type: Option<ScriptType>
) -> Result<Vec<Script>, Error>

Return the list of script_pubkeys

+

fn iter_utxos(&self) -> Result<Vec<UTXO>, Error>

Return the list of UTXOs

+

fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>

Return the list of raw transactions

+

fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error>

Return the list of transactions metadata

+

fn get_script_pubkey_from_path(
    &self,
    script_type: ScriptType,
    child: u32
) -> Result<Option<Script>, Error>

Fetch a script_pubkey given the script type and child number

+

fn get_path_from_script_pubkey(
    &self,
    script: &Script
) -> Result<Option<(ScriptType, u32)>, Error>

Fetch the script type and child number of a given script_pubkey

+

fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>

Fetch a UTXO given its [OutPoint]

+

fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>

Fetch a raw transaction given its [Txid]

+

fn get_tx(
    &self,
    txid: &Txid,
    include_raw: bool
) -> Result<Option<TransactionDetails>, Error>

Fetch the transaction metadata and optionally also the raw transaction

+

fn get_last_index(&self, script_type: ScriptType) -> Result<Option<u32>, Error>

Return the last defivation index for a script type

+

fn increment_last_index(
    &mut self,
    script_type: ScriptType
) -> Result<u32, Error>

Increment the last derivation index for a script type and returns it

+

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

+
Loading content... +

Implementations on Foreign Types

impl Database for Tree[src]

Loading content... +

Implementors

impl Database for MemoryDatabase[src]

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/fn.get_checksum.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/fn.get_checksum.html new file mode 100644 index 0000000000..43647729e3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/fn.get_checksum.html @@ -0,0 +1,2 @@ +bdk::descriptor::checksum::get_checksum - Rust

[][src]Function bdk::descriptor::checksum::get_checksum

pub fn get_checksum(desc: &str) -> Result<String, Error>

Compute the checksum of a descriptor

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/index.html new file mode 100644 index 0000000000..b6b7a26f33 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/index.html @@ -0,0 +1,6 @@ +bdk::descriptor::checksum - Rust

[][src]Module bdk::descriptor::checksum

Descriptor checksum

+

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

+

Functions

+
get_checksum

Compute the checksum of a descriptor

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/sidebar-items.js new file mode 100644 index 0000000000..e1add094a5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"fn":[["get_checksum","Compute the checksum of a descriptor"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Descriptor.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Descriptor.html new file mode 100644 index 0000000000..f94eab51f0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Descriptor.html @@ -0,0 +1,80 @@ +bdk::descriptor::Descriptor - Rust

[]Enum bdk::descriptor::Descriptor

pub enum Descriptor<Pk> where
    Pk: MiniscriptKey
{ + Bare(Miniscript<Pk, Legacy>), + Pk(Pk), + Pkh(Pk), + Wpkh(Pk), + ShWpkh(Pk), + Sh(Miniscript<Pk, Legacy>), + Wsh(Miniscript<Pk, Segwitv0>), + ShWsh(Miniscript<Pk, Segwitv0>), +}

Script descriptor

+

+ Variants

+
Bare(Miniscript<Pk, Legacy>)

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

+
Pk(Pk)

Pay-to-Pubkey

+
Pkh(Pk)

Pay-to-PubKey-Hash

+
Wpkh(Pk)

Pay-to-Witness-PubKey-Hash

+
ShWpkh(Pk)

Pay-to-Witness-PubKey-Hash inside P2SH

+

Pay-to-ScriptHash with Legacy context

+

Pay-to-Witness-ScriptHash with Segwitv0 context

+
ShWsh(Miniscript<Pk, Segwitv0>)

P2SH-P2WSH with Segwitv0 context

+

Implementations

impl<Pk> Descriptor<Pk> where
    Pk: MiniscriptKey

pub fn translate_pk<Fpk, Fpkh, Q, E>(
    &self,
    translatefpk: Fpk,
    translatefpkh: Fpkh
) -> Result<Descriptor<Q>, E> where
    Fpk: FnMut(&Pk) -> Result<Q, E>,
    Fpkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, E>,
    Q: MiniscriptKey

Convert a descriptor using abstract keys to one using specific keys +This will panic if translatefpk returns an uncompressed key when +converting to a Segwit descriptor. To prevent this panic, ensure +translatefpk returns an error in this case instead.

+

impl<Pk> Descriptor<Pk> where
    Pk: MiniscriptKey + ToPublicKey

pub fn address(&self, network: Network) -> Option<Address>

Computes the Bitcoin address of the descriptor, if one exists

+

pub fn script_pubkey(&self) -> Script

Computes the scriptpubkey of the descriptor

+

pub fn unsigned_script_sig(&self) -> Script

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

+

pub fn witness_script(&self) -> Script

Computes the "witness script" of the descriptor, i.e. 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.

+

pub fn satisfy<S>(&self, txin: &mut TxIn, satisfier: S) -> Result<(), Error> where
    S: Satisfier<Pk>, 

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

+

pub fn max_satisfaction_weight(&self) -> usize

Computes an upper bound on the weight of a satisfying witness to the +transaction. Assumes all signatures are 73 bytes, including push opcode +and sighash suffix. Includes the weight of the VarInts encoding the +scriptSig and witness stack length.

+

impl Descriptor<DescriptorPublicKey>

pub fn derive(&self, path: &[ChildNumber]) -> Descriptor<DescriptorPublicKey>

Derives all wildcard keys in the descriptor using the supplied path

+

pub fn parse_secret(
    s: &str
) -> Result<(Descriptor<DescriptorPublicKey>, HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>), Error>

pub fn to_string_with_secret(
    &self,
    key_map: &HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>
) -> String

Trait Implementations

impl<Pk> Clone for Descriptor<Pk> where
    Pk: MiniscriptKey + Clone

impl<Pk> Debug for Descriptor<Pk> where
    Pk: MiniscriptKey

impl<Pk> Display for Descriptor<Pk> where
    Pk: MiniscriptKey

impl<Pk> Eq for Descriptor<Pk> where
    Pk: MiniscriptKey + Eq

impl ExtractPolicy for Descriptor<DescriptorPublicKey>[src]

impl<Pk> FromStr for Descriptor<Pk> where
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

type Err = Error

The associated error which can be returned from parsing.

+

impl<Pk> FromTree for Descriptor<Pk> where
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

fn from_tree(top: &Tree) -> Result<Descriptor<Pk>, Error>

Parse an expression tree into a descriptor

+

impl<Pk> Liftable<Pk> for Descriptor<Pk> where
    Pk: MiniscriptKey

impl<Pk> Ord for Descriptor<Pk> where
    Pk: MiniscriptKey + Ord

impl<Pk> PartialEq<Descriptor<Pk>> for Descriptor<Pk> where
    Pk: MiniscriptKey + PartialEq<Pk>, 

impl<Pk> PartialOrd<Descriptor<Pk>> for Descriptor<Pk> where
    Pk: MiniscriptKey + PartialOrd<Pk>, 

impl<Pk> StructuralEq for Descriptor<Pk> where
    Pk: MiniscriptKey

impl<Pk> StructuralPartialEq for Descriptor<Pk> where
    Pk: MiniscriptKey

Auto Trait Implementations

impl<Pk> RefUnwindSafe for Descriptor<Pk> where
    Pk: RefUnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe

impl<Pk> Send for Descriptor<Pk> where
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk> Sync for Descriptor<Pk> where
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk> Unpin for Descriptor<Pk> where
    Pk: Unpin,
    <Pk as MiniscriptKey>::Hash: Unpin

impl<Pk> UnwindSafe for Descriptor<Pk> where
    Pk: RefUnwindSafe + UnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Legacy.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Legacy.html new file mode 100644 index 0000000000..bba267f6ac --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Legacy.html @@ -0,0 +1,32 @@ +bdk::descriptor::Legacy - Rust

[]Enum bdk::descriptor::Legacy

pub enum Legacy {}

Legacy ScriptContext

+

Trait Implementations

impl Clone for Legacy

impl Debug for Legacy

impl Eq for Legacy

impl Ord for Legacy

impl PartialEq<Legacy> for Legacy

impl PartialOrd<Legacy> for Legacy

impl ScriptContext for Legacy

impl StructuralEq for Legacy

impl StructuralPartialEq for Legacy

Auto Trait Implementations

impl RefUnwindSafe for Legacy

impl Send for Legacy

impl Sync for Legacy

impl Unpin for Legacy

impl UnwindSafe for Legacy

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Segwitv0.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Segwitv0.html new file mode 100644 index 0000000000..5011335983 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Segwitv0.html @@ -0,0 +1,32 @@ +bdk::descriptor::Segwitv0 - Rust

[]Enum bdk::descriptor::Segwitv0

pub enum Segwitv0 {}

Segwitv0 ScriptContext

+

Trait Implementations

impl Clone for Segwitv0

impl Debug for Segwitv0

impl Eq for Segwitv0

impl Ord for Segwitv0

impl PartialEq<Segwitv0> for Segwitv0

impl PartialOrd<Segwitv0> for Segwitv0

impl ScriptContext for Segwitv0

impl StructuralEq for Segwitv0

impl StructuralPartialEq for Segwitv0

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Terminal.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Terminal.html new file mode 100644 index 0000000000..123dafd5f4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Terminal.html @@ -0,0 +1,128 @@ +bdk::descriptor::Terminal - Rust

[]Enum bdk::descriptor::Terminal

pub enum Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey
{ + True, + False, + PkK(Pk), + PkH(<Pk as MiniscriptKey>::Hash), + After(u32), + Older(u32), + Sha256(Hash), + Hash256(Hash), + Ripemd160(Hash), + Hash160(Hash), + Alt(Arc<Miniscript<Pk, Ctx>>), + Swap(Arc<Miniscript<Pk, Ctx>>), + Check(Arc<Miniscript<Pk, Ctx>>), + DupIf(Arc<Miniscript<Pk, Ctx>>), + Verify(Arc<Miniscript<Pk, Ctx>>), + NonZero(Arc<Miniscript<Pk, Ctx>>), + ZeroNotEqual(Arc<Miniscript<Pk, Ctx>>), + AndV(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + AndB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + AndOr(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + OrB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + OrD(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + OrC(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + OrI(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + Thresh(usizeVec<Arc<Miniscript<Pk, Ctx>>>), + Multi(usizeVec<Pk>), +}

All AST elements

+

+ Variants

+
True

1

+
False

0

+
PkK(Pk)

<key>

+
PkH(<Pk as MiniscriptKey>::Hash)

DUP HASH160 <keyhash> EQUALVERIFY

+
After(u32)

n CHECKLOCKTIMEVERIFY

+
Older(u32)

n CHECKSEQUENCEVERIFY

+
Sha256(Hash)

SIZE 32 EQUALVERIFY SHA256 <hash> EQUAL

+
Hash256(Hash)

SIZE 32 EQUALVERIFY HASH256 <hash> EQUAL

+
Ripemd160(Hash)

SIZE 32 EQUALVERIFY RIPEMD160 <hash> EQUAL

+
Hash160(Hash)

SIZE 32 EQUALVERIFY HASH160 <hash> EQUAL

+
Alt(Arc<Miniscript<Pk, Ctx>>)

TOALTSTACK [E] FROMALTSTACK

+
Swap(Arc<Miniscript<Pk, Ctx>>)

SWAP [E1]

+
Check(Arc<Miniscript<Pk, Ctx>>)

[Kt]/[Ke] CHECKSIG

+
DupIf(Arc<Miniscript<Pk, Ctx>>)

DUP IF [V] ENDIF

+
Verify(Arc<Miniscript<Pk, Ctx>>)

[T] VERIFY

+
NonZero(Arc<Miniscript<Pk, Ctx>>)

SIZE 0NOTEQUAL IF Fn ENDIF

+
ZeroNotEqual(Arc<Miniscript<Pk, Ctx>>)

[X] 0NOTEQUAL

+
AndV(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[V] [T]/[V]/[F]/[Kt]

+
AndB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[E] [W] BOOLAND

+
AndOr(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[various] NOTIF [various] ELSE [various] ENDIF

+
OrB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[E] [W] BOOLOR

+
OrD(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[E] IFDUP NOTIF [T]/[E] ENDIF

+
OrC(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[E] NOTIF [V] ENDIF

+
OrI(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

IF [various] ELSE [various] ENDIF

+
Thresh(usizeVec<Arc<Miniscript<Pk, Ctx>>>)

[E] ([W] ADD)* k EQUAL

+
Multi(usizeVec<Pk>)

k ()* n CHECKMULTISIG

+

Implementations

impl<Pk, Ctx> Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn translate_pk<FPk, FPkh, Q, Error>(
    &self,
    translatefpk: &mut FPk,
    translatefpkh: &mut FPkh
) -> Result<Terminal<Q, Ctx>, Error> where
    FPk: FnMut(&Pk) -> Result<Q, Error>,
    FPkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, Error>,
    Q: MiniscriptKey

Convert an AST element with one public key type to one of another +public key type .This will panic while converting to +Segwit Miniscript using uncompressed public keys

+

impl<Pk, Ctx> Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey + ToPublicKey

pub fn encode(&self, builder: Builder) -> Builder

Encode the element as a fragment of Bitcoin Script. The inverse +function, from Script to an AST element, is implemented in the +parse module.

+

pub fn script_size(&self) -> usize

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.

+

pub fn max_dissatisfaction_witness_elements(&self) -> Option<usize>

Maximum number of witness elements used to dissatisfy the Miniscript +fragment. Used to estimate the weight of the VarInt that specifies +this number in a serialized transaction.

+

Will panic if the fragment is not an E, W or Ke.

+

pub fn max_dissatisfaction_size(&self, one_cost: usize) -> Option<usize>

Maximum dissatisfaction cost, in bytes, of a Miniscript fragment, +if it is possible to compute this. This function should probably +not ever be used directly. It is called from max_satisfaction_size.

+

Will panic if the fragment is not E, W or Ke

+

pub fn max_satisfaction_witness_elements(&self) -> usize

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

+

This number does not include the witness script itself, so 1 needs +to be added to the final result.

+

pub fn max_satisfaction_size(&self, one_cost: usize) -> usize

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.

+

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

+

Trait Implementations

impl<Pk, Ctx> Clone for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + Clone,
    Pk: MiniscriptKey + Clone,
    <Pk as MiniscriptKey>::Hash: Clone

impl<Pk, Ctx> Debug for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Display for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Eq for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + Eq,
    Pk: MiniscriptKey + Eq,
    <Pk as MiniscriptKey>::Hash: Eq

impl<Pk, Ctx> FromTree for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

impl<Pk, Ctx> Hash for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + Hash,
    Pk: MiniscriptKey + Hash,
    <Pk as MiniscriptKey>::Hash: Hash

impl<Pk, Ctx> Liftable<Pk> for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Ord for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + Ord,
    Pk: MiniscriptKey + Ord,
    <Pk as MiniscriptKey>::Hash: Ord

impl<Pk, Ctx> PartialEq<Terminal<Pk, Ctx>> for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + PartialEq<Ctx>,
    Pk: MiniscriptKey + PartialEq<Pk>,
    <Pk as MiniscriptKey>::Hash: PartialEq<<Pk as MiniscriptKey>::Hash>, 

impl<Pk, Ctx> PartialOrd<Terminal<Pk, Ctx>> for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + PartialOrd<Ctx>,
    Pk: MiniscriptKey + PartialOrd<Pk>,
    <Pk as MiniscriptKey>::Hash: PartialOrd<<Pk as MiniscriptKey>::Hash>, 

impl<Pk, Ctx> StructuralEq for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> StructuralPartialEq for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Auto Trait Implementations

impl<Pk, Ctx> RefUnwindSafe for Terminal<Pk, Ctx> where
    Ctx: RefUnwindSafe,
    Pk: RefUnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe

impl<Pk, Ctx> Send for Terminal<Pk, Ctx> where
    Ctx: Send + Sync,
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk, Ctx> Sync for Terminal<Pk, Ctx> where
    Ctx: Send + Sync,
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk, Ctx> Unpin for Terminal<Pk, Ctx> where
    Pk: Unpin,
    <Pk as MiniscriptKey>::Hash: Unpin

impl<Pk, Ctx> UnwindSafe for Terminal<Pk, Ctx> where
    Ctx: RefUnwindSafe,
    Pk: RefUnwindSafe + UnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/enum.Error.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/enum.Error.html new file mode 100644 index 0000000000..51b1b133bc --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/enum.Error.html @@ -0,0 +1,45 @@ +bdk::descriptor::error::Error - Rust

[][src]Enum bdk::descriptor::error::Error

pub enum Error {
+    InternalError,
+    InvalidPrefix(Vec<u8>),
+    HardenedDerivationOnXpub,
+    MalformedInput,
+    KeyParsingError(String),
+    Policy(PolicyError),
+    InputIndexDoesntExist,
+    MissingPublicKey,
+    MissingDetails,
+    InvalidDescriptorCharacter(char),
+    CantDeriveWithMiniscript,
+    BIP32(Error),
+    Base58(Error),
+    PK(Error),
+    Miniscript(Error),
+    Hex(Error),
+}

Errors related to the parsing and usage of descriptors

+

+ Variants

+
InternalError
InvalidPrefix(Vec<u8>)
HardenedDerivationOnXpub
MalformedInput
KeyParsingError(String)
Policy(PolicyError)
InputIndexDoesntExist
MissingPublicKey
MissingDetails
InvalidDescriptorCharacter(char)
CantDeriveWithMiniscript
BIP32(Error)
Base58(Error)
PK(Error)
Miniscript(Error)
Hex(Error)

Trait Implementations

impl Debug for Error[src]

impl Display for Error[src]

impl Error for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<PolicyError> for Error[src]

Auto Trait Implementations

impl RefUnwindSafe for Error

impl Send for Error

impl Sync for Error

impl Unpin for Error

impl UnwindSafe for Error

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/index.html new file mode 100644 index 0000000000..3c3a9a8451 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/index.html @@ -0,0 +1,4 @@ +bdk::descriptor::error - Rust

[][src]Module bdk::descriptor::error

Descriptor errors

+

Enums

+
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/0.1.0-beta.1/bdk/descriptor/error/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/sidebar-items.js new file mode 100644 index 0000000000..1ad99d4faf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"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/0.1.0-beta.1/bdk/descriptor/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/index.html new file mode 100644 index 0000000000..a4c4f2ecfd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/index.html @@ -0,0 +1,24 @@ +bdk::descriptor - Rust

[][src]Module bdk::descriptor

Descriptors

+

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

+

Re-exports

+
pub use self::checksum::get_checksum;
pub use self::policy::Policy;

Modules

+
checksum

Descriptor checksum

+
error

Descriptor errors

+
policy

Descriptor policy

+

Structs

+
Miniscript

Top-level script AST type

+

Enums

+
Descriptor

Script descriptor

+
Legacy

Legacy ScriptContext

+
Segwitv0

Segwitv0 ScriptContext

+
Terminal

All AST elements

+

Traits

+
ExtractPolicy

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

+
MiniscriptKey

Public key trait which can be converted to Hash type

+
ScriptContext
ToPublicKey

Trait describing public key types which can be converted to bitcoin pubkeys

+

Type Definitions

+
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

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.PolicyError.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.PolicyError.html new file mode 100644 index 0000000000..6f889566f7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.PolicyError.html @@ -0,0 +1,31 @@ +bdk::descriptor::policy::PolicyError - Rust

[][src]Enum bdk::descriptor::policy::PolicyError

pub enum PolicyError {
+    NotEnoughItemsSelected(String),
+    TooManyItemsSelected(String),
+    IndexOutOfRange(usize),
+    AddOnLeaf,
+    AddOnPartialComplete,
+    MixedTimelockUnits,
+    IncompatibleConditions,
+}

Errors that can happen while extracting and manipulating policies

+

+ Variants

+
NotEnoughItemsSelected(String)
TooManyItemsSelected(String)
IndexOutOfRange(usize)
AddOnLeaf
AddOnPartialComplete
MixedTimelockUnits
IncompatibleConditions

Trait Implementations

impl Debug for PolicyError[src]

impl Display for PolicyError[src]

impl Error for PolicyError[src]

impl From<PolicyError> for Error[src]

impl From<PolicyError> for Error[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.Satisfaction.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.Satisfaction.html new file mode 100644 index 0000000000..6ebd3a49a7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.Satisfaction.html @@ -0,0 +1,52 @@ +bdk::descriptor::policy::Satisfaction - Rust

[][src]Enum bdk::descriptor::policy::Satisfaction

pub enum Satisfaction {
+    Partial {
+        n: usize,
+        m: usize,
+        items: Vec<usize>,
+        conditions: ConditionMap,
+    },
+    PartialComplete {
+        n: usize,
+        m: usize,
+        items: Vec<usize>,
+        conditions: FoldedConditionMap,
+    },
+    Complete {
+        condition: Condition,
+    },
+    None,
+}

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

+

+ Variants

+
Partial

Only a partial satisfaction of some kind of threshold policy

+

Fields of Partial

n: usize

Total number of items

+
m: usize

Threshold

+
items: Vec<usize>

The items that can be satisfied by the descriptor

+
conditions: ConditionMap

Extra conditions that also need to be satisfied

+
PartialComplete

Can reach the threshold of some kind of threshold policy

+

Fields of PartialComplete

n: usize

Total number of items

+
m: usize

Threshold

+
items: Vec<usize>

The items that can be satisfied by the descriptor

+
conditions: FoldedConditionMap

Extra conditions that also need to be satisfied

+
Complete

Can satisfy the policy item

+

Fields of Complete

condition: Condition

Extra conditions that also need to be satisfied

+
None

Cannot satisfy or contribute to the policy item

+

Implementations

impl Satisfaction[src]

pub fn is_leaf(&self) -> bool[src]

Trait Implementations

impl Clone for Satisfaction[src]

impl Debug for Satisfaction[src]

impl From<bool> for Satisfaction[src]

impl Serialize for Satisfaction[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.SatisfiableItem.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.SatisfiableItem.html new file mode 100644 index 0000000000..a701a25eb3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.SatisfiableItem.html @@ -0,0 +1,51 @@ +bdk::descriptor::policy::SatisfiableItem - Rust

[][src]Enum bdk::descriptor::policy::SatisfiableItem

pub enum SatisfiableItem {
+    Signature(PKOrF),
+    SignatureKey(PKOrF),
+    SHA256Preimage {
+        hash: Hash,
+    },
+    HASH256Preimage {
+        hash: Hash,
+    },
+    RIPEMD160Preimage {
+        hash: Hash,
+    },
+    HASH160Preimage {
+        hash: Hash,
+    },
+    AbsoluteTimelock {
+        value: u32,
+    },
+    RelativeTimelock {
+        value: u32,
+    },
+    Thresh {
+        items: Vec<Policy>,
+        threshold: usize,
+    },
+    Multisig {
+        keys: Vec<PKOrF>,
+        threshold: usize,
+    },
+}

An item that need to be satisfied

+

+ Variants

+
Signature(PKOrF)
SignatureKey(PKOrF)
SHA256Preimage

Fields of SHA256Preimage

hash: Hash
HASH256Preimage

Fields of HASH256Preimage

hash: Hash
RIPEMD160Preimage

Fields of RIPEMD160Preimage

hash: Hash
HASH160Preimage

Fields of HASH160Preimage

hash: Hash
AbsoluteTimelock

Fields of AbsoluteTimelock

value: u32
RelativeTimelock

Fields of RelativeTimelock

value: u32
Thresh

Fields of Thresh

items: Vec<Policy>threshold: usize
Multisig

Fields of Multisig

keys: Vec<PKOrF>threshold: usize

Implementations

impl SatisfiableItem[src]

pub fn is_leaf(&self) -> bool[src]

pub fn id(&self) -> String[src]

Trait Implementations

impl Clone for SatisfiableItem[src]

impl Debug for SatisfiableItem[src]

impl From<SatisfiableItem> for Policy[src]

impl Serialize for SatisfiableItem[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/index.html new file mode 100644 index 0000000000..f494586dc6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/index.html @@ -0,0 +1,23 @@ +bdk::descriptor::policy - Rust

[][src]Module bdk::descriptor::policy

Descriptor policy

+

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

+

Example

+
+let desc = "wsh(and_v(v:pk(cV3oCth6zxZ1UVsHLnGothsWNsaoxRhC6aeNi5VbSdFpwUkgkEci),or_d(pk(cVMTy7uebJgvFaSBwcgvwk8qn8xSLc97dKow4MBetjrrahZoimm2),older(12960))))";
+
+let (extended_desc, key_map) = ExtendedDescriptor::parse_secret(desc)?;
+println!("{:?}", extended_desc);
+
+let signers = Arc::new(key_map.into());
+let policy = extended_desc.extract_policy(signers)?;
+println!("policy: {}", serde_json::to_string(&policy)?);
+

Structs

+
Condition

An extra condition that must be satisfied but that is out of control of the user

+
PKOrF

Raw public key or extended key fingerprint

+
Policy

Descriptor spending policy

+

Enums

+
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 need to be satisfied

+

Type Definitions

+
ConditionMap
FoldedConditionMap
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/sidebar-items.js new file mode 100644 index 0000000000..6928dca21e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["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 need to be satisfied"]],"struct":[["Condition","An extra condition that must be satisfied but that is out of control of the user"],["PKOrF","Raw public key or extended key fingerprint"],["Policy","Descriptor spending policy"]],"type":[["ConditionMap",""],["FoldedConditionMap",""]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Condition.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Condition.html new file mode 100644 index 0000000000..9d37306985 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Condition.html @@ -0,0 +1,38 @@ +bdk::descriptor::policy::Condition - Rust

[][src]Struct bdk::descriptor::policy::Condition

pub struct Condition {
+    pub csv: Option<u32>,
+    pub timelock: Option<u32>,
+}

An extra condition that must be satisfied but that is out of control of the user

+

+ Fields

csv: Option<u32>timelock: Option<u32>

Implementations

impl Condition[src]

pub fn is_null(&self) -> bool[src]

Trait Implementations

impl Clone for Condition[src]

impl Copy for Condition[src]

impl Debug for Condition[src]

impl Default for Condition[src]

impl Eq for Condition[src]

impl Hash for Condition[src]

impl Ord for Condition[src]

impl PartialEq<Condition> for Condition[src]

impl PartialOrd<Condition> for Condition[src]

impl Serialize for Condition[src]

impl StructuralEq for Condition[src]

impl StructuralPartialEq for Condition[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.PKOrF.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.PKOrF.html new file mode 100644 index 0000000000..49e3b43d94 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.PKOrF.html @@ -0,0 +1,20 @@ +bdk::descriptor::policy::PKOrF - Rust

[][src]Struct bdk::descriptor::policy::PKOrF

pub struct PKOrF { /* fields omitted */ }

Raw public key or extended key fingerprint

+

Trait Implementations

impl Clone for PKOrF[src]

impl Debug for PKOrF[src]

impl Default for PKOrF[src]

impl Serialize for PKOrF[src]

Auto Trait Implementations

impl RefUnwindSafe for PKOrF

impl Send for PKOrF

impl Sync for PKOrF

impl Unpin for PKOrF

impl UnwindSafe for PKOrF

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Policy.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Policy.html new file mode 100644 index 0000000000..b50b8d43da --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Policy.html @@ -0,0 +1,37 @@ +bdk::descriptor::policy::Policy - Rust

[][src]Struct bdk::descriptor::policy::Policy

pub struct Policy {
+    pub id: String,
+    pub item: SatisfiableItem,
+    pub satisfaction: Satisfaction,
+    pub contribution: Satisfaction,
+}

Descriptor spending policy

+

+ Fields

id: String

Identifier for this policy node

+
item: SatisfiableItem

Type of this policy node

+
satisfaction: Satisfaction

How a much given PSBT already satisfies this polcy node (currently unused)

+
contribution: Satisfaction

How the wallet's descriptor can satisfy this policy node

+

Implementations

impl Policy[src]

pub fn requires_path(&self) -> bool[src]

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 get_condition(
    &self,
    path: &BTreeMap<String, Vec<usize>>
) -> Result<Condition, PolicyError>
[src]

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

+

Trait Implementations

impl Clone for Policy[src]

impl Debug for Policy[src]

impl From<SatisfiableItem> for Policy[src]

impl Serialize for Policy[src]

Auto Trait Implementations

impl RefUnwindSafe for Policy

impl Send for Policy

impl Sync for Policy

impl Unpin for Policy

impl UnwindSafe for Policy

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.ConditionMap.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.ConditionMap.html new file mode 100644 index 0000000000..33b5632c7b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.ConditionMap.html @@ -0,0 +1 @@ +bdk::descriptor::policy::ConditionMap - Rust

[][src]Type Definition bdk::descriptor::policy::ConditionMap

type ConditionMap = BTreeMap<usize, HashSet<Condition>>;
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.FoldedConditionMap.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.FoldedConditionMap.html new file mode 100644 index 0000000000..ac1cee86e6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.FoldedConditionMap.html @@ -0,0 +1 @@ +bdk::descriptor::policy::FoldedConditionMap - Rust

[][src]Type Definition bdk::descriptor::policy::FoldedConditionMap

type FoldedConditionMap = BTreeMap<Vec<usize>, HashSet<Condition>>;
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/sidebar-items.js new file mode 100644 index 0000000000..8460b2d5c8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["Descriptor","Script descriptor"],["Legacy","Legacy ScriptContext"],["Segwitv0","Segwitv0 ScriptContext"],["Terminal","All AST elements"]],"mod":[["checksum","Descriptor checksum"],["error","Descriptor errors"],["policy","Descriptor policy"]],"struct":[["Miniscript","Top-level script AST type"]],"trait":[["ExtractPolicy","Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]"],["MiniscriptKey","Public key trait which can be converted to Hash type"],["ScriptContext",""],["ToPublicKey","Trait describing public key types which can be converted to bitcoin pubkeys"]],"type":[["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`]"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/struct.Miniscript.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/struct.Miniscript.html new file mode 100644 index 0000000000..ad08670aa5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/struct.Miniscript.html @@ -0,0 +1,97 @@ +bdk::descriptor::Miniscript - Rust

[]Struct bdk::descriptor::Miniscript

pub struct Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey
{ + pub node: Terminal<Pk, Ctx>, + pub ty: Type, + pub ext: ExtData, + // some fields omitted +}

Top-level script AST type

+

+ Fields

node: Terminal<Pk, Ctx>

A node in the Abstract Syntax Tree(

+
ty: Type

The correctness and malleability type information for the AST node

+
ext: ExtData

Additional information helpful for extra analysis.

+

Implementations

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn from_ast(t: Terminal<Pk, Ctx>) -> Result<Miniscript<Pk, Ctx>, Error>

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.

+

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn into_inner(self) -> Terminal<Pk, Ctx>

Extracts the AstElem representing the root of the miniscript

+

pub fn as_inner(&self) -> &Terminal<Pk, Ctx>

impl<Ctx> Miniscript<PublicKey, Ctx> where
    Ctx: ScriptContext

pub fn parse(script: &Script) -> Result<Miniscript<PublicKey, Ctx>, Error>

Attempt to parse a script into a Miniscript representation

+

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey + ToPublicKey

pub fn encode(&self) -> Script

Encode as a Bitcoin script

+

pub fn script_size(&self) -> usize

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.

+

pub fn max_satisfaction_witness_elements(&self) -> usize

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 misformed Miniscript objects which do +not correspond to semantically sane Scripts. (Such scripts should be +rejected at parse time. Any exceptions are bugs.)

+

pub fn max_satisfaction_size(&self, one_cost: usize) -> usize

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.

+

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

+

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn translate_pk<FPk, FPkh, Q, FuncError>(
    &self,
    translatefpk: &mut FPk,
    translatefpkh: &mut FPkh
) -> Result<Miniscript<Q, Ctx>, FuncError> where
    FPk: FnMut(&Pk) -> Result<Q, FuncError>,
    FPkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, FuncError>,
    Q: MiniscriptKey

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

+

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey + ToPublicKey

pub fn satisfy<S>(&self, satisfier: S) -> Option<Vec<Vec<u8>>> where
    S: Satisfier<Pk>, 

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

+

Trait Implementations

impl<Pk, Ctx> Clone for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext + Clone,
    Pk: MiniscriptKey + Clone

impl<Pk, Ctx> Debug for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Display for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Eq for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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

+

impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx>[src]

impl<Pk, Ctx> FromStr for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

type Err = Error

The associated error which can be returned from parsing.

+

impl<Pk, Ctx> FromTree for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

fn from_tree(top: &Tree) -> Result<Miniscript<Pk, Ctx>, Error>

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

+

impl<Pk, Ctx> Hash for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext + Hash,
    Pk: MiniscriptKey + Hash

impl<Pk, Ctx> Liftable<Pk> for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Ord for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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

+

impl<Pk, Ctx> PartialEq<Miniscript<Pk, Ctx>> for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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

+

impl<Pk, Ctx> PartialOrd<Miniscript<Pk, Ctx>> for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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

+

Auto Trait Implementations

impl<Pk, Ctx> RefUnwindSafe for Miniscript<Pk, Ctx> where
    Ctx: RefUnwindSafe,
    Pk: RefUnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe

impl<Pk, Ctx> Send for Miniscript<Pk, Ctx> where
    Ctx: Send + Sync,
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk, Ctx> Sync for Miniscript<Pk, Ctx> where
    Ctx: Send + Sync,
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync

impl<Pk, Ctx> Unpin for Miniscript<Pk, Ctx> where
    Ctx: Unpin,
    Pk: Unpin,
    <Pk as MiniscriptKey>::Hash: Unpin

impl<Pk, Ctx> UnwindSafe for Miniscript<Pk, Ctx> where
    Ctx: RefUnwindSafe + UnwindSafe,
    Pk: RefUnwindSafe + UnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ExtractPolicy.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ExtractPolicy.html new file mode 100644 index 0000000000..522bac569e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ExtractPolicy.html @@ -0,0 +1,6 @@ +bdk::descriptor::ExtractPolicy - Rust

[][src]Trait bdk::descriptor::ExtractPolicy

pub trait ExtractPolicy {
+    fn extract_policy(
        &self,
        signers: Arc<SignersContainer<DescriptorPublicKey>>
    ) -> Result<Option<Policy>, Error>; +}

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

+
+

Required methods

fn extract_policy(
    &self,
    signers: Arc<SignersContainer<DescriptorPublicKey>>
) -> Result<Option<Policy>, Error>

Loading content... +

Implementors

impl ExtractPolicy for Descriptor<DescriptorPublicKey>[src]

impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx>[src]

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.MiniscriptKey.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.MiniscriptKey.html new file mode 100644 index 0000000000..5fedd105d6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.MiniscriptKey.html @@ -0,0 +1,18 @@ +bdk::descriptor::MiniscriptKey - Rust

[]Trait bdk::descriptor::MiniscriptKey

pub trait MiniscriptKey: Clone + Eq + Ord + Debug + Display + Hash + FromStr {
+    type Hash: Clone + Eq + Ord + Debug + Display + Hash + FromStr;
+    fn to_pubkeyhash(&self) -> Self::Hash;
+
+    fn is_uncompressed(&self) -> bool { ... }
+}

Public key trait which can be converted to Hash type

+
+

Associated Types

type Hash: Clone + Eq + Ord + Debug + Display + Hash + FromStr

The associated Hash type with the publicKey

+
Loading content... +

Required methods

fn to_pubkeyhash(&self) -> Self::Hash

Converts an object to PublicHash

+
Loading content... +

Provided methods

fn is_uncompressed(&self) -> bool

Check if the publicKey is uncompressed. The default +implementation returns false

+
Loading content... +

Implementations on Foreign Types

impl MiniscriptKey for PublicKey

fn is_uncompressed(&self) -> bool

is_uncompressed returns true only for +bitcoin::Publickey type if the underlying key is uncompressed.

+

type Hash = Hash

impl MiniscriptKey for DummyKey

type Hash = DummyKeyHash

impl MiniscriptKey for DescriptorPublicKey

type Hash = Hash

impl MiniscriptKey for String

Loading content... +

Implementors

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ScriptContext.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ScriptContext.html new file mode 100644 index 0000000000..9c6bcf905b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ScriptContext.html @@ -0,0 +1,19 @@ +bdk::descriptor::ScriptContext - Rust

[]Trait bdk::descriptor::ScriptContext

pub trait ScriptContext: Sealed + Clone + PartialEq<Self> + Eq + Ord + PartialOrd<Self> + Debug {
+    fn check_frag_non_malleable<Pk, Ctx>(
        _frag: &Terminal<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
; +
fn check_frag_validity<Pk, Ctx>(
        _frag: &Terminal<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
; +}
+

Required methods

fn check_frag_non_malleable<Pk, Ctx>(
    _frag: &Terminal<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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.

+

fn check_frag_validity<Pk, Ctx>(
    _frag: &Terminal<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Depending on script Context, some of the Terminals might not be valid. +For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey +uncompressed public keys are non-standard and thus invalid. +Post Tapscript upgrade, this would have to consider other nodes. +This does not recursively check

+
Loading content... +

Implementors

impl ScriptContext for Legacy

impl ScriptContext for Segwitv0

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ToPublicKey.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ToPublicKey.html new file mode 100644 index 0000000000..a68f8be8e4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ToPublicKey.html @@ -0,0 +1,19 @@ +bdk::descriptor::ToPublicKey - Rust

[]Trait bdk::descriptor::ToPublicKey

pub trait ToPublicKey: MiniscriptKey {
+    fn to_public_key(&self) -> PublicKey;
+
fn hash_to_hash160(hash: &Self::Hash) -> Hash; + + fn serialized_len(&self) -> usize { ... } +}

Trait describing public key types which can be converted to bitcoin pubkeys

+
+

Required methods

fn to_public_key(&self) -> PublicKey

Converts an object to a public key

+

fn hash_to_hash160(hash: &Self::Hash) -> Hash

Converts a hashed version of the public key to a hash160 hash.

+

This method must be consistent with to_public_key, in the sense +that calling MiniscriptKey::to_pubkeyhash followed by this function +should give the same result as calling to_public_key and hashing +the result directly.

+
Loading content... +

Provided methods

fn serialized_len(&self) -> usize

Computes the size of a public key when serialized in a script, +including the length bytes

+
Loading content... +

Implementations on Foreign Types

impl ToPublicKey for DummyKey

impl ToPublicKey for DescriptorPublicKey

impl ToPublicKey for PublicKey

Loading content... +

Implementors

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.ExtendedDescriptor.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.ExtendedDescriptor.html new file mode 100644 index 0000000000..6cac36a187 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.ExtendedDescriptor.html @@ -0,0 +1,2 @@ +bdk::descriptor::ExtendedDescriptor - Rust

[][src]Type Definition bdk::descriptor::ExtendedDescriptor

type ExtendedDescriptor = Descriptor<DescriptorPublicKey>;

Alias for a Descriptor that can contain extended keys using [DescriptorPublicKey]

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.HDKeyPaths.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.HDKeyPaths.html new file mode 100644 index 0000000000..93e0240143 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.HDKeyPaths.html @@ -0,0 +1,3 @@ +bdk::descriptor::HDKeyPaths - Rust

[][src]Type Definition bdk::descriptor::HDKeyPaths

type HDKeyPaths = BTreeMap<PublicKey, (Fingerprint, DerivationPath)>;

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/0.1.0-beta.1/bdk/enum.Error.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/enum.Error.html new file mode 100644 index 0000000000..7a1673fb2e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/enum.Error.html @@ -0,0 +1,80 @@ +bdk::Error - Rust

[][src]Enum bdk::Error

pub enum Error {
+    KeyMismatch(PublicKey, PublicKey),
+    MissingInputUTXO(usize),
+    InvalidU32Bytes(Vec<u8>),
+    Generic(String),
+    ScriptDoesntHaveAddressForm,
+    SendAllMultipleOutputs,
+    NoAddressees,
+    OutputBelowDustLimit(usize),
+    InsufficientFunds,
+    InvalidAddressNetwork(Address),
+    UnknownUTXO,
+    DifferentTransactions,
+    TransactionNotFound,
+    TransactionConfirmed,
+    IrreplaceableTransaction,
+    FeeRateTooLow {
+        required: FeeRate,
+    },
+    ChecksumMismatch,
+    DifferentDescriptorStructure,
+    SpendingPolicyRequired,
+    InvalidPolicyPathError(PolicyError),
+    Signer(SignerError),
+    Uncapable(Capability),
+    OfflineClient,
+    InvalidProgressValue(f32),
+    ProgressUpdateError,
+    MissingCachedAddresses,
+    InvalidOutpoint(OutPoint),
+    Descriptor(Error),
+    AddressValidator(AddressValidatorError),
+    Encode(Error),
+    Miniscript(Error),
+    BIP32(Error),
+    Secp256k1(Error),
+    JSON(Error),
+    Hex(Error),
+    PSBT(Error),
+    Electrum(Error),
+    Esplora(EsploraError),
+    CompactFilters(CompactFiltersError),
+    Sled(Error),
+}

Errors that can be thrown by the Wallet

+

+ Variants

+
KeyMismatch(PublicKey, PublicKey)
MissingInputUTXO(usize)
InvalidU32Bytes(Vec<u8>)
Generic(String)
ScriptDoesntHaveAddressForm
SendAllMultipleOutputs
NoAddressees
OutputBelowDustLimit(usize)
InsufficientFunds
InvalidAddressNetwork(Address)
UnknownUTXO
DifferentTransactions
TransactionNotFound
TransactionConfirmed
IrreplaceableTransaction
FeeRateTooLow

Fields of FeeRateTooLow

required: FeeRate
ChecksumMismatch
DifferentDescriptorStructure
SpendingPolicyRequired
InvalidPolicyPathError(PolicyError)
Signer(SignerError)
Uncapable(Capability)
OfflineClient
InvalidProgressValue(f32)
ProgressUpdateError
MissingCachedAddresses
InvalidOutpoint(OutPoint)
Descriptor(Error)
AddressValidator(AddressValidatorError)
Encode(Error)
Miniscript(Error)
BIP32(Error)
Secp256k1(Error)
JSON(Error)
Hex(Error)
PSBT(Error)
Electrum(Error)
Esplora(EsploraError)
CompactFilters(CompactFiltersError)
Sled(Error)

Trait Implementations

impl Debug for Error[src]

impl Display for Error[src]

impl Error for Error[src]

impl From<AddressValidatorError> for Error[src]

impl From<CompactFiltersError> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for CompactFiltersError[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<EsploraError> for Error[src]

impl From<PolicyError> for Error[src]

impl From<SignerError> for Error[src]

Auto Trait Implementations

impl !RefUnwindSafe for Error

impl Send for Error

impl Sync for Error

impl Unpin for Error

impl !UnwindSafe for Error

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/enum.ScriptType.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/enum.ScriptType.html new file mode 100644 index 0000000000..d9a631eb91 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/enum.ScriptType.html @@ -0,0 +1,36 @@ +bdk::ScriptType - Rust

[][src]Enum bdk::ScriptType

pub enum ScriptType {
+    External,
+    Internal,
+}

Types of script

+

+ Variants

+
External
Internal

Implementations

impl ScriptType[src]

pub fn as_byte(&self) -> u8[src]

pub fn is_internal(&self) -> bool[src]

Trait Implementations

impl AsRef<[u8]> for ScriptType[src]

impl Clone for ScriptType[src]

impl Copy for ScriptType[src]

impl Debug for ScriptType[src]

impl<'de> Deserialize<'de> for ScriptType[src]

impl Eq for ScriptType[src]

impl Hash for ScriptType[src]

impl PartialEq<ScriptType> for ScriptType[src]

impl Serialize for ScriptType[src]

impl StructuralEq for ScriptType[src]

impl StructuralPartialEq for ScriptType[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Base32Len for T where
    T: AsRef<[u8]>, 

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<'f, T> CheckBase32<Vec<u5>> for T where
    T: AsRef<[u8]>, 

type Err = Error

Error type if conversion fails

+

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToBase32 for T where
    T: AsRef<[u8]>, 

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/error/enum.Error.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/error/enum.Error.html new file mode 100644 index 0000000000..113a951037 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/error/enum.Error.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../bdk/enum.Error.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/index.html new file mode 100644 index 0000000000..99f31df86c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/index.html @@ -0,0 +1,14 @@ +bdk - Rust

[][src]Crate bdk

Re-exports

+
pub extern crate bitcoin;
pub extern crate miniscript;
pub extern crate electrum_client;
pub extern crate reqwest;
pub extern crate sled;
pub use descriptor::HDKeyPaths;
pub use wallet::address_validator;
pub use wallet::signer;
pub use wallet::tx_builder::TxBuilder;
pub use wallet::OfflineWallet;
pub use wallet::Wallet;

Modules

+
blockchain

Blockchain backends

+
database

Database types

+
descriptor

Descriptors

+
wallet

Wallet

+

Structs

+
FeeRate

Fee rate

+
TransactionDetails

A wallet transaction

+
UTXO

A wallet unspent output

+

Enums

+
Error

Errors that can be thrown by the Wallet

+
ScriptType

Types of script

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/sidebar-items.js new file mode 100644 index 0000000000..9e94a707e4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["Error","Errors that can be thrown by the `Wallet`"],["ScriptType","Types of script"]],"mod":[["blockchain","Blockchain backends"],["database","Database types"],["descriptor","Descriptors"],["wallet","Wallet"]],"struct":[["FeeRate","Fee rate"],["TransactionDetails","A wallet transaction"],["UTXO","A wallet unspent output"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/struct.FeeRate.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/struct.FeeRate.html new file mode 100644 index 0000000000..b7a709594a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/struct.FeeRate.html @@ -0,0 +1,30 @@ +bdk::FeeRate - Rust

[][src]Struct bdk::FeeRate

pub struct FeeRate(_);

Fee rate

+

Implementations

impl FeeRate[src]

pub fn from_btc_per_kvb(btc_per_kvb: f32) -> Self[src]

Create a new instance of FeeRate given a float fee rate in btc/kvbytes

+

pub fn from_sat_per_vb(sat_per_vb: f32) -> Self[src]

Create a new instance of FeeRate given a float fee rate in satoshi/vbyte

+

pub fn default_min_relay_fee() -> Self[src]

Create a new FeeRate with the default min relay fee value

+

pub fn as_sat_vb(&self) -> f32[src]

Return the value as satoshi/vbyte

+

Trait Implementations

impl Clone for FeeRate[src]

impl Copy for FeeRate[src]

impl Debug for FeeRate[src]

impl Default for FeeRate[src]

impl PartialEq<FeeRate> for FeeRate[src]

impl PartialOrd<FeeRate> for FeeRate[src]

impl StructuralPartialEq for FeeRate[src]

Auto Trait Implementations

impl RefUnwindSafe for FeeRate

impl Send for FeeRate

impl Sync for FeeRate

impl Unpin for FeeRate

impl UnwindSafe for FeeRate

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/struct.TransactionDetails.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/struct.TransactionDetails.html new file mode 100644 index 0000000000..1aa1b86e06 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/struct.TransactionDetails.html @@ -0,0 +1,33 @@ +bdk::TransactionDetails - Rust

[][src]Struct bdk::TransactionDetails

pub struct TransactionDetails {
+    pub transaction: Option<Transaction>,
+    pub txid: Txid,
+    pub timestamp: u64,
+    pub received: u64,
+    pub sent: u64,
+    pub fees: u64,
+    pub height: Option<u32>,
+}

A wallet transaction

+

+ Fields

transaction: Option<Transaction>txid: Txidtimestamp: u64received: u64sent: u64fees: u64height: Option<u32>

Trait Implementations

impl Clone for TransactionDetails[src]

impl Debug for TransactionDetails[src]

impl Default for TransactionDetails[src]

impl<'de> Deserialize<'de> for TransactionDetails[src]

impl Eq for TransactionDetails[src]

impl PartialEq<TransactionDetails> for TransactionDetails[src]

impl Serialize for TransactionDetails[src]

impl StructuralEq for TransactionDetails[src]

impl StructuralPartialEq for TransactionDetails[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/struct.UTXO.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/struct.UTXO.html new file mode 100644 index 0000000000..3032d4e7b5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/struct.UTXO.html @@ -0,0 +1,28 @@ +bdk::UTXO - Rust

[][src]Struct bdk::UTXO

pub struct UTXO {
+    pub outpoint: OutPoint,
+    pub txout: TxOut,
+    pub is_internal: bool,
+}

A wallet unspent output

+

+ Fields

outpoint: OutPointtxout: TxOutis_internal: bool

Trait Implementations

impl Clone for UTXO[src]

impl Debug for UTXO[src]

impl<'de> Deserialize<'de> for UTXO[src]

impl Eq for UTXO[src]

impl PartialEq<UTXO> for UTXO[src]

impl Serialize for UTXO[src]

impl StructuralEq for UTXO[src]

impl StructuralPartialEq for UTXO[src]

Auto Trait Implementations

impl RefUnwindSafe for UTXO

impl Send for UTXO

impl Sync for UTXO

impl Unpin for UTXO

impl UnwindSafe for UTXO

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/types/enum.ScriptType.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/types/enum.ScriptType.html new file mode 100644 index 0000000000..b10e9a3fe6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/types/enum.ScriptType.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../bdk/enum.ScriptType.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.FeeRate.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.FeeRate.html new file mode 100644 index 0000000000..c8b0ec4f98 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.FeeRate.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../bdk/struct.FeeRate.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.TransactionDetails.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.TransactionDetails.html new file mode 100644 index 0000000000..5db5e06868 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.TransactionDetails.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../bdk/struct.TransactionDetails.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.UTXO.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.UTXO.html new file mode 100644 index 0000000000..1517bb40f5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.UTXO.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../bdk/struct.UTXO.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/enum.AddressValidatorError.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/enum.AddressValidatorError.html new file mode 100644 index 0000000000..bed4a97a0e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/enum.AddressValidatorError.html @@ -0,0 +1,37 @@ +bdk::wallet::address_validator::AddressValidatorError - Rust

[][src]Enum bdk::wallet::address_validator::AddressValidatorError

pub enum AddressValidatorError {
+    UserRejected,
+    ConnectionError,
+    TimeoutError,
+    InvalidScript,
+    Message(String),
+}

Errors that can be returned to fail the validation of an address

+

+ Variants

+
UserRejected
ConnectionError
TimeoutError
InvalidScript
Message(String)

Trait Implementations

impl Clone for AddressValidatorError[src]

impl Debug for AddressValidatorError[src]

impl Display for AddressValidatorError[src]

impl Eq for AddressValidatorError[src]

impl Error for AddressValidatorError[src]

impl From<AddressValidatorError> for Error[src]

impl PartialEq<AddressValidatorError> for AddressValidatorError[src]

impl StructuralEq for AddressValidatorError[src]

impl StructuralPartialEq for AddressValidatorError[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/index.html new file mode 100644 index 0000000000..30b19c6bc3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/index.html @@ -0,0 +1,44 @@ +bdk::wallet::address_validator - Rust

[][src]Module bdk::wallet::address_validator

Address validation callbacks

+

The typical usage of those callbacks is for displaying the newly-generated address on a +hardware wallet, so that the user can cross-check its correctness.

+

More generally speaking though, these callbacks can also be used to "do something" every time +an address is generated, without necessarily checking or validating it.

+

An address validator can be attached to a Wallet by using the +Wallet::add_address_validator method, and +whenever a new address is generated (either explicitly by the user with +Wallet::get_new_address or internally to create a change +address) all the attached validators will be polled, in sequence. All of them must complete +successfully to continue.

+

Example

+
+struct PrintAddressAndContinue;
+
+impl AddressValidator for PrintAddressAndContinue {
+    fn validate(
+        &self,
+        script_type: ScriptType,
+        hd_keypaths: &HDKeyPaths,
+        script: &Script
+    ) -> Result<(), AddressValidatorError> {
+        let address = Address::from_script(script, Network::Testnet)
+            .as_ref()
+            .map(Address::to_string)
+            .unwrap_or(script.to_string());
+        println!("New address of type {:?}: {}", script_type, address);
+        println!("HD keypaths: {:#?}", hd_keypaths);
+
+        Ok(())
+    }
+}
+
+let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+wallet.add_address_validator(Arc::new(Box::new(PrintAddressAndContinue)));
+
+let address = wallet.get_new_address()?;
+println!("Address: {}", address);
+

Enums

+
AddressValidatorError

Errors that can be returned to fail the validation of an address

+

Traits

+
AddressValidator

Trait to build address validators

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/sidebar-items.js new file mode 100644 index 0000000000..58959ba340 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["AddressValidatorError","Errors that can be returned to fail the validation of an address"]],"trait":[["AddressValidator","Trait to build address validators"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/trait.AddressValidator.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/trait.AddressValidator.html new file mode 100644 index 0000000000..8c46006675 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/trait.AddressValidator.html @@ -0,0 +1,11 @@ +bdk::wallet::address_validator::AddressValidator - Rust

[][src]Trait bdk::wallet::address_validator::AddressValidator

pub trait AddressValidator {
+    fn validate(
        &self,
        script_type: ScriptType,
        hd_keypaths: &HDKeyPaths,
        script: &Script
    ) -> Result<(), AddressValidatorError>; +}

Trait to build address validators

+

All the address validators attached to a wallet with Wallet::add_address_validator will be polled +every time an address (external or internal) is generated by the wallet. Errors returned in the +validator will be propagated up to the original caller that triggered the address generation.

+

For a usage example see this module's documentation.

+
+

Required methods

fn validate(
    &self,
    script_type: ScriptType,
    hd_keypaths: &HDKeyPaths,
    script: &Script
) -> Result<(), AddressValidatorError>

Validate or inspect an address

+
Loading content... +

Implementors

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/index.html new file mode 100644 index 0000000000..3f56b8d644 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/index.html @@ -0,0 +1,73 @@ +bdk::wallet::coin_selection - Rust

[][src]Module bdk::wallet::coin_selection

Coin selection

+

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

+

The coin selection algorithm is not globally part of a Wallet, instead it +is selected whenever a Wallet::create_tx call is made, through +the use of the TxBuilder structure, specifically with +TxBuilder::coin_selection method.

+

The DefaultCoinSelectionAlgorithm selects the default coin selection algorithm that +TxBuilder uses, if it's not explicitly overridden.

+

Example

+
+#[derive(Debug)]
+struct AlwaysSpendEverything;
+
+impl CoinSelectionAlgorithm for AlwaysSpendEverything {
+    fn coin_select(
+        &self,
+        utxos: Vec<UTXO>,
+        _use_all_utxos: bool,
+        fee_rate: FeeRate,
+        amount_needed: u64,
+        input_witness_weight: usize,
+        fee_amount: f32,
+    ) -> Result<CoinSelectionResult, bdk::Error> {
+        let selected_amount = utxos.iter().fold(0, |acc, utxo| acc + utxo.txout.value);
+        let all_utxos_selected = utxos
+            .into_iter()
+            .map(|utxo| {
+                (
+                    TxIn {
+                        previous_output: utxo.outpoint,
+                        ..Default::default()
+                    },
+                    utxo.txout.script_pubkey,
+                )
+            })
+            .collect::<Vec<_>>();
+        let additional_weight = all_utxos_selected.iter().fold(0, |acc, (txin, _)| {
+            acc + serialize(txin).len() * 4 + input_witness_weight
+        });
+        let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0;
+
+        if (fee_amount + additional_fees).ceil() as u64 + amount_needed > selected_amount {
+            return Err(bdk::Error::InsufficientFunds);
+        }
+
+        Ok(CoinSelectionResult {
+            txin: all_utxos_selected,
+            selected_amount,
+            fee_amount: fee_amount + additional_fees,
+        })
+    }
+}
+
+// create wallet, sync, ...
+
+let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+let (psbt, details) = wallet.create_tx(
+    TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+        .coin_selection(AlwaysSpendEverything),
+)?;
+
+// inspect, sign, broadcast, ...
+
+

Structs

+
CoinSelectionResult

Result of a successful coin selection

+
DumbCoinSelection

Simple and dumb coin selection

+

Traits

+
CoinSelectionAlgorithm

Trait for generalized coin selection algorithms

+

Type Definitions

+
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/0.1.0-beta.1/bdk/wallet/coin_selection/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/sidebar-items.js new file mode 100644 index 0000000000..d124fee721 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["CoinSelectionResult","Result of a successful coin selection"],["DumbCoinSelection","Simple and dumb coin selection"]],"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/0.1.0-beta.1/bdk/wallet/coin_selection/struct.CoinSelectionResult.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.CoinSelectionResult.html new file mode 100644 index 0000000000..45549badf6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.CoinSelectionResult.html @@ -0,0 +1,20 @@ +bdk::wallet::coin_selection::CoinSelectionResult - Rust

[][src]Struct bdk::wallet::coin_selection::CoinSelectionResult

pub struct CoinSelectionResult {
+    pub txin: Vec<(TxIn, Script)>,
+    pub selected_amount: u64,
+    pub fee_amount: f32,
+}

Result of a successful coin selection

+

+ Fields

txin: Vec<(TxIn, Script)>

List of inputs to use, with the respective previous script_pubkey

+
selected_amount: u64

Sum of the selected inputs' value

+
fee_amount: f32

Total fee amount in satoshi

+

Trait Implementations

impl Debug for CoinSelectionResult[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.DumbCoinSelection.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.DumbCoinSelection.html new file mode 100644 index 0000000000..a49bbca57f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.DumbCoinSelection.html @@ -0,0 +1,16 @@ +bdk::wallet::coin_selection::DumbCoinSelection - Rust

[][src]Struct bdk::wallet::coin_selection::DumbCoinSelection

pub struct DumbCoinSelection;

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

impl CoinSelectionAlgorithm for DumbCoinSelection[src]

impl Debug for DumbCoinSelection[src]

impl Default for DumbCoinSelection[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html new file mode 100644 index 0000000000..704db49dbf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html @@ -0,0 +1,18 @@ +bdk::wallet::coin_selection::CoinSelectionAlgorithm - Rust

[][src]Trait bdk::wallet::coin_selection::CoinSelectionAlgorithm

pub trait CoinSelectionAlgorithm: Debug {
+    fn coin_select(
        &self,
        utxos: Vec<UTXO>,
        use_all_utxos: bool,
        fee_rate: FeeRate,
        amount_needed: u64,
        input_witness_weight: usize,
        fee_amount: f32
    ) -> Result<CoinSelectionResult, Error>; +}

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

fn coin_select(
    &self,
    utxos: Vec<UTXO>,
    use_all_utxos: bool,
    fee_rate: FeeRate,
    amount_needed: u64,
    input_witness_weight: usize,
    fee_amount: f32
) -> Result<CoinSelectionResult, Error>

Perform the coin selection

+
    +
  • utxos: the list of spendable UTXOs
  • +
  • use_all_utxos: if true all utxos should be spent unconditionally
  • +
  • fee_rate: fee rate to use
  • +
  • amount_needed: the amount in satoshi to select
  • +
  • input_witness_weight: the weight of an input's witness to keep into account for the fees
  • +
  • fee_amount: the amount of fees in satoshi already accumulated from adding outputs
  • +
+
Loading content... +

Implementors

impl CoinSelectionAlgorithm for DumbCoinSelection[src]

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html new file mode 100644 index 0000000000..b1a07047c3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html @@ -0,0 +1,3 @@ +bdk::wallet::coin_selection::DefaultCoinSelectionAlgorithm - Rust

[][src]Type Definition bdk::wallet::coin_selection::DefaultCoinSelectionAlgorithm

type DefaultCoinSelectionAlgorithm = DumbCoinSelection;

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/0.1.0-beta.1/bdk/wallet/export/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/index.html new file mode 100644 index 0000000000..7bd0bc5222 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/index.html @@ -0,0 +1,28 @@ +bdk::wallet::export - Rust

[][src]Module bdk::wallet::export

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 = WalletExport::from_str(import)?;
+let wallet: OfflineWallet<_> = Wallet::new_offline(&import.descriptor(), import.change_descriptor().as_deref(), Network::Testnet, MemoryDatabase::default())?;
+

Export a Wallet

+
+let wallet: OfflineWallet<_> = Wallet::new_offline(
+    "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
+    Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
+    Network::Testnet,
+    MemoryDatabase::default()
+)?;
+let export = WalletExport::export_wallet(&wallet, "exported wallet", true)
+    .map_err(ToString::to_string)
+    .map_err(bdk::Error::Generic)?;
+
+println!("Exported: {}", export.to_string());
+

Structs

+
WalletExport

Structure that contains the export of a wallet

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/sidebar-items.js new file mode 100644 index 0000000000..06abb3c4ee --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["WalletExport","Structure that contains the export of a wallet"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/struct.WalletExport.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/struct.WalletExport.html new file mode 100644 index 0000000000..3e5d692275 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/struct.WalletExport.html @@ -0,0 +1,36 @@ +bdk::wallet::export::WalletExport - Rust

[][src]Struct bdk::wallet::export::WalletExport

pub struct WalletExport {
+    pub blockheight: u32,
+    pub label: String,
+    // some fields omitted
+}

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

impl WalletExport[src]

pub fn export_wallet<B: BlockchainMarker, D: BatchDatabase>(
    wallet: &Wallet<B, D>,
    label: &str,
    include_blockheight: bool
) -> Result<Self, &'static str>
[src]

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 descriptor(&self) -> String[src]

Return the external descriptor

+

pub fn change_descriptor(&self) -> Option<String>[src]

Return the internal descriptor, if present

+

Trait Implementations

impl Debug for WalletExport[src]

impl<'de> Deserialize<'de> for WalletExport[src]

impl FromStr for WalletExport[src]

type Err = Error

The associated error which can be returned from parsing.

+

impl Serialize for WalletExport[src]

impl ToString for WalletExport[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/index.html new file mode 100644 index 0000000000..bf698476e6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/index.html @@ -0,0 +1,16 @@ +bdk::wallet - Rust

[][src]Module bdk::wallet

Wallet

+

This module defines the Wallet structure.

+

Modules

+
address_validator

Address validation callbacks

+
coin_selection

Coin selection

+
export

Wallet export

+
signer

Generalized signers

+
time

Cross-platform time

+
tx_builder

Transaction builder

+

Structs

+
Wallet

A Bitcoin wallet

+

Traits

+
IsDust

Trait to check if a value is below the dust limit

+

Type Definitions

+
OfflineWallet

Type alias for a Wallet that uses OfflineBlockchain

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/sidebar-items.js new file mode 100644 index 0000000000..811ec3c2b5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"mod":[["address_validator","Address validation callbacks"],["coin_selection","Coin selection"],["export","Wallet export"],["signer","Generalized signers"],["time","Cross-platform time"],["tx_builder","Transaction builder"]],"struct":[["Wallet","A Bitcoin wallet"]],"trait":[["IsDust","Trait to check if a value is below the dust limit"]],"type":[["OfflineWallet","Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerError.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerError.html new file mode 100644 index 0000000000..efbc4c0b8b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerError.html @@ -0,0 +1,50 @@ +bdk::wallet::signer::SignerError - Rust

[][src]Enum bdk::wallet::signer::SignerError

pub enum SignerError {
+    MissingKey,
+    UserCanceled,
+    MissingSighash,
+    InputIndexOutOfRange,
+    MissingNonWitnessUtxo,
+    InvalidNonWitnessUtxo,
+    MissingWitnessUtxo,
+    MissingWitnessScript,
+    MissingHDKeypath,
+}

Signing error

+

+ Variants

+
MissingKey

The private key is missing for the required public key

+
UserCanceled

The user canceled the operation

+
MissingSighash

The sighash is missing in the PSBT input

+
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 requied to sign this input

+
MissingHDKeypath

The fingerprint and derivation path are missing from the psbt input

+

Trait Implementations

impl Clone for SignerError[src]

impl Debug for SignerError[src]

impl Display for SignerError[src]

impl Eq for SignerError[src]

impl Error for SignerError[src]

impl From<SignerError> for Error[src]

impl PartialEq<SignerError> for SignerError[src]

impl StructuralEq for SignerError[src]

impl StructuralPartialEq for SignerError[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerId.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerId.html new file mode 100644 index 0000000000..299e47f7b9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerId.html @@ -0,0 +1,31 @@ +bdk::wallet::signer::SignerId - Rust

[][src]Enum bdk::wallet::signer::SignerId

pub enum SignerId<Pk: MiniscriptKey> {
+    PkHash(<Pk as MiniscriptKey>::Hash),
+    Fingerprint(Fingerprint),
+}

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

+

+ Variants

+
PkHash(<Pk as MiniscriptKey>::Hash)
Fingerprint(Fingerprint)

Trait Implementations

impl<Pk: Clone + MiniscriptKey> Clone for SignerId<Pk>[src]

impl<Pk: Debug + MiniscriptKey> Debug for SignerId<Pk>[src]

impl<Pk: Eq + MiniscriptKey> Eq for SignerId<Pk>[src]

impl From<Fingerprint> for SignerId<DescriptorPublicKey>[src]

impl From<Hash> for SignerId<DescriptorPublicKey>[src]

impl<Pk: Hash + MiniscriptKey> Hash for SignerId<Pk>[src]

impl<Pk: PartialEq + MiniscriptKey> PartialEq<SignerId<Pk>> for SignerId<Pk>[src]

impl<Pk: MiniscriptKey> StructuralEq for SignerId<Pk>[src]

impl<Pk: MiniscriptKey> StructuralPartialEq for SignerId<Pk>[src]

Auto Trait Implementations

impl<Pk> RefUnwindSafe for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe

impl<Pk> Send for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Send

impl<Pk> Sync for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Sync

impl<Pk> Unpin for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Unpin

impl<Pk> UnwindSafe for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/index.html new file mode 100644 index 0000000000..6c88b63163 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/index.html @@ -0,0 +1,54 @@ +bdk::wallet::signer - Rust

[][src]Module bdk::wallet::signer

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 Signer for CustomSigner {
+    fn sign(
+        &self,
+        psbt: &mut psbt::PartiallySignedTransaction,
+        input_index: Option<usize>,
+    ) -> Result<(), SignerError> {
+        let input_index = input_index.ok_or(SignerError::InputIndexOutOfRange)?;
+        self.device.sign_input(psbt, input_index)?;
+
+        Ok(())
+    }
+
+    fn sign_whole_tx(&self) -> bool {
+        false
+    }
+}
+
+let custom_signer = CustomSigner::connect();
+
+let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+wallet.add_signer(
+    ScriptType::External,
+    Fingerprint::from_str("e30f11b8").unwrap().into(),
+    SignerOrdering(200),
+    Arc::new(Box::new(custom_signer))
+);
+
+

Structs

+
SignerOrdering

Defines the order in which signers are called

+
SignersContainer

Container for multiple signers

+

Enums

+
SignerError

Signing error

+
SignerId

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

+

Traits

+
Signer

Trait for signers

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/sidebar-items.js new file mode 100644 index 0000000000..8f3e3d79b6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["SignerError","Signing error"],["SignerId","Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among multiple of them"]],"struct":[["SignerOrdering","Defines the order in which signers are called"],["SignersContainer","Container for multiple signers"]],"trait":[["Signer","Trait for signers"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignerOrdering.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignerOrdering.html new file mode 100644 index 0000000000..1813c89d08 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignerOrdering.html @@ -0,0 +1,34 @@ +bdk::wallet::signer::SignerOrdering - Rust

[][src]Struct bdk::wallet::signer::SignerOrdering

pub struct SignerOrdering(pub usize);

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.

+

Trait Implementations

impl Clone for SignerOrdering[src]

impl Debug for SignerOrdering[src]

impl Default for SignerOrdering[src]

impl Eq for SignerOrdering[src]

impl Ord for SignerOrdering[src]

impl PartialEq<SignerOrdering> for SignerOrdering[src]

impl PartialOrd<SignerOrdering> for SignerOrdering[src]

impl StructuralEq for SignerOrdering[src]

impl StructuralPartialEq for SignerOrdering[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignersContainer.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignersContainer.html new file mode 100644 index 0000000000..014f8c419a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignersContainer.html @@ -0,0 +1,27 @@ +bdk::wallet::signer::SignersContainer - Rust

[][src]Struct bdk::wallet::signer::SignersContainer

pub struct SignersContainer<Pk: MiniscriptKey>(_);

Container for multiple signers

+

Implementations

impl SignersContainer<DescriptorPublicKey>[src]

pub fn as_key_map(&self) -> KeyMap[src]

impl<Pk: MiniscriptKey> SignersContainer<Pk>[src]

pub fn new() -> Self[src]

Default constructor

+

pub fn add_external(
    &mut self,
    id: SignerId<Pk>,
    ordering: SignerOrdering,
    signer: Arc<Box<dyn Signer>>
) -> Option<Arc<Box<dyn Signer>>>
[src]

Adds an external signer to the container for the specified id. Optionally returns the +signer that was previosuly in the container, if any

+

pub fn remove(
    &mut self,
    id: SignerId<Pk>,
    ordering: SignerOrdering
) -> Option<Arc<Box<dyn Signer>>>
[src]

Removes a signer from the container and returns it

+

pub fn ids(&self) -> Vec<&SignerId<Pk>>[src]

Returns the list of identifiers of all the signers in the container

+

pub fn signers(&self) -> Vec<&Arc<Box<dyn Signer>>>[src]

Returns the list of signers in the container, sorted by lowest to highest ordering

+

pub fn find(&self, id: SignerId<Pk>) -> Option<&Arc<Box<dyn Signer>>>[src]

Finds the signer with lowest ordering for a given id in the container.

+

Trait Implementations

impl<Pk: Clone + MiniscriptKey> Clone for SignersContainer<Pk>[src]

impl<Pk: Debug + MiniscriptKey> Debug for SignersContainer<Pk>[src]

impl<Pk: Default + MiniscriptKey> Default for SignersContainer<Pk>[src]

impl From<HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>> for SignersContainer<DescriptorPublicKey>[src]

Auto Trait Implementations

impl<Pk> !RefUnwindSafe for SignersContainer<Pk>

impl<Pk> !Send for SignersContainer<Pk>

impl<Pk> !Sync for SignersContainer<Pk>

impl<Pk> Unpin for SignersContainer<Pk> where
    <Pk as MiniscriptKey>::Hash: Unpin

impl<Pk> !UnwindSafe for SignersContainer<Pk>

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/trait.Signer.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/trait.Signer.html new file mode 100644 index 0000000000..3fc46e577c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/trait.Signer.html @@ -0,0 +1,23 @@ +bdk::wallet::signer::Signer - Rust

[][src]Trait bdk::wallet::signer::Signer

pub trait Signer: Debug {
+    fn sign(
        &self,
        psbt: &mut PartiallySignedTransaction,
        input_index: Option<usize>
    ) -> Result<(), SignerError>; +
fn sign_whole_tx(&self) -> bool; + + fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> { ... } +}

Trait for signers

+

This trait can be implemented to provide customized signers to the wallet. For an example see +this module's documentation.

+
+

Required methods

fn sign(
    &self,
    psbt: &mut PartiallySignedTransaction,
    input_index: Option<usize>
) -> Result<(), SignerError>

Sign a PSBT

+

The input_index argument is only provided if the wallet doesn't declare to sign the whole +transaction in one go (see Signer::sign_whole_tx). Otherwise its value is None and +can be ignored.

+

fn sign_whole_tx(&self) -> bool

Return whether or not the signer signs the whole transaction in one go instead of every +input individually

+
Loading content... +

Provided methods

fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey>

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

+
Loading content... +

Implementations on Foreign Types

impl Signer for DescriptorXKey<ExtendedPrivKey>[src]

impl Signer for PrivateKey[src]

Loading content... +

Implementors

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/struct.Wallet.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/struct.Wallet.html new file mode 100644 index 0000000000..19f74f62e1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/struct.Wallet.html @@ -0,0 +1,70 @@ +bdk::wallet::Wallet - Rust

[][src]Struct bdk::wallet::Wallet

pub struct Wallet<B: BlockchainMarker, D: BatchDatabase> { /* fields omitted */ }

A Bitcoin wallet

+

A wallet takes descriptors, a database and a +blockchain and implements the basic functions that a Bitcoin wallets +needs to operate, like generating addresses, returning the balance, +creating transactions, etc.

+

A wallet can be either "online" if the blockchain type provided +implements Blockchain, or "offline" OfflineBlockchain is used. Offline wallets only expose +methods that don't need any interaction with the blockchain to work.

+

Implementations

impl<B, D> Wallet<B, D> where
    B: BlockchainMarker,
    D: BatchDatabase
[src]

pub fn new_offline(
    descriptor: &str,
    change_descriptor: Option<&str>,
    network: Network,
    database: D
) -> Result<Self, Error>
[src]

Create a new "offline" wallet

+

pub fn get_new_address(&self) -> Result<Address, Error>[src]

Return a newly generated address using the external descriptor

+

pub fn is_mine(&self, script: &Script) -> Result<bool, Error>[src]

Return whether or not a script is part of this wallet (either internal or external)

+

pub fn list_unspent(&self) -> Result<Vec<UTXO>, Error>[src]

Return the list of unspent outputs of this wallet

+

Note that this methods only operate on the internal database, which first needs to be +Wallet::sync manually.

+

pub fn list_transactions(
    &self,
    include_raw: bool
) -> Result<Vec<TransactionDetails>, Error>
[src]

Return the list of transactions made and received by the wallet

+

Optionally fill the TransactionDetails::transaction field with the raw transaction if +include_raw is true.

+

Note that this methods only operate on the internal database, which first needs to be +Wallet::sync manually.

+

pub fn get_balance(&self) -> Result<u64, Error>[src]

Return the balance, meaning the sum of this wallet's unspent outputs' values

+

Note that this methods only operate on the internal database, which first needs to be +Wallet::sync manually.

+

pub fn add_signer(
    &mut self,
    script_type: ScriptType,
    id: SignerId<DescriptorPublicKey>,
    ordering: SignerOrdering,
    signer: Arc<Box<dyn Signer>>
)
[src]

Add an external signer

+

See the signer module for an example.

+

pub fn add_address_validator(
    &mut self,
    validator: Arc<Box<dyn AddressValidator>>
)
[src]

Add an address validator

+

See the address_validator module for an example.

+

pub fn create_tx<Cs: CoinSelectionAlgorithm>(
    &self,
    builder: TxBuilder<Cs>
) -> Result<(PSBT, TransactionDetails), Error>
[src]

Create a new transaction following the options specified in the builder

+

Example

+
+let (psbt, details) = wallet.create_tx(
+    TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+)?;
+// sign and broadcast ...
+

pub fn bump_fee<Cs: CoinSelectionAlgorithm>(
    &self,
    txid: &Txid,
    builder: TxBuilder<Cs>
) -> Result<(PSBT, TransactionDetails), Error>
[src]

Bump the fee of a transaction following the options specified in the builder

+

Return an error if the transaction is already confirmed or doesn't explicitly signal RBF.

+

NOTE: if the original transaction was made with TxBuilder::send_all, the same +option must be enabled when bumping its fees to correctly reduce the only output's value to +increase the fees.

+

Example

+
+let txid = Txid::from_str("faff0a466b70f5d5f92bd757a92c1371d4838bdd5bc53a06764e2488e51ce8f8").unwrap();
+let (psbt, details) = wallet.bump_fee(
+    &txid,
+    TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(5.0)),
+)?;
+// sign and broadcast ...
+

pub fn sign(
    &self,
    psbt: PSBT,
    assume_height: Option<u32>
) -> Result<(PSBT, bool), Error>
[src]

Sign a transaction with all the wallet's signers, in the order specified by every signer's +SignerOrdering

+

Example

+
+let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
+

pub fn policies(&self, script_type: ScriptType) -> Result<Option<Policy>, Error>[src]

Return the spending policies for the wallet's descriptor

+

pub fn public_descriptor(
    &self,
    script_type: ScriptType
) -> Result<Option<ExtendedDescriptor>, Error>
[src]

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 finalize_psbt(
    &self,
    psbt: PSBT,
    assume_height: Option<u32>
) -> Result<(PSBT, bool), Error>
[src]

Try to finalize a PSBT

+

impl<B, D> Wallet<B, D> where
    B: Blockchain,
    D: BatchDatabase
[src]

pub fn new(
    descriptor: &str,
    change_descriptor: Option<&str>,
    network: Network,
    database: D,
    client: B
) -> Result<Self, Error>
[src]

Create a new "online" wallet

+

pub fn sync<P: 'static + Progress>(
    &self,
    progress_update: P,
    max_address_param: Option<u32>
) -> Result<(), Error>
[src]

Sync the internal database with the blockchain

+

pub fn client(&self) -> Option<&B>[src]

Return a reference to the internal blockchain client

+

pub fn broadcast(&self, tx: Transaction) -> Result<Txid, Error>[src]

Broadcast a transaction to the network

+

Auto Trait Implementations

impl<B, D> !RefUnwindSafe for Wallet<B, D>

impl<B, D> !Send for Wallet<B, D>

impl<B, D> !Sync for Wallet<B, D>

impl<B, D> Unpin for Wallet<B, D> where
    B: Unpin,
    D: Unpin

impl<B, D> !UnwindSafe for Wallet<B, D>

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/fn.get_timestamp.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/fn.get_timestamp.html new file mode 100644 index 0000000000..201c354c30 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/fn.get_timestamp.html @@ -0,0 +1,2 @@ +bdk::wallet::time::get_timestamp - Rust

[][src]Function bdk::wallet::time::get_timestamp

pub fn get_timestamp() -> u64

Return the current timestamp in seconds

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/index.html new file mode 100644 index 0000000000..29bbc5d2b9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/index.html @@ -0,0 +1,8 @@ +bdk::wallet::time - Rust

[][src]Module bdk::wallet::time

Cross-platform time

+

This module provides a function to get the current timestamp that works on all the platforms +supported by the library.

+

It can be useful to compare it with the timestamps found in +TransactionDetails.

+

Functions

+
get_timestamp

Return the current timestamp in seconds

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/sidebar-items.js new file mode 100644 index 0000000000..22164ef49f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"fn":[["get_timestamp","Return the current timestamp in seconds"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/trait.IsDust.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/trait.IsDust.html new file mode 100644 index 0000000000..42f509f659 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/trait.IsDust.html @@ -0,0 +1,8 @@ +bdk::wallet::IsDust - Rust

[][src]Trait bdk::wallet::IsDust

pub trait IsDust {
+    fn is_dust(&self) -> bool;
+}

Trait to check if a value is below the dust limit

+
+

Required methods

fn is_dust(&self) -> bool

Check whether or not a value is below dust limit

+
Loading content... +

Implementations on Foreign Types

impl IsDust for u64[src]

Loading content... +

Implementors

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html new file mode 100644 index 0000000000..90f24df408 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html @@ -0,0 +1,42 @@ +bdk::wallet::tx_builder::ChangeSpendPolicy - Rust

[][src]Enum bdk::wallet::tx_builder::ChangeSpendPolicy

pub enum ChangeSpendPolicy {
+    ChangeAllowed,
+    OnlyChange,
+    ChangeForbidden,
+}

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

impl Clone for ChangeSpendPolicy[src]

impl Copy for ChangeSpendPolicy[src]

impl Debug for ChangeSpendPolicy[src]

impl Default for ChangeSpendPolicy[src]

impl Eq for ChangeSpendPolicy[src]

impl Hash for ChangeSpendPolicy[src]

impl Ord for ChangeSpendPolicy[src]

impl PartialEq<ChangeSpendPolicy> for ChangeSpendPolicy[src]

impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy[src]

impl StructuralEq for ChangeSpendPolicy[src]

impl StructuralPartialEq for ChangeSpendPolicy[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.TxOrdering.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.TxOrdering.html new file mode 100644 index 0000000000..61219124a8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.TxOrdering.html @@ -0,0 +1,42 @@ +bdk::wallet::tx_builder::TxOrdering - Rust

[][src]Enum bdk::wallet::tx_builder::TxOrdering

pub enum TxOrdering {
+    Shuffle,
+    Untouched,
+    BIP69Lexicographic,
+}

Ordering of the transaction's inputs and outputs

+

+ Variants

+
Shuffle

Randomized (default)

+
Untouched

Unchanged

+
BIP69Lexicographic

BIP69 / Lexicographic

+

Implementations

impl TxOrdering[src]

pub fn sort_tx(&self, tx: &mut Transaction)[src]

Trait Implementations

impl Clone for TxOrdering[src]

impl Copy for TxOrdering[src]

impl Debug for TxOrdering[src]

impl Default for TxOrdering[src]

impl Eq for TxOrdering[src]

impl Hash for TxOrdering[src]

impl Ord for TxOrdering[src]

impl PartialEq<TxOrdering> for TxOrdering[src]

impl PartialOrd<TxOrdering> for TxOrdering[src]

impl StructuralEq for TxOrdering[src]

impl StructuralPartialEq for TxOrdering[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/index.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/index.html new file mode 100644 index 0000000000..90c59e1cb8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/index.html @@ -0,0 +1,16 @@ +bdk::wallet::tx_builder - Rust

[][src]Module bdk::wallet::tx_builder

Transaction builder

+

Example

+
+// Create a transaction with one output to `to_address` of 50_000 satoshi, with a custom fee rate
+// of 5.0 satoshi/vbyte, only spending non-change outputs and with RBF signaling
+// enabled
+let builder = TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+    .fee_rate(FeeRate::from_sat_per_vb(5.0))
+    .do_not_spend_change()
+    .enable_rbf();
+

Structs

+
TxBuilder

A transaction builder

+

Enums

+
ChangeSpendPolicy

Policy regarding the use of change outputs when creating a transaction

+
TxOrdering

Ordering of the transaction's inputs and outputs

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/sidebar-items.js new file mode 100644 index 0000000000..e51db729e0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["ChangeSpendPolicy","Policy regarding the use of change outputs when creating a transaction"],["TxOrdering","Ordering of the transaction's inputs and outputs"]],"struct":[["TxBuilder","A transaction builder"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/struct.TxBuilder.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/struct.TxBuilder.html new file mode 100644 index 0000000000..6ead2e15a2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/struct.TxBuilder.html @@ -0,0 +1,70 @@ +bdk::wallet::tx_builder::TxBuilder - Rust

[][src]Struct bdk::wallet::tx_builder::TxBuilder

pub struct TxBuilder<Cs: CoinSelectionAlgorithm> { /* fields omitted */ }

A transaction builder

+

This structure contains the configuration that the wallet must follow to build a transaction.

+

For an example see this module's documentation;

+

Implementations

impl TxBuilder<DefaultCoinSelectionAlgorithm>[src]

pub fn new() -> Self[src]

Create an empty builder

+

pub fn with_recipients(recipients: Vec<(Script, u64)>) -> Self[src]

Create a builder starting from a list of recipients

+

impl<Cs: CoinSelectionAlgorithm> TxBuilder<Cs>[src]

pub fn set_recipients(self, recipients: Vec<(Script, u64)>) -> Self[src]

Replace the recipients already added with a new list

+

pub fn add_recipient(self, script_pubkey: Script, amount: u64) -> Self[src]

Add a recipient to the internal list

+

pub fn send_all(self) -> Self[src]

Send all the selected utxos to a single output

+

Adding more than one recipients with this option enabled will result in an error.

+

The value associated with the only recipient is irrelevant and will be replaced by the wallet.

+

pub fn fee_rate(self, fee_rate: FeeRate) -> Self[src]

Set a custom fee rate

+

pub fn policy_path(self, policy_path: BTreeMap<String, Vec<usize>>) -> Self[src]

Set the policy path to use while creating the transaction

+

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

+

pub fn utxos(self, utxos: Vec<OutPoint>) -> Self[src]

Replace the internal list of utxos that must be spent with a new list

+

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(self, utxo: OutPoint) -> Self[src]

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 unspendable(self, unspendable: Vec<OutPoint>) -> Self[src]

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::utxos and +TxBuilder::add_utxo have priority over these. See the docs of the two linked methods +for more details.

+

pub fn add_unspendable(self, unspendable: OutPoint) -> Self[src]

Add a utxo to the internal list of unspendable utxos

+

It's important to note that the "must-be-spent" utxos added with TxBuilder::utxos and +TxBuilder::add_utxo have priority over this. See the docs of the two linked methods +for more details.

+

pub fn sighash(self, sighash: SigHashType) -> Self[src]

Sign with a specific sig hash

+

Use this option very carefully

+

pub fn ordering(self, ordering: TxOrdering) -> Self[src]

Choose the ordering for inputs and outputs of the transaction

+

pub fn nlocktime(self, locktime: u32) -> Self[src]

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 enable_rbf(self) -> Self[src]

Enable signaling RBF

+

This will use the default nSequence value of 0xFFFFFFFD.

+

pub fn enable_rbf_with_sequence(self, nsequence: u32) -> Self[src]

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 version(self, version: u32) -> Self[src]

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 do_not_spend_change(self) -> Self[src]

Do not spend change outputs

+

This effectively adds all the change outputs to the "unspendable" list. See +TxBuilder::unspendable.

+

pub fn only_spend_change(self) -> Self[src]

Only spend change outputs

+

This effectively adds all the non-change outputs to the "unspendable" list. See +TxBuilder::unspendable.

+

pub fn change_policy(self, change_policy: ChangeSpendPolicy) -> Self[src]

pub fn force_non_witness_utxo(self) -> Self[src]

Fill-in the psbt::Input::non_witness_utxo field even if the wallet only has SegWit +descriptors.

+

This is useful for signers which always require it, like Trezor hardware wallets.

+

pub fn coin_selection<P: CoinSelectionAlgorithm>(
    self,
    coin_selection: P
) -> TxBuilder<P>
[src]

Choose the coin selection algorithm

+

Overrides the DefaultCoinSelectionAlgorithm.

+

Trait Implementations

impl<Cs: Debug + CoinSelectionAlgorithm> Debug for TxBuilder<Cs>[src]

impl<Cs: Default + CoinSelectionAlgorithm> Default for TxBuilder<Cs>[src]

Auto Trait Implementations

impl<Cs> RefUnwindSafe for TxBuilder<Cs> where
    Cs: RefUnwindSafe

impl<Cs> Send for TxBuilder<Cs> where
    Cs: Send

impl<Cs> Sync for TxBuilder<Cs> where
    Cs: Sync

impl<Cs> Unpin for TxBuilder<Cs> where
    Cs: Unpin

impl<Cs> UnwindSafe for TxBuilder<Cs> where
    Cs: UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/type.OfflineWallet.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/type.OfflineWallet.html new file mode 100644 index 0000000000..0f4efcc6f5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/type.OfflineWallet.html @@ -0,0 +1,2 @@ +bdk::wallet::OfflineWallet - Rust

[][src]Type Definition bdk::wallet::OfflineWallet

type OfflineWallet<D> = Wallet<OfflineBlockchain, D>;

Type alias for a Wallet that uses OfflineBlockchain

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/utils/trait.IsDust.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/utils/trait.IsDust.html new file mode 100644 index 0000000000..71ab5675d6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/utils/trait.IsDust.html @@ -0,0 +1,10 @@ + + + + + + +

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

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/brush.svg b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/brush.svg new file mode 100644 index 0000000000..ea266e856a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/brush.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/dark.css b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/dark.css new file mode 100644 index 0000000000..5df3fef0bc --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/dark.css @@ -0,0 +1 @@ +body{background-color:#353535;color:#ddd;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:#ddd;}h1.fqn{border-bottom-color:#d2d2d2;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){border-bottom-color:#d2d2d2;}.in-band{background-color:#353535;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#2A2A2A;}pre{background-color:#2A2A2A;}.sidebar{background-color:#505050;}*{scrollbar-color:rgb(64,65,67) #717171;}.sidebar{scrollbar-color:rgba(32,34,37,.6) transparent;}::-webkit-scrollbar-track{background-color:#717171;}::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar::-webkit-scrollbar-track{background-color:#717171;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar .current{background-color:#333;}.source .sidebar{background-color:#353535;}.sidebar .location{border-color:#fff;background:#575757;color:#DDD;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#444;}.line-numbers span{color:#3B91E2;}.line-numbers .line-highlighted{background-color:#0a042f !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#DDD;}.docblock table,.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#ddd;}.content .highlighted{color:#eee !important;background-color:#616161;}.content .highlighted a,.content .highlighted span{color:#eee !important;}.content .highlighted.trait{background-color:#013191;}.content .highlighted.traitalias{background-color:#013191;}.content .highlighted.mod,.content .highlighted.externcrate{background-color:#afc6e4;}.content .highlighted.mod{background-color:#803a1b;}.content .highlighted.externcrate{background-color:#396bac;}.content .highlighted.enum{background-color:#5b4e68;}.content .highlighted.struct{background-color:#194e9f;}.content .highlighted.union{background-color:#b7bd49;}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{background-color:#4950ed;}.content .highlighted.type{background-color:#38902c;}.content .highlighted.foreigntype{background-color:#b200d6;}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{background-color:#217d1c;}.content .highlighted.constant,.content .highlighted.static{background-color:#0063cc;}.content .highlighted.primitive{background-color:#00708a;}.content .highlighted.keyword{background-color:#884719;}.content .stability::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#82b089;}.content span.struct,.content a.struct,.block a.current.struct{color:#2dbfb8;}.content span.type,.content a.type,.block a.current.type{color:#ff7f00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#dd7de8;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#09bd00;}.content span.union,.content a.union,.block a.current.union{color:#a6ae37;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#82a5c9;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#43aec7;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#bda000;}.content span.trait,.content a.trait,.block a.current.trait{color:#b78cf2;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#b397da;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#2BAB63;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}pre.rust .comment{color:#8d8d8b;}pre.rust .doccomment{color:#8ca375;}nav:not(.sidebar){border-bottom-color:#4e4e4e;}nav.main .current{border-top-color:#eee;border-bottom-color:#eee;}nav.main .separator{border-color:#eee;}a{color:#ddd;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.stability a{color:#D2991D;}.stab.internal a{color:#304FFE;}a.test-arrow{color:#dedede;}.collapse-toggle{color:#999;}#crate-search{color:#111;background-color:#f0f0f0;border-color:#000;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input{color:#111;background-color:#f0f0f0;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input:focus{border-color:#008dfd;}.search-focus:disabled{background-color:#c5c4c4;}#crate-search+.search-input:focus{box-shadow:0 0 8px 4px #078dd8;}.module-item .stab{color:#ddd;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;color:#2f2f2f;}.stab.internal{background:#FFB9B3;border-color:#B71C1C;color:#2f2f2f;}.stab.deprecated{background:#F3DFFF;border-color:#7F0087;color:#2f2f2f;}.stab.portability{background:#C4ECFF;border-color:#7BA5DB;color:#2f2f2f;}.stab.portability>code{color:#ddd;}#help>div{background:#4d4d4d;border-color:#bfbfbf;}#help dt{border-color:#bfbfbf;background:rgba(0,0,0,0);color:black;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:#ddd;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#ab8ac1;}pre.rust .kw-2,pre.rust .prelude-ty{color:#769acb;}pre.rust .number,pre.rust .string{color:#83a300;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#ee6868;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#d97f26;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#4a4949;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label{color:#999;}:target>code,:target>.in-band{background-color:#494a3d;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.8);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.8);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.8);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.8);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip .tooltiptext{background-color:#000;color:#fff;border-color:#000;}.tooltip .tooltiptext::after{border-color:transparent black transparent transparent;}#titles>div:not(.selected){background-color:#252525;border-top-color:#252525;}#titles>div:hover,#titles>div.selected{border-top-color:#0089ff;}#titles>div>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#505050;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#505050;border-right-color:#000;}#sidebar-filler{background-color:#505050;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu{border-color:#e0e0e0;background:#f0f0f0;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus{border-color:#ffb900;}#theme-choices{border-color:#e0e0e0;background-color:#353535;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#4e4e4e;}@media (max-width:700px){#theme-picker{background:#f0f0f0;}}#all-types{background-color:#505050;}#all-types:hover{background-color:#606060;}.search-results td span.alias{color:#fff;}.search-results td span.grey{color:#ccc;}#sidebar-toggle{background-color:#565656;}#sidebar-toggle:hover{background-color:#676767;}#source-sidebar{background-color:#565656;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#444;}div.files>.selected{background-color:#333;}.setting-line>.title{border-bottom-color:#ddd;} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/down-arrow.svg b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/down-arrow.svg new file mode 100644 index 0000000000..35437e77a7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/down-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/favicon.ico b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/favicon.ico new file mode 100644 index 0000000000..b8ad23769a Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/favicon.ico differ diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/alloc/string/trait.ToString.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/alloc/string/trait.ToString.js new file mode 100644 index 0000000000..f3e935dbe1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/alloc/string/trait.ToString.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl ToString for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; +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/0.1.0-beta.1/implementors/bdk/blockchain/trait.Blockchain.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.Blockchain.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.Blockchain.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/0.1.0-beta.1/implementors/bdk/blockchain/trait.BlockchainMarker.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.BlockchainMarker.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.BlockchainMarker.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/0.1.0-beta.1/implementors/bdk/blockchain/trait.Progress.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.Progress.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.Progress.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/0.1.0-beta.1/implementors/bdk/database/trait.BatchDatabase.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.BatchDatabase.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.BatchDatabase.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/0.1.0-beta.1/implementors/bdk/database/trait.BatchOperations.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.BatchOperations.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.BatchOperations.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/0.1.0-beta.1/implementors/bdk/database/trait.Database.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.Database.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.Database.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/0.1.0-beta.1/implementors/bdk/descriptor/trait.ExtractPolicy.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ExtractPolicy.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ExtractPolicy.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/0.1.0-beta.1/implementors/bdk/descriptor/trait.MiniscriptKey.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.MiniscriptKey.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.MiniscriptKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/0.1.0-beta.1/implementors/bdk/descriptor/trait.ScriptContext.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ScriptContext.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ScriptContext.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/0.1.0-beta.1/implementors/bdk/descriptor/trait.ToPublicKey.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ToPublicKey.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ToPublicKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/0.1.0-beta.1/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/0.1.0-beta.1/implementors/bdk/wallet/signer/trait.Signer.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/signer/trait.Signer.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/signer/trait.Signer.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/0.1.0-beta.1/implementors/bdk/wallet/trait.IsDust.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/trait.IsDust.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/trait.IsDust.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/0.1.0-beta.1/implementors/core/clone/trait.Clone.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/clone/trait.Clone.js new file mode 100644 index 0000000000..795f3aa5e4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/clone/trait.Clone.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Clone for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Clone for NoopProgress","synthetic":false,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Clone for LogProgress","synthetic":false,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Clone for PKOrF","synthetic":false,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Clone for SatisfiableItem","synthetic":false,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Clone for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Clone for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Clone for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Clone for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl Clone for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Clone for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl Clone for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Clone for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: Clone + MiniscriptKey> Clone for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Clone for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Clone for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk: Clone + MiniscriptKey> Clone for SignersContainer<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Clone for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Clone for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/implementors/core/cmp/trait.Eq.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.Eq.js new file mode 100644 index 0000000000..7d046cd5c6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.Eq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Eq for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Eq for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Eq for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl Eq for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl Eq for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Eq for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: Eq + MiniscriptKey> Eq for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Eq for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Eq for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Eq for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Eq for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/implementors/core/cmp/trait.Ord.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.Ord.js new file mode 100644 index 0000000000..def6b4a7cf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.Ord.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Ord for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Ord for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Ord for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Ord for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/implementors/core/cmp/trait.PartialEq.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.PartialEq.js new file mode 100644 index 0000000000..317284f165 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.PartialEq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl PartialEq<Capability> for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl PartialEq<Condition> for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl PartialEq<ScriptType> for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl PartialEq<FeeRate> for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl PartialEq<UTXO> for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl PartialEq<TransactionDetails> for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl PartialEq<AddressValidatorError> for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: PartialEq + MiniscriptKey> PartialEq<SignerId<Pk>> for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl PartialEq<SignerError> for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl PartialEq<SignerOrdering> for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl PartialEq<TxOrdering> for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl PartialEq<ChangeSpendPolicy> for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/implementors/core/cmp/trait.PartialOrd.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.PartialOrd.js new file mode 100644 index 0000000000..a07fbbf60f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.PartialOrd.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl PartialOrd<Condition> for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl PartialOrd<FeeRate> for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl PartialOrd<SignerOrdering> for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl PartialOrd<TxOrdering> for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/implementors/core/convert/trait.AsRef.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/convert/trait.AsRef.js new file mode 100644 index 0000000000..cf12c34f1d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/convert/trait.AsRef.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl AsRef<[u8]> for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]}]; +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/0.1.0-beta.1/implementors/core/convert/trait.From.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/convert/trait.From.js new file mode 100644 index 0000000000..2f08ca5d8e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/convert/trait.From.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<AddressValidatorError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<PolicyError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<SignerError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<EsploraError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<CompactFiltersError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Client> for ElectrumBlockchain","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<ParseIntError> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<SystemTimeError> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<PolicyError> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<bool> for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl From<SatisfiableItem> for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl From<Hash> for SignerId<DescriptorPublicKey>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl From<Fingerprint> for SignerId<DescriptorPublicKey>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl From<HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>> for SignersContainer<DescriptorPublicKey>","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]}]; +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/0.1.0-beta.1/implementors/core/default/trait.Default.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/default/trait.Default.js new file mode 100644 index 0000000000..521ae3ac3c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/default/trait.Default.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Default for Mempool","synthetic":false,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Default for MemoryDatabase","synthetic":false,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Default for PKOrF","synthetic":false,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Default for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Default for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Default for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Default for DumbCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Default for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk: Default + MiniscriptKey> Default for SignersContainer<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Cs: Default + CoinSelectionAlgorithm> Default for TxBuilder<Cs>","synthetic":false,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Default for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Default for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/implementors/core/fmt/trait.Debug.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/fmt/trait.Debug.js new file mode 100644 index 0000000000..74c7308e86 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/fmt/trait.Debug.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Debug for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl Debug for EsploraBlockchain","synthetic":false,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Debug for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Debug for Mempool","synthetic":false,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Debug for Peer","synthetic":false,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Debug for CompactFiltersBlockchain","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Debug for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Debug for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Debug for MemoryDatabase","synthetic":false,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Debug for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl Debug for PKOrF","synthetic":false,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Debug for SatisfiableItem","synthetic":false,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Debug for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Debug for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Debug for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Debug for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl Debug for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl Debug for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Debug for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl Debug for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Debug for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Debug for CoinSelectionResult","synthetic":false,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Debug for DumbCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Debug for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl<Pk: Debug + MiniscriptKey> Debug for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Debug for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Debug for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk: Debug + MiniscriptKey> Debug for SignersContainer<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Cs: Debug + CoinSelectionAlgorithm> Debug for TxBuilder<Cs>","synthetic":false,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Debug for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Debug for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/implementors/core/fmt/trait.Display.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/fmt/trait.Display.js new file mode 100644 index 0000000000..e2ed5553a9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/fmt/trait.Display.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Display for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl Display for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Display for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Display for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl Display for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl Display for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Display for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]}]; +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/0.1.0-beta.1/implementors/core/hash/trait.Hash.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/hash/trait.Hash.js new file mode 100644 index 0000000000..a5da8ca7bd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/hash/trait.Hash.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Hash for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Hash for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Hash for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl<Pk: Hash + MiniscriptKey> Hash for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Hash for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Hash for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/implementors/core/marker/trait.Copy.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Copy.js new file mode 100644 index 0000000000..5f551c2945 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Copy.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Copy for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Copy for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Copy for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl Copy for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Copy for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Copy for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/implementors/core/marker/trait.Freeze.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Freeze.js new file mode 100644 index 0000000000..23dc06ecd5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Freeze.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Freeze for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Freeze for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl Freeze for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Freeze for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Freeze for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl Freeze for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl Freeze for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Freeze for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Freeze for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl !Freeze for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Freeze for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Freeze for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl !Freeze for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Freeze for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Freeze for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Freeze for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Freeze for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Freeze for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Freeze for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Freeze for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Freeze for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Freeze for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Freeze for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Freeze for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !Freeze for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Freeze for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Freeze for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Freeze for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Freeze for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Freeze for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> Freeze for SignersContainer<Pk>","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> Freeze for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Freeze, 
","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Freeze for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> Freeze for TxBuilder<Cs> where
    Cs: Freeze, 
","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Freeze for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Freeze for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/implementors/core/marker/trait.Send.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Send.js new file mode 100644 index 0000000000..764c51c5e0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Send.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Send for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Send for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl Send for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Send for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Send for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl Send for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl Send for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Send for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Send for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Send for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Send for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Send for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Send for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Send for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Send for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Send for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl !Send for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Send for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Send for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Send for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Send for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Send for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Send for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Send for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !Send for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Send for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Send for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Send for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Send for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Send for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> !Send for SignersContainer<Pk>","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> Send for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Send
","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Send for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> Send for TxBuilder<Cs> where
    Cs: Send
","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Send for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Send for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/implementors/core/marker/trait.StructuralEq.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.StructuralEq.js new file mode 100644 index 0000000000..9aa523c03e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.StructuralEq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl StructuralEq for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl StructuralEq for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl StructuralEq for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl StructuralEq for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl StructuralEq for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl StructuralEq for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: MiniscriptKey> StructuralEq for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl StructuralEq for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl StructuralEq for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl StructuralEq for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl StructuralEq for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/implementors/core/marker/trait.StructuralPartialEq.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.StructuralPartialEq.js new file mode 100644 index 0000000000..f0eb276a1d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.StructuralPartialEq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl StructuralPartialEq for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl StructuralPartialEq for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl StructuralPartialEq for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl StructuralPartialEq for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl StructuralPartialEq for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl StructuralPartialEq for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl StructuralPartialEq for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: MiniscriptKey> StructuralPartialEq for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl StructuralPartialEq for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl StructuralPartialEq for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl StructuralPartialEq for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl StructuralPartialEq for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/implementors/core/marker/trait.Sync.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Sync.js new file mode 100644 index 0000000000..1fd8f87484 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Sync.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Sync for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Sync for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl Sync for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Sync for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Sync for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl Sync for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl Sync for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Sync for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Sync for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Sync for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Sync for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Sync for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Sync for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Sync for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Sync for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Sync for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl !Sync for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Sync for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Sync for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Sync for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Sync for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Sync for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Sync for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Sync for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !Sync for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Sync for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Sync for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Sync for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Sync for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Sync for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> !Sync for SignersContainer<Pk>","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> Sync for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Sync
","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Sync for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> Sync for TxBuilder<Cs> where
    Cs: Sync
","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Sync for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Sync for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/implementors/core/marker/trait.Unpin.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Unpin.js new file mode 100644 index 0000000000..8cc0048d2d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Unpin.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Unpin for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Unpin for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl Unpin for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Unpin for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Unpin for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl Unpin for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl Unpin for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Unpin for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Unpin for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Unpin for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Unpin for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Unpin for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Unpin for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Unpin for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Unpin for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Unpin for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Unpin for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Unpin for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Unpin for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Unpin for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Unpin for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Unpin for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Unpin for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Unpin for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> Unpin for Wallet<B, D> where
    B: Unpin,
    D: Unpin
","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Unpin for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Unpin for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Unpin for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Unpin for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Unpin for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> Unpin for SignersContainer<Pk> where
    <Pk as MiniscriptKey>::Hash: Unpin
","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> Unpin for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: Unpin
","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Unpin for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> Unpin for TxBuilder<Cs> where
    Cs: Unpin
","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Unpin for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Unpin for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/implementors/core/str/trait.FromStr.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/str/trait.FromStr.js new file mode 100644 index 0000000000..fd4b285a22 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/core/str/trait.FromStr.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl FromStr for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; +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/0.1.0-beta.1/implementors/serde/de/trait.Deserialize.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/serde/de/trait.Deserialize.js new file mode 100644 index 0000000000..b54d94401d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/serde/de/trait.Deserialize.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl<'de> Deserialize<'de> for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl<'de> Deserialize<'de> for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl<'de> Deserialize<'de> for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl<'de> Deserialize<'de> for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; +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/0.1.0-beta.1/implementors/serde/ser/trait.Serialize.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/serde/ser/trait.Serialize.js new file mode 100644 index 0000000000..87f639e005 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/serde/ser/trait.Serialize.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Serialize for PKOrF","synthetic":false,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Serialize for SatisfiableItem","synthetic":false,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Serialize for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Serialize for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Serialize for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Serialize for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl Serialize for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl Serialize for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Serialize for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; +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/0.1.0-beta.1/implementors/std/error/trait.Error.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/std/error/trait.Error.js new file mode 100644 index 0000000000..7326983fef --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/std/error/trait.Error.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Error for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl Error for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Error for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Error for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl Error for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl Error for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Error for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]}]; +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/0.1.0-beta.1/implementors/std/panic/trait.RefUnwindSafe.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/std/panic/trait.RefUnwindSafe.js new file mode 100644 index 0000000000..29deba8e41 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/std/panic/trait.RefUnwindSafe.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl RefUnwindSafe for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl RefUnwindSafe for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl RefUnwindSafe for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl !RefUnwindSafe for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl RefUnwindSafe for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl RefUnwindSafe for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl RefUnwindSafe for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl RefUnwindSafe for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl RefUnwindSafe for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl RefUnwindSafe for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl !RefUnwindSafe for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl !RefUnwindSafe for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl RefUnwindSafe for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl !RefUnwindSafe for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl !RefUnwindSafe for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl !RefUnwindSafe for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl !RefUnwindSafe for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl RefUnwindSafe for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl RefUnwindSafe for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl RefUnwindSafe for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl RefUnwindSafe for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl RefUnwindSafe for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl RefUnwindSafe for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl RefUnwindSafe for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !RefUnwindSafe for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl RefUnwindSafe for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl RefUnwindSafe for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl RefUnwindSafe for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl RefUnwindSafe for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl RefUnwindSafe for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> !RefUnwindSafe for SignersContainer<Pk>","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> RefUnwindSafe for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe
","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl RefUnwindSafe for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> RefUnwindSafe for TxBuilder<Cs> where
    Cs: RefUnwindSafe
","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl RefUnwindSafe for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl RefUnwindSafe for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/implementors/std/panic/trait.UnwindSafe.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/std/panic/trait.UnwindSafe.js new file mode 100644 index 0000000000..1aa1c54fb5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/implementors/std/panic/trait.UnwindSafe.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl UnwindSafe for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl UnwindSafe for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl UnwindSafe for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl !UnwindSafe for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl UnwindSafe for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl UnwindSafe for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl UnwindSafe for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl UnwindSafe for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl UnwindSafe for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl UnwindSafe for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl !UnwindSafe for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl !UnwindSafe for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl UnwindSafe for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl !UnwindSafe for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl !UnwindSafe for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl !UnwindSafe for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl !UnwindSafe for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl UnwindSafe for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl UnwindSafe for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl UnwindSafe for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl UnwindSafe for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl UnwindSafe for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl UnwindSafe for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl UnwindSafe for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !UnwindSafe for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl UnwindSafe for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl UnwindSafe for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl UnwindSafe for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl UnwindSafe for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl UnwindSafe for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> !UnwindSafe for SignersContainer<Pk>","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> UnwindSafe for SignerId<Pk> where
    <Pk as MiniscriptKey>::Hash: UnwindSafe
","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl UnwindSafe for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> UnwindSafe for TxBuilder<Cs> where
    Cs: UnwindSafe
","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl UnwindSafe for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl UnwindSafe for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::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/0.1.0-beta.1/light.css b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/light.css new file mode 100644 index 0000000000..824281ebe9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/light.css @@ -0,0 +1 @@ + body{background-color:white;color:black;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:black;}h1.fqn{border-bottom-color:#D5D5D5;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){border-bottom-color:#DDDDDD;}.in-band{background-color:white;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#F5F5F5;}pre{background-color:#F5F5F5;}.sidebar{background-color:#F1F1F1;}*{scrollbar-color:rgba(36,37,39,0.6) #e6e6e6;}.sidebar{scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;}::-webkit-scrollbar-track{background-color:#ecebeb;}::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar::-webkit-scrollbar-track{background-color:#dcdcdc;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar .current{background-color:#fff;}.source .sidebar{background-color:#fff;}.sidebar .location{border-color:#000;background-color:#fff;color:#333;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#F5F5F5;}.line-numbers span{color:#c67e2d;}.line-numbers .line-highlighted{background-color:#f6fdb0 !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#ddd;}.docblock table,.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#4E4C4C;}.content .highlighted{color:#000 !important;background-color:#ccc;}.content .highlighted a,.content .highlighted span{color:#000 !important;}.content .highlighted.trait{background-color:#c7b6ff;}.content .highlighted.traitalias{background-color:#c7b6ff;}.content .highlighted.mod,.content .highlighted.externcrate{background-color:#afc6e4;}.content .highlighted.enum{background-color:#b4d1b9;}.content .highlighted.struct{background-color:#e7b1a0;}.content .highlighted.union{background-color:#b7bd49;}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{background-color:#c6afb3;}.content .highlighted.type{background-color:#ffc891;}.content .highlighted.foreigntype{background-color:#f5c4ff;}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{background-color:#8ce488;}.content .highlighted.constant,.content .highlighted.static{background-color:#c3e0ff;}.content .highlighted.primitive{background-color:#9aecff;}.content .highlighted.keyword{background-color:#f99650;}.content .stability::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#508157;}.content span.struct,.content a.struct,.block a.current.struct{color:#ad448e;}.content span.type,.content a.type,.block a.current.type{color:#ba5d00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#cd00e2;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#068000;}.content span.union,.content a.union,.block a.current.union{color:#767b27;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#546e8a;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#2c8093;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#4d76ae;}.content span.trait,.content a.trait,.block a.current.trait{color:#7c5af3;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#6841f1;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#9a6e31;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}pre.rust .comment{color:#8E908C;}pre.rust .doccomment{color:#4D4D4C;}nav:not(.sidebar){border-bottom-color:#e0e0e0;}nav.main .current{border-top-color:#000;border-bottom-color:#000;}nav.main .separator{border:1px solid #000;}a{color:#000;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.stability a{color:#3873AD;}.stab.internal a{color:#304FFE;}a.test-arrow{color:#f5f5f5;}.collapse-toggle{color:#999;}#crate-search{color:#555;background-color:white;border-color:#e0e0e0;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input{color:#555;background-color:white;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input:focus{border-color:#66afe9;}.search-focus:disabled{background-color:#e6e6e6;}#crate-search+.search-input:focus{box-shadow:0 0 8px #078dd8;}.module-item .stab{color:#000;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;}.stab.internal{background:#FFB9B3;border-color:#B71C1C;}.stab.deprecated{background:#F3DFFF;border-color:#7F0087;}.stab.portability{background:#C4ECFF;border-color:#7BA5DB;}.stab.portability>code{color:#000;}#help>div{background:#e9e9e9;border-color:#bfbfbf;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:black;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#8959A8;}pre.rust .kw-2,pre.rust .prelude-ty{color:#4271AE;}pre.rust .number,pre.rust .string{color:#718C00;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#C82829;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#B76514;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#c7c7c7;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label{color:#999;}:target>code,:target>.in-band{background:#FDFFD3;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.5);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.5);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.5);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip .tooltiptext{background-color:#000;color:#fff;}.tooltip .tooltiptext::after{border-color:transparent black transparent transparent;}#titles>div:not(.selected){background-color:#e6e6e6;border-top-color:#e6e6e6;}#titles>div:hover,#titles>div.selected{border-top-color:#0089ff;}#titles>div>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#F1F1F1;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#F1F1F1;border-right-color:#000;}#sidebar-filler{background-color:#F1F1F1;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu{border-color:#e0e0e0;background-color:#fff;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus{border-color:#717171;}#theme-choices{border-color:#ccc;background-color:#fff;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#eee;}@media (max-width:700px){#theme-picker{background:#fff;}}#all-types{background-color:#fff;}#all-types:hover{background-color:#f9f9f9;}.search-results td span.alias{color:#000;}.search-results td span.grey{color:#999;}#sidebar-toggle{background-color:#F1F1F1;}#sidebar-toggle:hover{background-color:#E0E0E0;}#source-sidebar{background-color:#F1F1F1;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#E0E0E0;}div.files>.selected{background-color:#fff;}.setting-line>.title{border-bottom-color:#D5D5D5;} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/main.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/main.js new file mode 100644 index 0000000000..0bdb14b511 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/main.js @@ -0,0 +1,7 @@ +if(!String.prototype.startsWith){String.prototype.startsWith=function(searchString,position){position=position||0;return this.indexOf(searchString,position)===position}}if(!String.prototype.endsWith){String.prototype.endsWith=function(suffix,length){var l=length||this.length;return this.indexOf(suffix,l-suffix.length)!==-1}}if(!DOMTokenList.prototype.add){DOMTokenList.prototype.add=function(className){if(className&&!hasClass(this,className)){if(this.className&&this.className.length>0){this.className+=" "+className}else{this.className=className}}}}if(!DOMTokenList.prototype.remove){DOMTokenList.prototype.remove=function(className){if(className&&this.className){this.className=(" "+this.className+" ").replace(" "+className+" "," ").trim()}}}function getSearchInput(){return document.getElementsByClassName("search-input")[0]}function getSearchElement(){return document.getElementById("search")}function focusSearchBar(){getSearchInput().focus()}function defocusSearchBar(){getSearchInput().blur()}(function(){"use strict";var itemTypes=["mod","externcrate","import","struct","enum","fn","type","static","trait","impl","tymethod","method","structfield","variant","macro","primitive","associatedtype","constant","associatedconstant","union","foreigntype","keyword","existential","attr","derive","traitalias"];var disableShortcuts=getCurrentValue("rustdoc-disable-shortcuts")==="true";var search_input=getSearchInput();var searchTimeout=null;var currentTab=0;var mouseMovedAfterSearch=true;var titleBeforeSearch=document.title;function clearInputTimeout(){if(searchTimeout!==null){clearTimeout(searchTimeout);searchTimeout=null}}function getPageId(){if(window.location.hash){var tmp=window.location.hash.replace(/^#/,"");if(tmp.length>0){return tmp}}return null}function showSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){addClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];if(sidebar){addClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(!filler){var div=document.createElement("div");div.id="sidebar-filler";sidebar.appendChild(div)}}var themePickers=document.getElementsByClassName("theme-picker");if(themePickers&&themePickers.length>0){themePickers[0].style.display="none"}}function hideSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){removeClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(filler){filler.remove()}document.getElementsByTagName("body")[0].style.marginTop="";var themePickers=document.getElementsByClassName("theme-picker");if(themePickers&&themePickers.length>0){themePickers[0].style.display=null}}function showSearchResults(search){if(search===null||typeof search==='undefined'){search=getSearchElement()}addClass(main,"hidden");removeClass(search,"hidden");mouseMovedAfterSearch=false}function hideSearchResults(search){if(search===null||typeof search==='undefined'){search=getSearchElement()}addClass(search,"hidden");removeClass(main,"hidden")}var TY_PRIMITIVE=itemTypes.indexOf("primitive");var TY_KEYWORD=itemTypes.indexOf("keyword");function getQueryStringParams(){var params={};window.location.search.substring(1).split("&").map(function(s){var pair=s.split("=");params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params}function browserSupportsHistoryApi(){return window.history&&typeof window.history.pushState==="function"}function isHidden(elem){return elem.offsetHeight===0}var main=document.getElementById("main");var savedHash="";function handleHashes(ev){var elem;var search=getSearchElement();if(ev!==null&&search&&!hasClass(search,"hidden")&&ev.newURL){hideSearchResults(search);var hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(browserSupportsHistoryApi()){history.replaceState(hash,"","?search=#"+hash)}elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}if(savedHash!==window.location.hash){savedHash=window.location.hash;if(savedHash.length===0){return}elem=document.getElementById(savedHash.slice(1));if(!elem||!isHidden(elem)){return}var parent=elem.parentNode;if(parent&&hasClass(parent,"impl-items")){onEachLazy(parent.getElementsByClassName("collapsed"),function(e){if(e.parentNode===parent){e.click();return true}});if(isHidden(elem)){if(hasClass(parent.lastElementChild,"collapse-toggle")){parent.lastElementChild.click()}}}}}function highlightSourceLines(match,ev){if(typeof match==="undefined"){hideSidebar();match=window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/)}if(!match){return}var from=parseInt(match[1],10);var to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(to0){collapseDocs(collapses[0],"show")}}}}function getVirtualKey(ev){if("key"in ev&&typeof ev.key!="undefined"){return ev.key}var c=ev.charCode||ev.keyCode;if(c==27){return"Escape"}return String.fromCharCode(c)}function getHelpElement(){return document.getElementById("help")}function displayHelp(display,ev,help){help=help?help:getHelpElement();if(display===true){if(hasClass(help,"hidden")){ev.preventDefault();removeClass(help,"hidden");addClass(document.body,"blur")}}else if(hasClass(help,"hidden")===false){ev.preventDefault();addClass(help,"hidden");removeClass(document.body,"blur")}}function handleEscape(ev){var help=getHelpElement();var search=getSearchElement();if(hasClass(help,"hidden")===false){displayHelp(false,ev,help)}else if(hasClass(search,"hidden")===false){clearInputTimeout();ev.preventDefault();hideSearchResults(search);document.title=titleBeforeSearch}defocusSearchBar()}function handleShortcut(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts===true){return}if(document.activeElement.tagName==="INPUT"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":displayHelp(false,ev);ev.preventDefault();focusSearchBar();break;case"+":case"-":ev.preventDefault();toggleAllDocs();break;case"?":if(ev.shiftKey){displayHelp(true,ev)}break}}}function findParentElement(elem,tagName){do{if(elem&&elem.tagName===tagName){return elem}elem=elem.parentNode}while(elem);return null}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);function resetMouseMoved(ev){mouseMovedAfterSearch=true}document.addEventListener("mousemove",resetMouseMoved);var handleSourceHighlight=(function(){var prev_line_id=0;var set_fragment=function(name){var x=window.scrollX,y=window.scrollY;if(browserSupportsHistoryApi()){history.replaceState(null,null,"#"+name);highlightSourceLines()}else{location.replace("#"+name)}window.scrollTo(x,y)};return function(ev){var cur_line_id=parseInt(ev.target.id,10);ev.preventDefault();if(ev.shiftKey&&prev_line_id){if(prev_line_id>cur_line_id){var tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());document.addEventListener("click",function(ev){if(hasClass(ev.target,"collapse-toggle")){collapseDocs(ev.target,"toggle")}else if(hasClass(ev.target.parentNode,"collapse-toggle")){collapseDocs(ev.target.parentNode,"toggle")}else if(ev.target.tagName==="SPAN"&&hasClass(ev.target.parentNode,"line-numbers")){handleSourceHighlight(ev)}else if(hasClass(getHelpElement(),"hidden")===false){var help=getHelpElement();var is_inside_help_popup=ev.target!==help&&help.contains(ev.target);if(is_inside_help_popup===false){addClass(help,"hidden");removeClass(document.body,"blur")}}else{var a=findParentElement(ev.target,"A");if(a&&a.hash){expandSection(a.hash.replace(/^#/,""))}}});(function(){var x=document.getElementsByClassName("version-selector");if(x.length>0){x[0].onchange=function(){var i,match,url=document.location.href,stripped="",len=rootPath.match(/\.\.\//g).length+1;for(i=0;i-1){var obj=searchIndex[results[i].id];obj.lev=results[i].lev;if(isType!==true||obj.type){var res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=obj.displayPath+obj.name;obj.fullPath+="|"+obj.ty;obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}}return out}function sortResults(results,isType){var ar=[];for(var entry in results){if(hasOwnProperty(results,entry)){ar.push(results[entry])}}results=ar;var i;var nresults=results.length;for(i=0;ib?+1:-1)}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}if((aaa.item.ty===TY_PRIMITIVE&&bbb.item.ty!==TY_KEYWORD)||(aaa.item.ty===TY_KEYWORD&&bbb.item.ty!==TY_PRIMITIVE)){return-1}if((bbb.item.ty===TY_PRIMITIVE&&aaa.item.ty!==TY_PRIMITIVE)||(bbb.item.ty===TY_KEYWORD&&aaa.item.ty!==TY_KEYWORD)){return 1}a=(aaa.item.desc==="");b=(bbb.item.desc==="");if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});var length=results.length;for(i=0;i"));return{name:val.substring(0,val.indexOf("<")),generics:values.split(/\s*,\s*/),}}return{name:val,generics:[],}}function getObjectFromId(id){if(typeof id==="number"){return searchIndex[id]}return{'name':id}}function checkGenerics(obj,val){var lev_distance=MAX_LEV_DISTANCE+1;if(val.generics.length>0){if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>=val.generics.length){var elems=obj[GENERICS_DATA].slice(0);var total=0;var done=0;var vlength=val.generics.length;for(var y=0;yGENERICS_DATA&&obj[GENERICS_DATA].length>=val.generics.length){var elems=obj[GENERICS_DATA].slice(0);var allFound=true;for(var y=0;allFound===true&&yGENERICS_DATA&&obj[GENERICS_DATA].length!==0){var tmp_lev=checkGenerics(obj,val);if(tmp_lev<=MAX_LEV_DISTANCE){return tmp_lev}}else{return 0}}if(literalSearch===true){if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>0){var length=obj[GENERICS_DATA].length;for(x=0;xGENERICS_DATA&&obj[GENERICS_DATA].length>0){var olength=obj[GENERICS_DATA].length;for(x=0;x0){var length=obj.type[INPUTS_DATA].length;for(var i=0;iOUTPUT_DATA){var ret=obj.type[OUTPUT_DATA];if(typeof ret[0]==="string"){ret=[ret]}for(var x=0;xlength){return MAX_LEV_DISTANCE+1}for(var i=0;ilength){break}var lev_total=0;var aborted=false;for(var x=0;xMAX_LEV_DISTANCE){aborted=true;break}lev_total+=lev}if(aborted===false){ret_lev=Math.min(ret_lev,Math.round(lev_total/clength))}}return ret_lev}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER)return true;if(filter===type)return true;var name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function generateId(ty){if(ty.parent&&ty.parent.name){return itemTypes[ty.ty]+ty.path+ty.parent.name+ty.name}return itemTypes[ty.ty]+ty.path+ty.name}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,desc:item.desc,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,}}function handleAliases(ret,query,filterCrates){var aliases=[];var crateAliases=[];var i;if(filterCrates!==undefined){if(ALIASES[filterCrates]&&ALIASES[filterCrates][query.search]){for(i=0;iMAX_RESULTS){ret.others.pop()}};onEach(aliases,pushFunc);onEach(crateAliases,pushFunc)}var nSearchWords=searchWords.length;var i;var ty;var fullId;var returned;var in_args;if((val.charAt(0)==="\""||val.charAt(0)==="'")&&val.charAt(val.length-1)===val.charAt(0)){val=extractGenerics(val.substr(1,val.length-2));for(i=0;i")>-1){var trimmer=function(s){return s.trim()};var parts=val.split("->").map(trimmer);var input=parts[0];var inputs=input.split(",").map(trimmer).sort();for(i=0;i1?paths.length-1:1);var lev;for(j=0;j1){lev=checkPath(contains,paths[paths.length-1],ty);if(lev>MAX_LEV_DISTANCE){continue}else if(lev>0){lev_add=lev/10}}returned=MAX_LEV_DISTANCE+1;in_args=MAX_LEV_DISTANCE+1;var index=-1;lev=MAX_LEV_DISTANCE+1;fullId=generateId(ty);if(searchWords[j].indexOf(split[i])>-1||searchWords[j].indexOf(val)>-1||searchWords[j].replace(/_/g,"").indexOf(val)>-1){if(typePassesFilter(typeFilter,ty.ty)&&results[fullId]===undefined){index=searchWords[j].replace(/_/g,"").indexOf(val)}}if((lev=levenshtein(searchWords[j],val))<=MAX_LEV_DISTANCE){if(typePassesFilter(typeFilter,ty.ty)===false){lev=MAX_LEV_DISTANCE+1}else{lev+=1}}in_args=findArg(ty,valGenerics,false,typeFilter);returned=checkReturned(ty,valGenerics,false,typeFilter);lev+=lev_add;if(lev>0&&val.length>3&&searchWords[j].indexOf(val)>-1){if(val.length<6){lev-=1}else{lev=0}}if(in_args<=MAX_LEV_DISTANCE){if(results_in_args[fullId]===undefined){results_in_args[fullId]={id:j,index:index,lev:in_args,}}results_in_args[fullId].lev=Math.min(results_in_args[fullId].lev,in_args)}if(returned<=MAX_LEV_DISTANCE){if(results_returned[fullId]===undefined){results_returned[fullId]={id:j,index:index,lev:returned,}}results_returned[fullId].lev=Math.min(results_returned[fullId].lev,returned)}if(index!==-1||lev<=MAX_LEV_DISTANCE){if(index!==-1&&paths.length<2){lev=0}if(results[fullId]===undefined){results[fullId]={id:j,index:index,lev:lev,}}results[fullId].lev=Math.min(results[fullId].lev,lev)}}}var ret={"in_args":sortResults(results_in_args,true),"returned":sortResults(results_returned,true),"others":sortResults(results),};handleAliases(ret,query,filterCrates);return ret}function validateResult(name,path,keys,parent){for(var i=0;i-1||path.indexOf(keys[i])>-1||(parent!==undefined&&parent.name!==undefined&&parent.name.toLowerCase().indexOf(keys[i])>-1)||levenshtein(name,keys[i])<=MAX_LEV_DISTANCE)){return false}}return true}function getQuery(raw){var matches,type,query;query=raw;matches=query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);if(matches){type=matches[1].replace(/^const$/,"constant");query=query.substring(matches[0].length)}return{raw:raw,query:query,type:type,id:query+type}}function initSearchNav(){var hoverTimeout;var click_func=function(e){var el=e.target;while(el.tagName!=="TR"){el=el.parentNode}var dst=e.target.getElementsByTagName("a");if(dst.length<1){return}dst=dst[0];if(window.location.pathname===dst.pathname){hideSearchResults();document.location.href=dst.href}};var mouseover_func=function(e){if(mouseMovedAfterSearch){var el=e.target;while(el.tagName!=="TR"){el=el.parentNode}clearTimeout(hoverTimeout);hoverTimeout=setTimeout(function(){onEachLazy(document.getElementsByClassName("search-results"),function(e){onEachLazy(e.getElementsByClassName("result"),function(i_e){removeClass(i_e,"highlighted")})});addClass(el,"highlighted")},20)}};onEachLazy(document.getElementsByClassName("search-results"),function(e){onEachLazy(e.getElementsByClassName("result"),function(i_e){i_e.onclick=click_func;i_e.onmouseover=mouseover_func})});search_input.onkeydown=function(e){var actives=[[],[],[]];var current=0;onEachLazy(document.getElementById("results").childNodes,function(e){onEachLazy(e.getElementsByClassName("highlighted"),function(e){actives[current].push(e)});current+=1});if(e.which===38){if(!actives[currentTab].length||!actives[currentTab][0].previousElementSibling){return}addClass(actives[currentTab][0].previousElementSibling,"highlighted");removeClass(actives[currentTab][0],"highlighted");e.preventDefault()}else if(e.which===40){if(!actives[currentTab].length){var results=document.getElementById("results").childNodes;if(results.length>0){var res=results[currentTab].getElementsByClassName("result");if(res.length>0){addClass(res[0],"highlighted")}}}else if(actives[currentTab][0].nextElementSibling){addClass(actives[currentTab][0].nextElementSibling,"highlighted");removeClass(actives[currentTab][0],"highlighted")}e.preventDefault()}else if(e.which===13){if(actives[currentTab].length){document.location.href=actives[currentTab][0].getElementsByTagName("a")[0].href}}else if(e.which===9){if(e.shiftKey){printTab(currentTab>0?currentTab-1:2)}else{printTab(currentTab>1?0:currentTab+1)}e.preventDefault()}else if(e.which===16){}else if(actives[currentTab].length>0){removeClass(actives[currentTab][0],"highlighted")}}}function buildHrefAndPath(item){var displayPath;var href;var type=itemTypes[item.ty];var name=item.name;var path=item.path;if(type==="mod"){displayPath=path+"::";href=rootPath+path.replace(/::/g,"/")+"/"+name+"/index.html"}else if(type==="primitive"||type==="keyword"){displayPath="";href=rootPath+path.replace(/::/g,"/")+"/"+type+"."+name+".html"}else if(type==="externcrate"){displayPath="";href=rootPath+name+"/index.html"}else if(item.parent!==undefined){var myparent=item.parent;var anchor="#"+type+"."+name;var parentType=itemTypes[myparent.ty];var pageType=parentType;var pageName=myparent.name;if(parentType==="primitive"){displayPath=myparent.name+"::"}else if(type==="structfield"&&parentType==="variant"){var splitPath=item.path.split("::");var enumName=splitPath.pop();path=splitPath.join("::");displayPath=path+"::"+enumName+"::"+myparent.name+"::";anchor="#variant."+myparent.name+".field."+name;pageType="enum";pageName=enumName}else{displayPath=path+"::"+myparent.name+"::"}href=rootPath+path.replace(/::/g,"/")+"/"+pageType+"."+pageName+".html"+anchor}else{displayPath=item.path+"::";href=rootPath+item.path.replace(/::/g,"/")+"/"+type+"."+name+".html"}return[displayPath,href]}function escape(content){var h1=document.createElement("h1");h1.textContent=content;return h1.innerHTML}function pathSplitter(path){var tmp=""+path.replace(/::/g,"::");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}function addTab(array,query,display){var extraStyle="";if(display===false){extraStyle=" style=\"display: none;\""}var output="";var duplicates={};var length=0;if(array.length>0){output="";array.forEach(function(item){var name,type;name=item.name;type=itemTypes[item.ty];if(item.is_alias!==true){if(duplicates[item.fullPath]){return}duplicates[item.fullPath]=true}length+=1;output+=""});output+="
"+""+(item.is_alias===true?(""+item.alias+"  - see "):"")+item.displayPath+""+name+""+""+""+escape(item.desc)+" 
"}else{output="
No results :(
"+"Try on DuckDuckGo?

"+"Or try looking in one of these:
"}return[output,length]}function makeTabHeader(tabNb,text,nbElems){if(currentTab===tabNb){return"
"+text+"
("+nbElems+")
"}return"
"+text+"
("+nbElems+")
"}function showResults(results){if(results.others.length===1&&getCurrentValue("rustdoc-go-to-only-result")==="true"){var elem=document.createElement("a");elem.href=results.others[0].href;elem.style.display="none";document.body.appendChild(elem);elem.click()}var query=getQuery(search_input.value);currentResults=query.id;var ret_others=addTab(results.others,query);var ret_in_args=addTab(results.in_args,query,false);var ret_returned=addTab(results.returned,query,false);var output="

Results for "+escape(query.query)+(query.type?" (type: "+escape(query.type)+")":"")+"

"+"
"+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
"+ret_others[0]+ret_in_args[0]+ret_returned[0]+"
";var search=getSearchElement();search.innerHTML=output;showSearchResults(search);var tds=search.getElementsByTagName("td");var td_width=0;if(tds.length>0){td_width=tds[0].offsetWidth}var width=search.offsetWidth-40-td_width;onEachLazy(search.getElementsByClassName("desc"),function(e){e.style.width=width+"px"});initSearchNav();var elems=document.getElementById("titles").childNodes;elems[0].onclick=function(){printTab(0)};elems[1].onclick=function(){printTab(1)};elems[2].onclick=function(){printTab(2)};printTab(currentTab)}function execSearch(query,searchWords,filterCrates){function getSmallest(arrays,positions,notDuplicates){var start=null;for(var it=0;itpositions[it]&&(start===null||start>arrays[it][positions[it]].lev)&&!notDuplicates[arrays[it][positions[it]].fullPath]){start=arrays[it][positions[it]].lev}}return start}function mergeArrays(arrays){var ret=[];var positions=[];var notDuplicates={};for(var x=0;xpositions[x]&&arrays[x][positions[x]].lev===smallest&&!notDuplicates[arrays[x][positions[x]].fullPath]){ret.push(arrays[x][positions[x]]);notDuplicates[arrays[x][positions[x]].fullPath]=true;positions[x]+=1}}}return ret}var queries=query.raw.split(",");var results={"in_args":[],"returned":[],"others":[],};for(var i=0;i1){return{"in_args":mergeArrays(results.in_args),"returned":mergeArrays(results.returned),"others":mergeArrays(results.others),}}return{"in_args":results.in_args[0],"returned":results.returned[0],"others":results.others[0],}}function getFilterCrates(){var elem=document.getElementById("crate-search");if(elem&&elem.value!=="All crates"&&hasOwnProperty(rawSearchIndex,elem.value)){return elem.value}return undefined}function search(e,forced){var params=getQueryStringParams();var query=getQuery(search_input.value.trim());if(e){e.preventDefault()}if(query.query.length===0){return}if(forced!==true&&query.id===currentResults){if(query.query.length>0){putBackSearch(search_input)}return}document.title="Results for "+query.query+" - Rust";if(browserSupportsHistoryApi()){if(!history.state&&!params.search){history.pushState(query,"","?search="+encodeURIComponent(query.raw))}else{history.replaceState(query,"","?search="+encodeURIComponent(query.raw))}}var filterCrates=getFilterCrates();showResults(execSearch(query,index,filterCrates))}function buildIndex(rawSearchIndex){searchIndex=[];var searchWords=[];var i;var currentIndex=0;for(var crate in rawSearchIndex){if(!hasOwnProperty(rawSearchIndex,crate)){continue}var crateSize=0;searchWords.push(crate);searchIndex.push({crate:crate,ty:1,name:crate,path:"",desc:rawSearchIndex[crate].doc,type:null,});currentIndex+=1;var items=rawSearchIndex[crate].i;var paths=rawSearchIndex[crate].p;var aliases=rawSearchIndex[crate].a;var len=paths.length;for(i=0;i0){search_input.value=params.search;search(e)}else{search_input.value="";hideSearchResults()}})}search()}index=buildIndex(rawSearchIndex);startSearch();if(rootPath==="../"||rootPath==="./"){var sidebar=document.getElementsByClassName("sidebar-elems")[0];if(sidebar){var div=document.createElement("div");div.className="block crate";div.innerHTML="

Crates

";var ul=document.createElement("ul");div.appendChild(ul);var crates=[];for(var crate in rawSearchIndex){if(!hasOwnProperty(rawSearchIndex,crate)){continue}crates.push(crate)}crates.sort();for(var i=0;i"+""+"
"+code.outerHTML+"
";list.appendChild(display)}}};if(window.pending_implementors){window.register_implementors(window.pending_implementors)}function labelForToggleButton(sectionIsCollapsed){if(sectionIsCollapsed){return"+"}return"\u2212"}function onEveryMatchingChild(elem,className,func){if(elem&&className&&func){var length=elem.childNodes.length;var nodes=elem.childNodes;for(var i=0;i"+labelForToggleButton(sectionIsCollapsed)+"
]";return toggle}function createToggle(toggle,otherMessage,fontSize,extraClass,show){var span=document.createElement("span");span.className="toggle-label";if(show){span.style.display="none"}if(!otherMessage){span.innerHTML=" Expand description"}else{span.innerHTML=otherMessage}if(fontSize){span.style.fontSize=fontSize}var mainToggle=toggle.cloneNode(true);mainToggle.appendChild(span);var wrapper=document.createElement("div");wrapper.className="toggle-wrapper";if(!show){addClass(wrapper,"collapsed");var inner=mainToggle.getElementsByClassName("inner");if(inner&&inner.length>0){inner[0].innerHTML="+"}}if(extraClass){addClass(wrapper,extraClass)}wrapper.appendChild(mainToggle);return wrapper}(function(){var toggle=createSimpleToggle(false);var hideMethodDocs=getCurrentValue("rustdoc-auto-hide-method-docs")==="true";var pageId=getPageId();var func=function(e){var next=e.nextElementSibling;if(!next){return}if(hasClass(next,"docblock")===true||(hasClass(next,"stability")===true&&hasClass(next.nextElementSibling,"docblock")===true)){var newToggle=toggle.cloneNode(true);insertAfter(newToggle,e.childNodes[e.childNodes.length-1]);if(hideMethodDocs===true&&hasClass(e,"method")===true){collapseDocs(newToggle,"hide",pageId)}}};var funcImpl=function(e){var next=e.nextElementSibling;if(next&&hasClass(next,"docblock")){next=next.nextElementSibling}if(!next){return}if(hasClass(e,"impl")&&(next.getElementsByClassName("method").length>0||next.getElementsByClassName("associatedconstant").length>0)){insertAfter(toggle.cloneNode(true),e.childNodes[e.childNodes.length-1])}};onEachLazy(document.getElementsByClassName("method"),func);onEachLazy(document.getElementsByClassName("associatedconstant"),func);onEachLazy(document.getElementsByClassName("impl"),funcImpl);var impl_call=function(){};if(hideMethodDocs===true){impl_call=function(e,newToggle){if(e.id.match(/^impl(?:-\d+)?$/)===null){if(hasClass(e,"impl")===true){collapseDocs(newToggle,"hide",pageId)}}}}var newToggle=document.createElement("a");newToggle.href="javascript:void(0)";newToggle.className="collapse-toggle hidden-default collapsed";newToggle.innerHTML="["+labelForToggleButton(true)+"] Show hidden undocumented items";function toggleClicked(){if(hasClass(this,"collapsed")){removeClass(this,"collapsed");onEachLazy(this.parentNode.getElementsByClassName("hidden"),function(x){if(hasClass(x,"content")===false){removeClass(x,"hidden");addClass(x,"x")}},true);this.innerHTML="["+labelForToggleButton(false)+"] Hide undocumented items"}else{addClass(this,"collapsed");onEachLazy(this.parentNode.getElementsByClassName("x"),function(x){if(hasClass(x,"content")===false){addClass(x,"hidden");removeClass(x,"x")}},true);this.innerHTML="["+labelForToggleButton(true)+"] Show hidden undocumented items"}}onEachLazy(document.getElementsByClassName("impl-items"),function(e){onEachLazy(e.getElementsByClassName("associatedconstant"),func);var hiddenElems=e.getElementsByClassName("hidden");var needToggle=false;var hlength=hiddenElems.length;for(var i=0;iLoading search results...";showSearchResults(search)}var sidebar_menu=document.getElementsByClassName("sidebar-menu")[0];if(sidebar_menu){sidebar_menu.onclick=function(){var sidebar=document.getElementsByClassName("sidebar")[0];if(hasClass(sidebar,"mobile")===true){hideSidebar()}else{showSidebar()}}}window.onresize=function(){hideSidebar()};if(main){onEachLazy(main.getElementsByClassName("loading-content"),function(e){e.remove()});onEachLazy(main.childNodes,function(e){if(e.tagName==="H2"||e.tagName==="H3"){var nextTagName=e.nextElementSibling.tagName;if(nextTagName=="H2"||nextTagName=="H3"){e.nextElementSibling.style.display="flex"}else{e.nextElementSibling.style.display="block"}}})}window.addSearchOptions=function(crates){var elem=document.getElementById("crate-search");if(!elem){return}var crates_text=[];if(Object.keys(crates).length>1){for(var crate in crates){if(hasOwnProperty(crates,crate)){crates_text.push(crate)}}}crates_text.sort(function(a,b){var lower_a=a.toLowerCase();var lower_b=b.toLowerCase();if(lower_alower_b){return 1}return 0});var savedCrate=getCurrentValue("rustdoc-saved-filter-crate");for(var i=0;i"
"+x[0]+"
"+x[1]+"
").join("");var div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

Keyboard Shortcuts

"+shortcuts+"
";var infos=["Prefix searches with a type followed by a colon (e.g., fn:) to \ + restrict the search to a given type.","Accepted types are: fn, mod, struct, \ + enum, trait, type, macro, \ + and const.","Search functions by type signature (e.g., vec -> usize or \ + * -> vec)","Search multiple things at once by splitting your query with comma (e.g., \ + str,u8 or String,struct:Vec,test)","You can look for items with an exact name by putting double quotes around \ + your request: \"string\"","Look for items inside another one by searching for a path: vec::Vec",].map(x=>"

"+x+"

").join("");var div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

Search Tricks

"+infos;container.appendChild(div_shortcuts);container.appendChild(div_infos);popup.appendChild(container);insertAfter(popup,getSearchElement())}onHashChange(null);window.onhashchange=onHashChange;buildHelperPopup()}());window.onunload=function(){} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/normalize.css b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/normalize.css new file mode 100644 index 0000000000..45b6cb2638 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/normalize.css @@ -0,0 +1,2 @@ +/*! normalize.css v3.0.0 | MIT License | git.io/normalize */ +html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/noscript.css b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/noscript.css new file mode 100644 index 0000000000..351b41cf8e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/noscript.css @@ -0,0 +1 @@ +#main>h2+div,#main>h2+h3,#main>h3+div{display:block;}.loading-content{display:none;}#main>h2+div,#main>h3+div{display:block;}#main>h2+h3{display:flex;} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/rust-logo.png b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/rust-logo.png new file mode 100644 index 0000000000..74b4bd6950 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/rust-logo.png differ diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/rustdoc.css b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/rustdoc.css new file mode 100644 index 0000000000..cbf40b2271 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/rustdoc.css @@ -0,0 +1 @@ + @font-face {font-family:'Fira Sans';font-style:normal;font-weight:400;src:local('Fira Sans'),url("FiraSans-Regular.woff") format('woff');}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:500;src:local('Fira Sans Medium'),url("FiraSans-Medium.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:normal;font-weight:400;src:local('Source Serif Pro'),url("SourceSerifPro-Regular.ttf.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:italic;font-weight:400;src:local('Source Serif Pro Italic'),url("SourceSerifPro-It.ttf.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:normal;font-weight:700;src:local('Source Serif Pro Bold'),url("SourceSerifPro-Bold.ttf.woff") format('woff');}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("SourceCodePro-Regular.woff") format('woff');}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("SourceCodePro-Semibold.woff") format('woff');}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}html{content:"";}@media (prefers-color-scheme:light){html{content:"light";}}@media (prefers-color-scheme:dark){html{content:"dark";}}body{font:16px/1.4 "Source Serif Pro",serif;margin:0;position:relative;padding:10px 15px 20px 15px;-webkit-font-feature-settings:"kern","liga";-moz-font-feature-settings:"kern","liga";font-feature-settings:"kern","liga";}h1{font-size:1.5em;}h2{font-size:1.4em;}h3{font-size:1.3em;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod):not(.important),h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){font-weight:500;margin:20px 0 15px 0;padding-bottom:6px;}h1.fqn{border-bottom:1px dashed;margin-top:0;}h1.fqn>.in-band>a:hover{text-decoration:underline;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){border-bottom:1px solid;}h3.impl,h3.method,h4.method,h3.type,h4.type,h4.associatedconstant{flex-basis:100%;font-weight:600;margin-top:16px;margin-bottom:10px;position:relative;}h3.impl,h3.method,h3.type{padding-left:15px;}h1,h2,h3,h4,.sidebar,a.source,.search-input,.content table :not(code)>a,.collapse-toggle,div.item-list .out-of-band,#source-sidebar,#sidebar-toggle{font-family:"Fira Sans",sans-serif;}ol,ul{padding-left:25px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:.6em;}p{margin:0 0 .6em 0;}summary{outline:none;}code,pre,a.test-arrow{font-family:"Source Code Pro",monospace;}.docblock code,.docblock-short code{border-radius:3px;padding:0 0.1em;}.docblock pre code,.docblock-short pre code{padding:0;}pre{padding:14px;}.source .content pre{padding:20px;}img{max-width:100%;}li{position:relative;}.source .content{margin-top:50px;max-width:none;overflow:visible;margin-left:0px;min-width:70em;}nav.sub{font-size:16px;text-transform:uppercase;}.sidebar{width:200px;position:fixed;left:0;top:0;bottom:0;overflow:auto;}*{scrollbar-width:initial;}.sidebar{scrollbar-width:thin;}::-webkit-scrollbar{width:12px;}.sidebar::-webkit-scrollbar{width:8px;}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0;}.sidebar .block>ul>li{margin-right:-10px;}.content,nav{max-width:960px;}.hidden{display:none !important;}.logo-container{height:100px;width:100px;position:relative;margin:20px auto;display:block;margin-top:10px;}.logo-container>img{max-width:100px;max-height:100px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);display:block;}.sidebar .location{border:1px solid;font-size:17px;margin:30px 10px 20px 10px;text-align:center;word-wrap:break-word;}.sidebar .version{font-size:15px;text-align:center;border-bottom:1px solid;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;}.location:empty{border:none;}.location a:first-child{font-weight:500;}.block{padding:0;margin-bottom:14px;}.block h2,.block h3{margin-top:0;margin-bottom:8px;text-align:center;}.block ul,.block li{margin:0 10px;padding:0;list-style:none;}.block a{display:block;text-overflow:ellipsis;overflow:hidden;line-height:15px;padding:7px 5px;font-size:14px;font-weight:300;transition:border 500ms ease-out;}.sidebar-title{border-top:1px solid;border-bottom:1px solid;text-align:center;font-size:17px;margin-bottom:5px;}.sidebar-links{margin-bottom:15px;}.sidebar-links>a{padding-left:10px;width:100%;}.sidebar-menu{display:none;}.content{padding:15px 0;}.source .content pre.rust{white-space:pre;overflow:auto;padding-left:0;}.rustdoc:not(.source) .example-wrap{display:inline-flex;margin-bottom:10px;position:relative;}.example-wrap{width:100%;}.example-wrap>pre.line-number{overflow:initial;border:1px solid;border-top-left-radius:5px;border-bottom-left-radius:5px;padding:13px 8px;text-align:right;}.rustdoc:not(.source) .example-wrap>pre.rust{width:100%;overflow-x:auto;}.rustdoc:not(.source) .example-wrap>pre{margin:0;}#search{margin-left:230px;position:relative;}#results{position:absolute;right:0;left:0;overflow:auto;}#results>table{width:100%;table-layout:fixed;}.content pre.line-numbers{float:left;border:none;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}.line-numbers span{cursor:pointer;}.docblock-short p{display:inline;}.docblock-short.nowrap{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.docblock-short p{overflow:hidden;text-overflow:ellipsis;margin:0;}.docblock code,.docblock-short code{white-space:pre-wrap;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom:1px solid;}#main>.docblock h1{font-size:1.3em;}#main>.docblock h2{font-size:1.15em;}#main>.docblock h3,#main>.docblock h4,#main>.docblock h5{font-size:1em;}#main>h2+div,#main>h2+h3,#main>h3+div{display:none;flex-wrap:wrap;}.docblock h1{font-size:1em;}.docblock h2{font-size:0.95em;}.docblock h3,.docblock h4,.docblock h5{font-size:0.9em;}.docblock{margin-left:24px;position:relative;}.content .out-of-band{float:right;font-size:23px;margin:0px;padding:0px;font-weight:normal;}h3.impl>.out-of-band{font-size:21px;}h4.method>.out-of-band{font-size:19px;}h4>code,h3>code,.invisible>code{max-width:calc(100% - 41px);display:block;}.invisible{width:100%;display:inline-block;}.content .in-band{margin:0px;padding:0px;}.in-band>code{display:inline-block;}#main{position:relative;}#main>.since{top:inherit;font-family:"Fira Sans",sans-serif;}.content table:not(.table-display){border-spacing:0 5px;}.content td{vertical-align:top;}.content td:first-child{padding-right:20px;}.content td p:first-child{margin-top:0;}.content td h1,.content td h2{margin-left:0;font-size:1.1em;}.content tr:first-child td{border-top:0;}.docblock table{margin:.5em 0;width:calc(100% - 2px);border:1px dashed;}.docblock table td{padding:.5em;border:1px dashed;}.docblock table th{padding:.5em;text-align:left;border:1px solid;}.fields+table{margin-bottom:1em;}.content .item-list{list-style-type:none;padding:0;}.content .multi-column{-moz-column-count:5;-moz-column-gap:2.5em;-webkit-column-count:5;-webkit-column-gap:2.5em;column-count:5;column-gap:2.5em;}.content .multi-column li{width:100%;display:inline-block;}.content .method{font-size:1em;position:relative;}.content .method .where,.content .fn .where,.content .where.fmt-newline{display:block;font-size:0.8em;}.content .methods>div{margin-left:40px;margin-bottom:15px;}.content .docblock>.impl-items{margin-left:20px;margin-top:-34px;}.content .docblock>.impl-items>h4{border-bottom:0;}.content .docblock>.impl-items .table-display{margin:0;}.content .docblock>.impl-items table td{padding:0;}.toggle-wrapper.marg-left>.collapse-toggle{left:-24px;}.content .docblock>.impl-items .table-display,.impl-items table td{border:none;}.content .stability code{font-size:90%;}.content .stability{position:relative;margin-left:33px;margin-top:-13px;}.sub-variant>div>.stability{margin-top:initial;}.content .stability::before{content:'⬑';font-size:25px;position:absolute;top:-6px;left:-19px;}.content .impl-items .method,.content .impl-items>.type,.impl-items>.associatedconstant{margin-left:20px;}.content .impl-items .docblock,.content .impl-items .stability{margin-bottom:.6em;}.content .impl-items>.stability{margin-left:40px;}.methods>.stability,.content .impl-items>.stability{margin-top:-8px;}.impl-items{flex-basis:100%;}#main>.stability{margin-top:0;}nav:not(.sidebar){border-bottom:1px solid;padding-bottom:10px;margin-bottom:10px;}nav.main{padding:20px 0;text-align:center;}nav.main .current{border-top:1px solid;border-bottom:1px solid;}nav.main .separator{border:1px solid;display:inline-block;height:23px;margin:0 20px;}nav.sum{text-align:right;}nav.sub form{display:inline;}nav.sub,.content{margin-left:230px;}a{text-decoration:none;background:transparent;}.small-section-header:hover>.anchor{display:initial;}.in-band:hover>.anchor,.impl:hover>.anchor{display:inline-block;position:absolute;}.anchor{display:none;position:absolute;left:-7px;}.anchor.field{left:-5px;}.small-section-header>.anchor{left:-28px;padding-right:10px;}.anchor:before{content:'\2002\00a7\2002';}.docblock a:not(.srclink):not(.test-arrow):hover,.docblock-short a:not(.srclink):not(.test-arrow):hover,.stability a{text-decoration:underline;}.invisible>.srclink,h4>code+.srclink{position:absolute;top:0;right:0;font-size:17px;font-weight:normal;}.block a.current.crate{font-weight:500;}.search-container{position:relative;}.search-container>div{display:inline-flex;width:calc(100% - 34px);}#crate-search{margin-top:5px;padding:6px;padding-right:19px;flex:none;border:0;border-right:0;border-radius:4px 0 0 4px;outline:none;cursor:pointer;border-right:1px solid;-moz-appearance:none;-webkit-appearance:none;text-indent:0.01px;text-overflow:"";background-repeat:no-repeat;background-color:transparent;background-size:20px;background-position:calc(100% - 1px) 56%;}.search-container>.top-button{position:absolute;right:0;top:10px;}.search-input{-moz-box-sizing:border-box !important;box-sizing:border-box !important;outline:none;border:none;border-radius:1px;margin-top:5px;padding:10px 16px;font-size:17px;transition:border-color 300ms ease;transition:border-radius 300ms ease-in-out;transition:box-shadow 300ms ease-in-out;width:100%;}#crate-search+.search-input{border-radius:0 1px 1px 0;width:calc(100% - 32px);}.search-input:focus{border-radius:2px;border:0;outline:0;}.search-results .desc{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;display:block;}.search-results a{display:block;}.content .search-results td:first-child{padding-right:0;width:50%;}.content .search-results td:first-child a{padding-right:10px;}.content .search-results td:first-child a:after{clear:both;content:"";display:block;}.content .search-results td:first-child a span{float:left;}tr.result span.primitive::after{content:' (primitive type)';font-style:italic;}tr.result span.keyword::after{content:' (keyword)';font-style:italic;}body.blur>:not(#help){filter:blur(8px);-webkit-filter:blur(8px);opacity:.7;}#help{width:100%;height:100vh;position:fixed;top:0;left:0;display:flex;justify-content:center;align-items:center;}#help>div{flex:0 0 auto;box-shadow:0 0 6px rgba(0,0,0,.2);width:550px;height:auto;border:1px solid;}#help dt{float:left;clear:left;display:block;}#help dd{margin:5px 35px;}#help .infos{padding-left:0;}#help h1,#help h2{margin-top:0;}#help>div div{width:50%;float:left;padding:20px;padding-left:17px;}.stab{display:table;border-width:1px;border-style:solid;padding:3px;margin-bottom:5px;font-size:90%;}.stab p{display:inline;}.stab summary{display:list-item;}.stab .emoji{font-size:1.5em;}.module-item .stab{border-radius:3px;display:inline-block;font-size:80%;line-height:1.2;margin-bottom:0;margin-right:.3em;padding:2px;vertical-align:text-bottom;}.module-item.unstable{opacity:0.65;}.since{font-weight:normal;font-size:initial;position:absolute;right:0;top:0;}.impl-items .since,.impl .since{flex-grow:0;padding-left:12px;padding-right:2px;position:initial;}.impl-items .srclink,.impl .srclink{flex-grow:0;font-size:17px;font-weight:normal;}.impl-items code,.impl code{flex-grow:1;}.impl-items h4,h4.impl,h3.impl{display:flex;flex-basis:100%;font-size:16px;margin-bottom:12px;justify-content:space-between;}.variants_table{width:100%;}.variants_table tbody tr td:first-child{width:1%;}td.summary-column{width:100%;}.summary{padding-right:0px;}pre.rust .question-mark{font-weight:bold;}a.test-arrow{display:inline-block;position:absolute;padding:5px 10px 5px 10px;border-radius:5px;font-size:130%;top:5px;right:5px;z-index:1;}a.test-arrow:hover{text-decoration:none;}.section-header:hover a:before{position:absolute;left:-25px;padding-right:10px;content:'\2002\00a7\2002';}.section-header:hover a{text-decoration:none;}.section-header a{color:inherit;}.collapse-toggle{font-weight:300;position:absolute;left:-23px;top:0;}h3>.collapse-toggle,h4>.collapse-toggle{font-size:0.8em;top:5px;}.toggle-wrapper>.collapse-toggle{left:-24px;margin-top:0px;}.toggle-wrapper{position:relative;margin-top:0;}.toggle-wrapper.collapsed{height:25px;transition:height .2s;margin-bottom:.6em;}.collapse-toggle>.inner{display:inline-block;width:1.2ch;text-align:center;}.collapse-toggle.hidden-default{position:relative;margin-left:20px;}.since+.srclink{display:table-cell;padding-left:10px;}.item-spacer{width:100%;height:12px;}.out-of-band>span.since{position:initial;font-size:20px;margin-right:5px;}.toggle-wrapper>.collapse-toggle{left:0;}.variant+.toggle-wrapper+.docblock>p{margin-top:5px;}.sub-variant,.sub-variant>h3{margin-top:1px !important;}#main>.sub-variant>h3{font-size:15px;margin-left:25px;margin-bottom:5px;}.sub-variant>div{margin-left:20px;margin-bottom:10px;}.sub-variant>div>span{display:block;position:relative;}.toggle-label{display:inline-block;margin-left:4px;margin-top:3px;}.enum>.toggle-wrapper+.docblock,.struct>.toggle-wrapper+.docblock{margin-left:30px;margin-bottom:20px;margin-top:5px;}.docblock>.section-header:first-child{margin-left:15px;margin-top:0;}.docblock>.section-header:first-child:hover>a:before{left:-10px;}.enum>.collapsed,.struct>.collapsed{margin-bottom:25px;}#main>.variant,#main>.structfield{display:block;}.attributes{display:block;margin-top:0px !important;margin-right:0px;margin-bottom:0px !important;margin-left:30px;}.toggle-attributes.collapsed{margin-bottom:0;}.impl-items>.toggle-attributes{margin-left:20px;}.impl-items .attributes{font-weight:500;}:target>code{opacity:1;}.information{position:absolute;left:-25px;margin-top:7px;z-index:1;}.tooltip{position:relative;display:inline-block;cursor:pointer;}.tooltip .tooltiptext{width:120px;display:none;text-align:center;padding:5px 3px 3px 3px;border-radius:6px;margin-left:5px;top:-5px;left:105%;z-index:10;font-size:16px;}.tooltip:hover .tooltiptext{display:inline;}.tooltip .tooltiptext::after{content:" ";position:absolute;top:50%;left:16px;margin-top:-5px;border-width:5px;border-style:solid;}.tooltip.compile_fail,.tooltip.should_panic,.tooltip.ignore{font-weight:bold;font-size:20px;}.tooltip .tooltiptext{border:1px solid;font-weight:normal;}pre.rust{position:relative;tab-size:4;-moz-tab-size:4;}.search-failed{text-align:center;margin-top:20px;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#titles{height:35px;}#titles>div{float:left;width:33.3%;text-align:center;font-size:18px;cursor:pointer;border-top:2px solid;}#titles>div:not(:last-child){margin-right:1px;width:calc(33.3% - 1px);}#titles>div>div.count{display:inline-block;font-size:16px;}#all-types{text-align:center;border:1px solid;margin:0 10px;margin-bottom:10px;display:block;border-radius:7px;}#all-types>p{margin:5px 0;}#sidebar-toggle{position:fixed;top:30px;left:300px;z-index:10;padding:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;cursor:pointer;font-weight:bold;transition:left .5s;font-size:1.2em;border:1px solid;border-left:0;}#source-sidebar{position:fixed;top:0;bottom:0;left:0;width:300px;z-index:1;overflow:auto;transition:left .5s;border-right:1px solid;}#source-sidebar>.title{font-size:1.5em;text-align:center;border-bottom:1px solid;margin-bottom:6px;}.theme-picker{position:absolute;left:211px;top:19px;}.theme-picker button{outline:none;}#settings-menu{position:absolute;right:0;top:10px;outline:none;}#theme-picker,#settings-menu{padding:4px;width:27px;height:29px;border:1px solid;border-radius:3px;cursor:pointer;}#theme-choices{display:none;position:absolute;left:0;top:28px;border:1px solid;border-radius:3px;z-index:1;cursor:pointer;}#theme-choices>button{border:none;width:100%;padding:4px;text-align:center;background:rgba(0,0,0,0);}#theme-choices>button:not(:first-child){border-top:1px solid;}@media (max-width:700px){body{padding-top:0px;}.rustdoc>.sidebar{height:45px;min-height:40px;margin:0;margin-left:-15px;padding:0 15px;position:static;z-index:11;}.sidebar>.location{float:right;margin:0px;margin-top:2px;padding:3px 10px 1px 10px;min-height:39px;background:inherit;text-align:left;font-size:24px;}.sidebar .location:empty{padding:0;}.sidebar .logo-container{width:35px;height:35px;margin-top:5px;margin-bottom:5px;float:left;margin-left:50px;}.sidebar .logo-container>img{max-width:35px;max-height:35px;}.sidebar-menu{position:fixed;z-index:10;font-size:2rem;cursor:pointer;width:45px;left:0;text-align:center;display:block;border-bottom:1px solid;border-right:1px solid;height:45px;}.rustdoc.source>.sidebar>.sidebar-menu{display:none;}.sidebar-elems{position:fixed;z-index:1;left:0;top:45px;bottom:0;overflow-y:auto;border-right:1px solid;display:none;}.sidebar>.block.version{border-bottom:none;margin-top:12px;}nav.sub{width:calc(100% - 32px);float:right;}.content{margin-left:0px;}#main{margin-top:45px;padding:0;}.content .in-band{width:100%;}.content h4>.out-of-band{position:inherit;}.toggle-wrapper>.collapse-toggle{left:0px;}.toggle-wrapper{height:1.5em;}#search{margin-left:0;}.content .impl-items .method,.content .impl-items>.type,.impl-items>.associatedconstant{display:flex;}.anchor{display:none !important;}h1.fqn{overflow:initial;}.theme-picker{left:10px;top:54px;z-index:1;}#titles>div>div.count{float:left;width:100%;}#titles{height:50px;}.sidebar.mobile{position:fixed;width:100%;margin-left:0;background-color:rgba(0,0,0,0);height:100%;}.sidebar{width:calc(100% + 30px);}.show-it{display:block;width:246px;}.show-it>.block.items{margin:8px 0;}.show-it>.block.items>ul{margin:0;}.show-it>.block.items>ul>li{text-align:center;margin:2px 0;}.show-it>.block.items>ul>li>a{font-size:21px;}#sidebar-filler{position:fixed;left:45px;width:calc(100% - 45px);top:0;height:45px;z-index:-1;border-bottom:1px solid;}.collapse-toggle{left:-20px;}.impl>.collapse-toggle{left:-10px;}#all-types{margin:10px;}#sidebar-toggle{top:100px;width:30px;font-size:1.5rem;text-align:center;padding:0;}#source-sidebar{z-index:11;}#main>.line-numbers{margin-top:0;}}@media print{nav.sub,.content .out-of-band,.collapse-toggle{display:none;}}@media (max-width:416px){#titles{height:73px;}#titles>div{height:73px;}}h3.important{margin:0;margin-bottom:13px;font-size:19px;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px;border-radius:3px;box-shadow:inset 0 -1px 0;cursor:default;}.hidden-by-impl-hider,.hidden-by-usual-hider{display:none !important;}#implementations-list>h3>span.in-band{width:100%;}.table-display{width:100%;border:0;border-collapse:collapse;border-spacing:0;font-size:16px;}.table-display tr td:first-child{padding-right:0;}.table-display tr td:last-child{float:right;}.table-display .out-of-band{position:relative;font-size:19px;display:block;}#implementors-list>.impl-items .table-display .out-of-band{font-size:17px;}.table-display td:hover .anchor{display:block;top:2px;left:-5px;}#main>ul{padding-left:10px;}#main>ul>li{list-style:none;}.non-exhaustive{margin-bottom:1em;}div.children{padding-left:27px;display:none;}div.name{cursor:pointer;position:relative;margin-left:16px;}div.files>a{display:block;padding:0 3px;}div.files>a:hover,div.name:hover{background-color:#a14b4b;}div.name.expand+.children{display:block;}div.name::before{content:"\25B6";padding-left:4px;font-size:0.7em;position:absolute;left:-16px;top:4px;}div.name.expand::before{transform:rotate(90deg);left:-15px;top:2px;}.type-decl>pre>.toggle-wrapper.toggle-attributes.top-attr{margin-left:0 !important;}.type-decl>pre>.docblock.attributes.top-attr{margin-left:1.8em !important;}.type-decl>pre>.toggle-attributes{margin-left:2.2em;}.type-decl>pre>.docblock.attributes{margin-left:4em;} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/search-index.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/search-index.js new file mode 100644 index 0000000000..ee6d03afb2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/search-index.js @@ -0,0 +1,4 @@ +var searchIndex = JSON.parse('{\ +"bdk":{"doc":"","i":[[3,"FeeRate","bdk","Fee rate",null,null],[3,"UTXO","","A wallet unspent output",null,null],[12,"outpoint","","",0,null],[12,"txout","","",0,null],[12,"is_internal","","",0,null],[3,"TransactionDetails","","A wallet transaction",null,null],[12,"transaction","","",1,null],[12,"txid","","",1,null],[12,"timestamp","","",1,null],[12,"received","","",1,null],[12,"sent","","",1,null],[12,"fees","","",1,null],[12,"height","","",1,null],[4,"Error","","Errors that can be thrown by the `Wallet`",null,null],[13,"KeyMismatch","","",2,null],[13,"MissingInputUTXO","","",2,null],[13,"InvalidU32Bytes","","",2,null],[13,"Generic","","",2,null],[13,"ScriptDoesntHaveAddressForm","","",2,null],[13,"SendAllMultipleOutputs","","",2,null],[13,"NoAddressees","","",2,null],[13,"OutputBelowDustLimit","","",2,null],[13,"InsufficientFunds","","",2,null],[13,"InvalidAddressNetwork","","",2,null],[13,"UnknownUTXO","","",2,null],[13,"DifferentTransactions","","",2,null],[13,"TransactionNotFound","","",2,null],[13,"TransactionConfirmed","","",2,null],[13,"IrreplaceableTransaction","","",2,null],[13,"FeeRateTooLow","","",2,null],[12,"required","bdk::Error","",3,null],[13,"ChecksumMismatch","bdk","",2,null],[13,"DifferentDescriptorStructure","","",2,null],[13,"SpendingPolicyRequired","","",2,null],[13,"InvalidPolicyPathError","","",2,null],[13,"Signer","","",2,null],[13,"Uncapable","","",2,null],[13,"OfflineClient","","",2,null],[13,"InvalidProgressValue","","",2,null],[13,"ProgressUpdateError","","",2,null],[13,"MissingCachedAddresses","","",2,null],[13,"InvalidOutpoint","","",2,null],[13,"Descriptor","","",2,null],[13,"AddressValidator","","",2,null],[13,"Encode","","",2,null],[13,"Miniscript","","",2,null],[13,"BIP32","","",2,null],[13,"Secp256k1","","",2,null],[13,"JSON","","",2,null],[13,"Hex","","",2,null],[13,"PSBT","","",2,null],[13,"Electrum","","",2,null],[13,"Esplora","","",2,null],[13,"CompactFilters","","",2,null],[13,"Sled","","",2,null],[4,"ScriptType","","Types of script",null,null],[13,"External","","",4,null],[13,"Internal","","",4,null],[0,"blockchain","","Blockchain backends",null,null],[3,"OfflineBlockchain","bdk::blockchain","Type that only implements [`Blockchain`] and is always…",null,null],[3,"NoopProgress","","Type that implements [`Progress`] and drops every update…",null,null],[3,"LogProgress","","Type that implements [`Progress`] and logs at level `INFO`…",null,null],[4,"Capability","","Capabilities that can be supported by a [`Blockchain`]…",null,null],[13,"FullHistory","","Can recover the full history of a wallet and not only the…",5,null],[13,"GetAnyTx","","Can fetch any historical transaction given its txid",5,null],[13,"AccurateFees","","Can compute accurate fees for the transactions found…",5,null],[5,"progress","","Shortcut to create a [`channel`] (pair of [`Sender`] and…",null,[[]]],[5,"noop_progress","","Create a new instance of [`NoopProgress`]",null,[[],["noopprogress",3]]],[5,"log_progress","","Create a nwe instance of [`LogProgress`]",null,[[],["logprogress",3]]],[0,"electrum","","Electrum",null,null],[3,"ElectrumBlockchain","bdk::blockchain::electrum","Wrapper over an Electrum Client that implements the…",null,null],[0,"esplora","bdk::blockchain","Esplora",null,null],[3,"EsploraBlockchain","bdk::blockchain::esplora","Structure that implements the logic to sync with Esplora",null,null],[4,"EsploraError","","Errors that can happen during a sync with…",null,null],[13,"Reqwest","","Error with the HTTP call",6,null],[13,"Parsing","","Invalid number returned",6,null],[13,"BitcoinEncoding","","Invalid Bitcoin data returned",6,null],[13,"TransactionNotFound","","Transaction not found",6,null],[11,"new","","Create a new instance of the client from a base URL",7,[[]]],[0,"compact_filters","bdk::blockchain","Compact Filters",null,null],[3,"Mempool","bdk::blockchain::compact_filters","Container for unconfirmed, but valid Bitcoin transactions",null,null],[3,"Peer","","A Bitcoin peer",null,null],[3,"CompactFiltersBlockchain","","Structure implementing the required blockchain traits",null,null],[4,"CompactFiltersError","","An error that can occur during sync with a…",null,null],[13,"InvalidResponse","","A peer sent an invalid or unexpected response",8,null],[13,"InvalidHeaders","","The headers returned are invalid",8,null],[13,"InvalidFilterHeader","","The compact filter headers returned are invalid",8,null],[13,"InvalidFilter","","The compact filter returned is invalid",8,null],[13,"MissingBlock","","The peer is missing a block in the valid chain",8,null],[13,"DataCorruption","","The data stored in the block filters storage are corrupted",8,null],[13,"NotConnected","","A peer is not connected",8,null],[13,"Timeout","","A peer took too long to reply to one of our messages",8,null],[13,"NoPeers","","No peers have been specified",8,null],[13,"DB","","Internal database error",8,null],[13,"IO","","Internal I/O error",8,null],[13,"BIP158","","Invalid BIP158 filter",8,null],[13,"Time","","Internal system time error",8,null],[13,"Global","","Wrapper for [`crate::error::Error`]",8,null],[11,"add_tx","","Add a transaction to the mempool",9,[[["transaction",3]]]],[11,"get_tx","","Look-up a transaction in the mempool given an…",9,[[["inventory",4]],[["option",4],["transaction",3]]]],[11,"has_tx","","Return whether or not the mempool contains a transaction…",9,[[["txid",3]]]],[11,"iter_txs","","Return the list of transactions contained in the mempool",9,[[],[["transaction",3],["vec",3]]]],[11,"connect","","Connect to a peer over a plaintext TCP connection",10,[[["tosocketaddrs",8],["network",4],["arc",3],["mempool",3]],[["result",4],["compactfilterserror",4]]]],[11,"connect_proxy","","Connect to a peer through a SOCKS5 proxy, optionally by…",10,[[["tosocketaddrs",8],["option",4],["totargetaddr",8],["arc",3],["mempool",3],["network",4]],[["result",4],["compactfilterserror",4]]]],[11,"get_version","","Return the [`VersionMessage`] sent by the peer",10,[[],["versionmessage",3]]],[11,"get_network","","Return the Bitcoin [`Network`] in use",10,[[],["network",4]]],[11,"get_mempool","","Return the mempool used by this peer",10,[[],[["arc",3],["mempool",3]]]],[11,"is_connected","","Return whether or not the peer is still connected",10,[[]]],[11,"send","","Send a raw Bitcoin message to the peer",10,[[["networkmessage",4]],[["compactfilterserror",4],["result",4]]]],[11,"recv","","Waits for a specific incoming Bitcoin message, optionally…",10,[[["option",4],["duration",3]],[["option",4],["compactfilterserror",4],["result",4]]]],[11,"new","","Construct a new instance given a list of peers, a path to…",11,[[["asref",8],["path",3],["option",4],["vec",3],["peer",3]],[["result",4],["compactfilterserror",4]]]],[6,"ProgressData","bdk::blockchain","Data sent with a progress update over a [`channel`]",null,null],[8,"BlockchainMarker","","Marker trait for a blockchain backend",null,null],[8,"Blockchain","","Trait that defines the actions that must be supported by a…",null,null],[10,"get_capabilities","","Return the set of [`Capability`] supported by this backend",12,[[],[["capability",4],["hashset",3]]]],[10,"setup","","Setup the backend and populate the internal database for…",12,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"sync","","Populate the internal database with transactions and UTXOs",12,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[10,"get_tx","","Fetch a transaction from the blockchain given its txid",12,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[10,"broadcast","","Broadcast a transaction",12,[[["transaction",3]],[["error",4],["result",4]]]],[10,"get_height","","Return the current height",12,[[],[["result",4],["error",4]]]],[10,"estimate_fee","","Estimate the fee rate required to confirm a transaction in…",12,[[],[["feerate",3],["error",4],["result",4]]]],[8,"Progress","","Trait for types that can receive and process progress…",null,null],[10,"update","","Send a new progress update",13,[[["string",3],["option",4]],[["error",4],["result",4]]]],[0,"database","bdk","Database types",null,null],[0,"memory","bdk::database","In-memory ephemeral database",null,null],[3,"MemoryDatabase","bdk::database::memory","In-memory ephemeral database",null,null],[11,"new","","Create a new empty database",14,[[]]],[8,"BatchOperations","bdk::database","Trait for operations that can be batched",null,null],[10,"set_script_pubkey","","Store a script_pubkey along with its script type and child…",15,[[["scripttype",4],["script",3]],[["error",4],["result",4]]]],[10,"set_utxo","","Store a [`UTXO`]",15,[[["utxo",3]],[["error",4],["result",4]]]],[10,"set_raw_tx","","Store a raw transaction",15,[[["transaction",3]],[["error",4],["result",4]]]],[10,"set_tx","","Store the metadata of a transaction",15,[[["transactiondetails",3]],[["error",4],["result",4]]]],[10,"set_last_index","","Store the last derivation index for a given script type",15,[[["scripttype",4]],[["error",4],["result",4]]]],[10,"del_script_pubkey_from_path","","Delete a script_pubkey given the script type and its child…",15,[[["scripttype",4]],[["error",4],["option",4],["result",4]]]],[10,"del_path_from_script_pubkey","","Delete the data related to a specific script_pubkey,…",15,[[["script",3]],[["option",4],["error",4],["result",4]]]],[10,"del_utxo","","Delete a [`UTXO`] given its [`OutPoint`]",15,[[["outpoint",3]],[["result",4],["error",4],["option",4]]]],[10,"del_raw_tx","","Delete a raw transaction given its [`Txid`]",15,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[10,"del_tx","","Delete the metadata of a transaction and optionally the…",15,[[["txid",3]],[["option",4],["error",4],["result",4]]]],[10,"del_last_index","","Delete the last derivation index for a script type",15,[[["scripttype",4]],[["result",4],["option",4],["error",4]]]],[8,"Database","","Trait for reading data from a database",null,null],[10,"check_descriptor_checksum","","Read and checks the descriptor checksum for a given script…",16,[[["scripttype",4],["asref",8]],[["error",4],["result",4]]]],[10,"iter_script_pubkeys","","Return the list of script_pubkeys",16,[[["option",4],["scripttype",4]],[["result",4],["vec",3],["error",4]]]],[10,"iter_utxos","","Return the list of [`UTXO`]s",16,[[],[["result",4],["vec",3],["error",4]]]],[10,"iter_raw_txs","","Return the list of raw transactions",16,[[],[["error",4],["vec",3],["result",4]]]],[10,"iter_txs","","Return the list of transactions metadata",16,[[],[["vec",3],["result",4],["error",4]]]],[10,"get_script_pubkey_from_path","","Fetch a script_pubkey given the script type and child number",16,[[["scripttype",4]],[["error",4],["option",4],["result",4]]]],[10,"get_path_from_script_pubkey","","Fetch the script type and child number of a given…",16,[[["script",3]],[["option",4],["error",4],["result",4]]]],[10,"get_utxo","","Fetch a [`UTXO`] given its [`OutPoint`]",16,[[["outpoint",3]],[["result",4],["error",4],["option",4]]]],[10,"get_raw_tx","","Fetch a raw transaction given its [`Txid`]",16,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[10,"get_tx","","Fetch the transaction metadata and optionally also the raw…",16,[[["txid",3]],[["option",4],["error",4],["result",4]]]],[10,"get_last_index","","Return the last defivation index for a script type",16,[[["scripttype",4]],[["result",4],["option",4],["error",4]]]],[10,"increment_last_index","","Increment the last derivation index for a script type and…",16,[[["scripttype",4]],[["result",4],["error",4]]]],[8,"BatchDatabase","","Trait for a database that supports batch operations",null,null],[16,"Batch","","Container for the operations",17,null],[10,"begin_batch","","Create a new batch container",17,[[]]],[10,"commit_batch","","Consume and apply a batch of operations",17,[[],[["error",4],["result",4]]]],[0,"descriptor","bdk","Descriptors",null,null],[4,"Descriptor","bdk::descriptor","Script descriptor",null,null],[13,"Bare","","A raw scriptpubkey (including pay-to-pubkey) under Legacy…",18,null],[13,"Pk","","Pay-to-Pubkey",18,null],[13,"Pkh","","Pay-to-PubKey-Hash",18,null],[13,"Wpkh","","Pay-to-Witness-PubKey-Hash",18,null],[13,"ShWpkh","","Pay-to-Witness-PubKey-Hash inside P2SH",18,null],[13,"Sh","","Pay-to-ScriptHash with Legacy context",18,null],[13,"Wsh","","Pay-to-Witness-ScriptHash with Segwitv0 context",18,null],[13,"ShWsh","","P2SH-P2WSH with Segwitv0 context",18,null],[4,"Legacy","","Legacy ScriptContext",null,null],[3,"Miniscript","","Top-level script AST type",null,null],[12,"node","","A node in the Abstract Syntax Tree(",19,null],[12,"ty","","The correctness and malleability type information for the…",19,null],[12,"ext","","Additional information helpful for extra analysis.",19,null],[8,"MiniscriptKey","","Public key trait which can be converted to Hash type",null,null],[11,"is_uncompressed","","Check if the publicKey is uncompressed. The default…",20,[[]]],[16,"Hash","","The associated Hash type with the publicKey",20,null],[10,"to_pubkeyhash","","Converts an object to PublicHash",20,[[]]],[8,"ScriptContext","","",null,null],[10,"check_frag_non_malleable","","Depending on ScriptContext, fragments can be malleable.…",21,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[10,"check_frag_validity","","Depending on script Context, some of the Terminals might…",21,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[4,"Segwitv0","","Segwitv0 ScriptContext",null,null],[4,"Terminal","","All AST elements",null,null],[13,"True","","`1`",22,null],[13,"False","","`0`",22,null],[13,"PkK","","``",22,null],[13,"PkH","","`DUP HASH160 EQUALVERIFY`",22,null],[13,"After","","`n CHECKLOCKTIMEVERIFY`",22,null],[13,"Older","","`n CHECKSEQUENCEVERIFY`",22,null],[13,"Sha256","","`SIZE 32 EQUALVERIFY SHA256 EQUAL`",22,null],[13,"Hash256","","`SIZE 32 EQUALVERIFY HASH256 EQUAL`",22,null],[13,"Ripemd160","","`SIZE 32 EQUALVERIFY RIPEMD160 EQUAL`",22,null],[13,"Hash160","","`SIZE 32 EQUALVERIFY HASH160 EQUAL`",22,null],[13,"Alt","","`TOALTSTACK [E] FROMALTSTACK`",22,null],[13,"Swap","","`SWAP [E1]`",22,null],[13,"Check","","`[Kt]/[Ke] CHECKSIG`",22,null],[13,"DupIf","","`DUP IF [V] ENDIF`",22,null],[13,"Verify","","[T] VERIFY",22,null],[13,"NonZero","","SIZE 0NOTEQUAL IF [Fn] ENDIF",22,null],[13,"ZeroNotEqual","","[X] 0NOTEQUAL",22,null],[13,"AndV","","[V] [T]/[V]/[F]/[Kt]",22,null],[13,"AndB","","[E] [W] BOOLAND",22,null],[13,"AndOr","","[various] NOTIF [various] ELSE [various] ENDIF",22,null],[13,"OrB","","[E] [W] BOOLOR",22,null],[13,"OrD","","[E] IFDUP NOTIF [T]/[E] ENDIF",22,null],[13,"OrC","","[E] NOTIF [V] ENDIF",22,null],[13,"OrI","","IF [various] ELSE [various] ENDIF",22,null],[13,"Thresh","","[E] ([W] ADD)* k EQUAL",22,null],[13,"Multi","","k ()* n CHECKMULTISIG",22,null],[8,"ToPublicKey","","Trait describing public key types which can be converted…",null,null],[10,"to_public_key","","Converts an object to a public key",23,[[],["publickey",3]]],[11,"serialized_len","","Computes the size of a public key when serialized in a…",23,[[]]],[10,"hash_to_hash160","","Converts a hashed version of the public key to a `hash160`…",23,[[],["hash",3]]],[0,"checksum","","Descriptor checksum",null,null],[5,"get_checksum","bdk::descriptor::checksum","Compute the checksum of a descriptor",null,[[],[["result",4],["string",3],["error",4]]]],[0,"error","bdk::descriptor","Descriptor errors",null,null],[4,"Error","bdk::descriptor::error","Errors related to the parsing and usage of descriptors",null,null],[13,"InternalError","","",24,null],[13,"InvalidPrefix","","",24,null],[13,"HardenedDerivationOnXpub","","",24,null],[13,"MalformedInput","","",24,null],[13,"KeyParsingError","","",24,null],[13,"Policy","","",24,null],[13,"InputIndexDoesntExist","","",24,null],[13,"MissingPublicKey","","",24,null],[13,"MissingDetails","","",24,null],[13,"InvalidDescriptorCharacter","","",24,null],[13,"CantDeriveWithMiniscript","","",24,null],[13,"BIP32","","",24,null],[13,"Base58","","",24,null],[13,"PK","","",24,null],[13,"Miniscript","","",24,null],[13,"Hex","","",24,null],[0,"policy","bdk::descriptor","Descriptor policy",null,null],[3,"PKOrF","bdk::descriptor::policy","Raw public key or extended key fingerprint",null,null],[3,"Policy","","Descriptor spending policy",null,null],[12,"id","","Identifier for this policy node",25,null],[12,"item","","Type of this policy node",25,null],[12,"satisfaction","","How a much given PSBT already satisfies this polcy node…",25,null],[12,"contribution","","How the wallet\'s descriptor can satisfy this policy node",25,null],[3,"Condition","","An extra condition that must be satisfied but that is out…",null,null],[12,"csv","","",26,null],[12,"timelock","","",26,null],[4,"SatisfiableItem","","An item that need to be satisfied",null,null],[13,"Signature","","",27,null],[13,"SignatureKey","","",27,null],[13,"SHA256Preimage","","",27,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","",28,null],[13,"HASH256Preimage","bdk::descriptor::policy","",27,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","",29,null],[13,"RIPEMD160Preimage","bdk::descriptor::policy","",27,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","",30,null],[13,"HASH160Preimage","bdk::descriptor::policy","",27,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","",31,null],[13,"AbsoluteTimelock","bdk::descriptor::policy","",27,null],[12,"value","bdk::descriptor::policy::SatisfiableItem","",32,null],[13,"RelativeTimelock","bdk::descriptor::policy","",27,null],[12,"value","bdk::descriptor::policy::SatisfiableItem","",33,null],[13,"Thresh","bdk::descriptor::policy","",27,null],[12,"items","bdk::descriptor::policy::SatisfiableItem","",34,null],[12,"threshold","","",34,null],[13,"Multisig","bdk::descriptor::policy","",27,null],[12,"keys","bdk::descriptor::policy::SatisfiableItem","",35,null],[12,"threshold","","",35,null],[4,"Satisfaction","bdk::descriptor::policy","Represent if and how much a policy item is satisfied by…",null,null],[13,"Partial","","Only a partial satisfaction of some kind of threshold policy",36,null],[12,"n","bdk::descriptor::policy::Satisfaction","Total number of items",37,null],[12,"m","","Threshold",37,null],[12,"items","","The items that can be satisfied by the descriptor",37,null],[12,"conditions","","Extra conditions that also need to be satisfied",37,null],[13,"PartialComplete","bdk::descriptor::policy","Can reach the threshold of some kind of threshold policy",36,null],[12,"n","bdk::descriptor::policy::Satisfaction","Total number of items",38,null],[12,"m","","Threshold",38,null],[12,"items","","The items that can be satisfied by the descriptor",38,null],[12,"conditions","","Extra conditions that also need to be satisfied",38,null],[13,"Complete","bdk::descriptor::policy","Can satisfy the policy item",36,null],[12,"condition","bdk::descriptor::policy::Satisfaction","Extra conditions that also need to be satisfied",39,null],[13,"None","bdk::descriptor::policy","Cannot satisfy or contribute to the policy item",36,null],[4,"PolicyError","","Errors that can happen while extracting and manipulating…",null,null],[13,"NotEnoughItemsSelected","","",40,null],[13,"TooManyItemsSelected","","",40,null],[13,"IndexOutOfRange","","",40,null],[13,"AddOnLeaf","","",40,null],[13,"AddOnPartialComplete","","",40,null],[13,"MixedTimelockUnits","","",40,null],[13,"IncompatibleConditions","","",40,null],[6,"ConditionMap","","",null,null],[6,"FoldedConditionMap","","",null,null],[11,"is_leaf","","",27,[[]]],[11,"id","","",27,[[],["string",3]]],[11,"is_leaf","","",36,[[]]],[11,"is_null","","",26,[[]]],[11,"requires_path","","Return whether or not a specific path in the policy tree…",25,[[]]],[11,"get_condition","","Return the conditions that are set by the spending policy…",25,[[["btreemap",3]],[["policyerror",4],["result",4],["condition",3]]]],[6,"ExtendedDescriptor","bdk::descriptor","Alias for a [`Descriptor`] that can contain extended keys…",null,null],[6,"HDKeyPaths","","Alias for the type of maps that represent derivation paths…",null,null],[8,"ExtractPolicy","","Trait implemented on [`Descriptor`]s to add a method to…",null,null],[10,"extract_policy","","",41,[[["signerscontainer",3],["arc",3]],[["error",4],["result",4],["option",4]]]],[11,"as_byte","bdk","",4,[[]]],[11,"is_internal","","",4,[[]]],[11,"from_btc_per_kvb","","Create a new instance of [`FeeRate`] given a float fee…",42,[[]]],[11,"from_sat_per_vb","","Create a new instance of [`FeeRate`] given a float fee…",42,[[]]],[11,"default_min_relay_fee","","Create a new [`FeeRate`] with the default min relay fee…",42,[[]]],[11,"as_sat_vb","","Return the value as satoshi/vbyte",42,[[]]],[0,"wallet","","Wallet",null,null],[3,"Wallet","bdk::wallet","A Bitcoin wallet",null,null],[0,"address_validator","","Address validation callbacks",null,null],[4,"AddressValidatorError","bdk::wallet::address_validator","Errors that can be returned to fail the validation of an…",null,null],[13,"UserRejected","","",43,null],[13,"ConnectionError","","",43,null],[13,"TimeoutError","","",43,null],[13,"InvalidScript","","",43,null],[13,"Message","","",43,null],[8,"AddressValidator","","Trait to build address validators",null,null],[10,"validate","","Validate or inspect an address",44,[[["scripttype",4],["script",3],["hdkeypaths",6]],[["result",4],["addressvalidatorerror",4]]]],[0,"coin_selection","bdk::wallet","Coin selection",null,null],[3,"CoinSelectionResult","bdk::wallet::coin_selection","Result of a successful coin selection",null,null],[12,"txin","","List of inputs to use, with the respective previous…",45,null],[12,"selected_amount","","Sum of the selected inputs\' value",45,null],[12,"fee_amount","","Total fee amount in satoshi",45,null],[3,"DumbCoinSelection","","Simple and dumb coin selection",null,null],[6,"DefaultCoinSelectionAlgorithm","","Default coin selection algorithm used by `TxBuilder` if…",null,null],[8,"CoinSelectionAlgorithm","","Trait for generalized coin selection algorithms",null,null],[10,"coin_select","","Perform the coin selection",46,[[["feerate",3],["vec",3],["utxo",3]],[["coinselectionresult",3],["error",4],["result",4]]]],[0,"export","bdk::wallet","Wallet export",null,null],[3,"WalletExport","bdk::wallet::export","Structure that contains the export of a wallet",null,null],[12,"blockheight","","Earliest block to rescan when looking for the wallet\'s…",47,null],[12,"label","","Arbitrary label for the wallet",47,null],[11,"export_wallet","","Export a wallet",47,[[["wallet",3]],["result",4]]],[11,"descriptor","","Return the external descriptor",47,[[],["string",3]]],[11,"change_descriptor","","Return the internal descriptor, if present",47,[[],[["string",3],["option",4]]]],[0,"signer","bdk::wallet","Generalized signers",null,null],[3,"SignerOrdering","bdk::wallet::signer","Defines the order in which signers are called",null,null],[12,"0","","",48,null],[3,"SignersContainer","","Container for multiple signers",null,null],[4,"SignerId","","Identifier of a signer in the `SignersContainers`. Used as…",null,null],[13,"PkHash","","",49,null],[13,"Fingerprint","","",49,null],[4,"SignerError","","Signing error",null,null],[13,"MissingKey","","The private key is missing for the required public key",50,null],[13,"UserCanceled","","The user canceled the operation",50,null],[13,"MissingSighash","","The sighash is missing in the PSBT input",50,null],[13,"InputIndexOutOfRange","","Input index is out of range",50,null],[13,"MissingNonWitnessUtxo","","The `non_witness_utxo` field of the transaction is…",50,null],[13,"InvalidNonWitnessUtxo","","The `non_witness_utxo` specified is invalid",50,null],[13,"MissingWitnessUtxo","","The `witness_utxo` field of the transaction is required to…",50,null],[13,"MissingWitnessScript","","The `witness_script` field of the transaction is requied…",50,null],[13,"MissingHDKeypath","","The fingerprint and derivation path are missing from the…",50,null],[8,"Signer","","Trait for signers",null,null],[10,"sign","","Sign a PSBT",51,[[["partiallysignedtransaction",3],["option",4]],[["result",4],["signererror",4]]]],[10,"sign_whole_tx","","Return whether or not the signer signs the whole…",51,[[]]],[11,"descriptor_secret_key","","Return the secret key for the signer",51,[[],[["descriptorsecretkey",4],["option",4]]]],[11,"as_key_map","","",52,[[],["keymap",6]]],[11,"new","","Default constructor",52,[[]]],[11,"add_external","","Adds an external signer to the container for the specified…",52,[[["signerid",4],["signerordering",3],["arc",3],["box",3]],[["arc",3],["option",4]]]],[11,"remove","","Removes a signer from the container and returns it",52,[[["signerid",4],["signerordering",3]],[["arc",3],["option",4]]]],[11,"ids","","Returns the list of identifiers of all the signers in the…",52,[[],[["vec",3],["signerid",4]]]],[11,"signers","","Returns the list of signers in the container, sorted by…",52,[[],[["vec",3],["arc",3]]]],[11,"find","","Finds the signer with lowest ordering for a given id in…",52,[[["signerid",4]],[["option",4],["arc",3]]]],[0,"time","bdk::wallet","Cross-platform time",null,null],[5,"get_timestamp","bdk::wallet::time","Return the current timestamp in seconds",null,[[]]],[0,"tx_builder","bdk::wallet","Transaction builder",null,null],[3,"TxBuilder","bdk::wallet::tx_builder","A transaction builder",null,null],[4,"TxOrdering","","Ordering of the transaction\'s inputs and outputs",null,null],[13,"Shuffle","","Randomized (default)",53,null],[13,"Untouched","","Unchanged",53,null],[13,"BIP69Lexicographic","","BIP69 / Lexicographic",53,null],[4,"ChangeSpendPolicy","","Policy regarding the use of change outputs when creating a…",null,null],[13,"ChangeAllowed","","Use both change and non-change outputs (default)",54,null],[13,"OnlyChange","","Only use change outputs (see…",54,null],[13,"ChangeForbidden","","Only use non-change outputs (see…",54,null],[11,"new","","Create an empty builder",55,[[]]],[11,"with_recipients","","Create a builder starting from a list of recipients",55,[[["vec",3]]]],[11,"set_recipients","","Replace the recipients already added with a new list",55,[[["vec",3]]]],[11,"add_recipient","","Add a recipient to the internal list",55,[[["script",3]]]],[11,"send_all","","Send all the selected utxos to a single output",55,[[]]],[11,"fee_rate","","Set a custom fee rate",55,[[["feerate",3]]]],[11,"policy_path","","Set the policy path to use while creating the transaction",55,[[["vec",3],["string",3],["btreemap",3]]]],[11,"utxos","","Replace the internal list of utxos that must be spent with…",55,[[["vec",3],["outpoint",3]]]],[11,"add_utxo","","Add a utxo to the internal list of utxos that must be spent",55,[[["outpoint",3]]]],[11,"unspendable","","Replace the internal list of unspendable utxos with a new…",55,[[["vec",3],["outpoint",3]]]],[11,"add_unspendable","","Add a utxo to the internal list of unspendable utxos",55,[[["outpoint",3]]]],[11,"sighash","","Sign with a specific sig hash",55,[[["sighashtype",4]]]],[11,"ordering","","Choose the ordering for inputs and outputs of the…",55,[[["txordering",4]]]],[11,"nlocktime","","Use a specific nLockTime while creating the transaction",55,[[]]],[11,"enable_rbf","","Enable signaling RBF",55,[[]]],[11,"enable_rbf_with_sequence","","Enable signaling RBF with a specific nSequence value",55,[[]]],[11,"version","","Build a transaction with a specific version",55,[[]]],[11,"do_not_spend_change","","Do not spend change outputs",55,[[]]],[11,"only_spend_change","","Only spend change outputs",55,[[]]],[11,"change_policy","","Set a specific [`ChangeSpendPolicy`]. See…",55,[[["changespendpolicy",4]]]],[11,"force_non_witness_utxo","","Fill-in the `psbt::Input::non_witness_utxo` field even if…",55,[[]]],[11,"coin_selection","","Choose the coin selection algorithm",55,[[["coinselectionalgorithm",8]],[["txbuilder",3],["coinselectionalgorithm",8]]]],[11,"sort_tx","","",53,[[["transaction",3]]]],[6,"OfflineWallet","bdk::wallet","Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]",null,null],[8,"IsDust","","Trait to check if a value is below the dust limit",null,null],[10,"is_dust","","Check whether or not a value is below dust limit",56,[[]]],[11,"new_offline","","Create a new \\\"offline\\\" wallet",57,[[["option",4],["network",4]],[["error",4],["result",4]]]],[11,"get_new_address","","Return a newly generated address using the external…",57,[[],[["address",3],["result",4],["error",4]]]],[11,"is_mine","","Return whether or not a `script` is part of this wallet…",57,[[["script",3]],[["error",4],["result",4]]]],[11,"list_unspent","","Return the list of unspent outputs of this wallet",57,[[],[["result",4],["vec",3],["error",4]]]],[11,"list_transactions","","Return the list of transactions made and received by the…",57,[[],[["vec",3],["result",4],["error",4]]]],[11,"get_balance","","Return the balance, meaning the sum of this wallet\'s…",57,[[],[["result",4],["error",4]]]],[11,"add_signer","","Add an external signer",57,[[["scripttype",4],["signerid",4],["signerordering",3],["descriptorpublickey",4],["arc",3],["box",3]]]],[11,"add_address_validator","","Add an address validator",57,[[["arc",3],["box",3]]]],[11,"create_tx","","Create a new transaction following the options specified…",57,[[["txbuilder",3],["coinselectionalgorithm",8]],[["error",4],["result",4]]]],[11,"bump_fee","","Bump the fee of a transaction following the options…",57,[[["txid",3],["txbuilder",3],["coinselectionalgorithm",8]],[["error",4],["result",4]]]],[11,"sign","","Sign a transaction with all the wallet\'s signers, in the…",57,[[["psbt",3],["option",4]],[["result",4],["error",4]]]],[11,"policies","","Return the spending policies for the wallet\'s descriptor",57,[[["scripttype",4]],[["result",4],["option",4],["error",4]]]],[11,"public_descriptor","","Return the \\\"public\\\" version of the wallet\'s descriptor,…",57,[[["scripttype",4]],[["option",4],["result",4],["error",4]]]],[11,"finalize_psbt","","Try to finalize a PSBT",57,[[["psbt",3],["option",4]],[["result",4],["error",4]]]],[11,"new","","Create a new \\\"online\\\" wallet",57,[[["option",4],["network",4]],[["error",4],["result",4]]]],[11,"sync","","Sync the internal database with the blockchain",57,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"client","","Return a reference to the internal blockchain client",57,[[],["option",4]]],[11,"broadcast","","Broadcast a transaction to the network",57,[[["transaction",3]],[["result",4],["txid",3],["error",4]]]],[11,"from","bdk","",42,[[]]],[11,"into","","",42,[[]]],[11,"to_owned","","",42,[[]]],[11,"clone_into","","",42,[[]]],[11,"try_from","","",42,[[],["result",4]]],[11,"try_into","","",42,[[],["result",4]]],[11,"borrow","","",42,[[]]],[11,"borrow_mut","","",42,[[]]],[11,"type_id","","",42,[[],["typeid",3]]],[11,"vzip","","",42,[[]]],[11,"from","","",0,[[]]],[11,"into","","",0,[[]]],[11,"to_owned","","",0,[[]]],[11,"clone_into","","",0,[[]]],[11,"try_from","","",0,[[],["result",4]]],[11,"try_into","","",0,[[],["result",4]]],[11,"borrow","","",0,[[]]],[11,"borrow_mut","","",0,[[]]],[11,"type_id","","",0,[[],["typeid",3]]],[11,"equivalent","","",0,[[]]],[11,"vzip","","",0,[[]]],[11,"from","","",1,[[]]],[11,"into","","",1,[[]]],[11,"to_owned","","",1,[[]]],[11,"clone_into","","",1,[[]]],[11,"try_from","","",1,[[],["result",4]]],[11,"try_into","","",1,[[],["result",4]]],[11,"borrow","","",1,[[]]],[11,"borrow_mut","","",1,[[]]],[11,"type_id","","",1,[[],["typeid",3]]],[11,"equivalent","","",1,[[]]],[11,"vzip","","",1,[[]]],[11,"from","","",2,[[]]],[11,"into","","",2,[[]]],[11,"to_string","","",2,[[],["string",3]]],[11,"try_from","","",2,[[],["result",4]]],[11,"try_into","","",2,[[],["result",4]]],[11,"borrow","","",2,[[]]],[11,"borrow_mut","","",2,[[]]],[11,"type_id","","",2,[[],["typeid",3]]],[11,"vzip","","",2,[[]]],[11,"from","","",4,[[]]],[11,"into","","",4,[[]]],[11,"to_owned","","",4,[[]]],[11,"clone_into","","",4,[[]]],[11,"try_from","","",4,[[],["result",4]]],[11,"try_into","","",4,[[],["result",4]]],[11,"borrow","","",4,[[]]],[11,"borrow_mut","","",4,[[]]],[11,"type_id","","",4,[[],["typeid",3]]],[11,"write_base32","","",4,[[],["result",4]]],[11,"base32_len","","",4,[[]]],[11,"check_base32","","",4,[[],[["result",4],["vec",3]]]],[11,"equivalent","","",4,[[]]],[11,"vzip","","",4,[[]]],[11,"from","bdk::blockchain","",58,[[]]],[11,"into","","",58,[[]]],[11,"try_from","","",58,[[],["result",4]]],[11,"try_into","","",58,[[],["result",4]]],[11,"borrow","","",58,[[]]],[11,"borrow_mut","","",58,[[]]],[11,"type_id","","",58,[[],["typeid",3]]],[11,"vzip","","",58,[[]]],[11,"from","","",59,[[]]],[11,"into","","",59,[[]]],[11,"to_owned","","",59,[[]]],[11,"clone_into","","",59,[[]]],[11,"try_from","","",59,[[],["result",4]]],[11,"try_into","","",59,[[],["result",4]]],[11,"borrow","","",59,[[]]],[11,"borrow_mut","","",59,[[]]],[11,"type_id","","",59,[[],["typeid",3]]],[11,"vzip","","",59,[[]]],[11,"from","","",60,[[]]],[11,"into","","",60,[[]]],[11,"to_owned","","",60,[[]]],[11,"clone_into","","",60,[[]]],[11,"try_from","","",60,[[],["result",4]]],[11,"try_into","","",60,[[],["result",4]]],[11,"borrow","","",60,[[]]],[11,"borrow_mut","","",60,[[]]],[11,"type_id","","",60,[[],["typeid",3]]],[11,"vzip","","",60,[[]]],[11,"from","","",5,[[]]],[11,"into","","",5,[[]]],[11,"to_owned","","",5,[[]]],[11,"clone_into","","",5,[[]]],[11,"try_from","","",5,[[],["result",4]]],[11,"try_into","","",5,[[],["result",4]]],[11,"borrow","","",5,[[]]],[11,"borrow_mut","","",5,[[]]],[11,"type_id","","",5,[[],["typeid",3]]],[11,"equivalent","","",5,[[]]],[11,"vzip","","",5,[[]]],[11,"from","bdk::blockchain::electrum","",61,[[]]],[11,"into","","",61,[[]]],[11,"try_from","","",61,[[],["result",4]]],[11,"try_into","","",61,[[],["result",4]]],[11,"borrow","","",61,[[]]],[11,"borrow_mut","","",61,[[]]],[11,"type_id","","",61,[[],["typeid",3]]],[11,"vzip","","",61,[[]]],[11,"from","bdk::blockchain::esplora","",7,[[]]],[11,"into","","",7,[[]]],[11,"try_from","","",7,[[],["result",4]]],[11,"try_into","","",7,[[],["result",4]]],[11,"borrow","","",7,[[]]],[11,"borrow_mut","","",7,[[]]],[11,"type_id","","",7,[[],["typeid",3]]],[11,"vzip","","",7,[[]]],[11,"from","","",6,[[]]],[11,"into","","",6,[[]]],[11,"to_string","","",6,[[],["string",3]]],[11,"try_from","","",6,[[],["result",4]]],[11,"try_into","","",6,[[],["result",4]]],[11,"borrow","","",6,[[]]],[11,"borrow_mut","","",6,[[]]],[11,"type_id","","",6,[[],["typeid",3]]],[11,"vzip","","",6,[[]]],[11,"from","bdk::blockchain::compact_filters","",9,[[]]],[11,"into","","",9,[[]]],[11,"try_from","","",9,[[],["result",4]]],[11,"try_into","","",9,[[],["result",4]]],[11,"borrow","","",9,[[]]],[11,"borrow_mut","","",9,[[]]],[11,"type_id","","",9,[[],["typeid",3]]],[11,"vzip","","",9,[[]]],[11,"from","","",10,[[]]],[11,"into","","",10,[[]]],[11,"try_from","","",10,[[],["result",4]]],[11,"try_into","","",10,[[],["result",4]]],[11,"borrow","","",10,[[]]],[11,"borrow_mut","","",10,[[]]],[11,"type_id","","",10,[[],["typeid",3]]],[11,"vzip","","",10,[[]]],[11,"from","","",11,[[]]],[11,"into","","",11,[[]]],[11,"try_from","","",11,[[],["result",4]]],[11,"try_into","","",11,[[],["result",4]]],[11,"borrow","","",11,[[]]],[11,"borrow_mut","","",11,[[]]],[11,"type_id","","",11,[[],["typeid",3]]],[11,"vzip","","",11,[[]]],[11,"from","","",8,[[]]],[11,"into","","",8,[[]]],[11,"to_string","","",8,[[],["string",3]]],[11,"try_from","","",8,[[],["result",4]]],[11,"try_into","","",8,[[],["result",4]]],[11,"borrow","","",8,[[]]],[11,"borrow_mut","","",8,[[]]],[11,"type_id","","",8,[[],["typeid",3]]],[11,"vzip","","",8,[[]]],[11,"from","bdk::database::memory","",14,[[]]],[11,"into","","",14,[[]]],[11,"try_from","","",14,[[],["result",4]]],[11,"try_into","","",14,[[],["result",4]]],[11,"borrow","","",14,[[]]],[11,"borrow_mut","","",14,[[]]],[11,"type_id","","",14,[[],["typeid",3]]],[11,"vzip","","",14,[[]]],[11,"from","bdk::descriptor","",18,[[]]],[11,"into","","",18,[[]]],[11,"to_owned","","",18,[[]]],[11,"clone_into","","",18,[[]]],[11,"to_string","","",18,[[],["string",3]]],[11,"try_from","","",18,[[],["result",4]]],[11,"try_into","","",18,[[],["result",4]]],[11,"borrow","","",18,[[]]],[11,"borrow_mut","","",18,[[]]],[11,"type_id","","",18,[[],["typeid",3]]],[11,"equivalent","","",18,[[]]],[11,"vzip","","",18,[[]]],[11,"from","","",62,[[]]],[11,"into","","",62,[[]]],[11,"to_owned","","",62,[[]]],[11,"clone_into","","",62,[[]]],[11,"try_from","","",62,[[],["result",4]]],[11,"try_into","","",62,[[],["result",4]]],[11,"borrow","","",62,[[]]],[11,"borrow_mut","","",62,[[]]],[11,"type_id","","",62,[[],["typeid",3]]],[11,"equivalent","","",62,[[]]],[11,"vzip","","",62,[[]]],[11,"from","","",19,[[]]],[11,"into","","",19,[[]]],[11,"to_owned","","",19,[[]]],[11,"clone_into","","",19,[[]]],[11,"to_string","","",19,[[],["string",3]]],[11,"try_from","","",19,[[],["result",4]]],[11,"try_into","","",19,[[],["result",4]]],[11,"borrow","","",19,[[]]],[11,"borrow_mut","","",19,[[]]],[11,"type_id","","",19,[[],["typeid",3]]],[11,"equivalent","","",19,[[]]],[11,"vzip","","",19,[[]]],[11,"from","","",63,[[]]],[11,"into","","",63,[[]]],[11,"to_owned","","",63,[[]]],[11,"clone_into","","",63,[[]]],[11,"try_from","","",63,[[],["result",4]]],[11,"try_into","","",63,[[],["result",4]]],[11,"borrow","","",63,[[]]],[11,"borrow_mut","","",63,[[]]],[11,"type_id","","",63,[[],["typeid",3]]],[11,"equivalent","","",63,[[]]],[11,"vzip","","",63,[[]]],[11,"from","","",22,[[]]],[11,"into","","",22,[[]]],[11,"to_owned","","",22,[[]]],[11,"clone_into","","",22,[[]]],[11,"to_string","","",22,[[],["string",3]]],[11,"try_from","","",22,[[],["result",4]]],[11,"try_into","","",22,[[],["result",4]]],[11,"borrow","","",22,[[]]],[11,"borrow_mut","","",22,[[]]],[11,"type_id","","",22,[[],["typeid",3]]],[11,"equivalent","","",22,[[]]],[11,"vzip","","",22,[[]]],[11,"from","bdk::descriptor::error","",24,[[]]],[11,"into","","",24,[[]]],[11,"to_string","","",24,[[],["string",3]]],[11,"try_from","","",24,[[],["result",4]]],[11,"try_into","","",24,[[],["result",4]]],[11,"borrow","","",24,[[]]],[11,"borrow_mut","","",24,[[]]],[11,"type_id","","",24,[[],["typeid",3]]],[11,"vzip","","",24,[[]]],[11,"from","bdk::descriptor::policy","",64,[[]]],[11,"into","","",64,[[]]],[11,"to_owned","","",64,[[]]],[11,"clone_into","","",64,[[]]],[11,"try_from","","",64,[[],["result",4]]],[11,"try_into","","",64,[[],["result",4]]],[11,"borrow","","",64,[[]]],[11,"borrow_mut","","",64,[[]]],[11,"type_id","","",64,[[],["typeid",3]]],[11,"vzip","","",64,[[]]],[11,"from","","",25,[[]]],[11,"into","","",25,[[]]],[11,"to_owned","","",25,[[]]],[11,"clone_into","","",25,[[]]],[11,"try_from","","",25,[[],["result",4]]],[11,"try_into","","",25,[[],["result",4]]],[11,"borrow","","",25,[[]]],[11,"borrow_mut","","",25,[[]]],[11,"type_id","","",25,[[],["typeid",3]]],[11,"vzip","","",25,[[]]],[11,"from","","",26,[[]]],[11,"into","","",26,[[]]],[11,"to_owned","","",26,[[]]],[11,"clone_into","","",26,[[]]],[11,"try_from","","",26,[[],["result",4]]],[11,"try_into","","",26,[[],["result",4]]],[11,"borrow","","",26,[[]]],[11,"borrow_mut","","",26,[[]]],[11,"type_id","","",26,[[],["typeid",3]]],[11,"equivalent","","",26,[[]]],[11,"vzip","","",26,[[]]],[11,"from","","",27,[[]]],[11,"into","","",27,[[]]],[11,"to_owned","","",27,[[]]],[11,"clone_into","","",27,[[]]],[11,"try_from","","",27,[[],["result",4]]],[11,"try_into","","",27,[[],["result",4]]],[11,"borrow","","",27,[[]]],[11,"borrow_mut","","",27,[[]]],[11,"type_id","","",27,[[],["typeid",3]]],[11,"vzip","","",27,[[]]],[11,"from","","",36,[[]]],[11,"into","","",36,[[]]],[11,"to_owned","","",36,[[]]],[11,"clone_into","","",36,[[]]],[11,"try_from","","",36,[[],["result",4]]],[11,"try_into","","",36,[[],["result",4]]],[11,"borrow","","",36,[[]]],[11,"borrow_mut","","",36,[[]]],[11,"type_id","","",36,[[],["typeid",3]]],[11,"vzip","","",36,[[]]],[11,"from","","",40,[[]]],[11,"into","","",40,[[]]],[11,"to_string","","",40,[[],["string",3]]],[11,"try_from","","",40,[[],["result",4]]],[11,"try_into","","",40,[[],["result",4]]],[11,"borrow","","",40,[[]]],[11,"borrow_mut","","",40,[[]]],[11,"type_id","","",40,[[],["typeid",3]]],[11,"vzip","","",40,[[]]],[11,"from","bdk::wallet","",57,[[]]],[11,"into","","",57,[[]]],[11,"try_from","","",57,[[],["result",4]]],[11,"try_into","","",57,[[],["result",4]]],[11,"borrow","","",57,[[]]],[11,"borrow_mut","","",57,[[]]],[11,"type_id","","",57,[[],["typeid",3]]],[11,"vzip","","",57,[[]]],[11,"from","bdk::wallet::address_validator","",43,[[]]],[11,"into","","",43,[[]]],[11,"to_owned","","",43,[[]]],[11,"clone_into","","",43,[[]]],[11,"to_string","","",43,[[],["string",3]]],[11,"try_from","","",43,[[],["result",4]]],[11,"try_into","","",43,[[],["result",4]]],[11,"borrow","","",43,[[]]],[11,"borrow_mut","","",43,[[]]],[11,"type_id","","",43,[[],["typeid",3]]],[11,"equivalent","","",43,[[]]],[11,"vzip","","",43,[[]]],[11,"from","bdk::wallet::coin_selection","",45,[[]]],[11,"into","","",45,[[]]],[11,"try_from","","",45,[[],["result",4]]],[11,"try_into","","",45,[[],["result",4]]],[11,"borrow","","",45,[[]]],[11,"borrow_mut","","",45,[[]]],[11,"type_id","","",45,[[],["typeid",3]]],[11,"vzip","","",45,[[]]],[11,"from","","",65,[[]]],[11,"into","","",65,[[]]],[11,"try_from","","",65,[[],["result",4]]],[11,"try_into","","",65,[[],["result",4]]],[11,"borrow","","",65,[[]]],[11,"borrow_mut","","",65,[[]]],[11,"type_id","","",65,[[],["typeid",3]]],[11,"vzip","","",65,[[]]],[11,"from","bdk::wallet::export","",47,[[]]],[11,"into","","",47,[[]]],[11,"to_string","","",47,[[],["string",3]]],[11,"try_from","","",47,[[],["result",4]]],[11,"try_into","","",47,[[],["result",4]]],[11,"borrow","","",47,[[]]],[11,"borrow_mut","","",47,[[]]],[11,"type_id","","",47,[[],["typeid",3]]],[11,"vzip","","",47,[[]]],[11,"from","bdk::wallet::signer","",48,[[]]],[11,"into","","",48,[[]]],[11,"to_owned","","",48,[[]]],[11,"clone_into","","",48,[[]]],[11,"try_from","","",48,[[],["result",4]]],[11,"try_into","","",48,[[],["result",4]]],[11,"borrow","","",48,[[]]],[11,"borrow_mut","","",48,[[]]],[11,"type_id","","",48,[[],["typeid",3]]],[11,"equivalent","","",48,[[]]],[11,"vzip","","",48,[[]]],[11,"from","","",52,[[]]],[11,"into","","",52,[[]]],[11,"to_owned","","",52,[[]]],[11,"clone_into","","",52,[[]]],[11,"try_from","","",52,[[],["result",4]]],[11,"try_into","","",52,[[],["result",4]]],[11,"borrow","","",52,[[]]],[11,"borrow_mut","","",52,[[]]],[11,"type_id","","",52,[[],["typeid",3]]],[11,"vzip","","",52,[[]]],[11,"from","","",49,[[]]],[11,"into","","",49,[[]]],[11,"to_owned","","",49,[[]]],[11,"clone_into","","",49,[[]]],[11,"try_from","","",49,[[],["result",4]]],[11,"try_into","","",49,[[],["result",4]]],[11,"borrow","","",49,[[]]],[11,"borrow_mut","","",49,[[]]],[11,"type_id","","",49,[[],["typeid",3]]],[11,"equivalent","","",49,[[]]],[11,"vzip","","",49,[[]]],[11,"from","","",50,[[]]],[11,"into","","",50,[[]]],[11,"to_owned","","",50,[[]]],[11,"clone_into","","",50,[[]]],[11,"to_string","","",50,[[],["string",3]]],[11,"try_from","","",50,[[],["result",4]]],[11,"try_into","","",50,[[],["result",4]]],[11,"borrow","","",50,[[]]],[11,"borrow_mut","","",50,[[]]],[11,"type_id","","",50,[[],["typeid",3]]],[11,"equivalent","","",50,[[]]],[11,"vzip","","",50,[[]]],[11,"from","bdk::wallet::tx_builder","",55,[[]]],[11,"into","","",55,[[]]],[11,"try_from","","",55,[[],["result",4]]],[11,"try_into","","",55,[[],["result",4]]],[11,"borrow","","",55,[[]]],[11,"borrow_mut","","",55,[[]]],[11,"type_id","","",55,[[],["typeid",3]]],[11,"vzip","","",55,[[]]],[11,"from","","",53,[[]]],[11,"into","","",53,[[]]],[11,"to_owned","","",53,[[]]],[11,"clone_into","","",53,[[]]],[11,"try_from","","",53,[[],["result",4]]],[11,"try_into","","",53,[[],["result",4]]],[11,"borrow","","",53,[[]]],[11,"borrow_mut","","",53,[[]]],[11,"type_id","","",53,[[],["typeid",3]]],[11,"equivalent","","",53,[[]]],[11,"vzip","","",53,[[]]],[11,"from","","",54,[[]]],[11,"into","","",54,[[]]],[11,"to_owned","","",54,[[]]],[11,"clone_into","","",54,[[]]],[11,"try_from","","",54,[[],["result",4]]],[11,"try_into","","",54,[[],["result",4]]],[11,"borrow","","",54,[[]]],[11,"borrow_mut","","",54,[[]]],[11,"type_id","","",54,[[],["typeid",3]]],[11,"equivalent","","",54,[[]]],[11,"vzip","","",54,[[]]],[11,"eq","bdk::descriptor","",19,[[["miniscript",3]]]],[11,"eq","","",18,[[["descriptor",4]]]],[11,"ne","","",18,[[["descriptor",4]]]],[11,"eq","","",63,[[["segwitv0",4]]]],[11,"eq","","",22,[[["terminal",4]]]],[11,"ne","","",22,[[["terminal",4]]]],[11,"eq","","",62,[[["legacy",4]]]],[11,"check_frag_non_malleable","","",62,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_frag_validity","","",62,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_frag_non_malleable","","",63,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_frag_validity","","",63,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"cmp","","",22,[[["terminal",4]],["ordering",4]]],[11,"cmp","","",63,[[["segwitv0",4]],["ordering",4]]],[11,"cmp","","",62,[[["legacy",4]],["ordering",4]]],[11,"cmp","","",18,[[["descriptor",4]],["ordering",4]]],[11,"cmp","","",19,[[["miniscript",3]],["ordering",4]]],[11,"fmt","","",19,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",18,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",22,[[["formatter",3]],[["result",4],["error",3]]]],[11,"from_str","","",18,[[],[["error",4],["descriptor",4],["result",4]]]],[11,"from_str","","",19,[[],[["error",4],["miniscript",3],["result",4]]]],[11,"hash","","",19,[[]]],[11,"hash","","",22,[[]]],[11,"fmt","","",19,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",63,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",62,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",22,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",18,[[["formatter",3]],[["result",4],["error",3]]]],[11,"partial_cmp","","",19,[[["miniscript",3]],[["ordering",4],["option",4]]]],[11,"partial_cmp","","",63,[[["segwitv0",4]],[["ordering",4],["option",4]]]],[11,"partial_cmp","","",18,[[["descriptor",4]],[["ordering",4],["option",4]]]],[11,"lt","","",18,[[["descriptor",4]]]],[11,"le","","",18,[[["descriptor",4]]]],[11,"gt","","",18,[[["descriptor",4]]]],[11,"ge","","",18,[[["descriptor",4]]]],[11,"partial_cmp","","",22,[[["terminal",4]],[["ordering",4],["option",4]]]],[11,"lt","","",22,[[["terminal",4]]]],[11,"le","","",22,[[["terminal",4]]]],[11,"gt","","",22,[[["terminal",4]]]],[11,"ge","","",22,[[["terminal",4]]]],[11,"partial_cmp","","",62,[[["legacy",4]],[["ordering",4],["option",4]]]],[11,"from_tree","","Parse an expression tree into a Miniscript. As a general…",19,[[["tree",3]],[["error",4],["miniscript",3],["result",4]]]],[11,"from_tree","","",22,[[["tree",3]],[["error",4],["terminal",4],["result",4]]]],[11,"from_tree","","Parse an expression tree into a descriptor",18,[[["tree",3]],[["error",4],["descriptor",4],["result",4]]]],[11,"lift","","",18,[[],["policy",4]]],[11,"lift","","",19,[[],["policy",4]]],[11,"lift","","",22,[[],["policy",4]]],[11,"clone","","",18,[[],["descriptor",4]]],[11,"clone","","",19,[[],["miniscript",3]]],[11,"clone","","",62,[[],["legacy",4]]],[11,"clone","","",63,[[],["segwitv0",4]]],[11,"clone","","",22,[[],["terminal",4]]],[11,"update","bdk::blockchain","",59,[[["string",3],["option",4]],[["error",4],["result",4]]]],[11,"update","","",60,[[["string",3],["option",4]],[["error",4],["result",4]]]],[11,"set_script_pubkey","bdk::database::memory","",14,[[["scripttype",4],["script",3]],[["error",4],["result",4]]]],[11,"set_utxo","","",14,[[["utxo",3]],[["error",4],["result",4]]]],[11,"set_raw_tx","","",14,[[["transaction",3]],[["error",4],["result",4]]]],[11,"set_tx","","",14,[[["transactiondetails",3]],[["error",4],["result",4]]]],[11,"set_last_index","","",14,[[["scripttype",4]],[["error",4],["result",4]]]],[11,"del_script_pubkey_from_path","","",14,[[["scripttype",4]],[["error",4],["option",4],["result",4]]]],[11,"del_path_from_script_pubkey","","",14,[[["script",3]],[["option",4],["error",4],["result",4]]]],[11,"del_utxo","","",14,[[["outpoint",3]],[["result",4],["error",4],["option",4]]]],[11,"del_raw_tx","","",14,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"del_tx","","",14,[[["txid",3]],[["option",4],["error",4],["result",4]]]],[11,"del_last_index","","",14,[[["scripttype",4]],[["result",4],["option",4],["error",4]]]],[11,"check_descriptor_checksum","","",14,[[["scripttype",4],["asref",8]],[["error",4],["result",4]]]],[11,"iter_script_pubkeys","","",14,[[["option",4],["scripttype",4]],[["result",4],["vec",3],["error",4]]]],[11,"iter_utxos","","",14,[[],[["result",4],["vec",3],["error",4]]]],[11,"iter_raw_txs","","",14,[[],[["error",4],["vec",3],["result",4]]]],[11,"iter_txs","","",14,[[],[["vec",3],["result",4],["error",4]]]],[11,"get_script_pubkey_from_path","","",14,[[["scripttype",4]],[["error",4],["option",4],["result",4]]]],[11,"get_path_from_script_pubkey","","",14,[[["script",3]],[["option",4],["error",4],["result",4]]]],[11,"get_utxo","","",14,[[["outpoint",3]],[["result",4],["error",4],["option",4]]]],[11,"get_raw_tx","","",14,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"get_tx","","",14,[[["txid",3]],[["option",4],["error",4],["result",4]]]],[11,"get_last_index","","",14,[[["scripttype",4]],[["result",4],["option",4],["error",4]]]],[11,"increment_last_index","","",14,[[["scripttype",4]],[["result",4],["error",4]]]],[11,"begin_batch","","",14,[[]]],[11,"commit_batch","","",14,[[],[["error",4],["result",4]]]],[11,"extract_policy","bdk::descriptor","",19,[[["signerscontainer",3],["arc",3]],[["error",4],["result",4],["option",4]]]],[11,"extract_policy","","",18,[[["signerscontainer",3],["arc",3]],[["error",4],["result",4],["option",4]]]],[11,"coin_select","bdk::wallet::coin_selection","",65,[[["feerate",3],["vec",3],["utxo",3]],[["coinselectionresult",3],["error",4],["result",4]]]],[11,"get_capabilities","bdk::blockchain::electrum","",61,[[],[["capability",4],["hashset",3]]]],[11,"setup","","",61,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"get_tx","","",61,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"broadcast","","",61,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",61,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",61,[[],[["feerate",3],["error",4],["result",4]]]],[11,"get_capabilities","bdk::blockchain::esplora","",7,[[],[["capability",4],["hashset",3]]]],[11,"setup","","",7,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"get_tx","","",7,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"broadcast","","",7,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",7,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",7,[[],[["feerate",3],["error",4],["result",4]]]],[11,"get_capabilities","bdk::blockchain::compact_filters","",11,[[],[["capability",4],["hashset",3]]]],[11,"setup","","",11,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"get_tx","","",11,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"broadcast","","",11,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",11,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",11,[[],[["feerate",3],["error",4],["result",4]]]],[11,"as_ref","bdk","",4,[[]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["addressvalidatorerror",4]]]],[11,"from","","",2,[[["policyerror",4]]]],[11,"from","","",2,[[["signererror",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",3]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["esploraerror",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["compactfilterserror",4]]]],[11,"from","bdk::blockchain::electrum","",61,[[["client",4]]]],[11,"from","bdk::blockchain::esplora","",6,[[["error",3]]]],[11,"from","","",6,[[["parseinterror",3]]]],[11,"from","","",6,[[["error",4]]]],[11,"from","bdk::blockchain::compact_filters","",8,[[["error",3]]]],[11,"from","","",8,[[["error",3]]]],[11,"from","","",8,[[["error",4]]]],[11,"from","","",8,[[["systemtimeerror",3]]]],[11,"from","","",8,[[["error",4]]]],[11,"from","bdk::descriptor::error","",24,[[["error",4]]]],[11,"from","","",24,[[["error",4]]]],[11,"from","","",24,[[["error",4]]]],[11,"from","","",24,[[["error",4]]]],[11,"from","","",24,[[["error",4]]]],[11,"from","","",24,[[["policyerror",4]]]],[11,"from","bdk::descriptor::policy","",36,[[]]],[11,"from","","",25,[[["satisfiableitem",4]]]],[11,"from","bdk::wallet::signer","",49,[[["hash",3]],[["signerid",4],["descriptorpublickey",4]]]],[11,"from","","",49,[[["fingerprint",3]],[["signerid",4],["descriptorpublickey",4]]]],[11,"from","","",52,[[["keymap",6]],[["signerscontainer",3],["descriptorpublickey",4]]]],[11,"clone","bdk::blockchain","",5,[[],["capability",4]]],[11,"clone","","",59,[[],["noopprogress",3]]],[11,"clone","","",60,[[],["logprogress",3]]],[11,"clone","bdk::descriptor::policy","",64,[[],["pkorf",3]]],[11,"clone","","",27,[[],["satisfiableitem",4]]],[11,"clone","","",36,[[],["satisfaction",4]]],[11,"clone","","",25,[[],["policy",3]]],[11,"clone","","",26,[[],["condition",3]]],[11,"clone","bdk","",4,[[],["scripttype",4]]],[11,"clone","","",42,[[],["feerate",3]]],[11,"clone","","",0,[[],["utxo",3]]],[11,"clone","","",1,[[],["transactiondetails",3]]],[11,"clone","bdk::wallet::address_validator","",43,[[],["addressvalidatorerror",4]]],[11,"clone","bdk::wallet::signer","",49,[[],["signerid",4]]],[11,"clone","","",50,[[],["signererror",4]]],[11,"clone","","",48,[[],["signerordering",3]]],[11,"clone","","",52,[[],["signerscontainer",3]]],[11,"clone","bdk::wallet::tx_builder","",53,[[],["txordering",4]]],[11,"clone","","",54,[[],["changespendpolicy",4]]],[11,"default","bdk::blockchain::compact_filters","",9,[[],["mempool",3]]],[11,"default","bdk::database::memory","",14,[[],["memorydatabase",3]]],[11,"default","bdk::descriptor::policy","",64,[[],["pkorf",3]]],[11,"default","","",26,[[],["condition",3]]],[11,"default","bdk","",42,[[]]],[11,"default","","",1,[[],["transactiondetails",3]]],[11,"default","bdk::wallet::coin_selection","",65,[[],["dumbcoinselection",3]]],[11,"default","bdk::wallet::signer","",48,[[]]],[11,"default","","",52,[[],["signerscontainer",3]]],[11,"default","bdk::wallet::tx_builder","",55,[[],["txbuilder",3]]],[11,"default","","",53,[[]]],[11,"default","","",54,[[]]],[11,"cmp","bdk::descriptor::policy","",26,[[["condition",3]],["ordering",4]]],[11,"cmp","bdk::wallet::signer","",48,[[["signerordering",3]],["ordering",4]]],[11,"cmp","bdk::wallet::tx_builder","",53,[[["txordering",4]],["ordering",4]]],[11,"cmp","","",54,[[["changespendpolicy",4]],["ordering",4]]],[11,"eq","bdk::blockchain","",5,[[["capability",4]]]],[11,"eq","bdk::descriptor::policy","",26,[[["condition",3]]]],[11,"ne","","",26,[[["condition",3]]]],[11,"eq","bdk","",4,[[["scripttype",4]]]],[11,"eq","","",42,[[["feerate",3]]]],[11,"ne","","",42,[[["feerate",3]]]],[11,"eq","","",0,[[["utxo",3]]]],[11,"ne","","",0,[[["utxo",3]]]],[11,"eq","","",1,[[["transactiondetails",3]]]],[11,"ne","","",1,[[["transactiondetails",3]]]],[11,"eq","bdk::wallet::address_validator","",43,[[["addressvalidatorerror",4]]]],[11,"ne","","",43,[[["addressvalidatorerror",4]]]],[11,"eq","bdk::wallet::signer","",49,[[["signerid",4]]]],[11,"ne","","",49,[[["signerid",4]]]],[11,"eq","","",50,[[["signererror",4]]]],[11,"eq","","",48,[[["signerordering",3]]]],[11,"ne","","",48,[[["signerordering",3]]]],[11,"eq","bdk::wallet::tx_builder","",53,[[["txordering",4]]]],[11,"eq","","",54,[[["changespendpolicy",4]]]],[11,"partial_cmp","bdk::descriptor::policy","",26,[[["condition",3]],[["option",4],["ordering",4]]]],[11,"lt","","",26,[[["condition",3]]]],[11,"le","","",26,[[["condition",3]]]],[11,"gt","","",26,[[["condition",3]]]],[11,"ge","","",26,[[["condition",3]]]],[11,"partial_cmp","bdk","",42,[[["feerate",3]],[["option",4],["ordering",4]]]],[11,"lt","","",42,[[["feerate",3]]]],[11,"le","","",42,[[["feerate",3]]]],[11,"gt","","",42,[[["feerate",3]]]],[11,"ge","","",42,[[["feerate",3]]]],[11,"partial_cmp","bdk::wallet::signer","",48,[[["signerordering",3]],[["option",4],["ordering",4]]]],[11,"lt","","",48,[[["signerordering",3]]]],[11,"le","","",48,[[["signerordering",3]]]],[11,"gt","","",48,[[["signerordering",3]]]],[11,"ge","","",48,[[["signerordering",3]]]],[11,"partial_cmp","bdk::wallet::tx_builder","",53,[[["txordering",4]],[["option",4],["ordering",4]]]],[11,"partial_cmp","","",54,[[["changespendpolicy",4]],[["option",4],["ordering",4]]]],[11,"to_string","bdk::wallet::export","",47,[[],["string",3]]],[11,"fmt","bdk","",2,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::esplora","",7,[[["formatter",3]],["result",6]]],[11,"fmt","","",6,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::compact_filters","",9,[[["formatter",3]],["result",6]]],[11,"fmt","","",10,[[["formatter",3]],["result",6]]],[11,"fmt","","",11,[[["formatter",3]],["result",6]]],[11,"fmt","","",8,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain","",5,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::database::memory","",14,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::error","",24,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::policy","",64,[[["formatter",3]],["result",6]]],[11,"fmt","","",27,[[["formatter",3]],["result",6]]],[11,"fmt","","",36,[[["formatter",3]],["result",6]]],[11,"fmt","","",25,[[["formatter",3]],["result",6]]],[11,"fmt","","",26,[[["formatter",3]],["result",6]]],[11,"fmt","","",40,[[["formatter",3]],["result",6]]],[11,"fmt","bdk","",4,[[["formatter",3]],["result",6]]],[11,"fmt","","",42,[[["formatter",3]],["result",6]]],[11,"fmt","","",0,[[["formatter",3]],["result",6]]],[11,"fmt","","",1,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::address_validator","",43,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::coin_selection","",45,[[["formatter",3]],["result",6]]],[11,"fmt","","",65,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::export","",47,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::signer","",49,[[["formatter",3]],["result",6]]],[11,"fmt","","",50,[[["formatter",3]],["result",6]]],[11,"fmt","","",48,[[["formatter",3]],["result",6]]],[11,"fmt","","",52,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::tx_builder","",55,[[["formatter",3]],["result",6]]],[11,"fmt","","",53,[[["formatter",3]],["result",6]]],[11,"fmt","","",54,[[["formatter",3]],["result",6]]],[11,"fmt","bdk","",2,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::esplora","",6,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::compact_filters","",8,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::error","",24,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::policy","",40,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::address_validator","",43,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::signer","",50,[[["formatter",3]],["result",6]]],[11,"hash","bdk::blockchain","",5,[[]]],[11,"hash","bdk::descriptor::policy","",26,[[]]],[11,"hash","bdk","",4,[[]]],[11,"hash","bdk::wallet::signer","",49,[[]]],[11,"hash","bdk::wallet::tx_builder","",53,[[]]],[11,"hash","","",54,[[]]],[11,"from_str","bdk::wallet::export","",47,[[],["result",4]]],[11,"serialize","bdk::descriptor::policy","",64,[[],["result",4]]],[11,"serialize","","",27,[[],["result",4]]],[11,"serialize","","",36,[[],["result",4]]],[11,"serialize","","",25,[[],["result",4]]],[11,"serialize","","",26,[[],["result",4]]],[11,"serialize","bdk","",4,[[],["result",4]]],[11,"serialize","","",0,[[],["result",4]]],[11,"serialize","","",1,[[],["result",4]]],[11,"serialize","bdk::wallet::export","",47,[[],["result",4]]],[11,"deserialize","bdk","",4,[[],["result",4]]],[11,"deserialize","","",0,[[],["result",4]]],[11,"deserialize","","",1,[[],["result",4]]],[11,"deserialize","bdk::wallet::export","",47,[[],["result",4]]],[11,"translate_pk","bdk::descriptor","Convert a descriptor using abstract keys to one using…",18,[[],[["result",4],["descriptor",4]]]],[11,"address","","Computes the Bitcoin address of the descriptor, if one…",18,[[["network",4]],[["option",4],["address",3]]]],[11,"script_pubkey","","Computes the scriptpubkey of the descriptor",18,[[],["script",3]]],[11,"unsigned_script_sig","","Computes the scriptSig that will be in place for an…",18,[[],["script",3]]],[11,"witness_script","","Computes the \\\"witness script\\\" of the descriptor, i.e. the…",18,[[],["script",3]]],[11,"satisfy","","Attempts to produce a satisfying witness and scriptSig to…",18,[[["txin",3]],[["error",4],["result",4]]]],[11,"max_satisfaction_weight","","Computes an upper bound on the weight of a satisfying…",18,[[]]],[11,"derive","","Derives all wildcard keys in the descriptor using the…",18,[[],[["descriptor",4],["descriptorpublickey",4]]]],[11,"parse_secret","","",18,[[],[["error",4],["result",4]]]],[11,"to_string_with_secret","","",18,[[["hashmap",3]],["string",3]]],[11,"from_ast","","Add type information(Type and Extdata) to Miniscript based…",19,[[["terminal",4]],[["error",4],["miniscript",3],["result",4]]]],[11,"into_inner","","Extracts the `AstElem` representing the root of the…",19,[[],["terminal",4]]],[11,"as_inner","","",19,[[],["terminal",4]]],[11,"parse","","Attempt to parse a script into a Miniscript representation",19,[[["script",3]],[["error",4],["miniscript",3],["result",4]]]],[11,"encode","","Encode as a Bitcoin script",19,[[],["script",3]]],[11,"script_size","","Size, in bytes of the script-pubkey. If this Miniscript is…",19,[[]]],[11,"max_satisfaction_witness_elements","","Maximum number of witness elements used to satisfy the…",19,[[]]],[11,"max_satisfaction_size","","Maximum size, in bytes, of a satisfying witness. For…",19,[[]]],[11,"translate_pk","","This will panic if translatefpk returns an uncompressed…",19,[[],[["miniscript",3],["result",4]]]],[11,"satisfy","","Attempt to produce a satisfying witness for the witness…",19,[[],[["vec",3],["option",4]]]],[11,"translate_pk","","Convert an AST element with one public key type to one of…",22,[[],[["terminal",4],["result",4]]]],[11,"encode","","Encode the element as a fragment of Bitcoin Script. The…",22,[[["builder",3]],["builder",3]]],[11,"script_size","","Size, in bytes of the script-pubkey. If this Miniscript is…",22,[[]]],[11,"max_dissatisfaction_witness_elements","","Maximum number of witness elements used to dissatisfy the…",22,[[],["option",4]]],[11,"max_dissatisfaction_size","","Maximum dissatisfaction cost, in bytes, of a Miniscript…",22,[[],["option",4]]],[11,"max_satisfaction_witness_elements","","Maximum number of witness elements used to satisfy the…",22,[[]]],[11,"max_satisfaction_size","","Maximum size, in bytes, of a satisfying witness. For…",22,[[]]]],"p":[[3,"UTXO"],[3,"TransactionDetails"],[4,"Error"],[13,"FeeRateTooLow"],[4,"ScriptType"],[4,"Capability"],[4,"EsploraError"],[3,"EsploraBlockchain"],[4,"CompactFiltersError"],[3,"Mempool"],[3,"Peer"],[3,"CompactFiltersBlockchain"],[8,"Blockchain"],[8,"Progress"],[3,"MemoryDatabase"],[8,"BatchOperations"],[8,"Database"],[8,"BatchDatabase"],[4,"Descriptor"],[3,"Miniscript"],[8,"MiniscriptKey"],[8,"ScriptContext"],[4,"Terminal"],[8,"ToPublicKey"],[4,"Error"],[3,"Policy"],[3,"Condition"],[4,"SatisfiableItem"],[13,"SHA256Preimage"],[13,"HASH256Preimage"],[13,"RIPEMD160Preimage"],[13,"HASH160Preimage"],[13,"AbsoluteTimelock"],[13,"RelativeTimelock"],[13,"Thresh"],[13,"Multisig"],[4,"Satisfaction"],[13,"Partial"],[13,"PartialComplete"],[13,"Complete"],[4,"PolicyError"],[8,"ExtractPolicy"],[3,"FeeRate"],[4,"AddressValidatorError"],[8,"AddressValidator"],[3,"CoinSelectionResult"],[8,"CoinSelectionAlgorithm"],[3,"WalletExport"],[3,"SignerOrdering"],[4,"SignerId"],[4,"SignerError"],[8,"Signer"],[3,"SignersContainer"],[4,"TxOrdering"],[4,"ChangeSpendPolicy"],[3,"TxBuilder"],[8,"IsDust"],[3,"Wallet"],[3,"OfflineBlockchain"],[3,"NoopProgress"],[3,"LogProgress"],[3,"ElectrumBlockchain"],[4,"Legacy"],[4,"Segwitv0"],[3,"PKOrF"],[3,"DumbCoinSelection"]]}\ +}'); +addSearchOptions(searchIndex);initSearch(searchIndex); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/settings.css b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/settings.css new file mode 100644 index 0000000000..6ce7665866 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/settings.css @@ -0,0 +1 @@ +.setting-line{padding:5px;position:relative;}.setting-line>div{max-width:calc(100% - 74px);display:inline-block;vertical-align:top;font-size:17px;padding-top:2px;}.setting-line>.title{font-size:19px;width:100%;max-width:none;border-bottom:1px solid;}.toggle{position:relative;display:inline-block;width:45px;height:27px;margin-right:20px;}.toggle input{display:none;}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.3s;transition:.3s;}.slider:before{position:absolute;content:"";height:19px;width:19px;left:4px;bottom:4px;background-color:white;-webkit-transition:.3s;transition:.3s;}input:checked+.slider{background-color:#2196F3;}input:focus+.slider{box-shadow:0 0 1px #2196F3;}input:checked+.slider:before{-webkit-transform:translateX(19px);-ms-transform:translateX(19px);transform:translateX(19px);}.setting-line>.sub-settings{padding-left:42px;width:100%;display:block;} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/settings.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/settings.html new file mode 100644 index 0000000000..12a71ee2cf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/settings.html @@ -0,0 +1,2 @@ +Rustdoc settings

Rustdoc settings

Auto-hide item declarations
Auto-hide structs declaration
Auto-hide enums declaration
Auto-hide unions declaration
Auto-hide traits declaration
Auto-hide macros declaration
+
Auto-hide item attributes.
Auto-hide item methods' documentation
Auto-hide trait implementations documentation
Directly go to item in search if there is only one result
Show line numbers on code examples
Disable keyboard shortcuts
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/settings.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/settings.js new file mode 100644 index 0000000000..9930309054 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/settings.js @@ -0,0 +1 @@ +(function(){function changeSetting(settingName,isEnabled){updateLocalStorage('rustdoc-'+settingName,isEnabled)}function getSettingValue(settingName){return getCurrentValue('rustdoc-'+settingName)}function setEvents(){var elems=document.getElementsByClassName("slider");if(!elems||elems.length===0){return}for(var i=0;i"){sidebar.style.left="";this.style.left="";child.innerText="<";updateLocalStorage("rustdoc-source-sidebar-show","true")}else{sidebar.style.left="-300px";this.style.left="0";child.innerText=">";updateLocalStorage("rustdoc-source-sidebar-show","false")}}function createSidebarToggle(){var sidebarToggle=document.createElement("div");sidebarToggle.id="sidebar-toggle";sidebarToggle.onclick=toggleSidebar;var inner1=document.createElement("div");inner1.style.position="relative";var inner2=document.createElement("div");inner2.style.paddingTop="3px";if(getCurrentValue("rustdoc-source-sidebar-show")==="true"){inner2.innerText="<"}else{inner2.innerText=">";sidebarToggle.style.left="0"}inner1.appendChild(inner2);sidebarToggle.appendChild(inner1);return sidebarToggle}function createSourceSidebar(){if(window.rootPath.endsWith("/")===false){window.rootPath+="/"}var main=document.getElementById("main");var sidebarToggle=createSidebarToggle();main.insertBefore(sidebarToggle,main.firstChild);var sidebar=document.createElement("div");sidebar.id="source-sidebar";if(getCurrentValue("rustdoc-source-sidebar-show")!=="true"){sidebar.style.left="-300px"}var currentFile=getCurrentFilePath();var hasFoundFile=false;var title=document.createElement("div");title.className="title";title.innerText="Files";sidebar.appendChild(title);Object.keys(sourcesIndex).forEach(function(key){sourcesIndex[key].name=key;hasFoundFile=createDirEntry(sourcesIndex[key],sidebar,"",currentFile,hasFoundFile)});main.insertBefore(sidebar,main.firstChild)} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/mod.rs.html new file mode 100644 index 0000000000..6fad4c357b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/mod.rs.html @@ -0,0 +1,1057 @@ +mod.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Compact Filters
+//!
+//! This module contains a multithreaded implementation of an [`Blockchain`] backend that
+//! uses BIP157 (aka "Neutrino") to populate the wallet's [database](crate::database::Database)
+//! by downloading compact filters from the P2P network.
+//!
+//! Since there are currently very few peers "in the wild" that advertise the required service
+//! flag, this implementation requires that one or more known peers are provided by the user.
+//! No dns or other kinds of peer discovery are done internally.
+//!
+//! Moreover, this module doesn't currently support detecting and resolving conflicts between
+//! messages received by different peers. Thus, it's recommended to use this module by only
+//! connecting to a single peer at a time, optionally by opening multiple connections if it's
+//! desirable to use multiple threads at once to sync in parallel.
+//!
+//! ## Example
+//!
+//! ```no_run
+//! # use std::sync::Arc;
+//! # use bitcoin::*;
+//! # use bdk::*;
+//! # use bdk::blockchain::compact_filters::*;
+//! let num_threads = 4;
+//!
+//! let mempool = Arc::new(Mempool::default());
+//! let peers = (0..num_threads)
+//!     .map(|_| Peer::connect(
+//!         "btcd-mainnet.lightning.computer:8333",
+//!         Arc::clone(&mempool),
+//!         Network::Bitcoin,
+//!     ))
+//!     .collect::<Result<_, _>>()?;
+//! let blockchain = CompactFiltersBlockchain::new(peers, "./wallet-filters", Some(500_000))?;
+//! # Ok::<(), bdk::error::Error>(())
+//! ```
+
+use std::collections::HashSet;
+use std::fmt;
+use std::path::Path;
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::{Arc, Mutex};
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use bitcoin::network::message_blockdata::Inventory;
+use bitcoin::{OutPoint, Transaction, Txid};
+
+use rocksdb::{Options, SliceTransform, DB};
+
+mod peer;
+mod store;
+mod sync;
+
+use super::{Blockchain, Capability, Progress};
+use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
+use crate::error::Error;
+use crate::types::{ScriptType, TransactionDetails, UTXO};
+use crate::FeeRate;
+
+use peer::*;
+use store::*;
+use sync::*;
+
+pub use peer::{Mempool, Peer};
+
+const SYNC_HEADERS_COST: f32 = 1.0;
+const SYNC_FILTERS_COST: f32 = 11.6 * 1_000.0;
+const PROCESS_BLOCKS_COST: f32 = 20_000.0;
+
+/// Structure implementing the required blockchain traits
+///
+/// ## Example
+/// See the [`blockchain::compact_filters`](crate::blockchain::compact_filters) module for a usage example.
+#[derive(Debug)]
+pub struct CompactFiltersBlockchain {
+    peers: Vec<Arc<Peer>>,
+    headers: Arc<ChainStore<Full>>,
+    skip_blocks: Option<usize>,
+}
+
+impl CompactFiltersBlockchain {
+    /// Construct a new instance given a list of peers, a path to store headers and block
+    /// filters downloaded during the sync and optionally a number of blocks to ignore starting
+    /// from the genesis while scanning for the wallet's outputs.
+    ///
+    /// For each [`Peer`] specified a new thread will be spawned to download and verify the filters
+    /// in parallel. It's currently recommended to only connect to a single peer to avoid
+    /// inconsistencies in the data returned, optionally with multiple connections in parallel to
+    /// speed-up the sync process.
+    pub fn new<P: AsRef<Path>>(
+        peers: Vec<Peer>,
+        storage_dir: P,
+        skip_blocks: Option<usize>,
+    ) -> Result<Self, CompactFiltersError> {
+        if peers.is_empty() {
+            return Err(CompactFiltersError::NoPeers);
+        }
+
+        let mut opts = Options::default();
+        opts.create_if_missing(true);
+        opts.set_prefix_extractor(SliceTransform::create_fixed_prefix(16));
+
+        let network = peers[0].get_network();
+
+        let cfs = DB::list_cf(&opts, &storage_dir).unwrap_or(vec!["default".to_string()]);
+        let db = DB::open_cf(&opts, &storage_dir, &cfs)?;
+        let headers = Arc::new(ChainStore::new(db, network)?);
+
+        // try to recover partial snapshots
+        for cf_name in &cfs {
+            if !cf_name.starts_with("_headers:") {
+                continue;
+            }
+
+            info!("Trying to recover: {:?}", cf_name);
+            headers.recover_snapshot(cf_name)?;
+        }
+
+        Ok(CompactFiltersBlockchain {
+            peers: peers.into_iter().map(Arc::new).collect(),
+            headers,
+            skip_blocks,
+        })
+    }
+
+    /// Process a transaction by looking for inputs that spend from a UTXO in the database or
+    /// outputs that send funds to a know script_pubkey.
+    fn process_tx<D: BatchDatabase>(
+        &self,
+        database: &mut D,
+        tx: &Transaction,
+        height: Option<u32>,
+        timestamp: u64,
+        internal_max_deriv: &mut Option<u32>,
+        external_max_deriv: &mut Option<u32>,
+    ) -> Result<(), Error> {
+        let mut updates = database.begin_batch();
+
+        let mut incoming: u64 = 0;
+        let mut outgoing: u64 = 0;
+
+        let mut inputs_sum: u64 = 0;
+        let mut outputs_sum: u64 = 0;
+
+        // look for our own inputs
+        for (i, input) in tx.input.iter().enumerate() {
+            if let Some(previous_output) = database.get_previous_output(&input.previous_output)? {
+                inputs_sum += previous_output.value;
+
+                if database.is_mine(&previous_output.script_pubkey)? {
+                    outgoing += previous_output.value;
+
+                    debug!("{} input #{} is mine, removing from utxo", tx.txid(), i);
+                    updates.del_utxo(&input.previous_output)?;
+                }
+            }
+        }
+
+        for (i, output) in tx.output.iter().enumerate() {
+            // to compute the fees later
+            outputs_sum += output.value;
+
+            // this output is ours, we have a path to derive it
+            if let Some((script_type, child)) =
+                database.get_path_from_script_pubkey(&output.script_pubkey)?
+            {
+                debug!("{} output #{} is mine, adding utxo", tx.txid(), i);
+                updates.set_utxo(&UTXO {
+                    outpoint: OutPoint::new(tx.txid(), i as u32),
+                    txout: output.clone(),
+                    is_internal: script_type.is_internal(),
+                })?;
+                incoming += output.value;
+
+                if script_type == ScriptType::Internal
+                    && (internal_max_deriv.is_none() || child > internal_max_deriv.unwrap_or(0))
+                {
+                    *internal_max_deriv = Some(child);
+                } else if script_type == ScriptType::External
+                    && (external_max_deriv.is_none() || child > external_max_deriv.unwrap_or(0))
+                {
+                    *external_max_deriv = Some(child);
+                }
+            }
+        }
+
+        if incoming > 0 || outgoing > 0 {
+            let tx = TransactionDetails {
+                txid: tx.txid(),
+                transaction: Some(tx.clone()),
+                received: incoming,
+                sent: outgoing,
+                height,
+                timestamp,
+                fees: inputs_sum.checked_sub(outputs_sum).unwrap_or(0),
+            };
+
+            info!("Saving tx {}", tx.txid);
+            updates.set_tx(&tx)?;
+        }
+
+        database.commit_batch(updates)?;
+
+        Ok(())
+    }
+}
+
+impl Blockchain for CompactFiltersBlockchain {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        vec![Capability::FullHistory].into_iter().collect()
+    }
+
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        _stop_gap: Option<usize>, // TODO: move to electrum and esplora only
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        let first_peer = &self.peers[0];
+
+        let skip_blocks = self.skip_blocks.unwrap_or(0);
+
+        let cf_sync = Arc::new(CFSync::new(Arc::clone(&self.headers), skip_blocks, 0x00)?);
+
+        let initial_height = self.headers.get_height()?;
+        let total_bundles = (first_peer.get_version().start_height as usize)
+            .checked_sub(skip_blocks)
+            .map(|x| x / 1000)
+            .unwrap_or(0)
+            + 1;
+        let expected_bundles_to_sync = total_bundles
+            .checked_sub(cf_sync.pruned_bundles()?)
+            .unwrap_or(0);
+
+        let headers_cost = (first_peer.get_version().start_height as usize)
+            .checked_sub(initial_height)
+            .unwrap_or(0) as f32
+            * SYNC_HEADERS_COST;
+        let filters_cost = expected_bundles_to_sync as f32 * SYNC_FILTERS_COST;
+
+        let total_cost = headers_cost + filters_cost + PROCESS_BLOCKS_COST;
+
+        if let Some(snapshot) = sync::sync_headers(
+            Arc::clone(&first_peer),
+            Arc::clone(&self.headers),
+            |new_height| {
+                let local_headers_cost =
+                    new_height.checked_sub(initial_height).unwrap_or(0) as f32 * SYNC_HEADERS_COST;
+                progress_update.update(
+                    local_headers_cost / total_cost * 100.0,
+                    Some(format!("Synced headers to {}", new_height)),
+                )
+            },
+        )? {
+            if snapshot.work()? > self.headers.work()? {
+                info!("Applying snapshot with work: {}", snapshot.work()?);
+                self.headers.apply_snapshot(snapshot)?;
+            }
+        }
+
+        let synced_height = self.headers.get_height()?;
+        let buried_height = synced_height
+            .checked_sub(sync::BURIED_CONFIRMATIONS)
+            .unwrap_or(0);
+        info!("Synced headers to height: {}", synced_height);
+
+        cf_sync.prepare_sync(Arc::clone(&first_peer))?;
+
+        let all_scripts = Arc::new(
+            database
+                .iter_script_pubkeys(None)?
+                .into_iter()
+                .map(|s| s.to_bytes())
+                .collect::<Vec<_>>(),
+        );
+
+        let last_synced_block = Arc::new(Mutex::new(synced_height));
+        let synced_bundles = Arc::new(AtomicUsize::new(0));
+        let progress_update = Arc::new(Mutex::new(progress_update));
+
+        let mut threads = Vec::with_capacity(self.peers.len());
+        for peer in &self.peers {
+            let cf_sync = Arc::clone(&cf_sync);
+            let peer = Arc::clone(&peer);
+            let headers = Arc::clone(&self.headers);
+            let all_scripts = Arc::clone(&all_scripts);
+            let last_synced_block = Arc::clone(&last_synced_block);
+            let progress_update = Arc::clone(&progress_update);
+            let synced_bundles = Arc::clone(&synced_bundles);
+
+            let thread = std::thread::spawn(move || {
+                cf_sync.capture_thread_for_sync(
+                    peer,
+                    |block_hash, filter| {
+                        if !filter
+                            .match_any(block_hash, &mut all_scripts.iter().map(AsRef::as_ref))?
+                        {
+                            return Ok(false);
+                        }
+
+                        let block_height = headers.get_height_for(block_hash)?.unwrap_or(0);
+                        let saved_correct_block = match headers.get_full_block(block_height)? {
+                            Some(block) if &block.block_hash() == block_hash => true,
+                            _ => false,
+                        };
+
+                        if saved_correct_block {
+                            Ok(false)
+                        } else {
+                            let mut last_synced_block = last_synced_block.lock().unwrap();
+
+                            // If we download a block older than `last_synced_block`, we update it so that
+                            // we know to delete and re-process all txs starting from that height
+                            if block_height < *last_synced_block {
+                                *last_synced_block = block_height;
+                            }
+
+                            Ok(true)
+                        }
+                    },
+                    |index| {
+                        let synced_bundles = synced_bundles.fetch_add(1, Ordering::SeqCst);
+                        let local_filters_cost = synced_bundles as f32 * SYNC_FILTERS_COST;
+                        progress_update.lock().unwrap().update(
+                            (headers_cost + local_filters_cost) / total_cost * 100.0,
+                            Some(format!(
+                                "Synced filters {} - {}",
+                                index * 1000 + 1,
+                                (index + 1) * 1000
+                            )),
+                        )
+                    },
+                )
+            });
+
+            threads.push(thread);
+        }
+
+        for t in threads {
+            t.join().unwrap()?;
+        }
+
+        progress_update.lock().unwrap().update(
+            (headers_cost + filters_cost) / total_cost * 100.0,
+            Some("Processing downloaded blocks and mempool".into()),
+        )?;
+
+        // delete all txs newer than last_synced_block
+        let last_synced_block = *last_synced_block.lock().unwrap();
+        log::debug!(
+            "Dropping transactions newer than `last_synced_block` = {}",
+            last_synced_block
+        );
+        let mut updates = database.begin_batch();
+        for details in database.iter_txs(false)? {
+            match details.height {
+                Some(height) if (height as usize) < last_synced_block => continue,
+                _ => updates.del_tx(&details.txid, false)?,
+            };
+        }
+        database.commit_batch(updates)?;
+
+        first_peer.ask_for_mempool()?;
+
+        let mut internal_max_deriv = None;
+        let mut external_max_deriv = None;
+
+        for (height, block) in self.headers.iter_full_blocks()? {
+            for tx in &block.txdata {
+                self.process_tx(
+                    database,
+                    tx,
+                    Some(height as u32),
+                    0,
+                    &mut internal_max_deriv,
+                    &mut external_max_deriv,
+                )?;
+            }
+        }
+        for tx in first_peer.get_mempool().iter_txs().iter() {
+            self.process_tx(
+                database,
+                tx,
+                None,
+                0,
+                &mut internal_max_deriv,
+                &mut external_max_deriv,
+            )?;
+        }
+
+        let current_ext = database.get_last_index(ScriptType::External)?.unwrap_or(0);
+        let first_ext_new = external_max_deriv.map(|x| x + 1).unwrap_or(0);
+        if first_ext_new > current_ext {
+            info!("Setting external index to {}", first_ext_new);
+            database.set_last_index(ScriptType::External, first_ext_new)?;
+        }
+
+        let current_int = database.get_last_index(ScriptType::Internal)?.unwrap_or(0);
+        let first_int_new = internal_max_deriv.map(|x| x + 1).unwrap_or(0);
+        if first_int_new > current_int {
+            info!("Setting internal index to {}", first_int_new);
+            database.set_last_index(ScriptType::Internal, first_int_new)?;
+        }
+
+        info!("Dropping blocks until {}", buried_height);
+        self.headers.delete_blocks_until(buried_height)?;
+
+        progress_update
+            .lock()
+            .unwrap()
+            .update(100.0, Some("Done".into()))?;
+
+        Ok(())
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        Ok(self.peers[0]
+            .get_mempool()
+            .get_tx(&Inventory::Transaction(*txid)))
+    }
+
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        self.peers[0].broadcast_tx(tx.clone())?;
+
+        Ok(())
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        Ok(self.headers.get_height()? as u32)
+    }
+
+    fn estimate_fee(&self, _target: usize) -> Result<FeeRate, Error> {
+        // TODO
+        Ok(FeeRate::default())
+    }
+}
+
+/// An error that can occur during sync with a [`CompactFiltersBlockchain`]
+#[derive(Debug)]
+pub enum CompactFiltersError {
+    /// A peer sent an invalid or unexpected response
+    InvalidResponse,
+    /// The headers returned are invalid
+    InvalidHeaders,
+    /// The compact filter headers returned are invalid
+    InvalidFilterHeader,
+    /// The compact filter returned is invalid
+    InvalidFilter,
+    /// The peer is missing a block in the valid chain
+    MissingBlock,
+    /// The data stored in the block filters storage are corrupted
+    DataCorruption,
+
+    /// A peer is not connected
+    NotConnected,
+    /// A peer took too long to reply to one of our messages
+    Timeout,
+
+    /// No peers have been specified
+    NoPeers,
+
+    /// Internal database error
+    DB(rocksdb::Error),
+    /// Internal I/O error
+    IO(std::io::Error),
+    /// Invalid BIP158 filter
+    BIP158(bitcoin::util::bip158::Error),
+    /// Internal system time error
+    Time(std::time::SystemTimeError),
+
+    /// Wrapper for [`crate::error::Error`]
+    Global(Box<crate::error::Error>),
+}
+
+impl fmt::Display for CompactFiltersError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for CompactFiltersError {}
+
+macro_rules! impl_error {
+    ( $from:ty, $to:ident ) => {
+        impl std::convert::From<$from> for CompactFiltersError {
+            fn from(err: $from) -> Self {
+                CompactFiltersError::$to(err)
+            }
+        }
+    };
+}
+
+impl_error!(rocksdb::Error, DB);
+impl_error!(std::io::Error, IO);
+impl_error!(bitcoin::util::bip158::Error, BIP158);
+impl_error!(std::time::SystemTimeError, Time);
+
+impl From<crate::error::Error> for CompactFiltersError {
+    fn from(err: crate::error::Error) -> Self {
+        CompactFiltersError::Global(Box::new(err))
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/peer.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/peer.rs.html new file mode 100644 index 0000000000..cdec7c7773 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/peer.rs.html @@ -0,0 +1,1103 @@ +peer.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::collections::HashMap;
+use std::net::{TcpStream, ToSocketAddrs};
+use std::sync::{Arc, Condvar, Mutex, RwLock};
+use std::thread;
+use std::time::{Duration, SystemTime, UNIX_EPOCH};
+
+use socks::{Socks5Stream, ToTargetAddr};
+
+use rand::{thread_rng, Rng};
+
+use bitcoin::consensus::Encodable;
+use bitcoin::hash_types::BlockHash;
+use bitcoin::hashes::Hash;
+use bitcoin::network::constants::ServiceFlags;
+use bitcoin::network::message::{NetworkMessage, RawNetworkMessage};
+use bitcoin::network::message_blockdata::*;
+use bitcoin::network::message_filter::*;
+use bitcoin::network::message_network::VersionMessage;
+use bitcoin::network::stream_reader::StreamReader;
+use bitcoin::network::Address;
+use bitcoin::{Block, Network, Transaction, Txid};
+
+use super::CompactFiltersError;
+
+type ResponsesMap = HashMap<&'static str, Arc<(Mutex<Vec<NetworkMessage>>, Condvar)>>;
+
+pub(crate) const TIMEOUT_SECS: u64 = 30;
+
+/// Container for unconfirmed, but valid Bitcoin transactions
+///
+/// It is normally shared between [`Peer`]s with the use of [`Arc`], so that transactions are not
+/// duplicated in memory.
+#[derive(Debug, Default)]
+pub struct Mempool {
+    txs: RwLock<HashMap<Txid, Transaction>>,
+}
+
+impl Mempool {
+    /// Add a transaction to the mempool
+    ///
+    /// Note that this doesn't propagate the transaction to other
+    /// peers. To do that, [`broadcast`](crate::blockchain::Blockchain::broadcast) should be used.
+    pub fn add_tx(&self, tx: Transaction) {
+        self.txs.write().unwrap().insert(tx.txid(), tx);
+    }
+
+    /// Look-up a transaction in the mempool given an [`Inventory`] request
+    pub fn get_tx(&self, inventory: &Inventory) -> Option<Transaction> {
+        let txid = match inventory {
+            Inventory::Error | Inventory::Block(_) | Inventory::WitnessBlock(_) => return None,
+            Inventory::Transaction(txid) => *txid,
+            Inventory::WitnessTransaction(wtxid) => Txid::from_inner(wtxid.into_inner()),
+        };
+        self.txs.read().unwrap().get(&txid).cloned()
+    }
+
+    /// Return whether or not the mempool contains a transaction with a given txid
+    pub fn has_tx(&self, txid: &Txid) -> bool {
+        self.txs.read().unwrap().contains_key(txid)
+    }
+
+    /// Return the list of transactions contained in the mempool
+    pub fn iter_txs(&self) -> Vec<Transaction> {
+        self.txs.read().unwrap().values().cloned().collect()
+    }
+}
+
+/// A Bitcoin peer
+#[derive(Debug)]
+pub struct Peer {
+    writer: Arc<Mutex<TcpStream>>,
+    responses: Arc<RwLock<ResponsesMap>>,
+
+    reader_thread: thread::JoinHandle<()>,
+    connected: Arc<RwLock<bool>>,
+
+    mempool: Arc<Mempool>,
+
+    version: VersionMessage,
+    network: Network,
+}
+
+impl Peer {
+    /// Connect to a peer over a plaintext TCP connection
+    ///
+    /// This function internally spawns a new thread that will monitor incoming messages from the
+    /// peer, and optionally reply to some of them transparently, like [pings](NetworkMessage::Ping)
+    pub fn connect<A: ToSocketAddrs>(
+        address: A,
+        mempool: Arc<Mempool>,
+        network: Network,
+    ) -> Result<Self, CompactFiltersError> {
+        let stream = TcpStream::connect(address)?;
+
+        Peer::from_stream(stream, mempool, network)
+    }
+
+    /// Connect to a peer through a SOCKS5 proxy, optionally by using some credentials, specified
+    /// as a tuple of `(username, password)`
+    ///
+    /// This function internally spawns a new thread that will monitor incoming messages from the
+    /// peer, and optionally reply to some of them transparently, like [pings](NetworkMessage::Ping)
+    pub fn connect_proxy<T: ToTargetAddr, P: ToSocketAddrs>(
+        target: T,
+        proxy: P,
+        credentials: Option<(&str, &str)>,
+        mempool: Arc<Mempool>,
+        network: Network,
+    ) -> Result<Self, CompactFiltersError> {
+        let socks_stream = if let Some((username, password)) = credentials {
+            Socks5Stream::connect_with_password(proxy, target, username, password)?
+        } else {
+            Socks5Stream::connect(proxy, target)?
+        };
+
+        Peer::from_stream(socks_stream.into_inner(), mempool, network)
+    }
+
+    /// Create a [`Peer`] from an already connected TcpStream
+    fn from_stream(
+        stream: TcpStream,
+        mempool: Arc<Mempool>,
+        network: Network,
+    ) -> Result<Self, CompactFiltersError> {
+        let writer = Arc::new(Mutex::new(stream.try_clone()?));
+        let responses: Arc<RwLock<ResponsesMap>> = Arc::new(RwLock::new(HashMap::new()));
+        let connected = Arc::new(RwLock::new(true));
+
+        let mut locked_writer = writer.lock().unwrap();
+
+        let reader_thread_responses = Arc::clone(&responses);
+        let reader_thread_writer = Arc::clone(&writer);
+        let reader_thread_mempool = Arc::clone(&mempool);
+        let reader_thread_connected = Arc::clone(&connected);
+        let reader_thread = thread::spawn(move || {
+            Self::reader_thread(
+                network,
+                stream,
+                reader_thread_responses,
+                reader_thread_writer,
+                reader_thread_mempool,
+                reader_thread_connected,
+            )
+        });
+
+        let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() as i64;
+        let nonce = thread_rng().gen();
+        let receiver = Address::new(&locked_writer.peer_addr()?, ServiceFlags::NONE);
+        let sender = Address {
+            services: ServiceFlags::NONE,
+            address: [0u16; 8],
+            port: 0,
+        };
+
+        Self::_send(
+            &mut locked_writer,
+            network.magic(),
+            NetworkMessage::Version(VersionMessage::new(
+                ServiceFlags::WITNESS,
+                timestamp,
+                receiver,
+                sender,
+                nonce,
+                "MagicalBitcoinWallet".into(),
+                0,
+            )),
+        )?;
+        let version = if let NetworkMessage::Version(version) =
+            Self::_recv(&responses, "version", None)?.unwrap()
+        {
+            version
+        } else {
+            return Err(CompactFiltersError::InvalidResponse);
+        };
+
+        if let NetworkMessage::Verack = Self::_recv(&responses, "verack", None)?.unwrap() {
+            Self::_send(&mut locked_writer, network.magic(), NetworkMessage::Verack)?;
+        } else {
+            return Err(CompactFiltersError::InvalidResponse);
+        }
+
+        std::mem::drop(locked_writer);
+
+        Ok(Peer {
+            writer,
+            reader_thread,
+            responses,
+            connected,
+            mempool,
+            network,
+            version,
+        })
+    }
+
+    /// Send a Bitcoin network message
+    fn _send(
+        writer: &mut TcpStream,
+        magic: u32,
+        payload: NetworkMessage,
+    ) -> Result<(), CompactFiltersError> {
+        log::trace!("==> {:?}", payload);
+
+        let raw_message = RawNetworkMessage { magic, payload };
+
+        raw_message
+            .consensus_encode(writer)
+            .map_err(|_| CompactFiltersError::DataCorruption)?;
+
+        Ok(())
+    }
+
+    /// Wait for a specific incoming Bitcoin message, optionally with a timeout
+    fn _recv(
+        responses: &Arc<RwLock<ResponsesMap>>,
+        wait_for: &'static str,
+        timeout: Option<Duration>,
+    ) -> Result<Option<NetworkMessage>, CompactFiltersError> {
+        let message_resp = {
+            let mut lock = responses.write().unwrap();
+            let message_resp = lock.entry(wait_for).or_default();
+            Arc::clone(&message_resp)
+        };
+
+        let (lock, cvar) = &*message_resp;
+
+        let mut messages = lock.lock().unwrap();
+        while messages.is_empty() {
+            match timeout {
+                None => messages = cvar.wait(messages).unwrap(),
+                Some(t) => {
+                    let result = cvar.wait_timeout(messages, t).unwrap();
+                    if result.1.timed_out() {
+                        return Ok(None);
+                    }
+
+                    messages = result.0;
+                }
+            }
+        }
+
+        Ok(messages.pop())
+    }
+
+    /// Return the [`VersionMessage`] sent by the peer
+    pub fn get_version(&self) -> &VersionMessage {
+        &self.version
+    }
+
+    /// Return the Bitcoin [`Network`] in use
+    pub fn get_network(&self) -> Network {
+        self.network
+    }
+
+    /// Return the mempool used by this peer
+    pub fn get_mempool(&self) -> Arc<Mempool> {
+        Arc::clone(&self.mempool)
+    }
+
+    /// Return whether or not the peer is still connected
+    pub fn is_connected(&self) -> bool {
+        *self.connected.read().unwrap()
+    }
+
+    /// Internal function called once the `reader_thread` is spawned
+    fn reader_thread(
+        network: Network,
+        connection: TcpStream,
+        reader_thread_responses: Arc<RwLock<ResponsesMap>>,
+        reader_thread_writer: Arc<Mutex<TcpStream>>,
+        reader_thread_mempool: Arc<Mempool>,
+        reader_thread_connected: Arc<RwLock<bool>>,
+    ) {
+        macro_rules! check_disconnect {
+            ($call:expr) => {
+                match $call {
+                    Ok(good) => good,
+                    Err(e) => {
+                        log::debug!("Error {:?}", e);
+                        *reader_thread_connected.write().unwrap() = false;
+
+                        break;
+                    }
+                }
+            };
+        }
+
+        let mut reader = StreamReader::new(connection, None);
+        loop {
+            let raw_message: RawNetworkMessage = check_disconnect!(reader.read_next());
+
+            let in_message = if raw_message.magic != network.magic() {
+                continue;
+            } else {
+                raw_message.payload
+            };
+
+            log::trace!("<== {:?}", in_message);
+
+            match in_message {
+                NetworkMessage::Ping(nonce) => {
+                    check_disconnect!(Self::_send(
+                        &mut reader_thread_writer.lock().unwrap(),
+                        network.magic(),
+                        NetworkMessage::Pong(nonce),
+                    ));
+
+                    continue;
+                }
+                NetworkMessage::Alert(_) => continue,
+                NetworkMessage::GetData(ref inv) => {
+                    let (found, not_found): (Vec<_>, Vec<_>) = inv
+                        .into_iter()
+                        .map(|item| (*item, reader_thread_mempool.get_tx(item)))
+                        .partition(|(_, d)| d.is_some());
+                    for (_, found_tx) in found {
+                        check_disconnect!(Self::_send(
+                            &mut reader_thread_writer.lock().unwrap(),
+                            network.magic(),
+                            NetworkMessage::Tx(found_tx.unwrap()),
+                        ));
+                    }
+
+                    if !not_found.is_empty() {
+                        check_disconnect!(Self::_send(
+                            &mut reader_thread_writer.lock().unwrap(),
+                            network.magic(),
+                            NetworkMessage::NotFound(
+                                not_found.into_iter().map(|(i, _)| i).collect(),
+                            ),
+                        ));
+                    }
+                }
+                _ => {}
+            }
+
+            let message_resp = {
+                let mut lock = reader_thread_responses.write().unwrap();
+                let message_resp = lock.entry(in_message.cmd()).or_default();
+                Arc::clone(&message_resp)
+            };
+
+            let (lock, cvar) = &*message_resp;
+            let mut messages = lock.lock().unwrap();
+            messages.push(in_message);
+            cvar.notify_all();
+        }
+    }
+
+    /// Send a raw Bitcoin message to the peer
+    pub fn send(&self, payload: NetworkMessage) -> Result<(), CompactFiltersError> {
+        let mut writer = self.writer.lock().unwrap();
+        Self::_send(&mut writer, self.network.magic(), payload)
+    }
+
+    /// Waits for a specific incoming Bitcoin message, optionally with a timeout
+    pub fn recv(
+        &self,
+        wait_for: &'static str,
+        timeout: Option<Duration>,
+    ) -> Result<Option<NetworkMessage>, CompactFiltersError> {
+        Self::_recv(&self.responses, wait_for, timeout)
+    }
+}
+
+pub trait CompactFiltersPeer {
+    fn get_cf_checkpt(
+        &self,
+        filter_type: u8,
+        stop_hash: BlockHash,
+    ) -> Result<CFCheckpt, CompactFiltersError>;
+    fn get_cf_headers(
+        &self,
+        filter_type: u8,
+        start_height: u32,
+        stop_hash: BlockHash,
+    ) -> Result<CFHeaders, CompactFiltersError>;
+    fn get_cf_filters(
+        &self,
+        filter_type: u8,
+        start_height: u32,
+        stop_hash: BlockHash,
+    ) -> Result<(), CompactFiltersError>;
+    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError>;
+}
+
+impl CompactFiltersPeer for Peer {
+    fn get_cf_checkpt(
+        &self,
+        filter_type: u8,
+        stop_hash: BlockHash,
+    ) -> Result<CFCheckpt, CompactFiltersError> {
+        self.send(NetworkMessage::GetCFCheckpt(GetCFCheckpt {
+            filter_type,
+            stop_hash,
+        }))?;
+
+        let response = self
+            .recv("cfcheckpt", Some(Duration::from_secs(TIMEOUT_SECS)))?
+            .ok_or(CompactFiltersError::Timeout)?;
+        let response = match response {
+            NetworkMessage::CFCheckpt(response) => response,
+            _ => return Err(CompactFiltersError::InvalidResponse),
+        };
+
+        if response.filter_type != filter_type {
+            return Err(CompactFiltersError::InvalidResponse);
+        }
+
+        Ok(response)
+    }
+
+    fn get_cf_headers(
+        &self,
+        filter_type: u8,
+        start_height: u32,
+        stop_hash: BlockHash,
+    ) -> Result<CFHeaders, CompactFiltersError> {
+        self.send(NetworkMessage::GetCFHeaders(GetCFHeaders {
+            filter_type,
+            start_height,
+            stop_hash,
+        }))?;
+
+        let response = self
+            .recv("cfheaders", Some(Duration::from_secs(TIMEOUT_SECS)))?
+            .ok_or(CompactFiltersError::Timeout)?;
+        let response = match response {
+            NetworkMessage::CFHeaders(response) => response,
+            _ => return Err(CompactFiltersError::InvalidResponse),
+        };
+
+        if response.filter_type != filter_type {
+            return Err(CompactFiltersError::InvalidResponse);
+        }
+
+        Ok(response)
+    }
+
+    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError> {
+        let response = self
+            .recv("cfilter", Some(Duration::from_secs(TIMEOUT_SECS)))?
+            .ok_or(CompactFiltersError::Timeout)?;
+        let response = match response {
+            NetworkMessage::CFilter(response) => response,
+            _ => return Err(CompactFiltersError::InvalidResponse),
+        };
+
+        Ok(response)
+    }
+
+    fn get_cf_filters(
+        &self,
+        filter_type: u8,
+        start_height: u32,
+        stop_hash: BlockHash,
+    ) -> Result<(), CompactFiltersError> {
+        self.send(NetworkMessage::GetCFilters(GetCFilters {
+            filter_type,
+            start_height,
+            stop_hash,
+        }))?;
+
+        Ok(())
+    }
+}
+
+pub trait InvPeer {
+    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError>;
+    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError>;
+    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError>;
+}
+
+impl InvPeer for Peer {
+    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError> {
+        self.send(NetworkMessage::GetData(vec![Inventory::WitnessBlock(
+            block_hash,
+        )]))?;
+
+        match self.recv("block", Some(Duration::from_secs(TIMEOUT_SECS)))? {
+            None => Ok(None),
+            Some(NetworkMessage::Block(response)) => Ok(Some(response)),
+            _ => Err(CompactFiltersError::InvalidResponse),
+        }
+    }
+
+    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError> {
+        self.send(NetworkMessage::MemPool)?;
+        let inv = match self.recv("inv", Some(Duration::from_secs(5)))? {
+            None => return Ok(()), // empty mempool
+            Some(NetworkMessage::Inv(inv)) => inv,
+            _ => return Err(CompactFiltersError::InvalidResponse),
+        };
+
+        let getdata = inv
+            .iter()
+            .cloned()
+            .filter(|item| match item {
+                Inventory::Transaction(txid) if !self.mempool.has_tx(txid) => true,
+                _ => false,
+            })
+            .collect::<Vec<_>>();
+        let num_txs = getdata.len();
+        self.send(NetworkMessage::GetData(getdata))?;
+
+        for _ in 0..num_txs {
+            let tx = self
+                .recv("tx", Some(Duration::from_secs(TIMEOUT_SECS)))?
+                .ok_or(CompactFiltersError::Timeout)?;
+            let tx = match tx {
+                NetworkMessage::Tx(tx) => tx,
+                _ => return Err(CompactFiltersError::InvalidResponse),
+            };
+
+            self.mempool.add_tx(tx);
+        }
+
+        Ok(())
+    }
+
+    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError> {
+        self.mempool.add_tx(tx.clone());
+        self.send(NetworkMessage::Tx(tx))?;
+
+        Ok(())
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/store.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/store.rs.html new file mode 100644 index 0000000000..64172790be --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/store.rs.html @@ -0,0 +1,1811 @@ +store.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::convert::TryInto;
+use std::fmt;
+use std::io::{Read, Write};
+use std::marker::PhantomData;
+use std::ops::Deref;
+use std::sync::Arc;
+use std::sync::RwLock;
+
+use rand::distributions::Alphanumeric;
+use rand::{thread_rng, Rng};
+
+use rocksdb::{Direction, IteratorMode, ReadOptions, WriteBatch, DB};
+
+use bitcoin::consensus::{deserialize, encode::VarInt, serialize, Decodable, Encodable};
+use bitcoin::hash_types::FilterHash;
+use bitcoin::hashes::hex::FromHex;
+use bitcoin::hashes::{sha256d, Hash};
+use bitcoin::util::bip158::BlockFilter;
+use bitcoin::util::uint::Uint256;
+use bitcoin::Block;
+use bitcoin::BlockHash;
+use bitcoin::BlockHeader;
+use bitcoin::Network;
+
+use super::CompactFiltersError;
+
+lazy_static! {
+    static ref MAINNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A29AB5F49FFFF001D1DAC2B7C0101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
+    static ref TESTNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4ADAE5494DFFFF001D1AA4AE180101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
+    static ref REGTEST_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4ADAE5494DFFFF7F20020000000101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
+}
+
+pub trait StoreType: Default + fmt::Debug {}
+
+#[derive(Default, Debug)]
+pub struct Full;
+impl StoreType for Full {}
+#[derive(Default, Debug)]
+pub struct Snapshot;
+impl StoreType for Snapshot {}
+
+pub enum StoreEntry {
+    BlockHeader(Option<usize>),
+    Block(Option<usize>),
+    BlockHeaderIndex(Option<BlockHash>),
+    CFilterTable((u8, Option<usize>)),
+}
+
+impl StoreEntry {
+    pub fn get_prefix(&self) -> Vec<u8> {
+        match self {
+            StoreEntry::BlockHeader(_) => b"z",
+            StoreEntry::Block(_) => b"x",
+            StoreEntry::BlockHeaderIndex(_) => b"i",
+            StoreEntry::CFilterTable(_) => b"t",
+        }
+        .to_vec()
+    }
+
+    pub fn get_key(&self) -> Vec<u8> {
+        let mut prefix = self.get_prefix();
+        match self {
+            StoreEntry::BlockHeader(Some(height)) => {
+                prefix.extend_from_slice(&height.to_be_bytes())
+            }
+            StoreEntry::Block(Some(height)) => prefix.extend_from_slice(&height.to_be_bytes()),
+            StoreEntry::BlockHeaderIndex(Some(hash)) => {
+                prefix.extend_from_slice(&hash.into_inner())
+            }
+            StoreEntry::CFilterTable((filter_type, bundle_index)) => {
+                prefix.push(*filter_type);
+                if let Some(bundle_index) = bundle_index {
+                    prefix.extend_from_slice(&bundle_index.to_be_bytes());
+                }
+            }
+            _ => {}
+        }
+
+        prefix
+    }
+}
+
+pub trait SerializeDb: Sized {
+    fn serialize(&self) -> Vec<u8>;
+    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError>;
+}
+
+impl<T> SerializeDb for T
+where
+    T: Encodable + Decodable,
+{
+    fn serialize(&self) -> Vec<u8> {
+        serialize(self)
+    }
+
+    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError> {
+        Ok(deserialize(data).map_err(|_| CompactFiltersError::DataCorruption)?)
+    }
+}
+
+impl Encodable for FilterHeader {
+    fn consensus_encode<W: Write>(
+        &self,
+        mut e: W,
+    ) -> Result<usize, bitcoin::consensus::encode::Error> {
+        let mut written = self.prev_header_hash.consensus_encode(&mut e)?;
+        written += self.filter_hash.consensus_encode(&mut e)?;
+        Ok(written)
+    }
+}
+
+impl Decodable for FilterHeader {
+    fn consensus_decode<D: Read>(mut d: D) -> Result<Self, bitcoin::consensus::encode::Error> {
+        let prev_header_hash = FilterHeaderHash::consensus_decode(&mut d)?;
+        let filter_hash = FilterHash::consensus_decode(&mut d)?;
+
+        Ok(FilterHeader {
+            prev_header_hash,
+            filter_hash,
+        })
+    }
+}
+
+impl Encodable for BundleStatus {
+    fn consensus_encode<W: Write>(
+        &self,
+        mut e: W,
+    ) -> Result<usize, bitcoin::consensus::encode::Error> {
+        let mut written = 0;
+
+        match self {
+            BundleStatus::Init => {
+                written += 0x00u8.consensus_encode(&mut e)?;
+            }
+            BundleStatus::CFHeaders { cf_headers } => {
+                written += 0x01u8.consensus_encode(&mut e)?;
+                written += VarInt(cf_headers.len() as u64).consensus_encode(&mut e)?;
+                for header in cf_headers {
+                    written += header.consensus_encode(&mut e)?;
+                }
+            }
+            BundleStatus::CFilters { cf_filters } => {
+                written += 0x02u8.consensus_encode(&mut e)?;
+                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
+                for filter in cf_filters {
+                    written += filter.consensus_encode(&mut e)?;
+                }
+            }
+            BundleStatus::Processed { cf_filters } => {
+                written += 0x03u8.consensus_encode(&mut e)?;
+                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
+                for filter in cf_filters {
+                    written += filter.consensus_encode(&mut e)?;
+                }
+            }
+            BundleStatus::Pruned => {
+                written += 0x04u8.consensus_encode(&mut e)?;
+            }
+            BundleStatus::Tip { cf_filters } => {
+                written += 0x05u8.consensus_encode(&mut e)?;
+                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
+                for filter in cf_filters {
+                    written += filter.consensus_encode(&mut e)?;
+                }
+            }
+        }
+
+        Ok(written)
+    }
+}
+
+impl Decodable for BundleStatus {
+    fn consensus_decode<D: Read>(mut d: D) -> Result<Self, bitcoin::consensus::encode::Error> {
+        let byte_type = u8::consensus_decode(&mut d)?;
+        match byte_type {
+            0x00 => Ok(BundleStatus::Init),
+            0x01 => {
+                let num = VarInt::consensus_decode(&mut d)?;
+                let num = num.0 as usize;
+
+                let mut cf_headers = Vec::with_capacity(num);
+                for _ in 0..num {
+                    cf_headers.push(FilterHeader::consensus_decode(&mut d)?);
+                }
+
+                Ok(BundleStatus::CFHeaders { cf_headers })
+            }
+            0x02 => {
+                let num = VarInt::consensus_decode(&mut d)?;
+                let num = num.0 as usize;
+
+                let mut cf_filters = Vec::with_capacity(num);
+                for _ in 0..num {
+                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
+                }
+
+                Ok(BundleStatus::CFilters { cf_filters })
+            }
+            0x03 => {
+                let num = VarInt::consensus_decode(&mut d)?;
+                let num = num.0 as usize;
+
+                let mut cf_filters = Vec::with_capacity(num);
+                for _ in 0..num {
+                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
+                }
+
+                Ok(BundleStatus::Processed { cf_filters })
+            }
+            0x04 => Ok(BundleStatus::Pruned),
+            0x05 => {
+                let num = VarInt::consensus_decode(&mut d)?;
+                let num = num.0 as usize;
+
+                let mut cf_filters = Vec::with_capacity(num);
+                for _ in 0..num {
+                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
+                }
+
+                Ok(BundleStatus::Tip { cf_filters })
+            }
+            _ => Err(bitcoin::consensus::encode::Error::ParseFailed(
+                "Invalid byte type",
+            )),
+        }
+    }
+}
+
+pub struct ChainStore<T: StoreType> {
+    store: Arc<RwLock<DB>>,
+    cf_name: String,
+    min_height: usize,
+    network: Network,
+    phantom: PhantomData<T>,
+}
+
+impl ChainStore<Full> {
+    pub fn new(store: DB, network: Network) -> Result<Self, CompactFiltersError> {
+        let genesis = match network {
+            Network::Bitcoin => MAINNET_GENESIS.deref(),
+            Network::Testnet => TESTNET_GENESIS.deref(),
+            Network::Regtest => REGTEST_GENESIS.deref(),
+        };
+
+        let cf_name = "default".to_string();
+        let cf_handle = store.cf_handle(&cf_name).unwrap();
+
+        let genesis_key = StoreEntry::BlockHeader(Some(0)).get_key();
+
+        if store.get_pinned_cf(cf_handle, &genesis_key)?.is_none() {
+            let mut batch = WriteBatch::default();
+            batch.put_cf(
+                cf_handle,
+                genesis_key,
+                (genesis.header, genesis.header.work()).serialize(),
+            );
+            batch.put_cf(
+                cf_handle,
+                StoreEntry::BlockHeaderIndex(Some(genesis.block_hash())).get_key(),
+                &0usize.to_be_bytes(),
+            );
+            store.write(batch)?;
+        }
+
+        Ok(ChainStore {
+            store: Arc::new(RwLock::new(store)),
+            cf_name,
+            min_height: 0,
+            network,
+            phantom: PhantomData,
+        })
+    }
+
+    pub fn get_locators(&self) -> Result<Vec<(BlockHash, usize)>, CompactFiltersError> {
+        let mut step = 1;
+        let mut index = self.get_height()?;
+        let mut answer = Vec::new();
+
+        let store_read = self.store.read().unwrap();
+        let cf_handle = store_read.cf_handle(&self.cf_name).unwrap();
+
+        loop {
+            if answer.len() > 10 {
+                step *= 2;
+            }
+
+            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(
+                &store_read
+                    .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(index)).get_key())?
+                    .unwrap(),
+            )?;
+            answer.push((header.block_hash(), index));
+
+            if let Some(new_index) = index.checked_sub(step) {
+                index = new_index;
+            } else {
+                break;
+            }
+        }
+
+        Ok(answer)
+    }
+
+    pub fn start_snapshot(&self, from: usize) -> Result<ChainStore<Snapshot>, CompactFiltersError> {
+        let new_cf_name: String = thread_rng().sample_iter(&Alphanumeric).take(16).collect();
+        let new_cf_name = format!("_headers:{}", new_cf_name);
+
+        let mut write_store = self.store.write().unwrap();
+
+        write_store.create_cf(&new_cf_name, &Default::default())?;
+
+        let cf_handle = write_store.cf_handle(&self.cf_name).unwrap();
+        let new_cf_handle = write_store.cf_handle(&new_cf_name).unwrap();
+
+        let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(
+            &write_store
+                .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
+                .ok_or(CompactFiltersError::DataCorruption)?,
+        )?;
+
+        let mut batch = WriteBatch::default();
+        batch.put_cf(
+            new_cf_handle,
+            StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
+            &from.to_be_bytes(),
+        );
+        batch.put_cf(
+            new_cf_handle,
+            StoreEntry::BlockHeader(Some(from)).get_key(),
+            (header, work).serialize(),
+        );
+        write_store.write(batch)?;
+
+        let store = Arc::clone(&self.store);
+        Ok(ChainStore {
+            store,
+            cf_name: new_cf_name,
+            min_height: from,
+            network: self.network,
+            phantom: PhantomData,
+        })
+    }
+
+    pub fn recover_snapshot(&self, cf_name: &str) -> Result<(), CompactFiltersError> {
+        let mut write_store = self.store.write().unwrap();
+        let snapshot_cf_handle = write_store.cf_handle(cf_name).unwrap();
+
+        let prefix = StoreEntry::BlockHeader(None).get_key();
+        let mut iterator = write_store.prefix_iterator_cf(snapshot_cf_handle, prefix);
+
+        let min_height = match iterator
+            .next()
+            .and_then(|(k, _)| k[1..].try_into().ok())
+            .map(|bytes| usize::from_be_bytes(bytes))
+        {
+            None => {
+                std::mem::drop(iterator);
+                write_store.drop_cf(cf_name).ok();
+
+                return Ok(());
+            }
+            Some(x) => x,
+        };
+        std::mem::drop(iterator);
+        std::mem::drop(write_store);
+
+        let snapshot = ChainStore {
+            store: Arc::clone(&self.store),
+            cf_name: cf_name.into(),
+            min_height,
+            network: self.network,
+            phantom: PhantomData,
+        };
+        if snapshot.work()? > self.work()? {
+            self.apply_snapshot(snapshot)?;
+        }
+
+        Ok(())
+    }
+
+    pub fn apply_snapshot(
+        &self,
+        snaphost: ChainStore<Snapshot>,
+    ) -> Result<(), CompactFiltersError> {
+        let mut batch = WriteBatch::default();
+
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+        let snapshot_cf_handle = read_store.cf_handle(&snaphost.cf_name).unwrap();
+
+        let from_key = StoreEntry::BlockHeader(Some(snaphost.min_height)).get_key();
+        let to_key = StoreEntry::BlockHeader(Some(usize::MAX)).get_key();
+
+        let mut opts = ReadOptions::default();
+        opts.set_iterate_upper_bound(to_key.clone());
+
+        log::debug!("Removing items");
+        batch.delete_range_cf(cf_handle, &from_key, &to_key);
+        for (_, v) in read_store.iterator_cf_opt(
+            cf_handle,
+            opts,
+            IteratorMode::From(&from_key, Direction::Forward),
+        ) {
+            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
+
+            batch.delete_cf(
+                cf_handle,
+                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
+            );
+        }
+
+        // Delete full blocks overriden by snapshot
+        let from_key = StoreEntry::Block(Some(snaphost.min_height)).get_key();
+        let to_key = StoreEntry::Block(Some(usize::MAX)).get_key();
+        batch.delete_range(&from_key, &to_key);
+
+        log::debug!("Copying over new items");
+        for (k, v) in read_store.iterator_cf(snapshot_cf_handle, IteratorMode::Start) {
+            batch.put_cf(cf_handle, k, v);
+        }
+
+        read_store.write(batch)?;
+
+        std::mem::drop(snapshot_cf_handle);
+        std::mem::drop(cf_handle);
+        std::mem::drop(read_store);
+
+        self.store.write().unwrap().drop_cf(&snaphost.cf_name)?;
+
+        Ok(())
+    }
+
+    pub fn get_height_for(
+        &self,
+        block_hash: &BlockHash,
+    ) -> Result<Option<usize>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let key = StoreEntry::BlockHeaderIndex(Some(block_hash.clone())).get_key();
+        let data = read_store.get_pinned_cf(cf_handle, key)?;
+        Ok(data
+            .map(|data| {
+                Ok::<_, CompactFiltersError>(usize::from_be_bytes(
+                    data.as_ref()
+                        .try_into()
+                        .map_err(|_| CompactFiltersError::DataCorruption)?,
+                ))
+            })
+            .transpose()?)
+    }
+
+    pub fn get_block_hash(&self, height: usize) -> Result<Option<BlockHash>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let key = StoreEntry::BlockHeader(Some(height)).get_key();
+        let data = read_store.get_pinned_cf(cf_handle, key)?;
+        Ok(data
+            .map(|data| {
+                let (header, _): (BlockHeader, Uint256) =
+                    deserialize(&data).map_err(|_| CompactFiltersError::DataCorruption)?;
+                Ok::<_, CompactFiltersError>(header.block_hash())
+            })
+            .transpose()?)
+    }
+
+    pub fn save_full_block(&self, block: &Block, height: usize) -> Result<(), CompactFiltersError> {
+        let key = StoreEntry::Block(Some(height)).get_key();
+        self.store.read().unwrap().put(key, block.serialize())?;
+
+        Ok(())
+    }
+
+    pub fn get_full_block(&self, height: usize) -> Result<Option<Block>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+
+        let key = StoreEntry::Block(Some(height)).get_key();
+        let opt_block = read_store.get_pinned(key)?;
+
+        Ok(opt_block
+            .map(|data| deserialize(&data))
+            .transpose()
+            .map_err(|_| CompactFiltersError::DataCorruption)?)
+    }
+
+    pub fn delete_blocks_until(&self, height: usize) -> Result<(), CompactFiltersError> {
+        let from_key = StoreEntry::Block(Some(0)).get_key();
+        let to_key = StoreEntry::Block(Some(height)).get_key();
+
+        let mut batch = WriteBatch::default();
+        batch.delete_range(&from_key, &to_key);
+
+        self.store.read().unwrap().write(batch)?;
+
+        Ok(())
+    }
+
+    pub fn iter_full_blocks(&self) -> Result<Vec<(usize, Block)>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+
+        let prefix = StoreEntry::Block(None).get_key();
+
+        let iterator = read_store.prefix_iterator(&prefix);
+        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
+        // have the right prefix
+        iterator
+            .filter(|(k, _)| k.starts_with(&prefix))
+            .map(|(k, v)| {
+                let height: usize = usize::from_be_bytes(
+                    k[1..]
+                        .try_into()
+                        .map_err(|_| CompactFiltersError::DataCorruption)?,
+                );
+                let block = SerializeDb::deserialize(&v)?;
+
+                Ok((height, block))
+            })
+            .collect::<Result<_, _>>()
+    }
+}
+
+impl<T: StoreType> ChainStore<T> {
+    pub fn work(&self) -> Result<Uint256, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let prefix = StoreEntry::BlockHeader(None).get_key();
+        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
+
+        Ok(iterator
+            .last()
+            .map(|(_, v)| -> Result<_, CompactFiltersError> {
+                let (_, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
+
+                Ok(work)
+            })
+            .transpose()?
+            .unwrap_or_default())
+    }
+
+    pub fn get_height(&self) -> Result<usize, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let prefix = StoreEntry::BlockHeader(None).get_key();
+        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
+
+        Ok(iterator
+            .last()
+            .map(|(k, _)| -> Result<_, CompactFiltersError> {
+                let height = usize::from_be_bytes(
+                    k[1..]
+                        .try_into()
+                        .map_err(|_| CompactFiltersError::DataCorruption)?,
+                );
+
+                Ok(height)
+            })
+            .transpose()?
+            .unwrap_or_default())
+    }
+
+    pub fn get_tip_hash(&self) -> Result<Option<BlockHash>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let prefix = StoreEntry::BlockHeader(None).get_key();
+        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
+
+        Ok(iterator
+            .last()
+            .map(|(_, v)| -> Result<_, CompactFiltersError> {
+                let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
+
+                Ok(header.block_hash())
+            })
+            .transpose()?)
+    }
+
+    pub fn apply(
+        &mut self,
+        from: usize,
+        headers: Vec<BlockHeader>,
+    ) -> Result<BlockHash, CompactFiltersError> {
+        let mut batch = WriteBatch::default();
+
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let (mut last_hash, mut accumulated_work) = read_store
+            .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
+            .map(|result| {
+                let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&result)?;
+                Ok::<_, CompactFiltersError>((header.block_hash(), work))
+            })
+            .transpose()?
+            .ok_or(CompactFiltersError::DataCorruption)?;
+
+        for (index, header) in headers.into_iter().enumerate() {
+            if header.prev_blockhash != last_hash {
+                return Err(CompactFiltersError::InvalidHeaders);
+            }
+
+            last_hash = header.block_hash();
+            accumulated_work = accumulated_work + header.work();
+
+            let height = from + index + 1;
+            batch.put_cf(
+                cf_handle,
+                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
+                &(height).to_be_bytes(),
+            );
+            batch.put_cf(
+                cf_handle,
+                StoreEntry::BlockHeader(Some(height)).get_key(),
+                (header, accumulated_work).serialize(),
+            );
+        }
+
+        std::mem::drop(cf_handle);
+        std::mem::drop(read_store);
+
+        self.store.write().unwrap().write(batch)?;
+        Ok(last_hash)
+    }
+}
+
+impl<T: StoreType> fmt::Debug for ChainStore<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct(&format!("ChainStore<{:?}>", T::default()))
+            .field("cf_name", &self.cf_name)
+            .field("min_height", &self.min_height)
+            .field("network", &self.network)
+            .field("headers_height", &self.get_height())
+            .field("tip_hash", &self.get_tip_hash())
+            .finish()
+    }
+}
+
+pub type FilterHeaderHash = FilterHash;
+
+#[derive(Debug, Clone)]
+pub struct FilterHeader {
+    prev_header_hash: FilterHeaderHash,
+    filter_hash: FilterHash,
+}
+
+impl FilterHeader {
+    fn header_hash(&self) -> FilterHeaderHash {
+        let mut hash_data = self.filter_hash.into_inner().to_vec();
+        hash_data.extend_from_slice(&self.prev_header_hash);
+        sha256d::Hash::hash(&hash_data).into()
+    }
+}
+
+pub enum BundleStatus {
+    Init,
+    CFHeaders { cf_headers: Vec<FilterHeader> },
+    CFilters { cf_filters: Vec<Vec<u8>> },
+    Processed { cf_filters: Vec<Vec<u8>> },
+    Tip { cf_filters: Vec<Vec<u8>> },
+    Pruned,
+}
+
+pub struct CFStore {
+    store: Arc<RwLock<DB>>,
+    filter_type: u8,
+}
+
+type BundleEntry = (BundleStatus, FilterHeaderHash);
+
+impl CFStore {
+    pub fn new(
+        headers_store: &ChainStore<Full>,
+        filter_type: u8,
+    ) -> Result<Self, CompactFiltersError> {
+        let cf_store = CFStore {
+            store: Arc::clone(&headers_store.store),
+            filter_type,
+        };
+
+        let genesis = match headers_store.network {
+            Network::Bitcoin => MAINNET_GENESIS.deref(),
+            Network::Testnet => TESTNET_GENESIS.deref(),
+            Network::Regtest => REGTEST_GENESIS.deref(),
+        };
+
+        let filter = BlockFilter::new_script_filter(genesis, |utxo| {
+            Err(bitcoin::util::bip158::Error::UtxoMissing(*utxo))
+        })?;
+        let first_key = StoreEntry::CFilterTable((filter_type, Some(0))).get_key();
+
+        // Add the genesis' filter
+        {
+            let read_store = cf_store.store.read().unwrap();
+            if read_store.get_pinned(&first_key)?.is_none() {
+                read_store.put(
+                    &first_key,
+                    (BundleStatus::Init, filter.filter_id(&FilterHash::default())).serialize(),
+                )?;
+            }
+        }
+
+        Ok(cf_store)
+    }
+
+    pub fn get_filter_type(&self) -> u8 {
+        self.filter_type
+    }
+
+    pub fn get_bundles(&self) -> Result<Vec<BundleEntry>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+
+        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
+        let iterator = read_store.prefix_iterator(&prefix);
+
+        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
+        // have the right prefix
+        iterator
+            .filter(|(k, _)| k.starts_with(&prefix))
+            .map(|(_, data)| BundleEntry::deserialize(&data))
+            .collect::<Result<_, _>>()
+    }
+
+    pub fn get_checkpoints(&self) -> Result<Vec<FilterHash>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+
+        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
+        let iterator = read_store.prefix_iterator(&prefix);
+
+        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
+        // have the right prefix
+        Ok(iterator
+            .filter(|(k, _)| k.starts_with(&prefix))
+            .skip(1)
+            .map(|(_, data)| Ok::<_, CompactFiltersError>(BundleEntry::deserialize(&data)?.1))
+            .collect::<Result<_, _>>()?)
+    }
+
+    pub fn replace_checkpoints(
+        &self,
+        checkpoints: Vec<FilterHash>,
+    ) -> Result<(), CompactFiltersError> {
+        let current_checkpoints = self.get_checkpoints()?;
+
+        let mut equal_bundles = 0;
+        for (index, (our, their)) in current_checkpoints
+            .iter()
+            .zip(checkpoints.iter())
+            .enumerate()
+        {
+            equal_bundles = index;
+
+            if our != their {
+                break;
+            }
+        }
+
+        let read_store = self.store.read().unwrap();
+        let mut batch = WriteBatch::default();
+
+        for (index, filter_hash) in checkpoints.iter().enumerate().skip(equal_bundles) {
+            let key = StoreEntry::CFilterTable((self.filter_type, Some(index + 1))).get_key(); // +1 to skip the genesis' filter
+
+            if let Some((BundleStatus::Tip { .. }, _)) = read_store
+                .get_pinned(&key)?
+                .map(|data| BundleEntry::deserialize(&data))
+                .transpose()?
+            {
+                println!("Keeping bundle #{} as Tip", index);
+            } else {
+                batch.put(&key, (BundleStatus::Init, *filter_hash).serialize());
+            }
+        }
+
+        read_store.write(batch)?;
+
+        Ok(())
+    }
+
+    pub fn advance_to_cf_headers(
+        &self,
+        bundle: usize,
+        checkpoint_hash: FilterHeaderHash,
+        filter_headers: Vec<FilterHash>,
+    ) -> Result<BundleStatus, CompactFiltersError> {
+        let mut last_hash = checkpoint_hash;
+        let cf_headers = filter_headers
+            .into_iter()
+            .map(|filter_hash| {
+                let filter_header = FilterHeader {
+                    prev_header_hash: last_hash,
+                    filter_hash,
+                };
+                last_hash = filter_header.header_hash();
+
+                filter_header
+            })
+            .collect();
+
+        let read_store = self.store.read().unwrap();
+
+        let next_key = StoreEntry::CFilterTable((self.filter_type, Some(bundle + 1))).get_key(); // +1 to skip the genesis' filter
+        if let Some((_, next_checkpoint)) = read_store
+            .get_pinned(&next_key)?
+            .map(|data| BundleEntry::deserialize(&data))
+            .transpose()?
+        {
+            // check connection with the next bundle if present
+            if last_hash != next_checkpoint {
+                return Err(CompactFiltersError::InvalidFilterHeader);
+            }
+        }
+
+        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
+        let value = (BundleStatus::CFHeaders { cf_headers }, checkpoint_hash);
+
+        read_store.put(key, value.serialize())?;
+
+        Ok(value.0)
+    }
+
+    pub fn advance_to_cf_filters(
+        &self,
+        bundle: usize,
+        checkpoint_hash: FilterHeaderHash,
+        headers: Vec<FilterHeader>,
+        filters: Vec<(usize, Vec<u8>)>,
+    ) -> Result<BundleStatus, CompactFiltersError> {
+        let cf_filters = filters
+            .into_iter()
+            .zip(headers.iter())
+            .map(|((_, filter_content), header)| {
+                if header.filter_hash != sha256d::Hash::hash(&filter_content).into() {
+                    return Err(CompactFiltersError::InvalidFilter);
+                }
+
+                Ok::<_, CompactFiltersError>(filter_content)
+            })
+            .collect::<Result<_, _>>()?;
+
+        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
+        let value = (BundleStatus::CFilters { cf_filters }, checkpoint_hash);
+
+        let read_store = self.store.read().unwrap();
+        read_store.put(key, value.serialize())?;
+
+        Ok(value.0)
+    }
+
+    pub fn prune_filters(
+        &self,
+        bundle: usize,
+        checkpoint_hash: FilterHeaderHash,
+    ) -> Result<BundleStatus, CompactFiltersError> {
+        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
+        let value = (BundleStatus::Pruned, checkpoint_hash);
+
+        let read_store = self.store.read().unwrap();
+        read_store.put(key, value.serialize())?;
+
+        Ok(value.0)
+    }
+
+    pub fn mark_as_tip(
+        &self,
+        bundle: usize,
+        cf_filters: Vec<Vec<u8>>,
+        checkpoint_hash: FilterHeaderHash,
+    ) -> Result<BundleStatus, CompactFiltersError> {
+        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
+        let value = (BundleStatus::Tip { cf_filters }, checkpoint_hash);
+
+        let read_store = self.store.read().unwrap();
+        read_store.put(key, value.serialize())?;
+
+        Ok(value.0)
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/sync.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/sync.rs.html new file mode 100644 index 0000000000..29d89bdd81 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/sync.rs.html @@ -0,0 +1,629 @@ +sync.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::collections::{BTreeMap, HashMap, VecDeque};
+use std::sync::{Arc, Mutex};
+use std::time::Duration;
+
+use bitcoin::hash_types::{BlockHash, FilterHash};
+use bitcoin::network::message::NetworkMessage;
+use bitcoin::network::message_blockdata::GetHeadersMessage;
+use bitcoin::util::bip158::BlockFilter;
+
+use super::peer::*;
+use super::store::*;
+use super::CompactFiltersError;
+use crate::error::Error;
+
+pub(crate) const BURIED_CONFIRMATIONS: usize = 100;
+
+pub struct CFSync {
+    headers_store: Arc<ChainStore<Full>>,
+    cf_store: Arc<CFStore>,
+    skip_blocks: usize,
+    bundles: Mutex<VecDeque<(BundleStatus, FilterHash, usize)>>,
+}
+
+impl CFSync {
+    pub fn new(
+        headers_store: Arc<ChainStore<Full>>,
+        skip_blocks: usize,
+        filter_type: u8,
+    ) -> Result<Self, CompactFiltersError> {
+        let cf_store = Arc::new(CFStore::new(&headers_store, filter_type)?);
+
+        Ok(CFSync {
+            headers_store,
+            cf_store,
+            skip_blocks,
+            bundles: Mutex::new(VecDeque::new()),
+        })
+    }
+
+    pub fn pruned_bundles(&self) -> Result<usize, CompactFiltersError> {
+        Ok(self
+            .cf_store
+            .get_bundles()?
+            .into_iter()
+            .skip(self.skip_blocks / 1000)
+            .fold(0, |acc, (status, _)| match status {
+                BundleStatus::Pruned => acc + 1,
+                _ => acc,
+            }))
+    }
+
+    pub fn prepare_sync(&self, peer: Arc<Peer>) -> Result<(), CompactFiltersError> {
+        let mut bundles_lock = self.bundles.lock().unwrap();
+
+        let resp = peer.get_cf_checkpt(
+            self.cf_store.get_filter_type(),
+            self.headers_store.get_tip_hash()?.unwrap(),
+        )?;
+        self.cf_store.replace_checkpoints(resp.filter_headers)?;
+
+        bundles_lock.clear();
+        for (index, (status, checkpoint)) in self.cf_store.get_bundles()?.into_iter().enumerate() {
+            bundles_lock.push_back((status, checkpoint, index));
+        }
+
+        Ok(())
+    }
+
+    pub fn capture_thread_for_sync<F, Q>(
+        &self,
+        peer: Arc<Peer>,
+        process: F,
+        completed_bundle: Q,
+    ) -> Result<(), CompactFiltersError>
+    where
+        F: Fn(&BlockHash, &BlockFilter) -> Result<bool, CompactFiltersError>,
+        Q: Fn(usize) -> Result<(), Error>,
+    {
+        let current_height = self.headers_store.get_height()?; // TODO: we should update it in case headers_store is also updated
+
+        loop {
+            let (mut status, checkpoint, index) = match self.bundles.lock().unwrap().pop_front() {
+                None => break,
+                Some(x) => x,
+            };
+
+            log::debug!(
+                "Processing bundle #{} - height {} to {}",
+                index,
+                index * 1000 + 1,
+                (index + 1) * 1000
+            );
+
+            let process_received_filters =
+                |expected_filters| -> Result<BTreeMap<usize, Vec<u8>>, CompactFiltersError> {
+                    let mut filters_map = BTreeMap::new();
+                    for _ in 0..expected_filters {
+                        let filter = peer.pop_cf_filter_resp()?;
+                        if filter.filter_type != self.cf_store.get_filter_type() {
+                            return Err(CompactFiltersError::InvalidResponse);
+                        }
+
+                        match self.headers_store.get_height_for(&filter.block_hash)? {
+                            Some(height) => filters_map.insert(height, filter.filter),
+                            None => return Err(CompactFiltersError::InvalidFilter),
+                        };
+                    }
+
+                    Ok(filters_map)
+                };
+
+            let start_height = index * 1000 + 1;
+            let mut already_processed = 0;
+
+            if start_height < self.skip_blocks {
+                status = self.cf_store.prune_filters(index, checkpoint)?;
+            }
+
+            let stop_height = std::cmp::min(current_height, start_height + 999);
+            let stop_hash = self.headers_store.get_block_hash(stop_height)?.unwrap();
+
+            if let BundleStatus::Init = status {
+                log::trace!("status: Init");
+
+                let resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
+
+                assert!(resp.previous_filter == checkpoint);
+                status =
+                    self.cf_store
+                        .advance_to_cf_headers(index, checkpoint, resp.filter_hashes)?;
+            }
+            if let BundleStatus::Tip { cf_filters } = status {
+                log::trace!("status: Tip (beginning) ");
+
+                already_processed = cf_filters.len();
+                let headers_resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
+
+                let cf_headers = match self.cf_store.advance_to_cf_headers(
+                    index,
+                    checkpoint,
+                    headers_resp.filter_hashes,
+                )? {
+                    BundleStatus::CFHeaders { cf_headers } => cf_headers,
+                    _ => return Err(CompactFiltersError::InvalidResponse),
+                };
+
+                peer.get_cf_filters(
+                    self.cf_store.get_filter_type(),
+                    (start_height + cf_filters.len()) as u32,
+                    stop_hash,
+                )?;
+                let expected_filters = stop_height - start_height + 1 - cf_filters.len();
+                let filters_map = process_received_filters(expected_filters)?;
+                let filters = cf_filters
+                    .into_iter()
+                    .enumerate()
+                    .chain(filters_map.into_iter())
+                    .collect();
+                status = self
+                    .cf_store
+                    .advance_to_cf_filters(index, checkpoint, cf_headers, filters)?;
+            }
+            if let BundleStatus::CFHeaders { cf_headers } = status {
+                log::trace!("status: CFHeaders");
+
+                peer.get_cf_filters(
+                    self.cf_store.get_filter_type(),
+                    start_height as u32,
+                    stop_hash,
+                )?;
+                let expected_filters = stop_height - start_height + 1;
+                let filters_map = process_received_filters(expected_filters)?;
+                status = self.cf_store.advance_to_cf_filters(
+                    index,
+                    checkpoint,
+                    cf_headers,
+                    filters_map.into_iter().collect(),
+                )?;
+            }
+            if let BundleStatus::CFilters { cf_filters } = status {
+                log::trace!("status: CFilters");
+
+                let last_sync_buried_height = (start_height + already_processed)
+                    .checked_sub(BURIED_CONFIRMATIONS)
+                    .unwrap_or(0);
+
+                for (filter_index, filter) in cf_filters.iter().enumerate() {
+                    let height = filter_index + start_height;
+
+                    // do not download blocks that were already "buried" since the last sync
+                    if height < last_sync_buried_height {
+                        continue;
+                    }
+
+                    let block_hash = self.headers_store.get_block_hash(height)?.unwrap();
+
+                    // TODO: also download random blocks?
+                    if process(&block_hash, &BlockFilter::new(&filter))? {
+                        log::debug!("Downloading block {}", block_hash);
+
+                        let block = peer
+                            .get_block(block_hash)?
+                            .ok_or(CompactFiltersError::MissingBlock)?;
+                        self.headers_store.save_full_block(&block, height)?;
+                    }
+                }
+
+                status = BundleStatus::Processed { cf_filters };
+            }
+            if let BundleStatus::Processed { cf_filters } = status {
+                log::trace!("status: Processed");
+
+                if current_height - stop_height > 1000 {
+                    status = self.cf_store.prune_filters(index, checkpoint)?;
+                } else {
+                    status = self.cf_store.mark_as_tip(index, cf_filters, checkpoint)?;
+                }
+
+                completed_bundle(index)?;
+            }
+            if let BundleStatus::Pruned = status {
+                log::trace!("status: Pruned");
+            }
+            if let BundleStatus::Tip { .. } = status {
+                log::trace!("status: Tip");
+            }
+        }
+
+        Ok(())
+    }
+}
+
+pub fn sync_headers<F>(
+    peer: Arc<Peer>,
+    store: Arc<ChainStore<Full>>,
+    sync_fn: F,
+) -> Result<Option<ChainStore<Snapshot>>, CompactFiltersError>
+where
+    F: Fn(usize) -> Result<(), Error>,
+{
+    let locators = store.get_locators()?;
+    let locators_vec = locators.iter().map(|(hash, _)| hash).cloned().collect();
+    let locators_map: HashMap<_, _> = locators.into_iter().collect();
+
+    peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
+        locators_vec,
+        Default::default(),
+    )))?;
+    let (mut snapshot, mut last_hash) = if let NetworkMessage::Headers(headers) = peer
+        .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
+        .ok_or(CompactFiltersError::Timeout)?
+    {
+        if headers.is_empty() {
+            return Ok(None);
+        }
+
+        match locators_map.get(&headers[0].prev_blockhash) {
+            None => return Err(CompactFiltersError::InvalidHeaders),
+            Some(from) => (
+                store.start_snapshot(*from)?,
+                headers[0].prev_blockhash.clone(),
+            ),
+        }
+    } else {
+        return Err(CompactFiltersError::InvalidResponse);
+    };
+
+    let mut sync_height = store.get_height()?;
+    while sync_height < peer.get_version().start_height as usize {
+        peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
+            vec![last_hash],
+            Default::default(),
+        )))?;
+        if let NetworkMessage::Headers(headers) = peer
+            .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
+            .ok_or(CompactFiltersError::Timeout)?
+        {
+            let batch_len = headers.len();
+            last_hash = snapshot.apply(sync_height, headers)?;
+
+            sync_height += batch_len;
+            sync_fn(sync_height)?;
+        } else {
+            return Err(CompactFiltersError::InvalidResponse);
+        }
+    }
+
+    Ok(Some(snapshot))
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/electrum.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/electrum.rs.html new file mode 100644 index 0000000000..c12b391f32 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/electrum.rs.html @@ -0,0 +1,353 @@ +electrum.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Electrum
+//!
+//! This module defines a [`Blockchain`] struct that wraps an [`electrum_client::Client`]
+//! and implements the logic required to populate the wallet's [database](crate::database::Database) by
+//! querying the inner client.
+//!
+//! ## Example
+//!
+//! ```no_run
+//! # use bdk::blockchain::electrum::ElectrumBlockchain;
+//! let client = electrum_client::Client::new("ssl://electrum.blockstream.info:50002", None)?;
+//! let blockchain = ElectrumBlockchain::from(client);
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use std::collections::HashSet;
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use bitcoin::{Script, Transaction, Txid};
+
+use electrum_client::{Client, ElectrumApi};
+
+use self::utils::{ELSGetHistoryRes, ELSListUnspentRes, ElectrumLikeSync};
+use super::*;
+use crate::database::BatchDatabase;
+use crate::error::Error;
+use crate::FeeRate;
+
+/// Wrapper over an Electrum Client that implements the required blockchain traits
+///
+/// ## Example
+/// See the [`blockchain::electrum`](crate::blockchain::electrum) module for a usage example.
+pub struct ElectrumBlockchain(Client);
+
+#[cfg(test)]
+#[cfg(feature = "test-electrum")]
+#[bdk_blockchain_tests(crate)]
+fn local_electrs() -> ElectrumBlockchain {
+    ElectrumBlockchain::from(Client::new(&testutils::get_electrum_url(), None).unwrap())
+}
+
+impl std::convert::From<Client> for ElectrumBlockchain {
+    fn from(client: Client) -> Self {
+        ElectrumBlockchain(client)
+    }
+}
+
+impl Blockchain for ElectrumBlockchain {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        vec![
+            Capability::FullHistory,
+            Capability::GetAnyTx,
+            Capability::AccurateFees,
+        ]
+        .into_iter()
+        .collect()
+    }
+
+    fn setup<D: BatchDatabase, P: Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        self.0
+            .electrum_like_setup(stop_gap, database, progress_update)
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        Ok(self.0.transaction_get(txid).map(Option::Some)?)
+    }
+
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        Ok(self.0.transaction_broadcast(tx).map(|_| ())?)
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        // TODO: unsubscribe when added to the client, or is there a better call to use here?
+
+        Ok(self
+            .0
+            .block_headers_subscribe()
+            .map(|data| data.height as u32)?)
+    }
+
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
+        Ok(FeeRate::from_btc_per_kvb(
+            self.0.estimate_fee(target)? as f32
+        ))
+    }
+}
+
+impl ElectrumLikeSync for Client {
+    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error> {
+        self.batch_script_get_history(scripts)
+            .map(|v| {
+                v.into_iter()
+                    .map(|v| {
+                        v.into_iter()
+                            .map(
+                                |electrum_client::GetHistoryRes {
+                                     height, tx_hash, ..
+                                 }| ELSGetHistoryRes {
+                                    height,
+                                    tx_hash,
+                                },
+                            )
+                            .collect()
+                    })
+                    .collect()
+            })
+            .map_err(Error::Electrum)
+    }
+
+    fn els_batch_script_list_unspent<'s, I: IntoIterator<Item = &'s Script>>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ELSListUnspentRes>>, Error> {
+        self.batch_script_list_unspent(scripts)
+            .map(|v| {
+                v.into_iter()
+                    .map(|v| {
+                        v.into_iter()
+                            .map(
+                                |electrum_client::ListUnspentRes {
+                                     height,
+                                     tx_hash,
+                                     tx_pos,
+                                     ..
+                                 }| ELSListUnspentRes {
+                                    height,
+                                    tx_hash,
+                                    tx_pos,
+                                },
+                            )
+                            .collect()
+                    })
+                    .collect()
+            })
+            .map_err(Error::Electrum)
+    }
+
+    fn els_transaction_get(&self, txid: &Txid) -> Result<Transaction, Error> {
+        self.transaction_get(txid).map_err(Error::Electrum)
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/esplora.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/esplora.rs.html new file mode 100644 index 0000000000..635d250df6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/esplora.rs.html @@ -0,0 +1,765 @@ +esplora.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Esplora
+//!
+//! This module defines a [`Blockchain`] struct that can query an Esplora backend
+//! populate the wallet's [database](crate::database::Database) by
+//!
+//! ## Example
+//!
+//! ```no_run
+//! # use bdk::blockchain::esplora::EsploraBlockchain;
+//! let blockchain = EsploraBlockchain::new("https://blockstream.info/testnet/api");
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use std::collections::{HashMap, HashSet};
+use std::fmt;
+
+use futures::stream::{self, StreamExt, TryStreamExt};
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use serde::Deserialize;
+
+use reqwest::{Client, StatusCode};
+
+use bitcoin::consensus::{deserialize, serialize};
+use bitcoin::hashes::hex::ToHex;
+use bitcoin::hashes::{sha256, Hash};
+use bitcoin::{Script, Transaction, Txid};
+
+use self::utils::{ELSGetHistoryRes, ELSListUnspentRes, ElectrumLikeSync};
+use super::*;
+use crate::database::BatchDatabase;
+use crate::error::Error;
+use crate::FeeRate;
+
+#[derive(Debug)]
+struct UrlClient {
+    url: String,
+    // We use the async client instead of the blocking one because it automatically uses `fetch`
+    // when the target platform is wasm32.
+    client: Client,
+}
+
+/// Structure that implements the logic to sync with Esplora
+///
+/// ## Example
+/// See the [`blockchain::esplora`](crate::blockchain::esplora) module for a usage example.
+#[derive(Debug)]
+pub struct EsploraBlockchain(UrlClient);
+
+impl std::convert::From<UrlClient> for EsploraBlockchain {
+    fn from(url_client: UrlClient) -> Self {
+        EsploraBlockchain(url_client)
+    }
+}
+
+impl EsploraBlockchain {
+    /// Create a new instance of the client from a base URL
+    pub fn new(base_url: &str) -> Self {
+        EsploraBlockchain(UrlClient {
+            url: base_url.to_string(),
+            client: Client::new(),
+        })
+    }
+}
+
+#[maybe_async]
+impl Blockchain for EsploraBlockchain {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        vec![
+            Capability::FullHistory,
+            Capability::GetAnyTx,
+            Capability::AccurateFees,
+        ]
+        .into_iter()
+        .collect()
+    }
+
+    fn setup<D: BatchDatabase, P: Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(self
+            .0
+            .electrum_like_setup(stop_gap, database, progress_update))
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        Ok(await_or_block!(self.0._get_tx(txid))?)
+    }
+
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        Ok(await_or_block!(self.0._broadcast(tx))?)
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        Ok(await_or_block!(self.0._get_height())?)
+    }
+
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
+        let estimates = await_or_block!(self.0._get_fee_estimates())?;
+
+        let fee_val = estimates
+            .into_iter()
+            .map(|(k, v)| Ok::<_, std::num::ParseIntError>((k.parse::<usize>()?, v)))
+            .collect::<Result<Vec<_>, _>>()
+            .map_err(|e| Error::Generic(e.to_string()))?
+            .into_iter()
+            .take_while(|(k, _)| k <= &target)
+            .map(|(_, v)| v)
+            .last()
+            .unwrap_or(1.0);
+
+        Ok(FeeRate::from_sat_per_vb(fee_val as f32))
+    }
+}
+
+impl UrlClient {
+    fn script_to_scripthash(script: &Script) -> String {
+        sha256::Hash::hash(script.as_bytes()).into_inner().to_hex()
+    }
+
+    async fn _get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, EsploraError> {
+        let resp = self
+            .client
+            .get(&format!("{}/tx/{}/raw", self.url, txid))
+            .send()
+            .await?;
+
+        if let StatusCode::NOT_FOUND = resp.status() {
+            return Ok(None);
+        }
+
+        Ok(Some(deserialize(&resp.error_for_status()?.bytes().await?)?))
+    }
+
+    async fn _broadcast(&self, transaction: &Transaction) -> Result<(), EsploraError> {
+        self.client
+            .post(&format!("{}/tx", self.url))
+            .body(serialize(transaction).to_hex())
+            .send()
+            .await?
+            .error_for_status()?;
+
+        Ok(())
+    }
+
+    async fn _get_height(&self) -> Result<u32, EsploraError> {
+        let req = self
+            .client
+            .get(&format!("{}/blocks/tip/height", self.url))
+            .send()
+            .await?;
+
+        Ok(req.error_for_status()?.text().await?.parse()?)
+    }
+
+    async fn _script_get_history(
+        &self,
+        script: &Script,
+    ) -> Result<Vec<ELSGetHistoryRes>, EsploraError> {
+        let mut result = Vec::new();
+        let scripthash = Self::script_to_scripthash(script);
+
+        // Add the unconfirmed transactions first
+        result.extend(
+            self.client
+                .get(&format!(
+                    "{}/scripthash/{}/txs/mempool",
+                    self.url, scripthash
+                ))
+                .send()
+                .await?
+                .error_for_status()?
+                .json::<Vec<EsploraGetHistory>>()
+                .await?
+                .into_iter()
+                .map(|x| ELSGetHistoryRes {
+                    tx_hash: x.txid,
+                    height: x.status.block_height.unwrap_or(0) as i32,
+                }),
+        );
+
+        debug!(
+            "Found {} mempool txs for {} - {:?}",
+            result.len(),
+            scripthash,
+            script
+        );
+
+        // Then go through all the pages of confirmed transactions
+        let mut last_txid = String::new();
+        loop {
+            let response = self
+                .client
+                .get(&format!(
+                    "{}/scripthash/{}/txs/chain/{}",
+                    self.url, scripthash, last_txid
+                ))
+                .send()
+                .await?
+                .error_for_status()?
+                .json::<Vec<EsploraGetHistory>>()
+                .await?;
+            let len = response.len();
+            if let Some(elem) = response.last() {
+                last_txid = elem.txid.to_hex();
+            }
+
+            debug!("... adding {} confirmed transactions", len);
+
+            result.extend(response.into_iter().map(|x| ELSGetHistoryRes {
+                tx_hash: x.txid,
+                height: x.status.block_height.unwrap_or(0) as i32,
+            }));
+
+            if len < 25 {
+                break;
+            }
+        }
+
+        Ok(result)
+    }
+
+    async fn _script_list_unspent(
+        &self,
+        script: &Script,
+    ) -> Result<Vec<ELSListUnspentRes>, EsploraError> {
+        Ok(self
+            .client
+            .get(&format!(
+                "{}/scripthash/{}/utxo",
+                self.url,
+                Self::script_to_scripthash(script)
+            ))
+            .send()
+            .await?
+            .error_for_status()?
+            .json::<Vec<EsploraListUnspent>>()
+            .await?
+            .into_iter()
+            .map(|x| ELSListUnspentRes {
+                tx_hash: x.txid,
+                height: x.status.block_height.unwrap_or(0),
+                tx_pos: x.vout,
+            })
+            .collect())
+    }
+
+    async fn _get_fee_estimates(&self) -> Result<HashMap<String, f64>, EsploraError> {
+        Ok(self
+            .client
+            .get(&format!("{}/fee-estimates", self.url,))
+            .send()
+            .await?
+            .error_for_status()?
+            .json::<HashMap<String, f64>>()
+            .await?)
+    }
+}
+
+#[maybe_async]
+impl ElectrumLikeSync for UrlClient {
+    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error> {
+        let future = async {
+            Ok(stream::iter(scripts)
+                .then(|script| self._script_get_history(&script))
+                .try_collect()
+                .await?)
+        };
+
+        await_or_block!(future)
+    }
+
+    fn els_batch_script_list_unspent<'s, I: IntoIterator<Item = &'s Script>>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ELSListUnspentRes>>, Error> {
+        let future = async {
+            Ok(stream::iter(scripts)
+                .then(|script| self._script_list_unspent(&script))
+                .try_collect()
+                .await?)
+        };
+
+        await_or_block!(future)
+    }
+
+    fn els_transaction_get(&self, txid: &Txid) -> Result<Transaction, Error> {
+        Ok(await_or_block!(self._get_tx(txid))?
+            .ok_or_else(|| EsploraError::TransactionNotFound(*txid))?)
+    }
+}
+
+#[derive(Deserialize)]
+struct EsploraGetHistoryStatus {
+    block_height: Option<usize>,
+}
+
+#[derive(Deserialize)]
+struct EsploraGetHistory {
+    txid: Txid,
+    status: EsploraGetHistoryStatus,
+}
+
+#[derive(Deserialize)]
+struct EsploraListUnspent {
+    txid: Txid,
+    vout: usize,
+    status: EsploraGetHistoryStatus,
+}
+
+/// Errors that can happen during a sync with [`EsploraBlockchain`]
+#[derive(Debug)]
+pub enum EsploraError {
+    /// Error with the HTTP call
+    Reqwest(reqwest::Error),
+    /// Invalid number returned
+    Parsing(std::num::ParseIntError),
+    /// Invalid Bitcoin data returned
+    BitcoinEncoding(bitcoin::consensus::encode::Error),
+
+    /// Transaction not found
+    TransactionNotFound(Txid),
+}
+
+impl fmt::Display for EsploraError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for EsploraError {}
+
+impl From<reqwest::Error> for EsploraError {
+    fn from(other: reqwest::Error) -> Self {
+        EsploraError::Reqwest(other)
+    }
+}
+
+impl From<std::num::ParseIntError> for EsploraError {
+    fn from(other: std::num::ParseIntError) -> Self {
+        EsploraError::Parsing(other)
+    }
+}
+
+impl From<bitcoin::consensus::encode::Error> for EsploraError {
+    fn from(other: bitcoin::consensus::encode::Error) -> Self {
+        EsploraError::BitcoinEncoding(other)
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/mod.rs.html new file mode 100644 index 0000000000..a059a898bb --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/mod.rs.html @@ -0,0 +1,509 @@ +mod.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Blockchain backends
+//!
+//! This module provides the implementation of a few commonly-used backends like
+//! [Electrum](crate::blockchain::electrum), [Esplora](crate::blockchain::esplora) and
+//! [Compact Filters/Neutrino](crate::blockchain::compact_filters), along with a generalized trait
+//! [`Blockchain`] that can be implemented to build customized backends.
+
+use std::collections::HashSet;
+use std::ops::Deref;
+use std::sync::mpsc::{channel, Receiver, Sender};
+use std::sync::Arc;
+
+use bitcoin::{Transaction, Txid};
+
+use crate::database::BatchDatabase;
+use crate::error::Error;
+use crate::FeeRate;
+
+pub(crate) mod utils;
+
+#[cfg(feature = "electrum")]
+#[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
+pub mod electrum;
+#[cfg(feature = "electrum")]
+pub use self::electrum::ElectrumBlockchain;
+
+#[cfg(feature = "esplora")]
+#[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
+pub mod esplora;
+#[cfg(feature = "esplora")]
+pub use self::esplora::EsploraBlockchain;
+
+#[cfg(feature = "compact_filters")]
+#[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
+pub mod compact_filters;
+#[cfg(feature = "compact_filters")]
+pub use self::compact_filters::CompactFiltersBlockchain;
+
+/// Capabilities that can be supported by a [`Blockchain`] backend
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum Capability {
+    /// Can recover the full history of a wallet and not only the set of currently spendable UTXOs
+    FullHistory,
+    /// Can fetch any historical transaction given its txid
+    GetAnyTx,
+    /// Can compute accurate fees for the transactions found during sync
+    AccurateFees,
+}
+
+/// Marker trait for a blockchain backend
+///
+/// This is a marker trait for blockchain types. It is automatically implemented for types that
+/// implement [`Blockchain`], so as a user of the library you won't have to implement this
+/// manually.
+///
+/// Users of the library will probably never have to implement this trait manually, but they
+/// could still need to import it to define types and structs with generics;
+/// Implementing only the marker trait is pointless, since [`OfflineBlockchain`]
+/// already does that, and whenever [`Blockchain`] is implemented, the marker trait is also
+/// automatically implemented by the library.
+pub trait BlockchainMarker {}
+
+/// The [`BlockchainMarker`] marker trait is automatically implemented for [`Blockchain`] types
+impl<T: Blockchain> BlockchainMarker for T {}
+
+/// Type that only implements [`Blockchain`] and is always "offline"
+pub struct OfflineBlockchain;
+impl BlockchainMarker for OfflineBlockchain {}
+
+/// Trait that defines the actions that must be supported by a blockchain backend
+#[maybe_async]
+pub trait Blockchain: BlockchainMarker {
+    /// Return the set of [`Capability`] supported by this backend
+    fn get_capabilities(&self) -> HashSet<Capability>;
+
+    /// Setup the backend and populate the internal database for the first time
+    ///
+    /// This method is the equivalent of [`Blockchain::sync`], but it's guaranteed to only be
+    /// called once, at the first [`Wallet::sync`](crate::wallet::Wallet::sync).
+    ///
+    /// The rationale behind the distinction between `sync` and `setup` is that some custom backends
+    /// might need to perform specific actions only the first time they are synced.
+    ///
+    /// For types that do not have that distinction, only this method can be implemented, since
+    /// [`Blockchain::sync`] defaults to calling this internally if not overridden.
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error>;
+    /// Populate the internal database with transactions and UTXOs
+    ///
+    /// If not overridden, it defaults to calling [`Blockchain::setup`] internally.
+    ///
+    /// This method should implement the logic required to iterate over the list of the wallet's
+    /// script_pubkeys using [`Database::iter_script_pubkeys`] and look for relevant transactions
+    /// in the blockchain to populate the database with [`BatchOperations::set_tx`] and
+    /// [`BatchOperations::set_utxo`].
+    ///
+    /// This method should also take care of removing UTXOs that are seen as spent in the
+    /// blockchain, using [`BatchOperations::del_utxo`].
+    ///
+    /// The `progress_update` object can be used to give the caller updates about the progress by using
+    /// [`Progress::update`].
+    ///
+    /// [`Database::iter_script_pubkeys`]: crate::database::Database::iter_script_pubkeys
+    /// [`BatchOperations::set_tx`]: crate::database::BatchOperations::set_tx
+    /// [`BatchOperations::set_utxo`]: crate::database::BatchOperations::set_utxo
+    /// [`BatchOperations::del_utxo`]: crate::database::BatchOperations::del_utxo
+    fn sync<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(self.setup(stop_gap, database, progress_update))
+    }
+
+    /// Fetch a transaction from the blockchain given its txid
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
+    /// Broadcast a transaction
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error>;
+
+    /// Return the current height
+    fn get_height(&self) -> Result<u32, Error>;
+    /// Estimate the fee rate required to confirm a transaction in a given `target` of blocks
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>;
+}
+
+/// Data sent with a progress update over a [`channel`]
+pub type ProgressData = (f32, Option<String>);
+
+/// Trait for types that can receive and process progress updates during [`Blockchain::sync`] and
+/// [`Blockchain::setup`]
+pub trait Progress: Send {
+    /// Send a new progress update
+    ///
+    /// The `progress` value should be in the range 0.0 - 100.0, and the `message` value is an
+    /// optional text message that can be displayed to the user.
+    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error>;
+}
+
+/// Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]
+pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>) {
+    channel()
+}
+
+impl Progress for Sender<ProgressData> {
+    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
+        if progress < 0.0 || progress > 100.0 {
+            return Err(Error::InvalidProgressValue(progress));
+        }
+
+        self.send((progress, message))
+            .map_err(|_| Error::ProgressUpdateError)
+    }
+}
+
+/// Type that implements [`Progress`] and drops every update received
+#[derive(Clone)]
+pub struct NoopProgress;
+
+/// Create a new instance of [`NoopProgress`]
+pub fn noop_progress() -> NoopProgress {
+    NoopProgress
+}
+
+impl Progress for NoopProgress {
+    fn update(&self, _progress: f32, _message: Option<String>) -> Result<(), Error> {
+        Ok(())
+    }
+}
+
+/// Type that implements [`Progress`] and logs at level `INFO` every update received
+#[derive(Clone)]
+pub struct LogProgress;
+
+/// Create a nwe instance of [`LogProgress`]
+pub fn log_progress() -> LogProgress {
+    LogProgress
+}
+
+impl Progress for LogProgress {
+    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
+        log::info!("Sync {:.3}%: `{}`", progress, message.unwrap_or("".into()));
+
+        Ok(())
+    }
+}
+
+#[maybe_async]
+impl<T: Blockchain> Blockchain for Arc<T> {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        maybe_await!(self.deref().get_capabilities())
+    }
+
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(self.deref().setup(stop_gap, database, progress_update))
+    }
+
+    fn sync<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(self.deref().sync(stop_gap, database, progress_update))
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        maybe_await!(self.deref().get_tx(txid))
+    }
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        maybe_await!(self.deref().broadcast(tx))
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        maybe_await!(self.deref().get_height())
+    }
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
+        maybe_await!(self.deref().estimate_fee(target))
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/utils.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/utils.rs.html new file mode 100644 index 0000000000..6983da4834 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/utils.rs.html @@ -0,0 +1,719 @@ +utils.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::cmp;
+use std::collections::{HashSet, VecDeque};
+use std::convert::TryFrom;
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use bitcoin::{Address, Network, OutPoint, Script, Transaction, Txid};
+
+use super::*;
+use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
+use crate::error::Error;
+use crate::types::{ScriptType, TransactionDetails, UTXO};
+use crate::wallet::utils::ChunksIterator;
+
+#[derive(Debug)]
+pub struct ELSGetHistoryRes {
+    pub height: i32,
+    pub tx_hash: Txid,
+}
+
+#[derive(Debug)]
+pub struct ELSListUnspentRes {
+    pub height: usize,
+    pub tx_hash: Txid,
+    pub tx_pos: usize,
+}
+
+/// Implements the synchronization logic for an Electrum-like client.
+#[maybe_async]
+pub trait ElectrumLikeSync {
+    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error>;
+
+    fn els_batch_script_list_unspent<'s, I: IntoIterator<Item = &'s Script>>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ELSListUnspentRes>>, Error>;
+
+    fn els_transaction_get(&self, txid: &Txid) -> Result<Transaction, Error>;
+
+    // Provided methods down here...
+
+    fn electrum_like_setup<D: BatchDatabase, P: Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        _progress_update: P,
+    ) -> Result<(), Error> {
+        // TODO: progress
+
+        let stop_gap = stop_gap.unwrap_or(20);
+        let batch_query_size = 20;
+
+        // check unconfirmed tx, delete so they are retrieved later
+        let mut del_batch = database.begin_batch();
+        for tx in database.iter_txs(false)? {
+            if tx.height.is_none() {
+                del_batch.del_tx(&tx.txid, false)?;
+            }
+        }
+        database.commit_batch(del_batch)?;
+
+        // maximum derivation index for a change address that we've seen during sync
+        let mut change_max_deriv = None;
+
+        let mut already_checked: HashSet<Script> = HashSet::new();
+        let mut to_check_later = VecDeque::with_capacity(batch_query_size);
+
+        // insert the first chunk
+        let mut iter_scriptpubkeys = database
+            .iter_script_pubkeys(Some(ScriptType::External))?
+            .into_iter();
+        let chunk: Vec<Script> = iter_scriptpubkeys.by_ref().take(batch_query_size).collect();
+        for item in chunk.into_iter().rev() {
+            to_check_later.push_front(item);
+        }
+
+        let mut iterating_external = true;
+        let mut index = 0;
+        let mut last_found = None;
+        while !to_check_later.is_empty() {
+            trace!("to_check_later size {}", to_check_later.len());
+
+            let until = cmp::min(to_check_later.len(), batch_query_size);
+            let chunk: Vec<Script> = to_check_later.drain(..until).collect();
+            let call_result = maybe_await!(self.els_batch_script_get_history(chunk.iter()))?;
+
+            for (script, history) in chunk.into_iter().zip(call_result.into_iter()) {
+                trace!("received history for {:?}, size {}", script, history.len());
+
+                if !history.is_empty() {
+                    last_found = Some(index);
+
+                    let mut check_later_scripts = maybe_await!(self.check_history(
+                        database,
+                        script,
+                        history,
+                        &mut change_max_deriv
+                    ))?
+                    .into_iter()
+                    .filter(|x| already_checked.insert(x.clone()))
+                    .collect();
+                    to_check_later.append(&mut check_later_scripts);
+                }
+
+                index += 1;
+            }
+
+            match iterating_external {
+                true if index - last_found.unwrap_or(0) >= stop_gap => iterating_external = false,
+                true => {
+                    trace!("pushing one more batch from `iter_scriptpubkeys`. index = {}, last_found = {:?}, stop_gap = {}", index, last_found, stop_gap);
+
+                    let chunk: Vec<Script> =
+                        iter_scriptpubkeys.by_ref().take(batch_query_size).collect();
+                    for item in chunk.into_iter().rev() {
+                        to_check_later.push_front(item);
+                    }
+                }
+                _ => {}
+            }
+        }
+
+        // check utxo
+        // TODO: try to minimize network requests and re-use scripts if possible
+        let mut batch = database.begin_batch();
+        for chunk in ChunksIterator::new(database.iter_utxos()?.into_iter(), batch_query_size) {
+            let scripts: Vec<_> = chunk.iter().map(|u| &u.txout.script_pubkey).collect();
+            let call_result = maybe_await!(self.els_batch_script_list_unspent(scripts))?;
+
+            // check which utxos are actually still unspent
+            for (utxo, list_unspent) in chunk.into_iter().zip(call_result.iter()) {
+                debug!(
+                    "outpoint {:?} is unspent for me, list unspent is {:?}",
+                    utxo.outpoint, list_unspent
+                );
+
+                let mut spent = true;
+                for unspent in list_unspent {
+                    let res_outpoint = OutPoint::new(unspent.tx_hash, unspent.tx_pos as u32);
+                    if utxo.outpoint == res_outpoint {
+                        spent = false;
+                        break;
+                    }
+                }
+                if spent {
+                    info!("{} not anymore unspent, removing", utxo.outpoint);
+                    batch.del_utxo(&utxo.outpoint)?;
+                }
+            }
+        }
+
+        let current_ext = database.get_last_index(ScriptType::External)?.unwrap_or(0);
+        let first_ext_new = last_found.map(|x| x + 1).unwrap_or(0) as u32;
+        if first_ext_new > current_ext {
+            info!("Setting external index to {}", first_ext_new);
+            database.set_last_index(ScriptType::External, first_ext_new)?;
+        }
+
+        let current_int = database.get_last_index(ScriptType::Internal)?.unwrap_or(0);
+        let first_int_new = change_max_deriv.map(|x| x + 1).unwrap_or(0);
+        if first_int_new > current_int {
+            info!("Setting internal index to {}", first_int_new);
+            database.set_last_index(ScriptType::Internal, first_int_new)?;
+        }
+
+        database.commit_batch(batch)?;
+
+        Ok(())
+    }
+
+    fn check_tx_and_descendant<D: BatchDatabase>(
+        &self,
+        database: &mut D,
+        txid: &Txid,
+        height: Option<u32>,
+        cur_script: &Script,
+        change_max_deriv: &mut Option<u32>,
+    ) -> Result<Vec<Script>, Error> {
+        debug!(
+            "check_tx_and_descendant of {}, height: {:?}, script: {}",
+            txid, height, cur_script
+        );
+        let mut updates = database.begin_batch();
+        let tx = match database.get_tx(&txid, true)? {
+            Some(mut saved_tx) => {
+                // update the height if it's different (in case of reorg)
+                if saved_tx.height != height {
+                    info!(
+                        "updating height from {:?} to {:?} for tx {}",
+                        saved_tx.height, height, txid
+                    );
+                    saved_tx.height = height;
+                    updates.set_tx(&saved_tx)?;
+                }
+
+                debug!("already have {} in db, returning the cached version", txid);
+
+                // unwrap since we explicitly ask for the raw_tx, if it's not present something
+                // went wrong
+                saved_tx.transaction.unwrap()
+            }
+            None => {
+                let fetched_tx = maybe_await!(self.els_transaction_get(&txid))?;
+                database.set_raw_tx(&fetched_tx)?;
+
+                fetched_tx
+            }
+        };
+
+        let mut incoming: u64 = 0;
+        let mut outgoing: u64 = 0;
+
+        let mut inputs_sum: u64 = 0;
+        let mut outputs_sum: u64 = 0;
+
+        // look for our own inputs
+        for (i, input) in tx.input.iter().enumerate() {
+            // the fact that we visit addresses in a BFS fashion starting from the external addresses
+            // should ensure that this query is always consistent (i.e. when we get to call this all
+            // the transactions at a lower depth have already been indexed, so if an outpoint is ours
+            // we are guaranteed to have it in the db).
+            if let Some(previous_output) = database.get_previous_output(&input.previous_output)? {
+                inputs_sum += previous_output.value;
+
+                if database.is_mine(&previous_output.script_pubkey)? {
+                    outgoing += previous_output.value;
+
+                    debug!("{} input #{} is mine, removing from utxo", txid, i);
+                    updates.del_utxo(&input.previous_output)?;
+                }
+            } else {
+                // The input is not ours, but we still need to count it for the fees. so fetch the
+                // tx (from the database or from network) and check it
+                let tx = match database.get_tx(&input.previous_output.txid, true)? {
+                    Some(saved_tx) => saved_tx.transaction.unwrap(),
+                    None => {
+                        let fetched_tx =
+                            maybe_await!(self.els_transaction_get(&input.previous_output.txid))?;
+                        database.set_raw_tx(&fetched_tx)?;
+
+                        fetched_tx
+                    }
+                };
+
+                inputs_sum += tx.output[input.previous_output.vout as usize].value;
+            }
+        }
+
+        let mut to_check_later = vec![];
+        for (i, output) in tx.output.iter().enumerate() {
+            // to compute the fees later
+            outputs_sum += output.value;
+
+            // this output is ours, we have a path to derive it
+            if let Some((script_type, child)) =
+                database.get_path_from_script_pubkey(&output.script_pubkey)?
+            {
+                debug!("{} output #{} is mine, adding utxo", txid, i);
+                updates.set_utxo(&UTXO {
+                    outpoint: OutPoint::new(tx.txid(), i as u32),
+                    txout: output.clone(),
+                    is_internal: script_type.is_internal(),
+                })?;
+                incoming += output.value;
+
+                if output.script_pubkey != *cur_script {
+                    debug!("{} output #{} script {} was not current script, adding script to be checked later", txid, i, output.script_pubkey);
+                    to_check_later.push(output.script_pubkey.clone())
+                }
+
+                // derive as many change addrs as external addresses that we've seen
+                if script_type == ScriptType::Internal
+                    && (change_max_deriv.is_none() || child > change_max_deriv.unwrap_or(0))
+                {
+                    *change_max_deriv = Some(child);
+                }
+            }
+        }
+
+        let tx = TransactionDetails {
+            txid: tx.txid(),
+            transaction: Some(tx),
+            received: incoming,
+            sent: outgoing,
+            height,
+            timestamp: 0,
+            fees: inputs_sum - outputs_sum,
+        };
+        info!("Saving tx {}", txid);
+        updates.set_tx(&tx)?;
+
+        database.commit_batch(updates)?;
+
+        Ok(to_check_later)
+    }
+
+    fn check_history<D: BatchDatabase>(
+        &self,
+        database: &mut D,
+        script_pubkey: Script,
+        txs: Vec<ELSGetHistoryRes>,
+        change_max_deriv: &mut Option<u32>,
+    ) -> Result<Vec<Script>, Error> {
+        let mut to_check_later = Vec::new();
+
+        debug!(
+            "history of {} script {} has {} tx",
+            Address::from_script(&script_pubkey, Network::Testnet).unwrap(),
+            script_pubkey,
+            txs.len()
+        );
+
+        for tx in txs {
+            let height: Option<u32> = match tx.height {
+                0 | -1 => None,
+                x => u32::try_from(x).ok(),
+            };
+
+            to_check_later.extend_from_slice(&maybe_await!(self.check_tx_and_descendant(
+                database,
+                &tx.tx_hash,
+                height,
+                &script_pubkey,
+                change_max_deriv,
+            ))?);
+        }
+
+        Ok(to_check_later)
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/keyvalue.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/keyvalue.rs.html new file mode 100644 index 0000000000..8e338397ad --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/keyvalue.rs.html @@ -0,0 +1,965 @@ +keyvalue.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::convert::TryInto;
+
+use sled::{Batch, Tree};
+
+use bitcoin::consensus::encode::{deserialize, serialize};
+use bitcoin::hash_types::Txid;
+use bitcoin::{OutPoint, Script, Transaction};
+
+use crate::database::memory::MapKey;
+use crate::database::{BatchDatabase, BatchOperations, Database};
+use crate::error::Error;
+use crate::types::*;
+
+macro_rules! impl_batch_operations {
+    ( { $($after_insert:tt)* }, $process_delete:ident ) => {
+        fn set_script_pubkey(&mut self, script: &Script, script_type: ScriptType, path: u32) -> Result<(), Error> {
+            let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
+            self.insert(key, serialize(script))$($after_insert)*;
+
+            let key = MapKey::Script(Some(script)).as_map_key();
+            let value = json!({
+                "t": script_type,
+                "p": path,
+            });
+            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
+
+            Ok(())
+        }
+
+        fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
+            let key = MapKey::UTXO(Some(&utxo.outpoint)).as_map_key();
+            let value = json!({
+                "t": utxo.txout,
+                "i": utxo.is_internal,
+            });
+            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
+
+            Ok(())
+        }
+
+        fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
+            let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
+            let value = serialize(transaction);
+            self.insert(key, value)$($after_insert)*;
+
+            Ok(())
+        }
+
+        fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
+            let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
+
+            // remove the raw tx from the serialized version
+            let mut value = serde_json::to_value(transaction)?;
+            value["transaction"] = serde_json::Value::Null;
+            let value = serde_json::to_vec(&value)?;
+
+            self.insert(key, value)$($after_insert)*;
+
+            // insert the raw_tx if present
+            if let Some(ref tx) = transaction.transaction {
+                self.set_raw_tx(tx)?;
+            }
+
+            Ok(())
+        }
+
+        fn set_last_index(&mut self, script_type: ScriptType, value: u32) -> Result<(), Error> {
+            let key = MapKey::LastIndex(script_type).as_map_key();
+            self.insert(key, &value.to_be_bytes())$($after_insert)*;
+
+            Ok(())
+        }
+
+        fn del_script_pubkey_from_path(&mut self, script_type: ScriptType, path: u32) -> Result<Option<Script>, Error> {
+            let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
+        }
+
+        fn del_path_from_script_pubkey(&mut self, script: &Script) -> Result<Option<(ScriptType, u32)>, Error> {
+            let key = MapKey::Script(Some(script)).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            match res {
+                None => Ok(None),
+                Some(b) => {
+                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
+                    let st = serde_json::from_value(val["t"].take())?;
+                    let path = serde_json::from_value(val["p"].take())?;
+
+                    Ok(Some((st, path)))
+                }
+            }
+        }
+
+        fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
+            let key = MapKey::UTXO(Some(outpoint)).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            match res {
+                None => Ok(None),
+                Some(b) => {
+                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
+                    let txout = serde_json::from_value(val["t"].take())?;
+                    let is_internal = serde_json::from_value(val["i"].take())?;
+
+                    Ok(Some(UTXO { outpoint: outpoint.clone(), txout, is_internal }))
+                }
+            }
+        }
+
+        fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+            let key = MapKey::RawTx(Some(txid)).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
+        }
+
+        fn del_tx(&mut self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
+            let raw_tx = if include_raw {
+                self.del_raw_tx(txid)?
+            } else {
+                None
+            };
+
+            let key = MapKey::Transaction(Some(txid)).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            match res {
+                None => Ok(None),
+                Some(b) => {
+                    let mut val: TransactionDetails = serde_json::from_slice(&b)?;
+                    val.transaction = raw_tx;
+
+                    Ok(Some(val))
+                }
+            }
+        }
+
+        fn del_last_index(&mut self, script_type: ScriptType) -> Result<Option<u32>, Error> {
+            let key = MapKey::LastIndex(script_type).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            match res {
+                None => Ok(None),
+                Some(b) => {
+                    let array: [u8; 4] = b.as_ref().try_into().map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
+                    let val = u32::from_be_bytes(array);
+                    Ok(Some(val))
+                }
+            }
+        }
+    }
+}
+
+macro_rules! process_delete_tree {
+    ($res:expr) => {
+        $res?
+    };
+}
+impl BatchOperations for Tree {
+    impl_batch_operations!({?}, process_delete_tree);
+}
+
+macro_rules! process_delete_batch {
+    ($res:expr) => {
+        None as Option<sled::IVec>
+    };
+}
+#[allow(unused_variables)]
+impl BatchOperations for Batch {
+    impl_batch_operations!({}, process_delete_batch);
+}
+
+impl Database for Tree {
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
+        &mut self,
+        script_type: ScriptType,
+        bytes: B,
+    ) -> Result<(), Error> {
+        let key = MapKey::DescriptorChecksum(script_type).as_map_key();
+
+        let prev = self.get(&key)?.map(|x| x.to_vec());
+        if let Some(val) = prev {
+            if val == bytes.as_ref() {
+                Ok(())
+            } else {
+                Err(Error::ChecksumMismatch)
+            }
+        } else {
+            self.insert(&key, bytes.as_ref())?;
+            Ok(())
+        }
+    }
+
+    fn iter_script_pubkeys(&self, script_type: Option<ScriptType>) -> Result<Vec<Script>, Error> {
+        let key = MapKey::Path((script_type, None)).as_map_key();
+        self.scan_prefix(key)
+            .map(|x| -> Result<_, Error> {
+                let (_, v) = x?;
+                Ok(deserialize(&v)?)
+            })
+            .collect()
+    }
+
+    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error> {
+        let key = MapKey::UTXO(None).as_map_key();
+        self.scan_prefix(key)
+            .map(|x| -> Result<_, Error> {
+                let (k, v) = x?;
+                let outpoint = deserialize(&k[1..])?;
+
+                let mut val: serde_json::Value = serde_json::from_slice(&v)?;
+                let txout = serde_json::from_value(val["t"].take())?;
+                let is_internal = serde_json::from_value(val["i"].take())?;
+
+                Ok(UTXO {
+                    outpoint,
+                    txout,
+                    is_internal,
+                })
+            })
+            .collect()
+    }
+
+    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
+        let key = MapKey::RawTx(None).as_map_key();
+        self.scan_prefix(key)
+            .map(|x| -> Result<_, Error> {
+                let (_, v) = x?;
+                Ok(deserialize(&v)?)
+            })
+            .collect()
+    }
+
+    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
+        let key = MapKey::Transaction(None).as_map_key();
+        self.scan_prefix(key)
+            .map(|x| -> Result<_, Error> {
+                let (k, v) = x?;
+                let mut txdetails: TransactionDetails = serde_json::from_slice(&v)?;
+                if include_raw {
+                    let txid = deserialize(&k[1..])?;
+                    txdetails.transaction = self.get_raw_tx(&txid)?;
+                }
+
+                Ok(txdetails)
+            })
+            .collect()
+    }
+
+    fn get_script_pubkey_from_path(
+        &self,
+        script_type: ScriptType,
+        path: u32,
+    ) -> Result<Option<Script>, Error> {
+        let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
+        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
+    }
+
+    fn get_path_from_script_pubkey(
+        &self,
+        script: &Script,
+    ) -> Result<Option<(ScriptType, u32)>, Error> {
+        let key = MapKey::Script(Some(script)).as_map_key();
+        self.get(key)?
+            .map(|b| -> Result<_, Error> {
+                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
+                let st = serde_json::from_value(val["t"].take())?;
+                let path = serde_json::from_value(val["p"].take())?;
+
+                Ok((st, path))
+            })
+            .transpose()
+    }
+
+    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
+        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
+        self.get(key)?
+            .map(|b| -> Result<_, Error> {
+                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
+                let txout = serde_json::from_value(val["t"].take())?;
+                let is_internal = serde_json::from_value(val["i"].take())?;
+
+                Ok(UTXO {
+                    outpoint: outpoint.clone(),
+                    txout,
+                    is_internal,
+                })
+            })
+            .transpose()
+    }
+
+    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        let key = MapKey::RawTx(Some(txid)).as_map_key();
+        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
+    }
+
+    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
+        let key = MapKey::Transaction(Some(txid)).as_map_key();
+        self.get(key)?
+            .map(|b| -> Result<_, Error> {
+                let mut txdetails: TransactionDetails = serde_json::from_slice(&b)?;
+                if include_raw {
+                    txdetails.transaction = self.get_raw_tx(&txid)?;
+                }
+
+                Ok(txdetails)
+            })
+            .transpose()
+    }
+
+    fn get_last_index(&self, script_type: ScriptType) -> Result<Option<u32>, Error> {
+        let key = MapKey::LastIndex(script_type).as_map_key();
+        self.get(key)?
+            .map(|b| -> Result<_, Error> {
+                let array: [u8; 4] = b
+                    .as_ref()
+                    .try_into()
+                    .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
+                let val = u32::from_be_bytes(array);
+                Ok(val)
+            })
+            .transpose()
+    }
+
+    // inserts 0 if not present
+    fn increment_last_index(&mut self, script_type: ScriptType) -> Result<u32, Error> {
+        let key = MapKey::LastIndex(script_type).as_map_key();
+        self.update_and_fetch(key, |prev| {
+            let new = match prev {
+                Some(b) => {
+                    let array: [u8; 4] = b.try_into().unwrap_or([0; 4]);
+                    let val = u32::from_be_bytes(array);
+
+                    val + 1
+                }
+                None => 0,
+            };
+
+            Some(new.to_be_bytes().to_vec())
+        })?
+        .map_or(Ok(0), |b| -> Result<_, Error> {
+            let array: [u8; 4] = b
+                .as_ref()
+                .try_into()
+                .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
+            let val = u32::from_be_bytes(array);
+            Ok(val)
+        })
+    }
+}
+
+impl BatchDatabase for Tree {
+    type Batch = sled::Batch;
+
+    fn begin_batch(&self) -> Self::Batch {
+        sled::Batch::default()
+    }
+
+    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
+        Ok(self.apply_batch(batch)?)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::sync::{Arc, Condvar, Mutex, Once};
+    use std::time::{SystemTime, UNIX_EPOCH};
+
+    use sled::{Db, Tree};
+
+    static mut COUNT: usize = 0;
+
+    lazy_static! {
+        static ref DB: Arc<(Mutex<Option<Db>>, Condvar)> =
+            Arc::new((Mutex::new(None), Condvar::new()));
+        static ref INIT: Once = Once::new();
+    }
+
+    fn get_tree() -> Tree {
+        unsafe {
+            let cloned = DB.clone();
+            let (mutex, cvar) = &*cloned;
+
+            INIT.call_once(|| {
+                let mut db = mutex.lock().unwrap();
+
+                let time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
+                let mut dir = std::env::temp_dir();
+                dir.push(format!("mbw_{}", time.as_nanos()));
+
+                *db = Some(sled::open(dir).unwrap());
+                cvar.notify_all();
+            });
+
+            let mut db = mutex.lock().unwrap();
+            while !db.is_some() {
+                db = cvar.wait(db).unwrap();
+            }
+
+            COUNT += 1;
+
+            db.as_ref()
+                .unwrap()
+                .open_tree(format!("tree_{}", COUNT))
+                .unwrap()
+        }
+    }
+
+    #[test]
+    fn test_script_pubkey() {
+        crate::database::test::test_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_batch_script_pubkey() {
+        crate::database::test::test_batch_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_iter_script_pubkey() {
+        crate::database::test::test_iter_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_del_script_pubkey() {
+        crate::database::test::test_del_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_utxo() {
+        crate::database::test::test_utxo(get_tree());
+    }
+
+    #[test]
+    fn test_raw_tx() {
+        crate::database::test::test_raw_tx(get_tree());
+    }
+
+    #[test]
+    fn test_tx() {
+        crate::database::test::test_tx(get_tree());
+    }
+
+    #[test]
+    fn test_last_index() {
+        crate::database::test::test_last_index(get_tree());
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/memory.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/memory.rs.html new file mode 100644 index 0000000000..7f900ff53a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/memory.rs.html @@ -0,0 +1,1119 @@ +memory.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! In-memory ephemeral database
+//!
+//! This module defines an in-memory database type called [`MemoryDatabase`] that is based on a
+//! [`BTreeMap`].
+
+use std::collections::BTreeMap;
+use std::ops::Bound::{Excluded, Included};
+
+use bitcoin::consensus::encode::{deserialize, serialize};
+use bitcoin::hash_types::Txid;
+use bitcoin::{OutPoint, Script, Transaction};
+
+use crate::database::{BatchDatabase, BatchOperations, Database};
+use crate::error::Error;
+use crate::types::*;
+
+// path -> script       p{i,e}<path> -> script
+// script -> path       s<script> -> {i,e}<path>
+// outpoint             u<outpoint> -> txout
+// rawtx                r<txid> -> tx
+// transactions         t<txid> -> tx details
+// deriv indexes        c{i,e} -> u32
+// descriptor checksum  d{i,e} -> vec<u8>
+
+pub(crate) enum MapKey<'a> {
+    Path((Option<ScriptType>, Option<u32>)),
+    Script(Option<&'a Script>),
+    UTXO(Option<&'a OutPoint>),
+    RawTx(Option<&'a Txid>),
+    Transaction(Option<&'a Txid>),
+    LastIndex(ScriptType),
+    DescriptorChecksum(ScriptType),
+}
+
+impl MapKey<'_> {
+    pub fn as_prefix(&self) -> Vec<u8> {
+        match self {
+            MapKey::Path((st, _)) => {
+                let mut v = b"p".to_vec();
+                if let Some(st) = st {
+                    v.push(st.as_byte());
+                }
+                v
+            }
+            MapKey::Script(_) => b"s".to_vec(),
+            MapKey::UTXO(_) => b"u".to_vec(),
+            MapKey::RawTx(_) => b"r".to_vec(),
+            MapKey::Transaction(_) => b"t".to_vec(),
+            MapKey::LastIndex(st) => [b"c", st.as_ref()].concat(),
+            MapKey::DescriptorChecksum(st) => [b"d", st.as_ref()].concat(),
+        }
+    }
+
+    fn serialize_content(&self) -> Vec<u8> {
+        match self {
+            MapKey::Path((_, Some(child))) => u32::from(*child).to_be_bytes().to_vec(),
+            MapKey::Script(Some(s)) => serialize(*s),
+            MapKey::UTXO(Some(s)) => serialize(*s),
+            MapKey::RawTx(Some(s)) => serialize(*s),
+            MapKey::Transaction(Some(s)) => serialize(*s),
+            _ => vec![],
+        }
+    }
+
+    pub fn as_map_key(&self) -> Vec<u8> {
+        let mut v = self.as_prefix();
+        v.extend_from_slice(&self.serialize_content());
+
+        v
+    }
+}
+
+fn after(key: &Vec<u8>) -> Vec<u8> {
+    let mut key = key.clone();
+    let mut idx = key.len();
+    while idx > 0 {
+        if key[idx - 1] == 0xFF {
+            idx -= 1;
+            continue;
+        } else {
+            key[idx - 1] += 1;
+            break;
+        }
+    }
+
+    key
+}
+
+/// In-memory ephemeral database
+///
+/// This database can be used as a temporary storage for wallets that are not kept permanently on
+/// a device, or on platforms that don't provide a filesystem, like `wasm32`.
+///
+/// Once it's dropped its content will be lost.
+///
+/// If you are looking for a permanent storage solution, you can try with the default key-value
+/// database called [`sled`]. See the [`database`] module documentation for more defailts.
+///
+/// [`database`]: crate::database
+#[derive(Debug, Default)]
+pub struct MemoryDatabase {
+    map: BTreeMap<Vec<u8>, Box<dyn std::any::Any>>,
+    deleted_keys: Vec<Vec<u8>>,
+}
+
+impl MemoryDatabase {
+    /// Create a new empty database
+    pub fn new() -> Self {
+        MemoryDatabase {
+            map: BTreeMap::new(),
+            deleted_keys: Vec::new(),
+        }
+    }
+}
+
+impl BatchOperations for MemoryDatabase {
+    fn set_script_pubkey(
+        &mut self,
+        script: &Script,
+        script_type: ScriptType,
+        path: u32,
+    ) -> Result<(), Error> {
+        let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
+        self.map.insert(key, Box::new(script.clone()));
+
+        let key = MapKey::Script(Some(script)).as_map_key();
+        let value = json!({
+            "t": script_type,
+            "p": path,
+        });
+        self.map.insert(key, Box::new(value));
+
+        Ok(())
+    }
+
+    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
+        let key = MapKey::UTXO(Some(&utxo.outpoint)).as_map_key();
+        self.map
+            .insert(key, Box::new((utxo.txout.clone(), utxo.is_internal)));
+
+        Ok(())
+    }
+    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
+        let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
+        self.map.insert(key, Box::new(transaction.clone()));
+
+        Ok(())
+    }
+    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
+        let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
+
+        // insert the raw_tx if present
+        if let Some(ref tx) = transaction.transaction {
+            self.set_raw_tx(tx)?;
+        }
+
+        // remove the raw tx from the serialized version
+        let mut transaction = transaction.clone();
+        transaction.transaction = None;
+
+        self.map.insert(key, Box::new(transaction));
+
+        Ok(())
+    }
+    fn set_last_index(&mut self, script_type: ScriptType, value: u32) -> Result<(), Error> {
+        let key = MapKey::LastIndex(script_type).as_map_key();
+        self.map.insert(key, Box::new(value));
+
+        Ok(())
+    }
+
+    fn del_script_pubkey_from_path(
+        &mut self,
+        script_type: ScriptType,
+        path: u32,
+    ) -> Result<Option<Script>, Error> {
+        let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
+    }
+    fn del_path_from_script_pubkey(
+        &mut self,
+        script: &Script,
+    ) -> Result<Option<(ScriptType, u32)>, Error> {
+        let key = MapKey::Script(Some(script)).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        match res {
+            None => Ok(None),
+            Some(b) => {
+                let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
+                let st = serde_json::from_value(val["t"].take())?;
+                let path = serde_json::from_value(val["p"].take())?;
+
+                Ok(Some((st, path)))
+            }
+        }
+    }
+    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
+        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        match res {
+            None => Ok(None),
+            Some(b) => {
+                let (txout, is_internal) = b.downcast_ref().cloned().unwrap();
+                Ok(Some(UTXO {
+                    outpoint: outpoint.clone(),
+                    txout,
+                    is_internal,
+                }))
+            }
+        }
+    }
+    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        let key = MapKey::RawTx(Some(txid)).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
+    }
+    fn del_tx(
+        &mut self,
+        txid: &Txid,
+        include_raw: bool,
+    ) -> Result<Option<TransactionDetails>, Error> {
+        let raw_tx = if include_raw {
+            self.del_raw_tx(txid)?
+        } else {
+            None
+        };
+
+        let key = MapKey::Transaction(Some(txid)).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        match res {
+            None => Ok(None),
+            Some(b) => {
+                let mut val: TransactionDetails = b.downcast_ref().cloned().unwrap();
+                val.transaction = raw_tx;
+
+                Ok(Some(val))
+            }
+        }
+    }
+    fn del_last_index(&mut self, script_type: ScriptType) -> Result<Option<u32>, Error> {
+        let key = MapKey::LastIndex(script_type).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        match res {
+            None => Ok(None),
+            Some(b) => Ok(Some(*b.downcast_ref().unwrap())),
+        }
+    }
+}
+
+impl Database for MemoryDatabase {
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
+        &mut self,
+        script_type: ScriptType,
+        bytes: B,
+    ) -> Result<(), Error> {
+        let key = MapKey::DescriptorChecksum(script_type).as_map_key();
+
+        let prev = self
+            .map
+            .get(&key)
+            .map(|x| x.downcast_ref::<Vec<u8>>().unwrap());
+        if let Some(val) = prev {
+            if val == &bytes.as_ref().to_vec() {
+                Ok(())
+            } else {
+                Err(Error::ChecksumMismatch)
+            }
+        } else {
+            self.map.insert(key, Box::new(bytes.as_ref().to_vec()));
+            Ok(())
+        }
+    }
+
+    fn iter_script_pubkeys(&self, script_type: Option<ScriptType>) -> Result<Vec<Script>, Error> {
+        let key = MapKey::Path((script_type, None)).as_map_key();
+        self.map
+            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
+            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
+            .collect()
+    }
+
+    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error> {
+        let key = MapKey::UTXO(None).as_map_key();
+        self.map
+            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
+            .map(|(k, v)| {
+                let outpoint = deserialize(&k[1..]).unwrap();
+                let (txout, is_internal) = v.downcast_ref().cloned().unwrap();
+                Ok(UTXO {
+                    outpoint,
+                    txout,
+                    is_internal,
+                })
+            })
+            .collect()
+    }
+
+    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
+        let key = MapKey::RawTx(None).as_map_key();
+        self.map
+            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
+            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
+            .collect()
+    }
+
+    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
+        let key = MapKey::Transaction(None).as_map_key();
+        self.map
+            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
+            .map(|(k, v)| {
+                let mut txdetails: TransactionDetails = v.downcast_ref().cloned().unwrap();
+                if include_raw {
+                    let txid = deserialize(&k[1..])?;
+                    txdetails.transaction = self.get_raw_tx(&txid)?;
+                }
+
+                Ok(txdetails)
+            })
+            .collect()
+    }
+
+    fn get_script_pubkey_from_path(
+        &self,
+        script_type: ScriptType,
+        path: u32,
+    ) -> Result<Option<Script>, Error> {
+        let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
+        Ok(self
+            .map
+            .get(&key)
+            .map(|b| b.downcast_ref().cloned().unwrap()))
+    }
+
+    fn get_path_from_script_pubkey(
+        &self,
+        script: &Script,
+    ) -> Result<Option<(ScriptType, u32)>, Error> {
+        let key = MapKey::Script(Some(script)).as_map_key();
+        Ok(self.map.get(&key).map(|b| {
+            let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
+            let st = serde_json::from_value(val["t"].take()).unwrap();
+            let path = serde_json::from_value(val["p"].take()).unwrap();
+
+            (st, path)
+        }))
+    }
+
+    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
+        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
+        Ok(self.map.get(&key).map(|b| {
+            let (txout, is_internal) = b.downcast_ref().cloned().unwrap();
+            UTXO {
+                outpoint: outpoint.clone(),
+                txout,
+                is_internal,
+            }
+        }))
+    }
+
+    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        let key = MapKey::RawTx(Some(txid)).as_map_key();
+        Ok(self
+            .map
+            .get(&key)
+            .map(|b| b.downcast_ref().cloned().unwrap()))
+    }
+
+    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
+        let key = MapKey::Transaction(Some(txid)).as_map_key();
+        Ok(self.map.get(&key).map(|b| {
+            let mut txdetails: TransactionDetails = b.downcast_ref().cloned().unwrap();
+            if include_raw {
+                txdetails.transaction = self.get_raw_tx(&txid).unwrap();
+            }
+
+            txdetails
+        }))
+    }
+
+    fn get_last_index(&self, script_type: ScriptType) -> Result<Option<u32>, Error> {
+        let key = MapKey::LastIndex(script_type).as_map_key();
+        Ok(self.map.get(&key).map(|b| *b.downcast_ref().unwrap()))
+    }
+
+    // inserts 0 if not present
+    fn increment_last_index(&mut self, script_type: ScriptType) -> Result<u32, Error> {
+        let key = MapKey::LastIndex(script_type).as_map_key();
+        let value = self
+            .map
+            .entry(key.clone())
+            .and_modify(|x| *x.downcast_mut::<u32>().unwrap() += 1)
+            .or_insert(Box::<u32>::new(0))
+            .downcast_mut()
+            .unwrap();
+
+        Ok(*value)
+    }
+}
+
+impl BatchDatabase for MemoryDatabase {
+    type Batch = Self;
+
+    fn begin_batch(&self) -> Self::Batch {
+        MemoryDatabase::new()
+    }
+
+    fn commit_batch(&mut self, mut batch: Self::Batch) -> Result<(), Error> {
+        for key in batch.deleted_keys {
+            self.map.remove(&key);
+        }
+
+        Ok(self.map.append(&mut batch.map))
+    }
+}
+
+#[cfg(test)]
+impl MemoryDatabase {
+    // Artificially insert a tx in the database, as if we had found it with a `sync`
+    pub fn received_tx(
+        &mut self,
+        tx_meta: testutils::TestIncomingTx,
+        current_height: Option<u32>,
+    ) -> bitcoin::Txid {
+        use std::str::FromStr;
+
+        let tx = Transaction {
+            version: 1,
+            lock_time: 0,
+            input: vec![],
+            output: tx_meta
+                .output
+                .iter()
+                .map(|out_meta| bitcoin::TxOut {
+                    value: out_meta.value,
+                    script_pubkey: bitcoin::Address::from_str(&out_meta.to_address)
+                        .unwrap()
+                        .script_pubkey(),
+                })
+                .collect(),
+        };
+
+        let txid = tx.txid();
+        let height = tx_meta
+            .min_confirmations
+            .map(|conf| current_height.unwrap().checked_sub(conf as u32).unwrap());
+
+        let tx_details = TransactionDetails {
+            transaction: Some(tx.clone()),
+            txid,
+            timestamp: 0,
+            height,
+            received: 0,
+            sent: 0,
+            fees: 0,
+        };
+
+        self.set_tx(&tx_details).unwrap();
+        for (vout, out) in tx.output.iter().enumerate() {
+            self.set_utxo(&UTXO {
+                txout: out.clone(),
+                outpoint: OutPoint {
+                    txid,
+                    vout: vout as u32,
+                },
+                is_internal: false,
+            })
+            .unwrap();
+        }
+
+        txid
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::MemoryDatabase;
+
+    fn get_tree() -> MemoryDatabase {
+        MemoryDatabase::new()
+    }
+
+    #[test]
+    fn test_script_pubkey() {
+        crate::database::test::test_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_batch_script_pubkey() {
+        crate::database::test::test_batch_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_iter_script_pubkey() {
+        crate::database::test::test_iter_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_del_script_pubkey() {
+        crate::database::test::test_del_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_utxo() {
+        crate::database::test::test_utxo(get_tree());
+    }
+
+    #[test]
+    fn test_raw_tx() {
+        crate::database::test::test_raw_tx(get_tree());
+    }
+
+    #[test]
+    fn test_tx() {
+        crate::database::test::test_tx(get_tree());
+    }
+
+    #[test]
+    fn test_last_index() {
+        crate::database::test::test_last_index(get_tree());
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/mod.rs.html new file mode 100644 index 0000000000..5836fe48fd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/mod.rs.html @@ -0,0 +1,739 @@ +mod.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Database types
+//!
+//! This module provides the implementation of some defaults database types, along with traits that
+//! can be implemented externally to let [`Wallet`]s use customized databases.
+//!
+//! It's important to note that the databases defined here only contains "blockchain-related" data.
+//! They can be seen more as a cache than a critical piece of storage that contains secrets and
+//! keys.
+//!
+//! The currently recommended database is [`sled`], which is a pretty simple key-value embedded
+//! database written in Rust. If the `key-value-db` feature is enabled (which by default is),
+//! this library automatically implements all the required traits for [`sled::Tree`].
+//!
+//! [`Wallet`]: crate::wallet::Wallet
+
+use bitcoin::hash_types::Txid;
+use bitcoin::{OutPoint, Script, Transaction, TxOut};
+
+use crate::error::Error;
+use crate::types::*;
+
+#[cfg(feature = "key-value-db")]
+pub(crate) mod keyvalue;
+
+pub mod memory;
+pub use memory::MemoryDatabase;
+
+/// Trait for operations that can be batched
+///
+/// This trait defines the list of operations that must be implemented on the [`Database`] type and
+/// the [`BatchDatabase::Batch`] type.
+pub trait BatchOperations {
+    /// Store a script_pubkey along with its script type and child number
+    fn set_script_pubkey(
+        &mut self,
+        script: &Script,
+        script_type: ScriptType,
+        child: u32,
+    ) -> Result<(), Error>;
+    /// Store a [`UTXO`]
+    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>;
+    /// Store a raw transaction
+    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>;
+    /// Store the metadata of a transaction
+    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>;
+    /// Store the last derivation index for a given script type
+    fn set_last_index(&mut self, script_type: ScriptType, value: u32) -> Result<(), Error>;
+
+    /// Delete a script_pubkey given the script type and its child number
+    fn del_script_pubkey_from_path(
+        &mut self,
+        script_type: ScriptType,
+        child: u32,
+    ) -> Result<Option<Script>, Error>;
+    /// Delete the data related to a specific script_pubkey, meaning the script type and the child
+    /// number
+    fn del_path_from_script_pubkey(
+        &mut self,
+        script: &Script,
+    ) -> Result<Option<(ScriptType, u32)>, Error>;
+    /// Delete a [`UTXO`] given its [`OutPoint`]
+    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>;
+    /// Delete a raw transaction given its [`Txid`]
+    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>;
+    /// Delete the metadata of a transaction and optionally the raw transaction itself
+    fn del_tx(
+        &mut self,
+        txid: &Txid,
+        include_raw: bool,
+    ) -> Result<Option<TransactionDetails>, Error>;
+    /// Delete the last derivation index for a script type
+    fn del_last_index(&mut self, script_type: ScriptType) -> Result<Option<u32>, Error>;
+}
+
+/// Trait for reading data from a database
+///
+/// This traits defines the operations that can be used to read data out of a database
+pub trait Database: BatchOperations {
+    /// Read and checks the descriptor checksum for a given script type
+    ///
+    /// Should return [`Error::ChecksumMismatch`](crate::error::Error::ChecksumMismatch) if the
+    /// checksum doesn't match. If there's no checksum in the database, simply store it for the
+    /// next time.
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
+        &mut self,
+        script_type: ScriptType,
+        bytes: B,
+    ) -> Result<(), Error>;
+
+    /// Return the list of script_pubkeys
+    fn iter_script_pubkeys(&self, script_type: Option<ScriptType>) -> Result<Vec<Script>, Error>;
+    /// Return the list of [`UTXO`]s
+    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error>;
+    /// Return the list of raw transactions
+    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>;
+    /// Return the list of transactions metadata
+    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error>;
+
+    /// Fetch a script_pubkey given the script type and child number
+    fn get_script_pubkey_from_path(
+        &self,
+        script_type: ScriptType,
+        child: u32,
+    ) -> Result<Option<Script>, Error>;
+    /// Fetch the script type and child number of a given script_pubkey
+    fn get_path_from_script_pubkey(
+        &self,
+        script: &Script,
+    ) -> Result<Option<(ScriptType, u32)>, Error>;
+    /// Fetch a [`UTXO`] given its [`OutPoint`]
+    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>;
+    /// Fetch a raw transaction given its [`Txid`]
+    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
+    /// Fetch the transaction metadata and optionally also the raw transaction
+    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error>;
+    /// Return the last defivation index for a script type
+    fn get_last_index(&self, script_type: ScriptType) -> Result<Option<u32>, Error>;
+
+    /// Increment the last derivation index for a script type and returns it
+    ///
+    /// It should insert and return `0` if not present in the database
+    fn increment_last_index(&mut self, script_type: ScriptType) -> Result<u32, Error>;
+}
+
+/// Trait for a database that supports batch operations
+///
+/// This trait defines the methods to start and apply a batch of operations.
+pub trait BatchDatabase: Database {
+    /// Container for the operations
+    type Batch: BatchOperations;
+
+    /// Create a new batch container
+    fn begin_batch(&self) -> Self::Batch;
+    /// Consume and apply a batch of operations
+    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>;
+}
+
+pub(crate) trait DatabaseUtils: Database {
+    fn is_mine(&self, script: &Script) -> Result<bool, Error> {
+        self.get_path_from_script_pubkey(script)
+            .map(|o| o.is_some())
+    }
+
+    fn get_raw_tx_or<F>(&self, txid: &Txid, f: F) -> Result<Option<Transaction>, Error>
+    where
+        F: FnOnce() -> Result<Option<Transaction>, Error>,
+    {
+        self.get_tx(txid, true)?
+            .map(|t| t.transaction)
+            .flatten()
+            .map_or_else(f, |t| Ok(Some(t)))
+    }
+
+    fn get_previous_output(&self, outpoint: &OutPoint) -> Result<Option<TxOut>, Error> {
+        self.get_raw_tx(&outpoint.txid)?
+            .map(|previous_tx| {
+                if outpoint.vout as usize >= previous_tx.output.len() {
+                    Err(Error::InvalidOutpoint(outpoint.clone()))
+                } else {
+                    Ok(previous_tx.output[outpoint.vout as usize].clone())
+                }
+            })
+            .transpose()
+    }
+}
+
+impl<T: Database> DatabaseUtils for T {}
+
+#[cfg(test)]
+pub mod test {
+    use std::str::FromStr;
+
+    use bitcoin::consensus::encode::deserialize;
+    use bitcoin::hashes::hex::*;
+    use bitcoin::*;
+
+    use super::*;
+
+    pub fn test_script_pubkey<D: Database>(mut tree: D) {
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let path = 42;
+        let script_type = ScriptType::External;
+
+        tree.set_script_pubkey(&script, script_type, path).unwrap();
+
+        assert_eq!(
+            tree.get_script_pubkey_from_path(script_type, path).unwrap(),
+            Some(script.clone())
+        );
+        assert_eq!(
+            tree.get_path_from_script_pubkey(&script).unwrap(),
+            Some((script_type, path.clone()))
+        );
+    }
+
+    pub fn test_batch_script_pubkey<D: BatchDatabase>(mut tree: D) {
+        let mut batch = tree.begin_batch();
+
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let path = 42;
+        let script_type = ScriptType::External;
+
+        batch.set_script_pubkey(&script, script_type, path).unwrap();
+
+        assert_eq!(
+            tree.get_script_pubkey_from_path(script_type, path).unwrap(),
+            None
+        );
+        assert_eq!(tree.get_path_from_script_pubkey(&script).unwrap(), None);
+
+        tree.commit_batch(batch).unwrap();
+
+        assert_eq!(
+            tree.get_script_pubkey_from_path(script_type, path).unwrap(),
+            Some(script.clone())
+        );
+        assert_eq!(
+            tree.get_path_from_script_pubkey(&script).unwrap(),
+            Some((script_type, path.clone()))
+        );
+    }
+
+    pub fn test_iter_script_pubkey<D: Database>(mut tree: D) {
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let path = 42;
+        let script_type = ScriptType::External;
+
+        tree.set_script_pubkey(&script, script_type, path).unwrap();
+
+        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 1);
+    }
+
+    pub fn test_del_script_pubkey<D: Database>(mut tree: D) {
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let path = 42;
+        let script_type = ScriptType::External;
+
+        tree.set_script_pubkey(&script, script_type, path).unwrap();
+        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 1);
+
+        tree.del_script_pubkey_from_path(script_type, path).unwrap();
+        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 0);
+    }
+
+    pub fn test_utxo<D: Database>(mut tree: D) {
+        let outpoint = OutPoint::from_str(
+            "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0",
+        )
+        .unwrap();
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let txout = TxOut {
+            value: 133742,
+            script_pubkey: script,
+        };
+        let utxo = UTXO {
+            txout,
+            outpoint,
+            is_internal: false,
+        };
+
+        tree.set_utxo(&utxo).unwrap();
+
+        assert_eq!(tree.get_utxo(&outpoint).unwrap(), Some(utxo));
+    }
+
+    pub fn test_raw_tx<D: Database>(mut tree: D) {
+        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
+        let tx: Transaction = deserialize(&hex_tx).unwrap();
+
+        tree.set_raw_tx(&tx).unwrap();
+
+        let txid = tx.txid();
+
+        assert_eq!(tree.get_raw_tx(&txid).unwrap(), Some(tx));
+    }
+
+    pub fn test_tx<D: Database>(mut tree: D) {
+        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
+        let tx: Transaction = deserialize(&hex_tx).unwrap();
+        let txid = tx.txid();
+        let mut tx_details = TransactionDetails {
+            transaction: Some(tx),
+            txid,
+            timestamp: 123456,
+            received: 1337,
+            sent: 420420,
+            fees: 140,
+            height: Some(1000),
+        };
+
+        tree.set_tx(&tx_details).unwrap();
+
+        // get with raw tx too
+        assert_eq!(
+            tree.get_tx(&tx_details.txid, true).unwrap(),
+            Some(tx_details.clone())
+        );
+        // get only raw_tx
+        assert_eq!(
+            tree.get_raw_tx(&tx_details.txid).unwrap(),
+            tx_details.transaction
+        );
+
+        // now get without raw_tx
+        tx_details.transaction = None;
+        assert_eq!(
+            tree.get_tx(&tx_details.txid, false).unwrap(),
+            Some(tx_details)
+        );
+    }
+
+    pub fn test_last_index<D: Database>(mut tree: D) {
+        tree.set_last_index(ScriptType::External, 1337).unwrap();
+
+        assert_eq!(
+            tree.get_last_index(ScriptType::External).unwrap(),
+            Some(1337)
+        );
+        assert_eq!(tree.get_last_index(ScriptType::Internal).unwrap(), None);
+
+        let res = tree.increment_last_index(ScriptType::External).unwrap();
+        assert_eq!(res, 1338);
+        let res = tree.increment_last_index(ScriptType::Internal).unwrap();
+        assert_eq!(res, 0);
+
+        assert_eq!(
+            tree.get_last_index(ScriptType::External).unwrap(),
+            Some(1338)
+        );
+        assert_eq!(tree.get_last_index(ScriptType::Internal).unwrap(), Some(0));
+    }
+
+    // TODO: more tests...
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/checksum.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/checksum.rs.html new file mode 100644 index 0000000000..33f8d47a15 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/checksum.rs.html @@ -0,0 +1,191 @@ +checksum.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Descriptor checksum
+//!
+//! This module contains a re-implementation of the function used by Bitcoin Core to calculate the
+//! checksum of a descriptor
+
+use std::iter::FromIterator;
+
+use crate::descriptor::Error;
+
+const INPUT_CHARSET: &str =  "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
+const CHECKSUM_CHARSET: &str = "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 of a descriptor
+pub fn get_checksum(desc: &str) -> Result<String, Error> {
+    let mut c = 1;
+    let mut cls = 0;
+    let mut clscount = 0;
+    for ch in desc.chars() {
+        let pos = INPUT_CHARSET
+            .find(ch)
+            .ok_or(Error::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 chars = Vec::with_capacity(8);
+    for j in 0..8 {
+        chars.push(
+            CHECKSUM_CHARSET
+                .chars()
+                .nth(((c >> (5 * (7 - j))) & 31) as usize)
+                .unwrap(),
+        );
+    }
+
+    Ok(String::from_iter(chars))
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/error.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/error.rs.html new file mode 100644 index 0000000000..78518b4f6b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/error.rs.html @@ -0,0 +1,135 @@ +error.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Descriptor errors
+
+/// Errors related to the parsing and usage of descriptors
+#[derive(Debug)]
+pub enum Error {
+    InternalError,
+    InvalidPrefix(Vec<u8>),
+    HardenedDerivationOnXpub,
+    MalformedInput,
+    KeyParsingError(String),
+
+    Policy(crate::descriptor::policy::PolicyError),
+
+    InputIndexDoesntExist,
+    MissingPublicKey,
+    MissingDetails,
+
+    InvalidDescriptorCharacter(char),
+
+    CantDeriveWithMiniscript,
+
+    BIP32(bitcoin::util::bip32::Error),
+    Base58(bitcoin::util::base58::Error),
+    PK(bitcoin::util::key::Error),
+    Miniscript(miniscript::Error),
+    Hex(bitcoin::hashes::hex::Error),
+}
+
+impl std::fmt::Display for Error {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for Error {}
+
+impl_error!(bitcoin::util::bip32::Error, BIP32);
+impl_error!(bitcoin::util::base58::Error, Base58);
+impl_error!(bitcoin::util::key::Error, PK);
+impl_error!(miniscript::Error, Miniscript);
+impl_error!(bitcoin::hashes::hex::Error, Hex);
+impl_error!(crate::descriptor::policy::PolicyError, Policy);
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/mod.rs.html new file mode 100644 index 0000000000..2e600ffa85 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/mod.rs.html @@ -0,0 +1,883 @@ +mod.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Descriptors
+//!
+//! This module contains generic utilities to work with descriptors, plus some re-exported types
+//! from [`miniscript`].
+
+use std::collections::{BTreeMap, HashMap};
+use std::fmt;
+use std::sync::Arc;
+
+use bitcoin::hashes::hash160;
+use bitcoin::secp256k1::Secp256k1;
+use bitcoin::util::bip32::{ChildNumber, DerivationPath, Fingerprint};
+use bitcoin::util::psbt;
+use bitcoin::{PublicKey, Script, TxOut};
+
+use miniscript::descriptor::{DescriptorPublicKey, DescriptorXKey, InnerXKey};
+pub use miniscript::{
+    Descriptor, Legacy, Miniscript, MiniscriptKey, ScriptContext, Segwitv0, Terminal, ToPublicKey,
+};
+
+pub mod checksum;
+pub mod error;
+pub mod policy;
+
+pub use self::checksum::get_checksum;
+use self::error::Error;
+pub use self::policy::Policy;
+use crate::wallet::signer::SignersContainer;
+
+/// Alias for a [`Descriptor`] that can contain extended keys using [`DescriptorPublicKey`]
+pub type ExtendedDescriptor = Descriptor<DescriptorPublicKey>;
+
+/// Alias for the type of maps that represent derivation paths in a [`psbt::Input`] or
+/// [`psbt::Output`]
+///
+/// [`psbt::Input`]: bitcoin::util::psbt::Input
+/// [`psbt::Output`]: bitcoin::util::psbt::Output
+pub type HDKeyPaths = BTreeMap<PublicKey, (Fingerprint, DerivationPath)>;
+
+/// Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]
+pub trait ExtractPolicy {
+    fn extract_policy(
+        &self,
+        signers: Arc<SignersContainer<DescriptorPublicKey>>,
+    ) -> Result<Option<Policy>, Error>;
+}
+
+pub(crate) trait XKeyUtils {
+    fn full_path(&self, append: &[ChildNumber]) -> DerivationPath;
+    fn root_fingerprint(&self) -> Fingerprint;
+}
+
+impl<K: InnerXKey> XKeyUtils for DescriptorXKey<K> {
+    fn full_path(&self, append: &[ChildNumber]) -> DerivationPath {
+        let full_path = match &self.source {
+            &Some((_, ref path)) => path
+                .into_iter()
+                .chain(self.derivation_path.into_iter())
+                .cloned()
+                .collect(),
+            &None => self.derivation_path.clone(),
+        };
+
+        if self.is_wildcard {
+            full_path
+                .into_iter()
+                .chain(append.into_iter())
+                .cloned()
+                .collect()
+        } else {
+            full_path
+        }
+    }
+
+    fn root_fingerprint(&self) -> Fingerprint {
+        match &self.source {
+            &Some((fingerprint, _)) => fingerprint.clone(),
+            &None => self.xkey.xkey_fingerprint(),
+        }
+    }
+}
+
+pub(crate) trait DescriptorMeta: Sized {
+    fn is_witness(&self) -> bool;
+    fn get_hd_keypaths(&self, index: u32) -> Result<HDKeyPaths, Error>;
+    fn is_fixed(&self) -> bool;
+    fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths) -> Option<Self>;
+    fn derive_from_psbt_input(&self, psbt_input: &psbt::Input, utxo: Option<TxOut>)
+        -> Option<Self>;
+}
+
+pub(crate) trait DescriptorScripts {
+    fn psbt_redeem_script(&self) -> Option<Script>;
+    fn psbt_witness_script(&self) -> Option<Script>;
+}
+
+impl<T> DescriptorScripts for Descriptor<T>
+where
+    T: miniscript::MiniscriptKey + miniscript::ToPublicKey,
+{
+    fn psbt_redeem_script(&self) -> Option<Script> {
+        match self {
+            Descriptor::ShWpkh(_) => Some(self.witness_script()),
+            Descriptor::ShWsh(ref script) => Some(script.encode().to_v0_p2wsh()),
+            Descriptor::Sh(ref script) => Some(script.encode()),
+            Descriptor::Bare(ref script) => Some(script.encode()),
+            _ => None,
+        }
+    }
+
+    fn psbt_witness_script(&self) -> Option<Script> {
+        match self {
+            Descriptor::Wsh(ref script) => Some(script.encode()),
+            Descriptor::ShWsh(ref script) => Some(script.encode()),
+            _ => None,
+        }
+    }
+}
+
+impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
+    fn is_witness(&self) -> bool {
+        match self {
+            Descriptor::Bare(_) | Descriptor::Pk(_) | Descriptor::Pkh(_) | Descriptor::Sh(_) => {
+                false
+            }
+            Descriptor::Wpkh(_)
+            | Descriptor::ShWpkh(_)
+            | Descriptor::Wsh(_)
+            | Descriptor::ShWsh(_) => true,
+        }
+    }
+
+    fn get_hd_keypaths(&self, index: u32) -> Result<HDKeyPaths, Error> {
+        let mut answer = BTreeMap::new();
+
+        let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
+            match key {
+                DescriptorPublicKey::PubKey(_) => {}
+                DescriptorPublicKey::XPub(xpub) => {
+                    let derive_path = if xpub.is_wildcard {
+                        xpub.derivation_path
+                            .into_iter()
+                            .chain([ChildNumber::from_normal_idx(index)?].iter())
+                            .cloned()
+                            .collect()
+                    } else {
+                        xpub.derivation_path.clone()
+                    };
+                    let derived_pubkey = xpub
+                        .xkey
+                        .derive_pub(&Secp256k1::verification_only(), &derive_path)?;
+
+                    answer.insert(
+                        derived_pubkey.public_key,
+                        (
+                            xpub.root_fingerprint(),
+                            xpub.full_path(&[ChildNumber::from_normal_idx(index)?]),
+                        ),
+                    );
+                }
+            }
+
+            Ok(DummyKey::default())
+        };
+        let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
+
+        self.translate_pk(translatefpk, translatefpkh)?;
+
+        Ok(answer)
+    }
+
+    fn is_fixed(&self) -> bool {
+        let mut found_wildcard = false;
+
+        let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
+            match key {
+                DescriptorPublicKey::PubKey(_) => {}
+                DescriptorPublicKey::XPub(xpub) => {
+                    if xpub.is_wildcard {
+                        found_wildcard = true;
+                    }
+                }
+            }
+
+            Ok(DummyKey::default())
+        };
+        let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
+
+        self.translate_pk(translatefpk, translatefpkh).unwrap();
+
+        !found_wildcard
+    }
+
+    fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths) -> Option<Self> {
+        let index: HashMap<_, _> = hd_keypaths.values().cloned().collect();
+
+        let mut derive_path = None::<DerivationPath>;
+        let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
+            if derive_path.is_some() {
+                // already found a matching path, we are done
+                return Ok(DummyKey::default());
+            }
+
+            if let DescriptorPublicKey::XPub(xpub) = key {
+                // Check if the key matches one entry in our `index`. If it does, `matches()` will
+                // return the "prefix" that matched, so we remove that prefix from the full path
+                // found in `index` and save it in `derive_path`
+                let root_fingerprint = xpub.root_fingerprint();
+                derive_path = index
+                    .get_key_value(&root_fingerprint)
+                    .and_then(|(fingerprint, path)| xpub.matches(*fingerprint, path))
+                    .map(|prefix_path| prefix_path.into_iter().cloned().collect::<Vec<_>>())
+                    .map(|prefix| {
+                        index
+                            .get(&xpub.root_fingerprint())
+                            .unwrap()
+                            .into_iter()
+                            .skip(prefix.len())
+                            .cloned()
+                            .collect()
+                    });
+            }
+
+            Ok(DummyKey::default())
+        };
+        let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
+
+        self.translate_pk(translatefpk, translatefpkh).unwrap();
+
+        derive_path.map(|path| self.derive(path.as_ref()))
+    }
+
+    fn derive_from_psbt_input(
+        &self,
+        psbt_input: &psbt::Input,
+        utxo: Option<TxOut>,
+    ) -> Option<Self> {
+        if let Some(derived) = self.derive_from_hd_keypaths(&psbt_input.hd_keypaths) {
+            return Some(derived);
+        } else if !self.is_fixed() {
+            // If the descriptor is not fixed we can't brute-force the derivation address, so just
+            // exit here
+            return None;
+        }
+
+        match self {
+            Descriptor::Pk(_)
+            | Descriptor::Pkh(_)
+            | Descriptor::Wpkh(_)
+            | Descriptor::ShWpkh(_)
+                if utxo.is_some()
+                    && self.script_pubkey() == utxo.as_ref().unwrap().script_pubkey =>
+            {
+                Some(self.clone())
+            }
+            Descriptor::Bare(ms) | Descriptor::Sh(ms)
+                if psbt_input.redeem_script.is_some()
+                    && &ms.encode() == psbt_input.redeem_script.as_ref().unwrap() =>
+            {
+                Some(self.clone())
+            }
+            Descriptor::Wsh(ms) | Descriptor::ShWsh(ms)
+                if psbt_input.witness_script.is_some()
+                    && &ms.encode() == psbt_input.witness_script.as_ref().unwrap() =>
+            {
+                Some(self.clone())
+            }
+            _ => None,
+        }
+    }
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, PartialOrd, Eq, Ord, Default)]
+struct DummyKey();
+
+impl fmt::Display for DummyKey {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "DummyKey")
+    }
+}
+
+impl std::str::FromStr for DummyKey {
+    type Err = ();
+
+    fn from_str(_: &str) -> Result<Self, Self::Err> {
+        Ok(DummyKey::default())
+    }
+}
+
+impl miniscript::MiniscriptKey for DummyKey {
+    type Hash = DummyKey;
+
+    fn to_pubkeyhash(&self) -> DummyKey {
+        DummyKey::default()
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::str::FromStr;
+
+    use bitcoin::consensus::encode::deserialize;
+    use bitcoin::hashes::hex::FromHex;
+    use bitcoin::util::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::PartiallySignedTransaction = 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))
+            .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::PartiallySignedTransaction = 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))
+            .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::PartiallySignedTransaction = 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))
+            .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::PartiallySignedTransaction = 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))
+            .is_some());
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/policy.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/policy.rs.html new file mode 100644 index 0000000000..b094837b39 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/policy.rs.html @@ -0,0 +1,1593 @@ +policy.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Descriptor policy
+//!
+//! This module implements the logic to extract and represent the spending policies of a descriptor
+//! in a more human-readable format.
+//!
+//! ## Example
+//!
+//! ```
+//! # use std::sync::Arc;
+//! # use bdk::descriptor::*;
+//! let desc = "wsh(and_v(v:pk(cV3oCth6zxZ1UVsHLnGothsWNsaoxRhC6aeNi5VbSdFpwUkgkEci),or_d(pk(cVMTy7uebJgvFaSBwcgvwk8qn8xSLc97dKow4MBetjrrahZoimm2),older(12960))))";
+//!
+//! let (extended_desc, key_map) = ExtendedDescriptor::parse_secret(desc)?;
+//! println!("{:?}", extended_desc);
+//!
+//! let signers = Arc::new(key_map.into());
+//! let policy = extended_desc.extract_policy(signers)?;
+//! println!("policy: {}", serde_json::to_string(&policy)?);
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use std::cmp::max;
+use std::collections::{BTreeMap, HashSet, VecDeque};
+use std::fmt;
+use std::sync::Arc;
+
+use serde::ser::SerializeMap;
+use serde::{Serialize, Serializer};
+
+use bitcoin::hashes::*;
+use bitcoin::util::bip32::Fingerprint;
+use bitcoin::PublicKey;
+
+use miniscript::descriptor::DescriptorPublicKey;
+use miniscript::{Descriptor, Miniscript, MiniscriptKey, ScriptContext, Terminal};
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use crate::descriptor::ExtractPolicy;
+use crate::wallet::signer::{SignerId, SignersContainer};
+
+use super::checksum::get_checksum;
+use super::error::Error;
+use super::XKeyUtils;
+
+/// Raw public key or extended key fingerprint
+#[derive(Debug, Clone, Default, Serialize)]
+pub struct PKOrF {
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pubkey: Option<PublicKey>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pubkey_hash: Option<hash160::Hash>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    fingerprint: Option<Fingerprint>,
+}
+
+impl PKOrF {
+    fn from_key(k: &DescriptorPublicKey) -> Self {
+        match k {
+            DescriptorPublicKey::PubKey(pubkey) => PKOrF {
+                pubkey: Some(*pubkey),
+                ..Default::default()
+            },
+            DescriptorPublicKey::XPub(xpub) => PKOrF {
+                fingerprint: Some(xpub.root_fingerprint()),
+                ..Default::default()
+            },
+        }
+    }
+
+    fn from_key_hash(k: hash160::Hash) -> Self {
+        PKOrF {
+            pubkey_hash: Some(k),
+            ..Default::default()
+        }
+    }
+}
+
+/// An item that need to be satisfied
+#[derive(Debug, Clone, Serialize)]
+#[serde(tag = "type", rename_all = "UPPERCASE")]
+pub enum SatisfiableItem {
+    // Leaves
+    Signature(PKOrF),
+    SignatureKey(PKOrF),
+    SHA256Preimage {
+        hash: sha256::Hash,
+    },
+    HASH256Preimage {
+        hash: sha256d::Hash,
+    },
+    RIPEMD160Preimage {
+        hash: ripemd160::Hash,
+    },
+    HASH160Preimage {
+        hash: hash160::Hash,
+    },
+    AbsoluteTimelock {
+        value: u32,
+    },
+    RelativeTimelock {
+        value: u32,
+    },
+
+    // Complex item
+    Thresh {
+        items: Vec<Policy>,
+        threshold: usize,
+    },
+    Multisig {
+        keys: Vec<PKOrF>,
+        threshold: usize,
+    },
+}
+
+impl SatisfiableItem {
+    pub fn is_leaf(&self) -> bool {
+        match self {
+            SatisfiableItem::Thresh {
+                items: _,
+                threshold: _,
+            } => false,
+            _ => true,
+        }
+    }
+
+    pub fn id(&self) -> String {
+        get_checksum(&serde_json::to_string(self).expect("Failed to serialize a SatisfiableItem"))
+            .expect("Failed to compute a SatisfiableItem id")
+    }
+}
+
+fn combinations(vec: &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
+}
+
+pub type ConditionMap = BTreeMap<usize, HashSet<Condition>>;
+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, 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
+        items: Vec<usize>,
+        #[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(
+            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 {
+    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) -> Result<(), PolicyError> {
+        // if partial try to bump it to a partialcomplete
+        if let Satisfaction::Partial {
+            n,
+            m,
+            items,
+            conditions,
+        } = 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 ([choosen 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 possibile options and check whether or not they are compatible.
+                    .map(|i_vec| {
+                        mix(i_vec
+                            .iter()
+                            .map(|i| {
+                                conditions
+                                    .get(i)
+                                    .and_then(|set| Some(set.clone().into_iter().collect()))
+                                    .unwrap_or(vec![])
+                            })
+                            .collect())
+                        .into_iter()
+                        .map(|x| (i_vec.clone(), x))
+                        .collect::<Vec<(Vec<usize>, Vec<Condition>)>>()
+                    })
+                    // .inspect(|x: &Vec<(Vec<usize>, Vec<Condition>)>| println!("fetch {:?}", x))
+                    // since the previous step can turn one item of the iterator into multiple ones, we call flatten to expand them out
+                    .flatten()
+                    // .inspect(|x| println!("flat {:?}", x))
+                    // try to fold all the conditions for this specific combination of indexes/options. if they are not compatibile, 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,
+                };
+            }
+        }
+
+        Ok(())
+    }
+}
+
+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, Serialize)]
+pub struct Policy {
+    /// Identifier for this policy node
+    pub id: String,
+
+    /// Type of this policy node
+    #[serde(flatten)]
+    pub item: SatisfiableItem,
+    /// How a much given PSBT already satisfies this polcy node **(currently unused)**
+    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
+#[derive(Hash, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default, Serialize)]
+pub struct Condition {
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub csv: Option<u32>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub timelock: Option<u32>,
+}
+
+impl Condition {
+    fn merge_timelock(a: u32, b: u32) -> Result<u32, PolicyError> {
+        const BLOCKS_TIMELOCK_THRESHOLD: u32 = 500000000;
+
+        if (a < BLOCKS_TIMELOCK_THRESHOLD) != (b < BLOCKS_TIMELOCK_THRESHOLD) {
+            Err(PolicyError::MixedTimelockUnits)
+        } else {
+            Ok(max(a, b))
+        }
+    }
+
+    fn merge(mut self, other: &Condition) -> Result<Self, PolicyError> {
+        match (self.csv, other.csv) {
+            (Some(a), Some(b)) => self.csv = Some(Self::merge_timelock(a, b)?),
+            (None, any) => self.csv = any,
+            _ => {}
+        }
+
+        match (self.timelock, other.timelock) {
+            (Some(a), Some(b)) => self.timelock = Some(Self::merge_timelock(a, b)?),
+            (None, any) => self.timelock = any,
+            _ => {}
+        }
+
+        Ok(self)
+    }
+
+    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)]
+pub enum PolicyError {
+    NotEnoughItemsSelected(String),
+    TooManyItemsSelected(String),
+    IndexOutOfRange(usize),
+    AddOnLeaf,
+    AddOnPartialComplete,
+    MixedTimelockUnits,
+    IncompatibleConditions,
+}
+
+impl fmt::Display for PolicyError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for PolicyError {}
+
+impl Policy {
+    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(),
+        };
+        for (index, item) in items.iter().enumerate() {
+            contribution.add(&item.contribution, index)?;
+        }
+        contribution.finalize()?;
+
+        let mut policy: Policy = SatisfiableItem::Thresh { items, threshold }.into();
+        policy.contribution = contribution;
+
+        Ok(Some(policy))
+    }
+
+    fn make_multisig(
+        keys: &Vec<DescriptorPublicKey>,
+        signers: Arc<SignersContainer<DescriptorPublicKey>>,
+        threshold: usize,
+    ) -> Result<Option<Policy>, PolicyError> {
+        if threshold == 0 {
+            return Ok(None);
+        }
+
+        let parsed_keys = keys.iter().map(|k| PKOrF::from_key(k)).collect();
+
+        let mut contribution = Satisfaction::Partial {
+            n: keys.len(),
+            m: threshold,
+            items: vec![],
+            conditions: Default::default(),
+        };
+        for (index, key) in keys.iter().enumerate() {
+            if let Some(_) = signers.find(signer_id(key)) {
+                contribution.add(
+                    &Satisfaction::Complete {
+                        condition: Default::default(),
+                    },
+                    index,
+                )?;
+            }
+        }
+        contribution.finalize()?;
+
+        let mut policy: Policy = SatisfiableItem::Multisig {
+            keys: parsed_keys,
+            threshold,
+        }
+        .into();
+        policy.contribution = contribution;
+
+        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).into_iter().collect()
+            }
+            _ => vec![],
+        };
+        let selected = match path.get(&self.id) {
+            _ if !default.is_empty() => &default,
+            Some(arr) => arr,
+            _ => &default,
+        };
+
+        match &self.item {
+            SatisfiableItem::Thresh { items, threshold } => {
+                let mapped_req = items
+                    .iter()
+                    .map(|i| i.get_condition(path))
+                    .collect::<Result<Vec<_>, _>>()?;
+
+                // if all the requirements are null we don't care about `selected` because there
+                // are no requirements
+                if mapped_req.iter().all(Condition::is_null) {
+                    return Ok(Condition::default());
+                }
+
+                // 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()));
+                } else if selected.len() > *threshold {
+                    return Err(PolicyError::TooManyItemsSelected(self.id.clone()));
+                }
+
+                // check the selected items, see if there are conflicting requirements
+                let mut requirements = Condition::default();
+                for item_index in selected {
+                    requirements = requirements.merge(
+                        mapped_req
+                            .get(*item_index)
+                            .ok_or(PolicyError::IndexOutOfRange(*item_index))?,
+                    )?;
+                }
+
+                Ok(requirements)
+            }
+            _ if !selected.is_empty() => Err(PolicyError::TooManyItemsSelected(self.id.clone())),
+            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) -> SignerId<DescriptorPublicKey> {
+    match key {
+        DescriptorPublicKey::PubKey(pubkey) => pubkey.to_pubkeyhash().into(),
+        DescriptorPublicKey::XPub(xpub) => xpub.root_fingerprint().into(),
+    }
+}
+
+fn signature(
+    key: &DescriptorPublicKey,
+    signers: Arc<SignersContainer<DescriptorPublicKey>>,
+) -> Policy {
+    let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key(key)).into();
+
+    policy.contribution = if signers.find(signer_id(key)).is_some() {
+        Satisfaction::Complete {
+            condition: Default::default(),
+        }
+    } else {
+        Satisfaction::None
+    };
+
+    policy
+}
+
+fn signature_key(
+    key_hash: &<DescriptorPublicKey as MiniscriptKey>::Hash,
+    signers: Arc<SignersContainer<DescriptorPublicKey>>,
+) -> Policy {
+    let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key_hash(*key_hash)).into();
+
+    if let Some(_) = signers.find(SignerId::PkHash(*key_hash)) {
+        policy.contribution = Satisfaction::Complete {
+            condition: Default::default(),
+        }
+    }
+
+    policy
+}
+
+impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx> {
+    fn extract_policy(
+        &self,
+        signers: Arc<SignersContainer<DescriptorPublicKey>>,
+    ) -> Result<Option<Policy>, Error> {
+        Ok(match &self.node {
+            // Leaves
+            Terminal::True | Terminal::False => None,
+            Terminal::PkK(pubkey) => Some(signature(pubkey, Arc::clone(&signers))),
+            Terminal::PkH(pubkey_hash) => Some(signature_key(pubkey_hash, Arc::clone(&signers))),
+            Terminal::After(value) => {
+                let mut policy: Policy = SatisfiableItem::AbsoluteTimelock { value: *value }.into();
+                policy.contribution = Satisfaction::Complete {
+                    condition: Condition {
+                        timelock: Some(*value),
+                        csv: None,
+                    },
+                };
+
+                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),
+                    },
+                };
+
+                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) => Policy::make_multisig(pks, Arc::clone(&signers), *k)?,
+            // 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(Arc::clone(&signers))?,
+            // Complex policies
+            Terminal::AndV(a, b) | Terminal::AndB(a, b) => Policy::make_and(
+                a.extract_policy(Arc::clone(&signers))?,
+                b.extract_policy(Arc::clone(&signers))?,
+            )?,
+            Terminal::AndOr(x, y, z) => Policy::make_or(
+                Policy::make_and(
+                    x.extract_policy(Arc::clone(&signers))?,
+                    y.extract_policy(Arc::clone(&signers))?,
+                )?,
+                z.extract_policy(Arc::clone(&signers))?,
+            )?,
+            Terminal::OrB(a, b)
+            | Terminal::OrD(a, b)
+            | Terminal::OrC(a, b)
+            | Terminal::OrI(a, b) => Policy::make_or(
+                a.extract_policy(Arc::clone(&signers))?,
+                b.extract_policy(Arc::clone(&signers))?,
+            )?,
+            Terminal::Thresh(k, nodes) => {
+                let mut threshold = *k;
+                let mapped: Vec<_> = nodes
+                    .iter()
+                    .map(|n| n.extract_policy(Arc::clone(&signers)))
+                    .collect::<Result<Vec<_>, _>>()?
+                    .into_iter()
+                    .filter_map(|x| x)
+                    .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)?
+            }
+        })
+    }
+}
+
+impl ExtractPolicy for Descriptor<DescriptorPublicKey> {
+    fn extract_policy(
+        &self,
+        signers: Arc<SignersContainer<DescriptorPublicKey>>,
+    ) -> Result<Option<Policy>, Error> {
+        match self {
+            Descriptor::Pk(pubkey)
+            | Descriptor::Pkh(pubkey)
+            | Descriptor::Wpkh(pubkey)
+            | Descriptor::ShWpkh(pubkey) => Ok(Some(signature(pubkey, signers))),
+            Descriptor::Bare(inner) | Descriptor::Sh(inner) => Ok(inner.extract_policy(signers)?),
+            Descriptor::Wsh(inner) | Descriptor::ShWsh(inner) => Ok(inner.extract_policy(signers)?),
+        }
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/error.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/error.rs.html new file mode 100644 index 0000000000..930ba161c0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/error.rs.html @@ -0,0 +1,283 @@ +error.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::fmt;
+
+use bitcoin::{Address, OutPoint};
+
+/// Errors that can be thrown by the [`Wallet`](crate::wallet::Wallet)
+#[derive(Debug)]
+pub enum Error {
+    KeyMismatch(bitcoin::secp256k1::PublicKey, bitcoin::secp256k1::PublicKey),
+    MissingInputUTXO(usize),
+    InvalidU32Bytes(Vec<u8>),
+    Generic(String),
+    ScriptDoesntHaveAddressForm,
+    SendAllMultipleOutputs,
+    NoAddressees,
+    OutputBelowDustLimit(usize),
+    InsufficientFunds,
+    InvalidAddressNetwork(Address),
+    UnknownUTXO,
+    DifferentTransactions,
+    TransactionNotFound,
+    TransactionConfirmed,
+    IrreplaceableTransaction,
+    FeeRateTooLow {
+        required: crate::types::FeeRate,
+    },
+
+    ChecksumMismatch,
+    DifferentDescriptorStructure,
+
+    SpendingPolicyRequired,
+    InvalidPolicyPathError(crate::descriptor::policy::PolicyError),
+
+    Signer(crate::wallet::signer::SignerError),
+
+    // Blockchain interface errors
+    Uncapable(crate::blockchain::Capability),
+    OfflineClient,
+    InvalidProgressValue(f32),
+    ProgressUpdateError,
+    MissingCachedAddresses,
+    InvalidOutpoint(OutPoint),
+
+    Descriptor(crate::descriptor::error::Error),
+    AddressValidator(crate::wallet::address_validator::AddressValidatorError),
+
+    Encode(bitcoin::consensus::encode::Error),
+    Miniscript(miniscript::Error),
+    BIP32(bitcoin::util::bip32::Error),
+    Secp256k1(bitcoin::secp256k1::Error),
+    JSON(serde_json::Error),
+    Hex(bitcoin::hashes::hex::Error),
+    PSBT(bitcoin::util::psbt::Error),
+
+    #[cfg(feature = "electrum")]
+    Electrum(electrum_client::Error),
+    #[cfg(feature = "esplora")]
+    Esplora(crate::blockchain::esplora::EsploraError),
+    #[cfg(feature = "compact_filters")]
+    CompactFilters(crate::blockchain::compact_filters::CompactFiltersError),
+    #[cfg(feature = "key-value-db")]
+    Sled(sled::Error),
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for Error {}
+
+macro_rules! impl_error {
+    ( $from:ty, $to:ident ) => {
+        impl std::convert::From<$from> for Error {
+            fn from(err: $from) -> Self {
+                Error::$to(err)
+            }
+        }
+    };
+}
+
+impl_error!(crate::descriptor::error::Error, Descriptor);
+impl_error!(
+    crate::wallet::address_validator::AddressValidatorError,
+    AddressValidator
+);
+impl_error!(
+    crate::descriptor::policy::PolicyError,
+    InvalidPolicyPathError
+);
+impl_error!(crate::wallet::signer::SignerError, Signer);
+
+impl_error!(bitcoin::consensus::encode::Error, Encode);
+impl_error!(miniscript::Error, Miniscript);
+impl_error!(bitcoin::util::bip32::Error, BIP32);
+impl_error!(bitcoin::secp256k1::Error, Secp256k1);
+impl_error!(serde_json::Error, JSON);
+impl_error!(bitcoin::hashes::hex::Error, Hex);
+impl_error!(bitcoin::util::psbt::Error, PSBT);
+
+#[cfg(feature = "electrum")]
+impl_error!(electrum_client::Error, Electrum);
+#[cfg(feature = "esplora")]
+impl_error!(crate::blockchain::esplora::EsploraError, Esplora);
+#[cfg(feature = "key-value-db")]
+impl_error!(sled::Error, Sled);
+
+#[cfg(feature = "compact_filters")]
+impl From<crate::blockchain::compact_filters::CompactFiltersError> for Error {
+    fn from(other: crate::blockchain::compact_filters::CompactFiltersError) -> Self {
+        match other {
+            crate::blockchain::compact_filters::CompactFiltersError::Global(e) => *e,
+            err @ _ => Error::CompactFilters(err),
+        }
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/lib.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/lib.rs.html new file mode 100644 index 0000000000..01356c108c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/lib.rs.html @@ -0,0 +1,179 @@ +lib.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+// only enables the `doc_cfg` feature when
+// the `docsrs` configuration attribute is defined
+#![cfg_attr(docsrs, feature(doc_cfg))]
+// only enables the nightly `external_doc` feature when
+// `test-md-docs` is enabled
+#![cfg_attr(feature = "test-md-docs", feature(external_doc))]
+
+pub extern crate bitcoin;
+extern crate log;
+pub extern crate miniscript;
+extern crate serde;
+#[macro_use]
+extern crate serde_json;
+
+#[cfg(any(target_arch = "wasm32", feature = "async-interface"))]
+#[macro_use]
+extern crate async_trait;
+#[macro_use]
+extern crate bdk_macros;
+
+#[cfg(any(test, feature = "compact_filters"))]
+#[macro_use]
+extern crate lazy_static;
+
+#[cfg(feature = "electrum")]
+pub extern crate electrum_client;
+
+#[cfg(feature = "esplora")]
+pub extern crate reqwest;
+
+#[cfg(feature = "key-value-db")]
+pub extern crate sled;
+
+#[cfg(feature = "cli-utils")]
+pub mod cli;
+
+#[cfg(test)]
+#[macro_use]
+extern crate testutils;
+#[cfg(test)]
+#[macro_use]
+extern crate testutils_macros;
+#[cfg(test)]
+#[macro_use]
+extern crate serial_test;
+
+#[macro_use]
+pub(crate) mod error;
+pub mod blockchain;
+pub mod database;
+pub mod descriptor;
+#[cfg(feature = "test-md-docs")]
+mod doctest;
+pub(crate) mod psbt;
+pub(crate) mod types;
+pub mod wallet;
+
+pub use descriptor::HDKeyPaths;
+pub use error::Error;
+pub use types::*;
+pub use wallet::address_validator;
+pub use wallet::signer;
+pub use wallet::tx_builder::TxBuilder;
+pub use wallet::{OfflineWallet, Wallet};
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/psbt/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/psbt/mod.rs.html new file mode 100644 index 0000000000..cd35634064 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/psbt/mod.rs.html @@ -0,0 +1,107 @@ +mod.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
+use bitcoin::TxOut;
+
+pub trait PSBTUtils {
+    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut>;
+}
+
+impl PSBTUtils for PSBT {
+    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut> {
+        let tx = &self.global.unsigned_tx;
+
+        if input_index >= tx.input.len() {
+            return None;
+        }
+
+        if let Some(input) = self.inputs.get(input_index) {
+            if let Some(wit_utxo) = &input.witness_utxo {
+                Some(wit_utxo.clone())
+            } else if let Some(in_tx) = &input.non_witness_utxo {
+                Some(in_tx.output[tx.input[input_index].previous_output.vout as usize].clone())
+            } else {
+                None
+            }
+        } else {
+            None
+        }
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/types.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/types.rs.html new file mode 100644 index 0000000000..8fe99a773d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/types.rs.html @@ -0,0 +1,227 @@ +types.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::convert::AsRef;
+
+use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxOut};
+use bitcoin::hash_types::Txid;
+
+use serde::{Deserialize, Serialize};
+
+/// Types of script
+#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum ScriptType {
+    External = 0,
+    Internal = 1,
+}
+
+impl ScriptType {
+    pub fn as_byte(&self) -> u8 {
+        match self {
+            ScriptType::External => 'e' as u8,
+            ScriptType::Internal => 'i' as u8,
+        }
+    }
+
+    pub fn is_internal(&self) -> bool {
+        self == &ScriptType::Internal
+    }
+}
+
+impl AsRef<[u8]> for ScriptType {
+    fn as_ref(&self) -> &[u8] {
+        match self {
+            ScriptType::External => b"e",
+            ScriptType::Internal => b"i",
+        }
+    }
+}
+
+/// Fee rate
+#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
+// Internally stored as satoshi/vbyte
+pub struct FeeRate(f32);
+
+impl FeeRate {
+    /// Create a new instance of [`FeeRate`] given a float fee rate in btc/kvbytes
+    pub fn from_btc_per_kvb(btc_per_kvb: f32) -> Self {
+        FeeRate(btc_per_kvb * 1e5)
+    }
+
+    /// Create a new instance of [`FeeRate`] given a float fee rate in satoshi/vbyte
+    pub fn from_sat_per_vb(sat_per_vb: f32) -> Self {
+        FeeRate(sat_per_vb)
+    }
+
+    /// Create a new [`FeeRate`] with the default min relay fee value
+    pub fn default_min_relay_fee() -> Self {
+        FeeRate(1.0)
+    }
+
+    /// Return the value as satoshi/vbyte
+    pub fn as_sat_vb(&self) -> f32 {
+        self.0
+    }
+}
+
+impl std::default::Default for FeeRate {
+    fn default() -> Self {
+        FeeRate::default_min_relay_fee()
+    }
+}
+
+/// A wallet unspent output
+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
+pub struct UTXO {
+    pub outpoint: OutPoint,
+    pub txout: TxOut,
+    pub is_internal: bool,
+}
+
+/// A wallet transaction
+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
+pub struct TransactionDetails {
+    pub transaction: Option<Transaction>,
+    pub txid: Txid,
+    pub timestamp: u64,
+    pub received: u64,
+    pub sent: u64,
+    pub fees: u64,
+    pub height: Option<u32>,
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/address_validator.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/address_validator.rs.html new file mode 100644 index 0000000000..c674ae642a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/address_validator.rs.html @@ -0,0 +1,327 @@ +address_validator.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Address validation callbacks
+//!
+//! The typical usage of those callbacks is for displaying the newly-generated address on a
+//! hardware wallet, so that the user can cross-check its correctness.
+//!
+//! More generally speaking though, these callbacks can also be used to "do something" every time
+//! an address is generated, without necessarily checking or validating it.
+//!
+//! An address validator can be attached to a [`Wallet`](super::Wallet) by using the
+//! [`Wallet::add_address_validator`](super::Wallet::add_address_validator) method, and
+//! whenever a new address is generated (either explicitly by the user with
+//! [`Wallet::get_new_address`](super::Wallet::get_new_address) or internally to create a change
+//! address) all the attached validators will be polled, in sequence. All of them must complete
+//! successfully to continue.
+//!
+//! ## Example
+//!
+//! ```
+//! # use std::sync::Arc;
+//! # use bitcoin::*;
+//! # use bdk::address_validator::*;
+//! # use bdk::database::*;
+//! # use bdk::*;
+//! struct PrintAddressAndContinue;
+//!
+//! impl AddressValidator for PrintAddressAndContinue {
+//!     fn validate(
+//!         &self,
+//!         script_type: ScriptType,
+//!         hd_keypaths: &HDKeyPaths,
+//!         script: &Script
+//!     ) -> Result<(), AddressValidatorError> {
+//!         let address = Address::from_script(script, Network::Testnet)
+//!             .as_ref()
+//!             .map(Address::to_string)
+//!             .unwrap_or(script.to_string());
+//!         println!("New address of type {:?}: {}", script_type, address);
+//!         println!("HD keypaths: {:#?}", hd_keypaths);
+//!
+//!         Ok(())
+//!     }
+//! }
+//!
+//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+//! let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+//! wallet.add_address_validator(Arc::new(Box::new(PrintAddressAndContinue)));
+//!
+//! let address = wallet.get_new_address()?;
+//! println!("Address: {}", address);
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use std::fmt;
+
+use bitcoin::Script;
+
+use crate::descriptor::HDKeyPaths;
+use crate::types::ScriptType;
+
+/// Errors that can be returned to fail the validation of an address
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum AddressValidatorError {
+    UserRejected,
+    ConnectionError,
+    TimeoutError,
+    InvalidScript,
+    Message(String),
+}
+
+impl fmt::Display for AddressValidatorError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for AddressValidatorError {}
+
+/// Trait to build address validators
+///
+/// All the address validators attached to a wallet with [`Wallet::add_address_validator`](super::Wallet::add_address_validator) will be polled
+/// every time an address (external or internal) is generated by the wallet. Errors returned in the
+/// validator will be propagated up to the original caller that triggered the address generation.
+///
+/// For a usage example see [this module](crate::address_validator)'s documentation.
+pub trait AddressValidator {
+    /// Validate or inspect an address
+    fn validate(
+        &self,
+        script_type: ScriptType,
+        hd_keypaths: &HDKeyPaths,
+        script: &Script,
+    ) -> Result<(), AddressValidatorError>;
+}
+
+#[cfg(test)]
+mod test {
+    use std::sync::Arc;
+
+    use super::*;
+    use crate::wallet::test::{get_funded_wallet, get_test_wpkh};
+    use crate::wallet::TxBuilder;
+
+    struct TestValidator;
+    impl AddressValidator for TestValidator {
+        fn validate(
+            &self,
+            _script_type: ScriptType,
+            _hd_keypaths: &HDKeyPaths,
+            _script: &bitcoin::Script,
+        ) -> Result<(), AddressValidatorError> {
+            Err(AddressValidatorError::InvalidScript)
+        }
+    }
+
+    #[test]
+    #[should_panic(expected = "InvalidScript")]
+    fn test_address_validator_external() {
+        let (mut wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        wallet.add_address_validator(Arc::new(Box::new(TestValidator)));
+
+        wallet.get_new_address().unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "InvalidScript")]
+    fn test_address_validator_internal() {
+        let (mut wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        wallet.add_address_validator(Arc::new(Box::new(TestValidator)));
+
+        let addr = testutils!(@external descriptors, 10);
+        wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/coin_selection.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/coin_selection.rs.html new file mode 100644 index 0000000000..f795967e71 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/coin_selection.rs.html @@ -0,0 +1,701 @@ +coin_selection.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Coin selection
+//!
+//! This module provides the trait [`CoinSelectionAlgorithm`] that can be implemented to
+//! define custom coin selection algorithms.
+//!
+//! The coin selection algorithm is not globally part of a [`Wallet`](super::Wallet), instead it
+//! is selected whenever a [`Wallet::create_tx`](super::Wallet::create_tx) call is made, through
+//! the use of the [`TxBuilder`] structure, specifically with
+//! [`TxBuilder::coin_selection`](super::tx_builder::TxBuilder::coin_selection) method.
+//!
+//! The [`DefaultCoinSelectionAlgorithm`] selects the default coin selection algorithm that
+//! [`TxBuilder`] uses, if it's not explicitly overridden.
+//!
+//! [`TxBuilder`]: super::tx_builder::TxBuilder
+//!
+//! ## Example
+//!
+//! ```no_run
+//! # use std::str::FromStr;
+//! # use bitcoin::*;
+//! # use bitcoin::consensus::serialize;
+//! # use bdk::wallet::coin_selection::*;
+//! # use bdk::*;
+//! #[derive(Debug)]
+//! struct AlwaysSpendEverything;
+//!
+//! impl CoinSelectionAlgorithm for AlwaysSpendEverything {
+//!     fn coin_select(
+//!         &self,
+//!         utxos: Vec<UTXO>,
+//!         _use_all_utxos: bool,
+//!         fee_rate: FeeRate,
+//!         amount_needed: u64,
+//!         input_witness_weight: usize,
+//!         fee_amount: f32,
+//!     ) -> Result<CoinSelectionResult, bdk::Error> {
+//!         let selected_amount = utxos.iter().fold(0, |acc, utxo| acc + utxo.txout.value);
+//!         let all_utxos_selected = utxos
+//!             .into_iter()
+//!             .map(|utxo| {
+//!                 (
+//!                     TxIn {
+//!                         previous_output: utxo.outpoint,
+//!                         ..Default::default()
+//!                     },
+//!                     utxo.txout.script_pubkey,
+//!                 )
+//!             })
+//!             .collect::<Vec<_>>();
+//!         let additional_weight = all_utxos_selected.iter().fold(0, |acc, (txin, _)| {
+//!             acc + serialize(txin).len() * 4 + input_witness_weight
+//!         });
+//!         let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0;
+//!
+//!         if (fee_amount + additional_fees).ceil() as u64 + amount_needed > selected_amount {
+//!             return Err(bdk::Error::InsufficientFunds);
+//!         }
+//!
+//!         Ok(CoinSelectionResult {
+//!             txin: all_utxos_selected,
+//!             selected_amount,
+//!             fee_amount: fee_amount + additional_fees,
+//!         })
+//!     }
+//! }
+//!
+//! # let wallet: OfflineWallet<_> = Wallet::new_offline("", None, Network::Testnet, bdk::database::MemoryDatabase::default())?;
+//! // create wallet, sync, ...
+//!
+//! let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+//! let (psbt, details) = wallet.create_tx(
+//!     TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+//!         .coin_selection(AlwaysSpendEverything),
+//! )?;
+//!
+//! // inspect, sign, broadcast, ...
+//!
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use bitcoin::consensus::encode::serialize;
+use bitcoin::{Script, TxIn};
+
+use crate::error::Error;
+use crate::types::{FeeRate, UTXO};
+
+/// Default coin selection algorithm used by [`TxBuilder`](super::tx_builder::TxBuilder) if not
+/// overridden
+pub type DefaultCoinSelectionAlgorithm = DumbCoinSelection;
+
+/// Result of a successful coin selection
+#[derive(Debug)]
+pub struct CoinSelectionResult {
+    /// List of inputs to use, with the respective previous script_pubkey
+    pub txin: Vec<(TxIn, Script)>,
+    /// Sum of the selected inputs' value
+    pub selected_amount: u64,
+    /// Total fee amount in satoshi
+    pub fee_amount: f32,
+}
+
+/// 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: std::fmt::Debug {
+    /// Perform the coin selection
+    ///
+    /// - `utxos`: the list of spendable UTXOs
+    /// - `use_all_utxos`: if true all utxos should be spent unconditionally
+    /// - `fee_rate`: fee rate to use
+    /// - `amount_needed`: the amount in satoshi to select
+    /// - `input_witness_weight`: the weight of an input's witness to keep into account for the fees
+    /// - `fee_amount`: the amount of fees in satoshi already accumulated from adding outputs
+    fn coin_select(
+        &self,
+        utxos: Vec<UTXO>,
+        use_all_utxos: bool,
+        fee_rate: FeeRate,
+        amount_needed: u64,
+        input_witness_weight: usize,
+        fee_amount: f32,
+    ) -> 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)]
+pub struct DumbCoinSelection;
+
+impl CoinSelectionAlgorithm for DumbCoinSelection {
+    fn coin_select(
+        &self,
+        mut utxos: Vec<UTXO>,
+        use_all_utxos: bool,
+        fee_rate: FeeRate,
+        outgoing_amount: u64,
+        input_witness_weight: usize,
+        mut fee_amount: f32,
+    ) -> Result<CoinSelectionResult, Error> {
+        let mut txin = Vec::new();
+        let calc_fee_bytes = |wu| (wu as f32) * fee_rate.as_sat_vb() / 4.0;
+
+        log::debug!(
+            "outgoing_amount = `{}`, fee_amount = `{}`, fee_rate = `{:?}`",
+            outgoing_amount,
+            fee_amount,
+            fee_rate
+        );
+
+        // sort so that we pick them starting from the larger.
+        utxos.sort_by(|a, b| a.txout.value.partial_cmp(&b.txout.value).unwrap());
+
+        let mut selected_amount: u64 = 0;
+        while use_all_utxos || selected_amount < outgoing_amount + (fee_amount.ceil() as u64) {
+            let utxo = match utxos.pop() {
+                Some(utxo) => utxo,
+                None if selected_amount < outgoing_amount + (fee_amount.ceil() as u64) => {
+                    return Err(Error::InsufficientFunds)
+                }
+                None if use_all_utxos => break,
+                None => return Err(Error::InsufficientFunds),
+            };
+
+            let new_in = TxIn {
+                previous_output: utxo.outpoint,
+                script_sig: Script::default(),
+                sequence: 0, // Let the caller choose the right nSequence
+                witness: vec![],
+            };
+            fee_amount += calc_fee_bytes(serialize(&new_in).len() * 4 + input_witness_weight);
+            log::debug!(
+                "Selected {}, updated fee_amount = `{}`",
+                new_in.previous_output,
+                fee_amount
+            );
+
+            txin.push((new_in, utxo.txout.script_pubkey));
+            selected_amount += utxo.txout.value;
+        }
+
+        Ok(CoinSelectionResult {
+            txin,
+            fee_amount,
+            selected_amount,
+        })
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::str::FromStr;
+
+    use bitcoin::{OutPoint, Script, TxOut};
+
+    use super::*;
+    use crate::types::*;
+
+    const P2WPKH_WITNESS_SIZE: usize = 73 + 33 + 2;
+
+    fn get_test_utxos() -> Vec<UTXO> {
+        vec![
+            UTXO {
+                outpoint: OutPoint::from_str(
+                    "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:0",
+                )
+                .unwrap(),
+                txout: TxOut {
+                    value: 100_000,
+                    script_pubkey: Script::new(),
+                },
+                is_internal: false,
+            },
+            UTXO {
+                outpoint: OutPoint::from_str(
+                    "65d92ddff6b6dc72c89624a6491997714b90f6004f928d875bc0fd53f264fa85:0",
+                )
+                .unwrap(),
+                txout: TxOut {
+                    value: 200_000,
+                    script_pubkey: Script::new(),
+                },
+                is_internal: true,
+            },
+        ]
+    }
+
+    #[test]
+    fn test_dumb_coin_selection_success() {
+        let utxos = get_test_utxos();
+
+        let result = DumbCoinSelection
+            .coin_select(
+                utxos,
+                false,
+                FeeRate::from_sat_per_vb(1.0),
+                250_000,
+                P2WPKH_WITNESS_SIZE,
+                50.0,
+            )
+            .unwrap();
+
+        assert_eq!(result.txin.len(), 2);
+        assert_eq!(result.selected_amount, 300_000);
+        assert_eq!(result.fee_amount, 186.0);
+    }
+
+    #[test]
+    fn test_dumb_coin_selection_use_all() {
+        let utxos = get_test_utxos();
+
+        let result = DumbCoinSelection
+            .coin_select(
+                utxos,
+                true,
+                FeeRate::from_sat_per_vb(1.0),
+                20_000,
+                P2WPKH_WITNESS_SIZE,
+                50.0,
+            )
+            .unwrap();
+
+        assert_eq!(result.txin.len(), 2);
+        assert_eq!(result.selected_amount, 300_000);
+        assert_eq!(result.fee_amount, 186.0);
+    }
+
+    #[test]
+    fn test_dumb_coin_selection_use_only_necessary() {
+        let utxos = get_test_utxos();
+
+        let result = DumbCoinSelection
+            .coin_select(
+                utxos,
+                false,
+                FeeRate::from_sat_per_vb(1.0),
+                20_000,
+                P2WPKH_WITNESS_SIZE,
+                50.0,
+            )
+            .unwrap();
+
+        assert_eq!(result.txin.len(), 1);
+        assert_eq!(result.selected_amount, 200_000);
+        assert_eq!(result.fee_amount, 118.0);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_dumb_coin_selection_insufficient_funds() {
+        let utxos = get_test_utxos();
+
+        DumbCoinSelection
+            .coin_select(
+                utxos,
+                false,
+                FeeRate::from_sat_per_vb(1.0),
+                500_000,
+                P2WPKH_WITNESS_SIZE,
+                50.0,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_dumb_coin_selection_insufficient_funds_high_fees() {
+        let utxos = get_test_utxos();
+
+        DumbCoinSelection
+            .coin_select(
+                utxos,
+                false,
+                FeeRate::from_sat_per_vb(1000.0),
+                250_000,
+                P2WPKH_WITNESS_SIZE,
+                50.0,
+            )
+            .unwrap();
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/export.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/export.rs.html new file mode 100644 index 0000000000..eae5ac9953 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/export.rs.html @@ -0,0 +1,683 @@ +export.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! 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::database::*;
+//! # use bdk::wallet::export::*;
+//! # use bdk::*;
+//! let import = r#"{
+//!     "descriptor": "wpkh([c258d2e4\/84h\/1h\/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe\/0\/*)",
+//!     "blockheight":1782088,
+//!     "label":"testnet"
+//! }"#;
+//!
+//! let import = WalletExport::from_str(import)?;
+//! let wallet: OfflineWallet<_> = Wallet::new_offline(&import.descriptor(), import.change_descriptor().as_deref(), Network::Testnet, MemoryDatabase::default())?;
+//! # Ok::<_, bdk::Error>(())
+//! ```
+//!
+//! ### Export a `Wallet`
+//! ```
+//! # use bitcoin::*;
+//! # use bdk::database::*;
+//! # use bdk::wallet::export::*;
+//! # use bdk::*;
+//! let wallet: OfflineWallet<_> = Wallet::new_offline(
+//!     "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
+//!     Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
+//!     Network::Testnet,
+//!     MemoryDatabase::default()
+//! )?;
+//! let export = WalletExport::export_wallet(&wallet, "exported wallet", true)
+//!     .map_err(ToString::to_string)
+//!     .map_err(bdk::Error::Generic)?;
+//!
+//! println!("Exported: {}", export.to_string());
+//! # Ok::<_, bdk::Error>(())
+//! ```
+
+use std::str::FromStr;
+
+use serde::{Deserialize, Serialize};
+
+use miniscript::{Descriptor, ScriptContext, Terminal};
+
+use crate::blockchain::BlockchainMarker;
+use crate::database::BatchDatabase;
+use crate::wallet::Wallet;
+
+/// 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 WalletExport {
+    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 ToString for WalletExport {
+    fn to_string(&self) -> String {
+        serde_json::to_string(self).unwrap()
+    }
+}
+
+impl FromStr for WalletExport {
+    type Err = serde_json::Error;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        serde_json::from_str(s)
+    }
+}
+
+impl WalletExport {
+    /// 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<B: BlockchainMarker, D: BatchDatabase>(
+        wallet: &Wallet<B, D>,
+        label: &str,
+        include_blockheight: bool,
+    ) -> Result<Self, &'static str> {
+        let descriptor = wallet
+            .descriptor
+            .to_string_with_secret(&wallet.signers.as_key_map());
+        Self::is_compatible_with_core(&descriptor)?;
+
+        let blockheight = match wallet.database.borrow().iter_txs(false) {
+            _ if !include_blockheight => 0,
+            Err(_) => 0,
+            Ok(txs) => {
+                let mut heights = txs
+                    .into_iter()
+                    .map(|tx| tx.height.unwrap_or(0))
+                    .collect::<Vec<_>>();
+                heights.sort();
+
+                *heights.last().unwrap_or(&0)
+            }
+        };
+
+        let export = WalletExport {
+            descriptor,
+            label: label.into(),
+            blockheight,
+        };
+
+        if export.change_descriptor()
+            != wallet
+                .change_descriptor
+                .as_ref()
+                .map(|d| d.to_string_with_secret(&wallet.change_signers.as_key_map()))
+        {
+            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")
+            }
+        }
+
+        match Descriptor::<String>::from_str(descriptor).map_err(|_| "Invalid descriptor")? {
+            Descriptor::Pk(_)
+            | Descriptor::Pkh(_)
+            | Descriptor::Wpkh(_)
+            | Descriptor::ShWpkh(_) => Ok(()),
+            Descriptor::Sh(ms) => check_ms(ms.node),
+            Descriptor::Wsh(ms) | Descriptor::ShWsh(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 std::str::FromStr;
+
+    use bitcoin::{Network, Txid};
+
+    use super::*;
+    use crate::database::{memory::MemoryDatabase, BatchOperations};
+    use crate::types::TransactionDetails;
+    use crate::wallet::{OfflineWallet, Wallet};
+
+    fn get_test_db() -> MemoryDatabase {
+        let mut db = MemoryDatabase::new();
+        db.set_tx(&TransactionDetails {
+            transaction: None,
+            txid: Txid::from_str(
+                "4ddff1fa33af17f377f62b72357b43107c19110a8009b36fb832af505efed98a",
+            )
+            .unwrap(),
+            timestamp: 12345678,
+            received: 100_000,
+            sent: 0,
+            fees: 500,
+            height: Some(5000),
+        })
+        .unwrap();
+
+        db
+    }
+
+    #[test]
+    fn test_export_bip44() {
+        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
+        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
+
+        let wallet: OfflineWallet<_> = Wallet::new_offline(
+            descriptor,
+            Some(change_descriptor),
+            Network::Testnet,
+            get_test_db(),
+        )
+        .unwrap();
+        let export = WalletExport::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: OfflineWallet<_> =
+            Wallet::new_offline(descriptor, None, Network::Testnet, get_test_db()).unwrap();
+        WalletExport::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: OfflineWallet<_> = Wallet::new_offline(
+            descriptor,
+            Some(change_descriptor),
+            Network::Testnet,
+            get_test_db(),
+        )
+        .unwrap();
+        WalletExport::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: OfflineWallet<_> = Wallet::new_offline(
+            descriptor,
+            Some(change_descriptor),
+            Network::Testnet,
+            get_test_db(),
+        )
+        .unwrap();
+        let export = WalletExport::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: OfflineWallet<_> = Wallet::new_offline(
+            descriptor,
+            Some(change_descriptor),
+            Network::Testnet,
+            get_test_db(),
+        )
+        .unwrap();
+        let export = WalletExport::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 = WalletExport::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/0.1.0-beta.1/src/bdk/wallet/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/mod.rs.html new file mode 100644 index 0000000000..46a90673f2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/mod.rs.html @@ -0,0 +1,4881 @@ +mod.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Wallet
+//!
+//! This module defines the [`Wallet`] structure.
+
+use std::cell::RefCell;
+use std::collections::HashMap;
+use std::collections::{BTreeMap, HashSet};
+use std::ops::{Deref, DerefMut};
+use std::sync::Arc;
+
+use bitcoin::consensus::encode::serialize;
+use bitcoin::util::bip32::ChildNumber;
+use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
+use bitcoin::{Address, Network, OutPoint, Script, SigHashType, Transaction, TxOut, Txid};
+
+use miniscript::descriptor::DescriptorPublicKey;
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+pub mod address_validator;
+pub mod coin_selection;
+pub mod export;
+mod rbf;
+pub mod signer;
+pub mod time;
+pub mod tx_builder;
+pub(crate) mod utils;
+
+pub use utils::IsDust;
+
+use address_validator::AddressValidator;
+use signer::{Signer, SignerId, SignerOrdering, SignersContainer};
+use tx_builder::TxBuilder;
+use utils::{After, Older};
+
+use crate::blockchain::{Blockchain, BlockchainMarker, OfflineBlockchain, Progress};
+use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
+use crate::descriptor::{
+    get_checksum, DescriptorMeta, DescriptorScripts, ExtendedDescriptor, ExtractPolicy, Policy,
+};
+use crate::error::Error;
+use crate::psbt::PSBTUtils;
+use crate::types::*;
+
+const CACHE_ADDR_BATCH_SIZE: u32 = 100;
+
+/// Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]
+pub type OfflineWallet<D> = Wallet<OfflineBlockchain, D>;
+
+/// A Bitcoin wallet
+///
+/// A wallet takes descriptors, a [`database`](crate::database) and a
+/// [`blockchain`](crate::blockchain) and implements the basic functions that a Bitcoin wallets
+/// needs to operate, like [generating addresses](Wallet::get_new_address), [returning the balance](Wallet::get_balance),
+/// [creating transactions](Wallet::create_tx), etc.
+///
+/// A wallet can be either "online" if the [`blockchain`](crate::blockchain) type provided
+/// implements [`Blockchain`], or "offline" [`OfflineBlockchain`] is used. Offline wallets only expose
+/// methods that don't need any interaction with the blockchain to work.
+pub struct Wallet<B: BlockchainMarker, D: BatchDatabase> {
+    descriptor: ExtendedDescriptor,
+    change_descriptor: Option<ExtendedDescriptor>,
+
+    signers: Arc<SignersContainer<DescriptorPublicKey>>,
+    change_signers: Arc<SignersContainer<DescriptorPublicKey>>,
+
+    address_validators: Vec<Arc<Box<dyn AddressValidator>>>,
+
+    network: Network,
+
+    current_height: Option<u32>,
+
+    client: Option<B>,
+    database: RefCell<D>,
+}
+
+// offline actions, always available
+impl<B, D> Wallet<B, D>
+where
+    B: BlockchainMarker,
+    D: BatchDatabase,
+{
+    /// Create a new "offline" wallet
+    pub fn new_offline(
+        descriptor: &str,
+        change_descriptor: Option<&str>,
+        network: Network,
+        mut database: D,
+    ) -> Result<Self, Error> {
+        database.check_descriptor_checksum(
+            ScriptType::External,
+            get_checksum(descriptor)?.as_bytes(),
+        )?;
+        let (descriptor, keymap) = ExtendedDescriptor::parse_secret(descriptor)?;
+        let signers = Arc::new(SignersContainer::from(keymap));
+        let (change_descriptor, change_signers) = match change_descriptor {
+            Some(desc) => {
+                database.check_descriptor_checksum(
+                    ScriptType::Internal,
+                    get_checksum(desc)?.as_bytes(),
+                )?;
+
+                let (change_descriptor, change_keymap) = ExtendedDescriptor::parse_secret(desc)?;
+                let change_signers = Arc::new(SignersContainer::from(change_keymap));
+                // if !parsed.same_structure(descriptor.as_ref()) {
+                //     return Err(Error::DifferentDescriptorStructure);
+                // }
+
+                (Some(change_descriptor), change_signers)
+            }
+            None => (None, Arc::new(SignersContainer::new())),
+        };
+
+        Ok(Wallet {
+            descriptor,
+            change_descriptor,
+            signers,
+            change_signers,
+            address_validators: Vec::new(),
+
+            network,
+
+            current_height: None,
+
+            client: None,
+            database: RefCell::new(database),
+        })
+    }
+
+    /// Return a newly generated address using the external descriptor
+    pub fn get_new_address(&self) -> Result<Address, Error> {
+        let index = self.fetch_and_increment_index(ScriptType::External)?;
+
+        self.descriptor
+            .derive(&[ChildNumber::from_normal_idx(index).unwrap()])
+            .address(self.network)
+            .ok_or(Error::ScriptDoesntHaveAddressForm)
+    }
+
+    /// Return whether or not a `script` is part of this wallet (either internal or external)
+    pub fn is_mine(&self, script: &Script) -> Result<bool, Error> {
+        self.database.borrow().is_mine(script)
+    }
+
+    /// Return the list of unspent outputs of this wallet
+    ///
+    /// Note that this methods only operate on the internal database, which first needs to be
+    /// [`Wallet::sync`] manually.
+    pub fn list_unspent(&self) -> Result<Vec<UTXO>, Error> {
+        self.database.borrow().iter_utxos()
+    }
+
+    /// Return the list of transactions made and received by the wallet
+    ///
+    /// Optionally fill the [`TransactionDetails::transaction`] field with the raw transaction if
+    /// `include_raw` is `true`.
+    ///
+    /// Note that this methods only operate on the internal database, which first needs to be
+    /// [`Wallet::sync`] manually.
+    pub fn list_transactions(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
+        self.database.borrow().iter_txs(include_raw)
+    }
+
+    /// Return the balance, meaning the sum of this wallet's unspent outputs' values
+    ///
+    /// Note that this methods only operate on the internal database, which first needs to be
+    /// [`Wallet::sync`] manually.
+    pub fn get_balance(&self) -> Result<u64, Error> {
+        Ok(self
+            .list_unspent()?
+            .iter()
+            .fold(0, |sum, i| sum + i.txout.value))
+    }
+
+    /// Add an external signer
+    ///
+    /// See [the `signer` module](signer) for an example.
+    pub fn add_signer(
+        &mut self,
+        script_type: ScriptType,
+        id: SignerId<DescriptorPublicKey>,
+        ordering: SignerOrdering,
+        signer: Arc<Box<dyn Signer>>,
+    ) {
+        let signers = match script_type {
+            ScriptType::External => Arc::make_mut(&mut self.signers),
+            ScriptType::Internal => Arc::make_mut(&mut self.change_signers),
+        };
+
+        signers.add_external(id, ordering, signer);
+    }
+
+    /// Add an address validator
+    ///
+    /// See [the `address_validator` module](address_validator) for an example.
+    pub fn add_address_validator(&mut self, validator: Arc<Box<dyn AddressValidator>>) {
+        self.address_validators.push(validator);
+    }
+
+    /// Create a new transaction following the options specified in the `builder`
+    ///
+    /// ## Example
+    ///
+    /// ```no_run
+    /// # use std::str::FromStr;
+    /// # use bitcoin::*;
+    /// # use bdk::*;
+    /// # use bdk::database::*;
+    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+    /// let (psbt, details) = wallet.create_tx(
+    ///     TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+    /// )?;
+    /// // sign and broadcast ...
+    /// # Ok::<(), bdk::Error>(())
+    /// ```
+    pub fn create_tx<Cs: coin_selection::CoinSelectionAlgorithm>(
+        &self,
+        builder: TxBuilder<Cs>,
+    ) -> Result<(PSBT, TransactionDetails), Error> {
+        if builder.recipients.is_empty() {
+            return Err(Error::NoAddressees);
+        }
+
+        // TODO: fetch both internal and external policies
+        let policy = self
+            .descriptor
+            .extract_policy(Arc::clone(&self.signers))?
+            .unwrap();
+        if policy.requires_path() && builder.policy_path.is_none() {
+            return Err(Error::SpendingPolicyRequired);
+        }
+        let requirements =
+            policy.get_condition(builder.policy_path.as_ref().unwrap_or(&BTreeMap::new()))?;
+        debug!("requirements: {:?}", requirements);
+
+        let version = match builder.version {
+            Some(tx_builder::Version(0)) => {
+                return Err(Error::Generic("Invalid version `0`".into()))
+            }
+            Some(tx_builder::Version(1)) if requirements.csv.is_some() => {
+                return Err(Error::Generic(
+                    "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
+                        .into(),
+                ))
+            }
+            Some(tx_builder::Version(x)) => x,
+            None if requirements.csv.is_some() => 2,
+            _ => 1,
+        };
+
+        let lock_time = match builder.locktime {
+            None => requirements.timelock.unwrap_or(0),
+            Some(x) if requirements.timelock.is_none() => x,
+            Some(x) if requirements.timelock.unwrap() <= x => x,
+            Some(x) => return Err(Error::Generic(format!("TxBuilder requested timelock of `{}`, but at least `{}` is required to spend from this script", x, requirements.timelock.unwrap())))
+        };
+
+        let n_sequence = match (builder.rbf, requirements.csv) {
+            (None, Some(csv)) => csv,
+            (Some(rbf), Some(csv)) if rbf < csv => return Err(Error::Generic(format!("Cannot enable RBF with nSequence `{}`, since at least `{}` is required to spend with OP_CSV", rbf, csv))),
+            (None, _) if requirements.timelock.is_some() => 0xFFFFFFFE,
+            (Some(rbf), _) if rbf >= 0xFFFFFFFE => return Err(Error::Generic("Cannot enable RBF with a nSequence >= 0xFFFFFFFE".into())),
+            (Some(rbf), _) => rbf,
+            (None, _) => 0xFFFFFFFF,
+        };
+
+        let mut tx = Transaction {
+            version,
+            lock_time,
+            input: vec![],
+            output: vec![],
+        };
+
+        let fee_rate = builder.fee_rate.unwrap_or_default();
+        if builder.send_all && builder.recipients.len() != 1 {
+            return Err(Error::SendAllMultipleOutputs);
+        }
+
+        // we keep it as a float while we accumulate it, and only round it at the end
+        let mut fee_amount: f32 = 0.0;
+        let mut outgoing: u64 = 0;
+        let mut received: u64 = 0;
+
+        let calc_fee_bytes = |wu| (wu as f32) * fee_rate.as_sat_vb() / 4.0;
+        fee_amount += calc_fee_bytes(tx.get_weight());
+
+        for (index, (script_pubkey, satoshi)) in builder.recipients.iter().enumerate() {
+            let value = match builder.send_all {
+                true => 0,
+                false if satoshi.is_dust() => return Err(Error::OutputBelowDustLimit(index)),
+                false => *satoshi,
+            };
+
+            if self.is_mine(script_pubkey)? {
+                received += value;
+            }
+
+            let new_out = TxOut {
+                script_pubkey: script_pubkey.clone(),
+                value,
+            };
+            fee_amount += calc_fee_bytes(serialize(&new_out).len() * 4);
+
+            tx.output.push(new_out);
+
+            outgoing += value;
+        }
+
+        // TODO: use the right weight instead of the maximum, and only fall-back to it if the
+        // script is unknown in the database
+        let input_witness_weight = std::cmp::max(
+            self.get_descriptor_for_script_type(ScriptType::Internal)
+                .0
+                .max_satisfaction_weight(),
+            self.get_descriptor_for_script_type(ScriptType::External)
+                .0
+                .max_satisfaction_weight(),
+        );
+
+        if builder.change_policy != tx_builder::ChangeSpendPolicy::ChangeAllowed
+            && self.change_descriptor.is_none()
+        {
+            return Err(Error::Generic(
+                "The `change_policy` can be set only if the wallet has a change_descriptor".into(),
+            ));
+        }
+
+        let (available_utxos, use_all_utxos) = self.get_available_utxos(
+            builder.change_policy,
+            &builder.utxos,
+            &builder.unspendable,
+            builder.send_all,
+        )?;
+        let coin_selection::CoinSelectionResult {
+            txin,
+            selected_amount,
+            mut fee_amount,
+        } = builder.coin_selection.coin_select(
+            available_utxos,
+            use_all_utxos,
+            fee_rate,
+            outgoing,
+            input_witness_weight,
+            fee_amount,
+        )?;
+        let (mut txin, prev_script_pubkeys): (Vec<_>, Vec<_>) = txin.into_iter().unzip();
+        // map that allows us to lookup the prev_script_pubkey for a given previous_output
+        let prev_script_pubkeys = txin
+            .iter()
+            .zip(prev_script_pubkeys.into_iter())
+            .map(|(txin, script)| (txin.previous_output, script))
+            .collect::<HashMap<_, _>>();
+
+        txin.iter_mut().for_each(|i| i.sequence = n_sequence);
+        tx.input = txin;
+
+        // prepare the change output
+        let change_output = match builder.send_all {
+            true => None,
+            false => {
+                let change_script = self.get_change_address()?;
+                let change_output = TxOut {
+                    script_pubkey: change_script,
+                    value: 0,
+                };
+
+                // take the change into account for fees
+                fee_amount += calc_fee_bytes(serialize(&change_output).len() * 4);
+                Some(change_output)
+            }
+        };
+
+        let mut fee_amount = fee_amount.ceil() as u64;
+        let change_val = selected_amount - outgoing - fee_amount;
+        if !builder.send_all && !change_val.is_dust() {
+            let mut change_output = change_output.unwrap();
+            change_output.value = change_val;
+            received += change_val;
+
+            tx.output.push(change_output);
+        } else if builder.send_all && !change_val.is_dust() {
+            // there's only one output, send everything to it
+            tx.output[0].value = change_val;
+
+            // send_all to our address
+            if self.is_mine(&tx.output[0].script_pubkey)? {
+                received = change_val;
+            }
+        } else if !builder.send_all && change_val.is_dust() {
+            // skip the change output because it's dust, this adds up to the fees
+            fee_amount += change_val;
+        } else if builder.send_all {
+            // send_all but the only output would be below dust limit
+            return Err(Error::InsufficientFunds); // TODO: or OutputBelowDustLimit?
+        }
+
+        // sort input/outputs according to the chosen algorithm
+        builder.ordering.sort_tx(&mut tx);
+
+        let txid = tx.txid();
+        let psbt = self.complete_transaction(tx, prev_script_pubkeys, builder)?;
+
+        let transaction_details = TransactionDetails {
+            transaction: None,
+            txid,
+            timestamp: time::get_timestamp(),
+            received,
+            sent: selected_amount,
+            fees: fee_amount,
+            height: None,
+        };
+
+        Ok((psbt, transaction_details))
+    }
+
+    /// Bump the fee of a transaction following the options specified in the `builder`
+    ///
+    /// Return an error if the transaction is already confirmed or doesn't explicitly signal RBF.
+    ///
+    /// **NOTE**: if the original transaction was made with [`TxBuilder::send_all`], the same
+    /// option must be enabled when bumping its fees to correctly reduce the only output's value to
+    /// increase the fees.
+    ///
+    /// ## Example
+    ///
+    /// ```no_run
+    /// # use std::str::FromStr;
+    /// # use bitcoin::*;
+    /// # use bdk::*;
+    /// # use bdk::database::*;
+    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+    /// let txid = Txid::from_str("faff0a466b70f5d5f92bd757a92c1371d4838bdd5bc53a06764e2488e51ce8f8").unwrap();
+    /// let (psbt, details) = wallet.bump_fee(
+    ///     &txid,
+    ///     TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(5.0)),
+    /// )?;
+    /// // sign and broadcast ...
+    /// # Ok::<(), bdk::Error>(())
+    /// ```
+    // TODO: support for merging multiple transactions while bumping the fees
+    // TODO: option to force addition of an extra output? seems bad for privacy to update the
+    // change
+    pub fn bump_fee<Cs: coin_selection::CoinSelectionAlgorithm>(
+        &self,
+        txid: &Txid,
+        builder: TxBuilder<Cs>,
+    ) -> Result<(PSBT, TransactionDetails), Error> {
+        let mut details = match self.database.borrow().get_tx(&txid, true)? {
+            None => return Err(Error::TransactionNotFound),
+            Some(tx) if tx.transaction.is_none() => return Err(Error::TransactionNotFound),
+            Some(tx) if tx.height.is_some() => return Err(Error::TransactionConfirmed),
+            Some(tx) => tx,
+        };
+        let mut tx = details.transaction.take().unwrap();
+        if !tx.input.iter().any(|txin| txin.sequence <= 0xFFFFFFFD) {
+            return Err(Error::IrreplaceableTransaction);
+        }
+
+        // the new tx must "pay for its bandwidth"
+        let vbytes = tx.get_weight() as f32 / 4.0;
+        let required_feerate = FeeRate::from_sat_per_vb(details.fees as f32 / vbytes + 1.0);
+        let new_feerate = builder.fee_rate.unwrap_or_default();
+
+        if new_feerate < required_feerate {
+            return Err(Error::FeeRateTooLow {
+                required: required_feerate,
+            });
+        }
+        let mut fee_difference =
+            (new_feerate.as_sat_vb() * tx.get_weight() as f32 / 4.0).ceil() as u64 - details.fees;
+
+        if builder.send_all && tx.output.len() > 1 {
+            return Err(Error::SendAllMultipleOutputs);
+        }
+
+        // find the index of the output that we can update. either the change or the only one if
+        // it's `send_all`
+        let updatable_output = if builder.send_all {
+            0
+        } else {
+            let mut change_output = None;
+            for (index, txout) in tx.output.iter().enumerate() {
+                // look for an output that we know and that has the right ScriptType. We use
+                // `get_deget_descriptor_for` to find what's the ScriptType for `Internal`
+                // addresses really is, because if there's no change_descriptor it's actually equal
+                // to "External"
+                let (_, change_type) = self.get_descriptor_for_script_type(ScriptType::Internal);
+                match self
+                    .database
+                    .borrow()
+                    .get_path_from_script_pubkey(&txout.script_pubkey)?
+                {
+                    Some((script_type, _)) if script_type == change_type => {
+                        change_output = Some(index);
+                        break;
+                    }
+                    _ => {}
+                }
+            }
+
+            // we need a change output, add one here and take into account the extra fees for it
+            if change_output.is_none() {
+                let change_script = self.get_change_address()?;
+                let change_txout = TxOut {
+                    script_pubkey: change_script,
+                    value: 0,
+                };
+                fee_difference +=
+                    (serialize(&change_txout).len() as f32 * new_feerate.as_sat_vb()).ceil() as u64;
+                tx.output.push(change_txout);
+
+                change_output = Some(tx.output.len() - 1);
+            }
+
+            change_output.unwrap()
+        };
+
+        // if `builder.utxos` is Some(_) we have to add inputs and we skip down to the last branch
+        match tx.output[updatable_output]
+            .value
+            .checked_sub(fee_difference)
+        {
+            Some(new_value) if !new_value.is_dust() && builder.utxos.is_none() => {
+                // try to reduce the "updatable output" amount
+                tx.output[updatable_output].value = new_value;
+                if self.is_mine(&tx.output[updatable_output].script_pubkey)? {
+                    details.received -= fee_difference;
+                }
+
+                details.fees += fee_difference;
+            }
+            _ if builder.send_all && builder.utxos.is_none() => {
+                // if the tx is "send_all" it doesn't make sense to either remove the only output
+                // or add more inputs
+                return Err(Error::InsufficientFunds);
+            }
+            _ => {
+                // initially always remove the change output
+                let mut removed_change_output = tx.output.remove(updatable_output);
+                if self.is_mine(&removed_change_output.script_pubkey)? {
+                    details.received -= removed_change_output.value;
+                }
+
+                // we want to add more inputs if:
+                // - builder.utxos tells us to do so
+                // - the removed change value is lower than the fee_difference we want to add
+                let needs_more_inputs =
+                    builder.utxos.is_some() || removed_change_output.value <= fee_difference;
+                let added_amount = if needs_more_inputs {
+                    // TODO: use the right weight instead of the maximum, and only fall-back to it if the
+                    // script is unknown in the database
+                    let input_witness_weight = std::cmp::max(
+                        self.get_descriptor_for_script_type(ScriptType::Internal)
+                            .0
+                            .max_satisfaction_weight(),
+                        self.get_descriptor_for_script_type(ScriptType::External)
+                            .0
+                            .max_satisfaction_weight(),
+                    );
+
+                    let (available_utxos, use_all_utxos) = self.get_available_utxos(
+                        builder.change_policy,
+                        &builder.utxos,
+                        &builder.unspendable,
+                        false,
+                    )?;
+                    let available_utxos = rbf::filter_available(
+                        self.database.borrow().deref(),
+                        available_utxos.into_iter(),
+                    )?;
+                    let coin_selection::CoinSelectionResult {
+                        txin,
+                        selected_amount,
+                        fee_amount,
+                    } = builder.coin_selection.coin_select(
+                        available_utxos,
+                        use_all_utxos,
+                        new_feerate,
+                        fee_difference
+                            .checked_sub(removed_change_output.value)
+                            .unwrap_or(0),
+                        input_witness_weight,
+                        0.0,
+                    )?;
+                    fee_difference += fee_amount.ceil() as u64;
+
+                    // add the new inputs
+                    let (mut txin, _): (Vec<_>, Vec<_>) = txin.into_iter().unzip();
+
+                    // TODO: use tx_builder.sequence ??
+                    // copy the n_sequence from the inputs that were already in the transaction
+                    txin.iter_mut()
+                        .for_each(|i| i.sequence = tx.input[0].sequence);
+                    tx.input.extend_from_slice(&mut txin);
+
+                    details.sent += selected_amount;
+                    selected_amount
+                } else {
+                    // otherwise just remove the output and add 0 new coins
+                    0
+                };
+
+                match (removed_change_output.value + added_amount).checked_sub(fee_difference) {
+                    None => return Err(Error::InsufficientFunds),
+                    Some(new_value) if new_value.is_dust() => {
+                        // the change would be dust, add that to fees
+                        details.fees += fee_difference + new_value;
+                    }
+                    Some(new_value) => {
+                        // add the change back
+                        removed_change_output.value = new_value;
+                        tx.output.push(removed_change_output);
+
+                        details.received += new_value;
+                        details.fees += fee_difference;
+                    }
+                }
+            }
+        };
+
+        // clear witnesses
+        for input in &mut tx.input {
+            input.script_sig = Script::default();
+            input.witness = vec![];
+        }
+
+        // sort input/outputs according to the chosen algorithm
+        builder.ordering.sort_tx(&mut tx);
+
+        // TODO: check that we are not replacing more than 100 txs from mempool
+
+        details.txid = tx.txid();
+        details.timestamp = time::get_timestamp();
+
+        let prev_script_pubkeys = tx
+            .input
+            .iter()
+            .map(|txin| {
+                Ok((
+                    txin.previous_output.clone(),
+                    self.database
+                        .borrow()
+                        .get_previous_output(&txin.previous_output)?,
+                ))
+            })
+            .collect::<Result<Vec<_>, Error>>()?
+            .into_iter()
+            .filter_map(|(outpoint, txout)| match txout {
+                Some(txout) => Some((outpoint, txout.script_pubkey)),
+                None => None,
+            })
+            .collect();
+        let psbt = self.complete_transaction(tx, prev_script_pubkeys, builder)?;
+
+        Ok((psbt, details))
+    }
+
+    /// Sign a transaction with all the wallet's signers, in the order specified by every signer's
+    /// [`SignerOrdering`]
+    ///
+    /// ## Example
+    ///
+    /// ```no_run
+    /// # use std::str::FromStr;
+    /// # use bitcoin::*;
+    /// # use bdk::*;
+    /// # use bdk::database::*;
+    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+    /// # let (psbt, _) = wallet.create_tx(TxBuilder::new())?;
+    /// let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
+    /// # Ok::<(), bdk::Error>(())
+    pub fn sign(&self, mut psbt: PSBT, assume_height: Option<u32>) -> Result<(PSBT, bool), Error> {
+        // this helps us doing our job later
+        self.add_input_hd_keypaths(&mut psbt)?;
+
+        for signer in self
+            .signers
+            .signers()
+            .iter()
+            .chain(self.change_signers.signers().iter())
+        {
+            if signer.sign_whole_tx() {
+                signer.sign(&mut psbt, None)?;
+            } else {
+                for index in 0..psbt.inputs.len() {
+                    signer.sign(&mut psbt, Some(index))?;
+                }
+            }
+        }
+
+        // attempt to finalize
+        self.finalize_psbt(psbt, assume_height)
+    }
+
+    /// Return the spending policies for the wallet's descriptor
+    pub fn policies(&self, script_type: ScriptType) -> Result<Option<Policy>, Error> {
+        match (script_type, self.change_descriptor.as_ref()) {
+            (ScriptType::External, _) => {
+                Ok(self.descriptor.extract_policy(Arc::clone(&self.signers))?)
+            }
+            (ScriptType::Internal, None) => Ok(None),
+            (ScriptType::Internal, Some(desc)) => {
+                Ok(desc.extract_policy(Arc::clone(&self.change_signers))?)
+            }
+        }
+    }
+
+    /// 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,
+        script_type: ScriptType,
+    ) -> Result<Option<ExtendedDescriptor>, Error> {
+        match (script_type, self.change_descriptor.as_ref()) {
+            (ScriptType::External, _) => Ok(Some(self.descriptor.clone())),
+            (ScriptType::Internal, None) => Ok(None),
+            (ScriptType::Internal, Some(desc)) => Ok(Some(desc.clone())),
+        }
+    }
+
+    /// Try to finalize a PSBT
+    pub fn finalize_psbt(
+        &self,
+        mut psbt: PSBT,
+        assume_height: Option<u32>,
+    ) -> Result<(PSBT, bool), Error> {
+        let mut tx = psbt.global.unsigned_tx.clone();
+
+        for (n, (input, psbt_input)) in tx.input.iter_mut().zip(psbt.inputs.iter()).enumerate() {
+            // if the height is None in the database it means it's still unconfirmed, so consider
+            // that as a very high value
+            let create_height = self
+                .database
+                .borrow()
+                .get_tx(&input.previous_output.txid, false)?
+                .and_then(|tx| Some(tx.height.unwrap_or(std::u32::MAX)));
+            let current_height = assume_height.or(self.current_height);
+
+            debug!(
+                "Input #{} - {}, using `create_height` = {:?}, `current_height` = {:?}",
+                n, input.previous_output, create_height, current_height
+            );
+
+            // - Try to derive the descriptor by looking at the txout. If it's in our database, we
+            //   know exactly which `script_type` 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 `hd_keypaths`,
+            //   `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 = if let Some(desc) = psbt
+                .get_utxo_for(n)
+                .map(|txout| self.get_descriptor_for_txout(&txout))
+                .transpose()?
+                .flatten()
+            {
+                desc
+            } else if let Some(desc) = self
+                .descriptor
+                .derive_from_psbt_input(psbt_input, psbt.get_utxo_for(n))
+            {
+                desc
+            } else if let Some(desc) = self
+                .change_descriptor
+                .as_ref()
+                .and_then(|desc| desc.derive_from_psbt_input(psbt_input, psbt.get_utxo_for(n)))
+            {
+                desc
+            } else {
+                debug!("Couldn't find the right derived descriptor for input {}", n);
+                return Ok((psbt, false));
+            };
+
+            match desc.satisfy(
+                input,
+                (
+                    psbt_input.clone(),
+                    After::new(current_height, false),
+                    Older::new(current_height, create_height, false),
+                ),
+            ) {
+                Ok(_) => continue,
+                Err(e) => {
+                    debug!("satisfy error {:?} for input {}", e, n);
+                    return Ok((psbt, false));
+                }
+            }
+        }
+
+        // consume tx to extract its input's script_sig and witnesses and move them into the psbt
+        for (input, psbt_input) in tx.input.into_iter().zip(psbt.inputs.iter_mut()) {
+            psbt_input.final_script_sig = Some(input.script_sig);
+            psbt_input.final_script_witness = Some(input.witness);
+        }
+
+        Ok((psbt, true))
+    }
+
+    // Internals
+
+    fn get_descriptor_for_script_type(
+        &self,
+        script_type: ScriptType,
+    ) -> (&ExtendedDescriptor, ScriptType) {
+        let desc = match script_type {
+            ScriptType::Internal if self.change_descriptor.is_some() => (
+                self.change_descriptor.as_ref().unwrap(),
+                ScriptType::Internal,
+            ),
+            _ => (&self.descriptor, ScriptType::External),
+        };
+
+        desc
+    }
+
+    fn get_descriptor_for_txout(&self, txout: &TxOut) -> Result<Option<ExtendedDescriptor>, Error> {
+        Ok(self
+            .database
+            .borrow()
+            .get_path_from_script_pubkey(&txout.script_pubkey)?
+            .map(|(script_type, child)| (self.get_descriptor_for_script_type(script_type).0, child))
+            .map(|(desc, child)| desc.derive(&[ChildNumber::from_normal_idx(child).unwrap()])))
+    }
+
+    fn get_change_address(&self) -> Result<Script, Error> {
+        let (desc, script_type) = self.get_descriptor_for_script_type(ScriptType::Internal);
+        let index = self.fetch_and_increment_index(script_type)?;
+
+        Ok(desc
+            .derive(&[ChildNumber::from_normal_idx(index).unwrap()])
+            .script_pubkey())
+    }
+
+    fn fetch_and_increment_index(&self, script_type: ScriptType) -> Result<u32, Error> {
+        let (descriptor, script_type) = self.get_descriptor_for_script_type(script_type);
+        let index = match descriptor.is_fixed() {
+            true => 0,
+            false => self
+                .database
+                .borrow_mut()
+                .increment_last_index(script_type)?,
+        };
+
+        if self
+            .database
+            .borrow()
+            .get_script_pubkey_from_path(script_type, index)?
+            .is_none()
+        {
+            self.cache_addresses(script_type, index, CACHE_ADDR_BATCH_SIZE)?;
+        }
+
+        let hd_keypaths = descriptor.get_hd_keypaths(index)?;
+        let script = descriptor
+            .derive(&[ChildNumber::from_normal_idx(index).unwrap()])
+            .script_pubkey();
+        for validator in &self.address_validators {
+            validator.validate(script_type, &hd_keypaths, &script)?;
+        }
+
+        Ok(index)
+    }
+
+    fn cache_addresses(
+        &self,
+        script_type: ScriptType,
+        from: u32,
+        mut count: u32,
+    ) -> Result<(), Error> {
+        let (descriptor, script_type) = self.get_descriptor_for_script_type(script_type);
+        if descriptor.is_fixed() {
+            if from > 0 {
+                return Ok(());
+            }
+
+            count = 1;
+        }
+
+        let mut address_batch = self.database.borrow().begin_batch();
+
+        let start_time = time::Instant::new();
+        for i in from..(from + count) {
+            address_batch.set_script_pubkey(
+                &descriptor
+                    .derive(&[ChildNumber::from_normal_idx(i).unwrap()])
+                    .script_pubkey(),
+                script_type,
+                i,
+            )?;
+        }
+
+        info!(
+            "Derivation of {} addresses from {} took {} ms",
+            count,
+            from,
+            start_time.elapsed().as_millis()
+        );
+
+        self.database.borrow_mut().commit_batch(address_batch)?;
+
+        Ok(())
+    }
+
+    fn get_available_utxos(
+        &self,
+        change_policy: tx_builder::ChangeSpendPolicy,
+        utxo: &Option<Vec<OutPoint>>,
+        unspendable: &Option<Vec<OutPoint>>,
+        send_all: bool,
+    ) -> Result<(Vec<UTXO>, bool), Error> {
+        let unspendable_set = match unspendable {
+            None => HashSet::new(),
+            Some(vec) => vec.into_iter().collect(),
+        };
+
+        match utxo {
+            // with manual coin selection we always want to spend all the selected utxos, no matter
+            // what (even if they are marked as unspendable)
+            Some(raw_utxos) => {
+                let full_utxos = raw_utxos
+                    .iter()
+                    .map(|u| self.database.borrow().get_utxo(&u))
+                    .collect::<Result<Vec<_>, _>>()?;
+                if !full_utxos.iter().all(|u| u.is_some()) {
+                    return Err(Error::UnknownUTXO);
+                }
+
+                Ok((full_utxos.into_iter().map(|x| x.unwrap()).collect(), true))
+            }
+            // otherwise limit ourselves to the spendable utxos for the selected policy, and the `send_all` setting
+            None => {
+                let utxos = self.list_unspent()?.into_iter();
+                let utxos = change_policy.filter_utxos(utxos).into_iter();
+
+                Ok((
+                    utxos
+                        .filter(|u| !unspendable_set.contains(&u.outpoint))
+                        .collect(),
+                    send_all,
+                ))
+            }
+        }
+    }
+
+    fn complete_transaction<Cs: coin_selection::CoinSelectionAlgorithm>(
+        &self,
+        tx: Transaction,
+        prev_script_pubkeys: HashMap<OutPoint, Script>,
+        builder: TxBuilder<Cs>,
+    ) -> Result<PSBT, Error> {
+        let mut psbt = PSBT::from_unsigned_tx(tx)?;
+
+        // add metadata for the inputs
+        for (psbt_input, input) in psbt
+            .inputs
+            .iter_mut()
+            .zip(psbt.global.unsigned_tx.input.iter())
+        {
+            let prev_script = match prev_script_pubkeys.get(&input.previous_output) {
+                Some(prev_script) => prev_script,
+                None => continue,
+            };
+
+            // Add sighash, default is obviously "ALL"
+            psbt_input.sighash_type = builder.sighash.or(Some(SigHashType::All));
+
+            // Try to find the prev_script in our db to figure out if this is internal or external,
+            // and the derivation index
+            let (script_type, child) = match self
+                .database
+                .borrow()
+                .get_path_from_script_pubkey(&prev_script)?
+            {
+                Some(x) => x,
+                None => continue,
+            };
+
+            let (desc, _) = self.get_descriptor_for_script_type(script_type);
+            psbt_input.hd_keypaths = desc.get_hd_keypaths(child)?;
+            let derived_descriptor = desc.derive(&[ChildNumber::from_normal_idx(child).unwrap()]);
+
+            psbt_input.redeem_script = derived_descriptor.psbt_redeem_script();
+            psbt_input.witness_script = derived_descriptor.psbt_witness_script();
+
+            let prev_output = input.previous_output;
+            if let Some(prev_tx) = self.database.borrow().get_raw_tx(&prev_output.txid)? {
+                if derived_descriptor.is_witness() {
+                    psbt_input.witness_utxo =
+                        Some(prev_tx.output[prev_output.vout as usize].clone());
+                }
+                if !derived_descriptor.is_witness() || builder.force_non_witness_utxo {
+                    psbt_input.non_witness_utxo = Some(prev_tx);
+                }
+            }
+        }
+
+        // probably redundant but it doesn't hurt...
+        self.add_input_hd_keypaths(&mut psbt)?;
+
+        // add metadata for the outputs
+        for (psbt_output, tx_output) in psbt
+            .outputs
+            .iter_mut()
+            .zip(psbt.global.unsigned_tx.output.iter())
+        {
+            if let Some((script_type, child)) = self
+                .database
+                .borrow()
+                .get_path_from_script_pubkey(&tx_output.script_pubkey)?
+            {
+                let (desc, _) = self.get_descriptor_for_script_type(script_type);
+                psbt_output.hd_keypaths = desc.get_hd_keypaths(child)?;
+            }
+        }
+
+        Ok(psbt)
+    }
+
+    fn add_input_hd_keypaths(&self, psbt: &mut PSBT) -> Result<(), Error> {
+        let mut input_utxos = Vec::with_capacity(psbt.inputs.len());
+        for n in 0..psbt.inputs.len() {
+            input_utxos.push(psbt.get_utxo_for(n).clone());
+        }
+
+        // try to add hd_keypaths if we've already seen the output
+        for (psbt_input, out) in psbt.inputs.iter_mut().zip(input_utxos.iter()) {
+            if let Some(out) = out {
+                if let Some((script_type, child)) = self
+                    .database
+                    .borrow()
+                    .get_path_from_script_pubkey(&out.script_pubkey)?
+                {
+                    debug!("Found descriptor {:?}/{}", script_type, child);
+
+                    // merge hd_keypaths
+                    let (desc, _) = self.get_descriptor_for_script_type(script_type);
+                    let mut hd_keypaths = desc.get_hd_keypaths(child)?;
+                    psbt_input.hd_keypaths.append(&mut hd_keypaths);
+                }
+            }
+        }
+
+        Ok(())
+    }
+}
+
+impl<B, D> Wallet<B, D>
+where
+    B: Blockchain,
+    D: BatchDatabase,
+{
+    /// Create a new "online" wallet
+    #[maybe_async]
+    pub fn new(
+        descriptor: &str,
+        change_descriptor: Option<&str>,
+        network: Network,
+        database: D,
+        client: B,
+    ) -> Result<Self, Error> {
+        let mut wallet = Self::new_offline(descriptor, change_descriptor, network, database)?;
+
+        wallet.current_height = Some(maybe_await!(client.get_height())? as u32);
+        wallet.client = Some(client);
+
+        Ok(wallet)
+    }
+
+    /// Sync the internal database with the blockchain
+    #[maybe_async]
+    pub fn sync<P: 'static + Progress>(
+        &self,
+        progress_update: P,
+        max_address_param: Option<u32>,
+    ) -> Result<(), Error> {
+        debug!("Begin sync...");
+
+        let mut run_setup = false;
+
+        let max_address = match self.descriptor.is_fixed() {
+            true => 0,
+            false => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
+        };
+        if self
+            .database
+            .borrow()
+            .get_script_pubkey_from_path(ScriptType::External, max_address)?
+            .is_none()
+        {
+            run_setup = true;
+            self.cache_addresses(ScriptType::External, 0, max_address)?;
+        }
+
+        if let Some(change_descriptor) = &self.change_descriptor {
+            let max_address = match change_descriptor.is_fixed() {
+                true => 0,
+                false => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
+            };
+
+            if self
+                .database
+                .borrow()
+                .get_script_pubkey_from_path(
+                    ScriptType::Internal,
+                    max_address.checked_sub(1).unwrap_or(0),
+                )?
+                .is_none()
+            {
+                run_setup = true;
+                self.cache_addresses(ScriptType::Internal, 0, max_address)?;
+            }
+        }
+
+        // TODO: what if i generate an address first and cache some addresses?
+        // TODO: we should sync if generating an address triggers a new batch to be stored
+        if run_setup {
+            maybe_await!(self.client.as_ref().ok_or(Error::OfflineClient)?.setup(
+                None,
+                self.database.borrow_mut().deref_mut(),
+                progress_update,
+            ))
+        } else {
+            maybe_await!(self.client.as_ref().ok_or(Error::OfflineClient)?.sync(
+                None,
+                self.database.borrow_mut().deref_mut(),
+                progress_update,
+            ))
+        }
+    }
+
+    /// Return a reference to the internal blockchain client
+    pub fn client(&self) -> Option<&B> {
+        self.client.as_ref()
+    }
+
+    /// Broadcast a transaction to the network
+    #[maybe_async]
+    pub fn broadcast(&self, tx: Transaction) -> Result<Txid, Error> {
+        maybe_await!(self
+            .client
+            .as_ref()
+            .ok_or(Error::OfflineClient)?
+            .broadcast(&tx))?;
+
+        Ok(tx.txid())
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::str::FromStr;
+
+    use bitcoin::Network;
+
+    use crate::database::memory::MemoryDatabase;
+    use crate::database::Database;
+    use crate::types::ScriptType;
+
+    use super::*;
+
+    #[test]
+    fn test_cache_addresses_fixed() {
+        let db = MemoryDatabase::new();
+        let wallet: OfflineWallet<_> = Wallet::new_offline(
+            "wpkh(L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6)",
+            None,
+            Network::Testnet,
+            db,
+        )
+        .unwrap();
+
+        assert_eq!(
+            wallet.get_new_address().unwrap().to_string(),
+            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
+        );
+        assert_eq!(
+            wallet.get_new_address().unwrap().to_string(),
+            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
+        );
+
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(ScriptType::External, 0)
+            .unwrap()
+            .is_some());
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(ScriptType::Internal, 0)
+            .unwrap()
+            .is_none());
+    }
+
+    #[test]
+    fn test_cache_addresses() {
+        let db = MemoryDatabase::new();
+        let wallet: OfflineWallet<_> = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
+
+        assert_eq!(
+            wallet.get_new_address().unwrap().to_string(),
+            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
+        );
+        assert_eq!(
+            wallet.get_new_address().unwrap().to_string(),
+            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
+        );
+
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(ScriptType::External, CACHE_ADDR_BATCH_SIZE - 1)
+            .unwrap()
+            .is_some());
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(ScriptType::External, CACHE_ADDR_BATCH_SIZE)
+            .unwrap()
+            .is_none());
+    }
+
+    #[test]
+    fn test_cache_addresses_refill() {
+        let db = MemoryDatabase::new();
+        let wallet: OfflineWallet<_> = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
+
+        assert_eq!(
+            wallet.get_new_address().unwrap().to_string(),
+            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
+        );
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(ScriptType::External, CACHE_ADDR_BATCH_SIZE - 1)
+            .unwrap()
+            .is_some());
+
+        for _ in 0..CACHE_ADDR_BATCH_SIZE {
+            wallet.get_new_address().unwrap();
+        }
+
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(ScriptType::External, CACHE_ADDR_BATCH_SIZE * 2 - 1)
+            .unwrap()
+            .is_some());
+    }
+
+    pub(crate) fn get_test_wpkh() -> &'static str {
+        "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)"
+    }
+
+    pub(crate) fn get_test_single_sig_csv() -> &'static str {
+        // and(pk(Alice),older(6))
+        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),older(6)))"
+    }
+
+    pub(crate) fn get_test_single_sig_cltv() -> &'static str {
+        // and(pk(Alice),after(100000))
+        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(100000)))"
+    }
+
+    pub(crate) fn get_funded_wallet(
+        descriptor: &str,
+    ) -> (
+        OfflineWallet<MemoryDatabase>,
+        (String, Option<String>),
+        bitcoin::Txid,
+    ) {
+        let descriptors = testutils!(@descriptors (descriptor));
+        let wallet: OfflineWallet<_> = Wallet::new_offline(
+            &descriptors.0,
+            None,
+            Network::Regtest,
+            MemoryDatabase::new(),
+        )
+        .unwrap();
+
+        let txid = wallet.database.borrow_mut().received_tx(
+            testutils! {
+                @tx ( (@external descriptors, 0) => 50_000 ) (@confirmations 1)
+            },
+            Some(100),
+        );
+
+        (wallet, descriptors, txid)
+    }
+
+    macro_rules! assert_fee_rate {
+        ($tx:expr, $fees:expr, $fee_rate:expr $( ,@dust_change $( $dust_change:expr )* )* $( ,@add_signature $( $add_signature:expr )* )* ) => ({
+            let mut tx = $tx.clone();
+            $(
+                $( $add_signature )*
+                for txin in &mut tx.input {
+                    txin.witness.push([0x00; 108].to_vec()); // fake signature
+                }
+            )*
+
+            #[allow(unused_mut)]
+            #[allow(unused_assignments)]
+            let mut dust_change = false;
+            $(
+                $( $dust_change )*
+                dust_change = true;
+            )*
+
+            let tx_fee_rate = $fees as f32 / (tx.get_weight() as f32 / 4.0);
+            let fee_rate = $fee_rate.as_sat_vb();
+
+            if !dust_change {
+                assert!((tx_fee_rate - fee_rate).abs() < 0.5, format!("Expected fee rate of {}, the tx has {}", fee_rate, tx_fee_rate));
+            } else {
+                assert!(tx_fee_rate >= fee_rate, format!("Expected fee rate of at least {}, the tx has {}", fee_rate, tx_fee_rate));
+            }
+        });
+    }
+
+    #[test]
+    #[should_panic(expected = "NoAddressees")]
+    fn test_create_tx_empty_recipients() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        wallet
+            .create_tx(TxBuilder::with_recipients(vec![]).version(0))
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "Invalid version `0`")]
+    fn test_create_tx_version_0() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(0))
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
+    )]
+    fn test_create_tx_version_1_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(1))
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_custom_version() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(42))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.version, 42);
+    }
+
+    #[test]
+    fn test_create_tx_default_locktime() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.lock_time, 0);
+    }
+
+    #[test]
+    fn test_create_tx_default_locktime_cltv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.lock_time, 100_000);
+    }
+
+    #[test]
+    fn test_create_tx_custom_locktime() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(630_000),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
+    }
+
+    #[test]
+    fn test_create_tx_custom_locktime_compatible_with_cltv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(630_000),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "TxBuilder requested timelock of `50000`, but at least `100000` is required to spend from this script"
+    )]
+    fn test_create_tx_custom_locktime_incompatible_with_cltv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(50000),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_no_rbf_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 6);
+    }
+
+    #[test]
+    fn test_create_tx_with_default_rbf_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFD);
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "Cannot enable RBF with nSequence `3`, since at least `6` is required to spend with OP_CSV"
+    )]
+    fn test_create_tx_with_custom_rbf_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .enable_rbf_with_sequence(3),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_no_rbf_cltv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFE);
+    }
+
+    #[test]
+    #[should_panic(expected = "Cannot enable RBF with a nSequence >= 0xFFFFFFFE")]
+    fn test_create_tx_invalid_rbf_sequence() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .enable_rbf_with_sequence(0xFFFFFFFE),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_custom_rbf_sequence() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .enable_rbf_with_sequence(0xDEADBEEF),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xDEADBEEF);
+    }
+
+    #[test]
+    fn test_create_tx_default_sequence() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFF);
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "The `change_policy` can be set only if the wallet has a change_descriptor"
+    )]
+    fn test_create_tx_change_policy_no_internal() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .do_not_spend_change(),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "SendAllMultipleOutputs")]
+    fn test_create_tx_send_all_multiple_outputs() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![
+                    (addr.script_pubkey(), 25_000),
+                    (addr.script_pubkey(), 10_000),
+                ])
+                .send_all(),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_send_all() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
+        assert_eq!(
+            psbt.global.unsigned_tx.output[0].value,
+            50_000 - details.fees
+        );
+    }
+
+    #[test]
+    fn test_create_tx_default_fee_rate() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::default(), @add_signature);
+    }
+
+    #[test]
+    fn test_create_tx_custom_fee_rate() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
+                    .fee_rate(FeeRate::from_sat_per_vb(5.0))
+                    .send_all(),
+            )
+            .unwrap();
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(5.0), @add_signature);
+    }
+
+    #[test]
+    fn test_create_tx_add_change() {
+        use super::tx_builder::TxOrdering;
+
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .ordering(TxOrdering::Untouched),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 2);
+        assert_eq!(psbt.global.unsigned_tx.output[0].value, 25_000);
+        assert_eq!(
+            psbt.global.unsigned_tx.output[1].value,
+            25_000 - details.fees
+        );
+    }
+
+    #[test]
+    fn test_create_tx_skip_change_dust() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                49_800,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
+        assert_eq!(psbt.global.unsigned_tx.output[0].value, 49_800);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_create_tx_send_all_dust_amount() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        // very high fee rate, so that the only output would be below dust
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
+                    .send_all()
+                    .fee_rate(crate::FeeRate::from_sat_per_vb(453.0)),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_ordering_respected() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![
+                    (addr.script_pubkey(), 30_000),
+                    (addr.script_pubkey(), 10_000),
+                ])
+                .ordering(super::tx_builder::TxOrdering::BIP69Lexicographic),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 3);
+        assert_eq!(
+            psbt.global.unsigned_tx.output[0].value,
+            10_000 - details.fees
+        );
+        assert_eq!(psbt.global.unsigned_tx.output[1].value, 10_000);
+        assert_eq!(psbt.global.unsigned_tx.output[2].value, 30_000);
+    }
+
+    #[test]
+    fn test_create_tx_default_sighash() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                30_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.inputs[0].sighash_type, Some(bitcoin::SigHashType::All));
+    }
+
+    #[test]
+    fn test_create_tx_custom_sighash() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 30_000)])
+                    .sighash(bitcoin::SigHashType::Single),
+            )
+            .unwrap();
+
+        assert_eq!(
+            psbt.inputs[0].sighash_type,
+            Some(bitcoin::SigHashType::Single)
+        );
+    }
+
+    #[test]
+    fn test_create_tx_input_hd_keypaths() {
+        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
+        use std::str::FromStr;
+
+        let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*)");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        assert_eq!(psbt.inputs[0].hd_keypaths.len(), 1);
+        assert_eq!(
+            psbt.inputs[0].hd_keypaths.values().nth(0).unwrap(),
+            &(
+                Fingerprint::from_str("d34db33f").unwrap(),
+                DerivationPath::from_str("m/44'/0'/0'/0/0").unwrap()
+            )
+        );
+    }
+
+    #[test]
+    fn test_create_tx_output_hd_keypaths() {
+        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
+        use std::str::FromStr;
+
+        let (wallet, descriptors, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*)");
+        // cache some addresses
+        wallet.get_new_address().unwrap();
+
+        let addr = testutils!(@external descriptors, 5);
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        assert_eq!(psbt.outputs[0].hd_keypaths.len(), 1);
+        assert_eq!(
+            psbt.outputs[0].hd_keypaths.values().nth(0).unwrap(),
+            &(
+                Fingerprint::from_str("d34db33f").unwrap(),
+                DerivationPath::from_str("m/44'/0'/0'/0/5").unwrap()
+            )
+        );
+    }
+
+    #[test]
+    fn test_create_tx_set_redeem_script_p2sh() {
+        use bitcoin::hashes::hex::FromHex;
+
+        let (wallet, _, _) =
+            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        assert_eq!(
+            psbt.inputs[0].redeem_script,
+            Some(Script::from(
+                Vec::<u8>::from_hex(
+                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
+                )
+                .unwrap()
+            ))
+        );
+        assert_eq!(psbt.inputs[0].witness_script, None);
+    }
+
+    #[test]
+    fn test_create_tx_set_witness_script_p2wsh() {
+        use bitcoin::hashes::hex::FromHex;
+
+        let (wallet, _, _) =
+            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        assert_eq!(psbt.inputs[0].redeem_script, None);
+        assert_eq!(
+            psbt.inputs[0].witness_script,
+            Some(Script::from(
+                Vec::<u8>::from_hex(
+                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
+                )
+                .unwrap()
+            ))
+        );
+    }
+
+    #[test]
+    fn test_create_tx_set_redeem_witness_script_p2wsh_p2sh() {
+        use bitcoin::hashes::hex::FromHex;
+
+        let (wallet, _, _) =
+            get_funded_wallet("sh(wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        let script = Script::from(
+            Vec::<u8>::from_hex(
+                "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac",
+            )
+            .unwrap(),
+        );
+
+        assert_eq!(psbt.inputs[0].redeem_script, Some(script.to_v0_p2wsh()));
+        assert_eq!(psbt.inputs[0].witness_script, Some(script));
+    }
+
+    #[test]
+    fn test_create_tx_non_witness_utxo() {
+        let (wallet, _, _) =
+            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        assert!(psbt.inputs[0].non_witness_utxo.is_some());
+        assert!(psbt.inputs[0].witness_utxo.is_none());
+    }
+
+    #[test]
+    fn test_create_tx_only_witness_utxo() {
+        let (wallet, _, _) =
+            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        assert!(psbt.inputs[0].non_witness_utxo.is_none());
+        assert!(psbt.inputs[0].witness_utxo.is_some());
+    }
+
+    #[test]
+    fn test_create_tx_both_non_witness_utxo_and_witness_utxo() {
+        let (wallet, _, _) =
+            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
+                    .force_non_witness_utxo()
+                    .send_all(),
+            )
+            .unwrap();
+
+        assert!(psbt.inputs[0].non_witness_utxo.is_some());
+        assert!(psbt.inputs[0].witness_utxo.is_some());
+    }
+
+    #[test]
+    #[should_panic(expected = "IrreplaceableTransaction")]
+    fn test_bump_fee_irreplaceable_tx() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, mut details) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+        let tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the utxos, we know they can't be used anyways
+        details.transaction = Some(tx);
+        wallet.database.borrow_mut().set_tx(&details).unwrap();
+
+        wallet.bump_fee(&txid, TxBuilder::new()).unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "TransactionConfirmed")]
+    fn test_bump_fee_confirmed_tx() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, mut details) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+        let tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the utxos, we know they can't be used anyways
+        details.transaction = Some(tx);
+        details.height = Some(42);
+        wallet.database.borrow_mut().set_tx(&details).unwrap();
+
+        wallet.bump_fee(&txid, TxBuilder::new()).unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "FeeRateTooLow")]
+    fn test_bump_fee_low_fee_rate() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, mut details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the utxos, we know they can't be used anyways
+        details.transaction = Some(tx);
+        wallet.database.borrow_mut().set_tx(&details).unwrap();
+
+        wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(1.0)),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_bump_fee_reduce_change() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(2.5)),
+            )
+            .unwrap();
+
+        assert_eq!(details.sent, original_details.sent);
+        assert_eq!(
+            details.received + details.fees,
+            original_details.received + original_details.fees
+        );
+        assert!(details.fees > original_details.fees);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            25_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(2.5), @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_reduce_send_all() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
+                    .send_all()
+                    .enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new()
+                    .send_all()
+                    .fee_rate(FeeRate::from_sat_per_vb(2.5)),
+            )
+            .unwrap();
+
+        assert_eq!(details.sent, original_details.sent);
+        assert!(details.fees > original_details.fees);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.output.len(), 1);
+        assert_eq!(tx.output[0].value + details.fees, details.sent);
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(2.5), @add_signature);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_bump_fee_remove_send_all_output() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        // receive an extra tx, to make sure that in case of "send_all" we get an error and it
+        // doesn't try to pick more inputs
+        let incoming_txid = wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
+                    .utxos(vec![OutPoint {
+                        txid: incoming_txid,
+                        vout: 0,
+                    }])
+                    .send_all()
+                    .enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+        assert_eq!(original_details.sent, 25_000);
+
+        wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new()
+                    .send_all()
+                    .fee_rate(FeeRate::from_sat_per_vb(225.0)),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_bump_fee_add_input() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(50.0)),
+            )
+            .unwrap();
+
+        assert_eq!(details.sent, original_details.sent + 25_000);
+        assert_eq!(details.fees + details.received, 30_000);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            45_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(50.0), @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_no_change_add_input_and_change() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        let incoming_txid = wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
+                    .send_all()
+                    .add_utxo(OutPoint {
+                        txid: incoming_txid,
+                        vout: 0,
+                    })
+                    .enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        // NOTE: we don't set "send_all" here. so we have a transaction with only one input, but
+        // here we are allowed to add more, and we will also have to add a change
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(50.0)),
+            )
+            .unwrap();
+
+        let original_send_all_amount = original_details.sent - original_details.fees;
+        assert_eq!(details.sent, original_details.sent + 50_000);
+        assert_eq!(
+            details.received,
+            75_000 - original_send_all_amount - details.fees
+        );
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            original_send_all_amount
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            75_000 - original_send_all_amount - details.fees
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(50.0), @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_add_input_change_dust() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        assert_eq!(tx.input.len(), 1);
+        assert_eq!(tx.output.len(), 2);
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(140.0)),
+            )
+            .unwrap();
+
+        assert_eq!(original_details.received, 5_000 - original_details.fees);
+
+        assert_eq!(details.sent, original_details.sent + 25_000);
+        assert_eq!(details.fees, 30_000);
+        assert_eq!(details.received, 0);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 1);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            45_000
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(140.0), @dust_change, @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_force_add_input() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        let incoming_txid = wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        // the new fee_rate is low enough that just reducing the change would be fine, but we force
+        // the addition of an extra input with `add_utxo()`
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new()
+                    .add_utxo(OutPoint {
+                        txid: incoming_txid,
+                        vout: 0,
+                    })
+                    .fee_rate(FeeRate::from_sat_per_vb(5.0)),
+            )
+            .unwrap();
+
+        assert_eq!(details.sent, original_details.sent + 25_000);
+        assert_eq!(details.fees + details.received, 30_000);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            45_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(5.0), @add_signature);
+    }
+
+    #[test]
+    fn test_sign_single_xprv() {
+        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
+        assert_eq!(finalized, true);
+
+        let extracted = signed_psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+
+    #[test]
+    fn test_sign_single_wif() {
+        let (wallet, _, _) =
+            get_funded_wallet("wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
+        assert_eq!(finalized, true);
+
+        let extracted = signed_psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+
+    #[test]
+    fn test_sign_single_xprv_no_hd_keypaths() {
+        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
+        let addr = wallet.get_new_address().unwrap();
+        let (mut psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
+            .unwrap();
+
+        psbt.inputs[0].hd_keypaths.clear();
+        assert_eq!(psbt.inputs[0].hd_keypaths.len(), 0);
+
+        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
+        assert_eq!(finalized, true);
+
+        let extracted = signed_psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/rbf.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/rbf.rs.html new file mode 100644 index 0000000000..2f536bf64b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/rbf.rs.html @@ -0,0 +1,257 @@ +rbf.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use crate::database::Database;
+use crate::error::Error;
+use crate::types::*;
+
+/// Filters unspent utxos
+pub(super) fn filter_available<I: Iterator<Item = UTXO>, D: Database>(
+    database: &D,
+    iter: I,
+) -> Result<Vec<UTXO>, Error> {
+    Ok(iter
+        .map(|utxo| {
+            Ok(match database.get_tx(&utxo.outpoint.txid, true)? {
+                None => None,
+                Some(tx) if tx.height.is_none() => None,
+                Some(_) => Some(utxo),
+            })
+        })
+        .collect::<Result<Vec<_>, Error>>()?
+        .into_iter()
+        .filter_map(|x| x)
+        .collect())
+}
+
+#[cfg(test)]
+mod test {
+    use std::str::FromStr;
+
+    use bitcoin::{OutPoint, Transaction, TxIn, TxOut, Txid};
+
+    use super::*;
+    use crate::database::{BatchOperations, MemoryDatabase};
+
+    fn add_transaction(
+        database: &mut MemoryDatabase,
+        spend: Vec<OutPoint>,
+        outputs: Vec<u64>,
+    ) -> Txid {
+        let tx = Transaction {
+            version: 1,
+            lock_time: 0,
+            input: spend
+                .iter()
+                .cloned()
+                .map(|previous_output| TxIn {
+                    previous_output,
+                    ..Default::default()
+                })
+                .collect(),
+            output: outputs
+                .iter()
+                .cloned()
+                .map(|value| TxOut {
+                    value,
+                    ..Default::default()
+                })
+                .collect(),
+        };
+        let txid = tx.txid();
+
+        for input in &spend {
+            database.del_utxo(input).unwrap();
+        }
+        for vout in 0..outputs.len() {
+            database
+                .set_utxo(&UTXO {
+                    txout: tx.output[vout].clone(),
+                    outpoint: OutPoint {
+                        txid,
+                        vout: vout as u32,
+                    },
+                    is_internal: true,
+                })
+                .unwrap();
+        }
+        database
+            .set_tx(&TransactionDetails {
+                txid,
+                transaction: Some(tx),
+                height: None,
+                ..Default::default()
+            })
+            .unwrap();
+
+        txid
+    }
+
+    #[test]
+    fn test_filter_available() {
+        let mut database = MemoryDatabase::new();
+        add_transaction(
+            &mut database,
+            vec![OutPoint::from_str(
+                "aad194c72fd5cfd16d23da9462930ca91e35df1cfee05242b62f4034f50c3d41:5",
+            )
+            .unwrap()],
+            vec![50_000],
+        );
+
+        let filtered =
+            filter_available(&database, database.iter_utxos().unwrap().into_iter()).unwrap();
+        assert_eq!(filtered, &[]);
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/signer.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/signer.rs.html new file mode 100644 index 0000000000..8678817881 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/signer.rs.html @@ -0,0 +1,1029 @@ +signer.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! 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 std::sync::Arc;
+//! # use std::str::FromStr;
+//! # use bitcoin::*;
+//! # use bitcoin::util::psbt;
+//! # use bitcoin::util::bip32::Fingerprint;
+//! # use bdk::signer::*;
+//! # use bdk::database::*;
+//! # use bdk::*;
+//! # #[derive(Debug)]
+//! # struct CustomHSM;
+//! # impl CustomHSM {
+//! #     fn sign_input(&self, _psbt: &mut psbt::PartiallySignedTransaction, _input: usize) -> Result<(), SignerError> {
+//! #         Ok(())
+//! #     }
+//! #     fn connect() -> Self {
+//! #         CustomHSM
+//! #     }
+//! # }
+//! #[derive(Debug)]
+//! struct CustomSigner {
+//!     device: CustomHSM,
+//! }
+//!
+//! impl CustomSigner {
+//!     fn connect() -> Self {
+//!         CustomSigner { device: CustomHSM::connect() }
+//!     }
+//! }
+//!
+//! impl Signer for CustomSigner {
+//!     fn sign(
+//!         &self,
+//!         psbt: &mut psbt::PartiallySignedTransaction,
+//!         input_index: Option<usize>,
+//!     ) -> Result<(), SignerError> {
+//!         let input_index = input_index.ok_or(SignerError::InputIndexOutOfRange)?;
+//!         self.device.sign_input(psbt, input_index)?;
+//!
+//!         Ok(())
+//!     }
+//!
+//!     fn sign_whole_tx(&self) -> bool {
+//!         false
+//!     }
+//! }
+//!
+//! let custom_signer = CustomSigner::connect();
+//!
+//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+//! let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+//! wallet.add_signer(
+//!     ScriptType::External,
+//!     Fingerprint::from_str("e30f11b8").unwrap().into(),
+//!     SignerOrdering(200),
+//!     Arc::new(Box::new(custom_signer))
+//! );
+//!
+//! # Ok::<_, bdk::Error>(())
+//! ```
+
+use std::cmp::Ordering;
+use std::collections::BTreeMap;
+use std::fmt;
+use std::ops::Bound::Included;
+use std::sync::Arc;
+
+use bitcoin::blockdata::opcodes;
+use bitcoin::blockdata::script::Builder as ScriptBuilder;
+use bitcoin::hashes::{hash160, Hash};
+use bitcoin::secp256k1::{Message, Secp256k1};
+use bitcoin::util::bip32::{ExtendedPrivKey, Fingerprint};
+use bitcoin::util::{bip143, psbt};
+use bitcoin::{PrivateKey, SigHash, SigHashType};
+
+use miniscript::descriptor::{DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey, KeyMap};
+use miniscript::{Legacy, MiniscriptKey, Segwitv0};
+
+use crate::descriptor::XKeyUtils;
+
+/// Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among
+/// multiple of them
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum SignerId<Pk: MiniscriptKey> {
+    PkHash(<Pk as MiniscriptKey>::Hash),
+    Fingerprint(Fingerprint),
+}
+
+impl From<hash160::Hash> for SignerId<DescriptorPublicKey> {
+    fn from(hash: hash160::Hash) -> SignerId<DescriptorPublicKey> {
+        SignerId::PkHash(hash)
+    }
+}
+
+impl From<Fingerprint> for SignerId<DescriptorPublicKey> {
+    fn from(fing: Fingerprint) -> SignerId<DescriptorPublicKey> {
+        SignerId::Fingerprint(fing)
+    }
+}
+
+/// Signing error
+#[derive(Debug, PartialEq, Eq, Clone)]
+pub enum SignerError {
+    /// The private key is missing for the required public key
+    MissingKey,
+    /// The user canceled the operation
+    UserCanceled,
+    /// The sighash is missing in the PSBT input
+    MissingSighash,
+    /// 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 requied to sign this input
+    MissingWitnessScript,
+    /// The fingerprint and derivation path are missing from the psbt input
+    MissingHDKeypath,
+}
+
+impl fmt::Display for SignerError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for SignerError {}
+
+/// Trait for signers
+///
+/// This trait can be implemented to provide customized signers to the wallet. For an example see
+/// [`this module`](crate::wallet::signer)'s documentation.
+pub trait Signer: fmt::Debug {
+    /// Sign a PSBT
+    ///
+    /// The `input_index` argument is only provided if the wallet doesn't declare to sign the whole
+    /// transaction in one go (see [`Signer::sign_whole_tx`]). Otherwise its value is `None` and
+    /// can be ignored.
+    fn sign(
+        &self,
+        psbt: &mut psbt::PartiallySignedTransaction,
+        input_index: Option<usize>,
+    ) -> Result<(), SignerError>;
+
+    /// Return whether or not the signer signs the whole transaction in one go instead of every
+    /// input individually
+    fn sign_whole_tx(&self) -> bool;
+
+    /// 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
+    }
+}
+
+impl Signer for DescriptorXKey<ExtendedPrivKey> {
+    fn sign(
+        &self,
+        psbt: &mut psbt::PartiallySignedTransaction,
+        input_index: Option<usize>,
+    ) -> Result<(), SignerError> {
+        let input_index = input_index.unwrap();
+        if input_index >= psbt.inputs.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let deriv_path = match psbt.inputs[input_index]
+            .hd_keypaths
+            .iter()
+            .filter_map(|(_, &(fingerprint, ref path))| self.matches(fingerprint.clone(), &path))
+            .next()
+        {
+            Some(deriv_path) => deriv_path,
+            None => return Ok(()), // TODO: should report an error maybe?
+        };
+
+        let ctx = Secp256k1::signing_only();
+
+        let derived_key = self.xkey.derive_priv(&ctx, &deriv_path).unwrap();
+        derived_key.private_key.sign(psbt, Some(input_index))
+    }
+
+    fn sign_whole_tx(&self) -> bool {
+        false
+    }
+
+    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
+        Some(DescriptorSecretKey::XPrv(self.clone()))
+    }
+}
+
+impl Signer for PrivateKey {
+    fn sign(
+        &self,
+        psbt: &mut psbt::PartiallySignedTransaction,
+        input_index: Option<usize>,
+    ) -> Result<(), SignerError> {
+        let input_index = input_index.unwrap();
+        if input_index >= psbt.inputs.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let ctx = Secp256k1::signing_only();
+
+        let pubkey = self.public_key(&ctx);
+        if psbt.inputs[input_index].partial_sigs.contains_key(&pubkey) {
+            return Ok(());
+        }
+
+        // FIXME: use the presence of `witness_utxo` as an indication that we should make a bip143
+        // sig. Does this make sense? Should we add an extra argument to explicitly swith between
+        // these? The original idea was to declare sign() as sign<Ctx: ScriptContex>() and use Ctx,
+        // but that violates the rules for trait-objects, so we can't do it.
+        let (hash, sighash) = match psbt.inputs[input_index].witness_utxo {
+            Some(_) => Segwitv0::sighash(psbt, input_index)?,
+            None => Legacy::sighash(psbt, input_index)?,
+        };
+
+        let signature = ctx.sign(
+            &Message::from_slice(&hash.into_inner()[..]).unwrap(),
+            &self.key,
+        );
+
+        let mut final_signature = Vec::with_capacity(75);
+        final_signature.extend_from_slice(&signature.serialize_der());
+        final_signature.push(sighash.as_u32() as u8);
+
+        psbt.inputs[input_index]
+            .partial_sigs
+            .insert(pubkey, final_signature);
+
+        Ok(())
+    }
+
+    fn sign_whole_tx(&self) -> bool {
+        false
+    }
+
+    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
+        Some(DescriptorSecretKey::PrivKey(self.clone()))
+    }
+}
+
+/// 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 std::default::Default for SignerOrdering {
+    fn default() -> Self {
+        SignerOrdering(100)
+    }
+}
+
+#[derive(Debug, Clone)]
+struct SignersContainerKey<Pk: MiniscriptKey> {
+    id: SignerId<Pk>,
+    ordering: SignerOrdering,
+}
+
+impl<Pk: MiniscriptKey> From<(SignerId<Pk>, SignerOrdering)> for SignersContainerKey<Pk> {
+    fn from(tuple: (SignerId<Pk>, SignerOrdering)) -> Self {
+        SignersContainerKey {
+            id: tuple.0,
+            ordering: tuple.1,
+        }
+    }
+}
+
+/// Container for multiple signers
+#[derive(Debug, Default, Clone)]
+pub struct SignersContainer<Pk: MiniscriptKey>(
+    BTreeMap<SignersContainerKey<Pk>, Arc<Box<dyn Signer>>>,
+);
+
+impl SignersContainer<DescriptorPublicKey> {
+    pub fn as_key_map(&self) -> KeyMap {
+        self.0
+            .values()
+            .filter_map(|signer| signer.descriptor_secret_key())
+            .filter_map(|secret| secret.as_public().ok().map(|public| (public, secret)))
+            .collect()
+    }
+}
+
+impl From<KeyMap> for SignersContainer<DescriptorPublicKey> {
+    fn from(keymap: KeyMap) -> SignersContainer<DescriptorPublicKey> {
+        let mut container = SignersContainer::new();
+
+        for (_, secret) in keymap {
+            match secret {
+                DescriptorSecretKey::PrivKey(private_key) => container.add_external(
+                    SignerId::from(
+                        private_key
+                            .public_key(&Secp256k1::signing_only())
+                            .to_pubkeyhash(),
+                    ),
+                    SignerOrdering::default(),
+                    Arc::new(Box::new(private_key)),
+                ),
+                DescriptorSecretKey::XPrv(xprv) => container.add_external(
+                    SignerId::from(xprv.root_fingerprint()),
+                    SignerOrdering::default(),
+                    Arc::new(Box::new(xprv)),
+                ),
+            };
+        }
+
+        container
+    }
+}
+
+impl<Pk: MiniscriptKey> SignersContainer<Pk> {
+    /// 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 previosuly in the container, if any
+    pub fn add_external(
+        &mut self,
+        id: SignerId<Pk>,
+        ordering: SignerOrdering,
+        signer: Arc<Box<dyn Signer>>,
+    ) -> Option<Arc<Box<dyn Signer>>> {
+        self.0.insert((id, ordering).into(), signer)
+    }
+
+    /// Removes a signer from the container and returns it
+    pub fn remove(
+        &mut self,
+        id: SignerId<Pk>,
+        ordering: SignerOrdering,
+    ) -> Option<Arc<Box<dyn Signer>>> {
+        self.0.remove(&(id, ordering).into())
+    }
+
+    /// Returns the list of identifiers of all the signers in the container
+    pub fn ids(&self) -> Vec<&SignerId<Pk>> {
+        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<Box<dyn Signer>>> {
+        self.0.values().collect()
+    }
+
+    /// Finds the signer with lowest ordering for a given id in the container.
+    pub fn find(&self, id: SignerId<Pk>) -> Option<&Arc<Box<dyn Signer>>> {
+        self.0
+            .range((
+                Included(&(id.clone(), SignerOrdering(0)).into()),
+                Included(&(id, SignerOrdering(usize::MAX)).into()),
+            ))
+            .map(|(_, v)| v)
+            .nth(0)
+    }
+}
+
+pub(crate) trait ComputeSighash {
+    fn sighash(
+        psbt: &psbt::PartiallySignedTransaction,
+        input_index: usize,
+    ) -> Result<(SigHash, SigHashType), SignerError>;
+}
+
+impl ComputeSighash for Legacy {
+    fn sighash(
+        psbt: &psbt::PartiallySignedTransaction,
+        input_index: usize,
+    ) -> Result<(SigHash, SigHashType), SignerError> {
+        if input_index >= psbt.inputs.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let psbt_input = &psbt.inputs[input_index];
+        let tx_input = &psbt.global.unsigned_tx.input[input_index];
+
+        let sighash = psbt_input.sighash_type.ok_or(SignerError::MissingSighash)?;
+        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((
+            psbt.global
+                .unsigned_tx
+                .signature_hash(input_index, &script, sighash.as_u32()),
+            sighash,
+        ))
+    }
+}
+
+impl ComputeSighash for Segwitv0 {
+    fn sighash(
+        psbt: &psbt::PartiallySignedTransaction,
+        input_index: usize,
+    ) -> Result<(SigHash, SigHashType), SignerError> {
+        if input_index >= psbt.inputs.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let psbt_input = &psbt.inputs[input_index];
+
+        let sighash = psbt_input.sighash_type.ok_or(SignerError::MissingSighash)?;
+
+        let witness_utxo = psbt_input
+            .witness_utxo
+            .as_ref()
+            .ok_or(SignerError::MissingNonWitnessUtxo)?;
+        let value = witness_utxo.value;
+
+        let script = match &psbt_input.witness_script {
+            &Some(ref witness_script) => witness_script.clone(),
+            &None => {
+                if witness_utxo.script_pubkey.is_v0_p2wpkh() {
+                    ScriptBuilder::new()
+                        .push_opcode(opcodes::all::OP_DUP)
+                        .push_opcode(opcodes::all::OP_HASH160)
+                        .push_slice(&witness_utxo.script_pubkey[2..])
+                        .push_opcode(opcodes::all::OP_EQUALVERIFY)
+                        .push_opcode(opcodes::all::OP_CHECKSIG)
+                        .into_script()
+                } else {
+                    return Err(SignerError::MissingWitnessScript);
+                }
+            }
+        };
+
+        Ok((
+            bip143::SigHashCache::new(&psbt.global.unsigned_tx).signature_hash(
+                input_index,
+                &script,
+                value,
+                sighash,
+            ),
+            sighash,
+        ))
+    }
+}
+
+impl<Pk: MiniscriptKey> PartialOrd for SignersContainerKey<Pk> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.cmp(other))
+    }
+}
+
+impl<Pk: MiniscriptKey> Ord for SignersContainerKey<Pk> {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.ordering.cmp(&other.ordering)
+    }
+}
+
+impl<Pk: MiniscriptKey> PartialEq for SignersContainerKey<Pk> {
+    fn eq(&self, other: &Self) -> bool {
+        self.ordering == other.ordering
+    }
+}
+
+impl<Pk: MiniscriptKey> Eq for SignersContainerKey<Pk> {}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/time.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/time.rs.html new file mode 100644 index 0000000000..a608dd4158 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/time.rs.html @@ -0,0 +1,175 @@ +time.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Cross-platform time
+//!
+//! This module provides a function to get the current timestamp that works on all the platforms
+//! supported by the library.
+//!
+//! It can be useful to compare it with the timestamps found in
+//! [`TransactionDetails`](crate::types::TransactionDetails).
+
+use std::time::Duration;
+
+#[cfg(target_arch = "wasm32")]
+use js_sys::Date;
+#[cfg(not(target_arch = "wasm32"))]
+use std::time::{Instant as SystemInstant, SystemTime, UNIX_EPOCH};
+
+/// Return the current timestamp in seconds
+#[cfg(not(target_arch = "wasm32"))]
+pub fn get_timestamp() -> u64 {
+    SystemTime::now()
+        .duration_since(UNIX_EPOCH)
+        .unwrap()
+        .as_secs()
+}
+/// Return the current timestamp in seconds
+#[cfg(target_arch = "wasm32")]
+pub fn get_timestamp() -> u64 {
+    let millis = Date::now();
+
+    (millis / 1000.0) as u64
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+pub(crate) struct Instant(SystemInstant);
+#[cfg(target_arch = "wasm32")]
+pub(crate) struct Instant(Duration);
+
+impl Instant {
+    #[cfg(not(target_arch = "wasm32"))]
+    pub fn new() -> Self {
+        Instant(SystemInstant::now())
+    }
+    #[cfg(target_arch = "wasm32")]
+    pub fn new() -> Self {
+        let millis = Date::now();
+
+        let secs = millis / 1000.0;
+        let nanos = (millis % 1000.0) * 1e6;
+
+        Instant(Duration::new(secs as u64, nanos as u32))
+    }
+
+    #[cfg(not(target_arch = "wasm32"))]
+    pub fn elapsed(&self) -> Duration {
+        self.0.elapsed()
+    }
+    #[cfg(target_arch = "wasm32")]
+    pub fn elapsed(&self) -> Duration {
+        let now = Instant::new();
+
+        now.0.checked_sub(self.0).unwrap_or(Duration::new(0, 0))
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/tx_builder.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/tx_builder.rs.html new file mode 100644 index 0000000000..389d6daf07 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/tx_builder.rs.html @@ -0,0 +1,979 @@ +tx_builder.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Transaction builder
+//!
+//! ## Example
+//!
+//! ```
+//! # use std::str::FromStr;
+//! # use bitcoin::*;
+//! # use bdk::*;
+//! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+//! // Create a transaction with one output to `to_address` of 50_000 satoshi, with a custom fee rate
+//! // of 5.0 satoshi/vbyte, only spending non-change outputs and with RBF signaling
+//! // enabled
+//! let builder = TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+//!     .fee_rate(FeeRate::from_sat_per_vb(5.0))
+//!     .do_not_spend_change()
+//!     .enable_rbf();
+//! ```
+
+use std::collections::BTreeMap;
+use std::default::Default;
+
+use bitcoin::{OutPoint, Script, SigHashType, Transaction};
+
+use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm};
+use crate::types::{FeeRate, UTXO};
+
+/// A transaction builder
+///
+/// This structure contains the configuration that the wallet must follow to build a transaction.
+///
+/// For an example see [this module](super::tx_builder)'s documentation;
+#[derive(Debug, Default)]
+pub struct TxBuilder<Cs: CoinSelectionAlgorithm> {
+    pub(crate) recipients: Vec<(Script, u64)>,
+    pub(crate) send_all: bool,
+    pub(crate) fee_rate: Option<FeeRate>,
+    pub(crate) policy_path: Option<BTreeMap<String, Vec<usize>>>,
+    pub(crate) utxos: Option<Vec<OutPoint>>,
+    pub(crate) unspendable: Option<Vec<OutPoint>>,
+    pub(crate) sighash: Option<SigHashType>,
+    pub(crate) ordering: TxOrdering,
+    pub(crate) locktime: Option<u32>,
+    pub(crate) rbf: Option<u32>,
+    pub(crate) version: Option<Version>,
+    pub(crate) change_policy: ChangeSpendPolicy,
+    pub(crate) force_non_witness_utxo: bool,
+    pub(crate) coin_selection: Cs,
+}
+
+impl TxBuilder<DefaultCoinSelectionAlgorithm> {
+    /// Create an empty builder
+    pub fn new() -> Self {
+        Self::default()
+    }
+
+    /// Create a builder starting from a list of recipients
+    pub fn with_recipients(recipients: Vec<(Script, u64)>) -> Self {
+        Self::default().set_recipients(recipients)
+    }
+}
+
+impl<Cs: CoinSelectionAlgorithm> TxBuilder<Cs> {
+    /// Replace the recipients already added with a new list
+    pub fn set_recipients(mut self, recipients: Vec<(Script, u64)>) -> Self {
+        self.recipients = recipients;
+        self
+    }
+
+    /// Add a recipient to the internal list
+    pub fn add_recipient(mut self, script_pubkey: Script, amount: u64) -> Self {
+        self.recipients.push((script_pubkey, amount));
+        self
+    }
+
+    /// Send all the selected utxos to a single output
+    ///
+    /// Adding more than one recipients with this option enabled will result in an error.
+    ///
+    /// The value associated with the only recipient is irrelevant and will be replaced by the wallet.
+    pub fn send_all(mut self) -> Self {
+        self.send_all = true;
+        self
+    }
+
+    /// Set a custom fee rate
+    pub fn fee_rate(mut self, fee_rate: FeeRate) -> Self {
+        self.fee_rate = Some(fee_rate);
+        self
+    }
+
+    /// Set the policy path to use while creating the transaction
+    ///
+    /// 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)).
+    pub fn policy_path(mut self, policy_path: BTreeMap<String, Vec<usize>>) -> Self {
+        self.policy_path = Some(policy_path);
+        self
+    }
+
+    /// Replace the internal list of utxos that **must** be spent with a new list
+    ///
+    /// 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 utxos(mut self, utxos: Vec<OutPoint>) -> Self {
+        self.utxos = Some(utxos);
+        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, utxo: OutPoint) -> Self {
+        self.utxos.get_or_insert(vec![]).push(utxo);
+        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::utxos`] and
+    /// [`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>) -> Self {
+        self.unspendable = Some(unspendable);
+        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::utxos`] and
+    /// [`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) -> Self {
+        self.unspendable.get_or_insert(vec![]).push(unspendable);
+        self
+    }
+
+    /// Sign with a specific sig hash
+    ///
+    /// **Use this option very carefully**
+    pub fn sighash(mut self, sighash: SigHashType) -> Self {
+        self.sighash = Some(sighash);
+        self
+    }
+
+    /// Choose the ordering for inputs and outputs of the transaction
+    pub fn ordering(mut self, ordering: TxOrdering) -> Self {
+        self.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: u32) -> Self {
+        self.locktime = Some(locktime);
+        self
+    }
+
+    /// Enable signaling RBF
+    ///
+    /// This will use the default nSequence value of `0xFFFFFFFD`.
+    pub fn enable_rbf(self) -> Self {
+        self.enable_rbf_with_sequence(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.
+    pub fn enable_rbf_with_sequence(mut self, nsequence: u32) -> Self {
+        self.rbf = Some(nsequence);
+        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: u32) -> Self {
+        self.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) -> Self {
+        self.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) -> Self {
+        self.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) -> Self {
+        self.change_policy = change_policy;
+        self
+    }
+
+    /// Fill-in the [`psbt::Input::non_witness_utxo`](bitcoin::util::psbt::Input::non_witness_utxo) field even if the wallet only has SegWit
+    /// descriptors.
+    ///
+    /// This is useful for signers which always require it, like Trezor hardware wallets.
+    pub fn force_non_witness_utxo(mut self) -> Self {
+        self.force_non_witness_utxo = true;
+        self
+    }
+
+    /// Choose the coin selection algorithm
+    ///
+    /// Overrides the [`DefaultCoinSelectionAlgorithm`](super::coin_selection::DefaultCoinSelectionAlgorithm).
+    pub fn coin_selection<P: CoinSelectionAlgorithm>(self, coin_selection: P) -> TxBuilder<P> {
+        TxBuilder {
+            recipients: self.recipients,
+            send_all: self.send_all,
+            fee_rate: self.fee_rate,
+            policy_path: self.policy_path,
+            utxos: self.utxos,
+            unspendable: self.unspendable,
+            sighash: self.sighash,
+            ordering: self.ordering,
+            locktime: self.locktime,
+            rbf: self.rbf,
+            version: self.version,
+            change_policy: self.change_policy,
+            force_non_witness_utxo: self.force_non_witness_utxo,
+            coin_selection,
+        }
+    }
+}
+
+/// Ordering of the transaction's inputs and outputs
+#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
+pub enum TxOrdering {
+    /// Randomized (default)
+    Shuffle,
+    /// Unchanged
+    Untouched,
+    /// BIP69 / Lexicographic
+    BIP69Lexicographic,
+}
+
+impl Default for TxOrdering {
+    fn default() -> Self {
+        TxOrdering::Shuffle
+    }
+}
+
+impl TxOrdering {
+    pub fn sort_tx(&self, tx: &mut Transaction) {
+        match self {
+            TxOrdering::Untouched => {}
+            TxOrdering::Shuffle => {
+                use rand::seq::SliceRandom;
+                #[cfg(test)]
+                use rand::SeedableRng;
+
+                #[cfg(not(test))]
+                let mut rng = rand::thread_rng();
+                #[cfg(test)]
+                let mut rng = rand::rngs::StdRng::seed_from_u64(0);
+
+                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) u32);
+
+impl Default for Version {
+    fn default() -> Self {
+        Version(1)
+    }
+}
+
+/// Policy regarding the use of change outputs when creating a transaction
+#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
+pub enum ChangeSpendPolicy {
+    /// Use both change and non-change outputs (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 Default for ChangeSpendPolicy {
+    fn default() -> Self {
+        ChangeSpendPolicy::ChangeAllowed
+    }
+}
+
+impl ChangeSpendPolicy {
+    pub(crate) fn filter_utxos<I: Iterator<Item = UTXO>>(&self, iter: I) -> Vec<UTXO> {
+        match self {
+            ChangeSpendPolicy::ChangeAllowed => iter.collect(),
+            ChangeSpendPolicy::OnlyChange => iter.filter(|utxo| utxo.is_internal).collect(),
+            ChangeSpendPolicy::ChangeForbidden => iter.filter(|utxo| !utxo.is_internal).collect(),
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    const ORDERING_TEST_TX: &'static 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 bitcoin::consensus::deserialize;
+    use bitcoin::hashes::hex::FromHex;
+
+    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();
+
+        TxOrdering::Shuffle.sort_tx(&mut tx);
+
+        assert_eq!(original_tx.input, tx.input);
+        assert_ne!(original_tx.output, tx.output);
+    }
+
+    #[test]
+    fn test_output_ordering_bip69() {
+        use std::str::FromStr;
+
+        let original_tx = ordering_test_tx!();
+        let mut tx = original_tx.clone();
+
+        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, 800);
+        assert_eq!(tx.output[1].script_pubkey, From::from(vec![0xAA]));
+        assert_eq!(tx.output[2].script_pubkey, From::from(vec![0xAA, 0xEE]));
+    }
+
+    fn get_test_utxos() -> Vec<UTXO> {
+        vec![
+            UTXO {
+                outpoint: OutPoint {
+                    txid: Default::default(),
+                    vout: 0,
+                },
+                txout: Default::default(),
+                is_internal: false,
+            },
+            UTXO {
+                outpoint: OutPoint {
+                    txid: Default::default(),
+                    vout: 1,
+                },
+                txout: Default::default(),
+                is_internal: true,
+            },
+        ]
+    }
+
+    #[test]
+    fn test_change_spend_policy_default() {
+        let change_spend_policy = ChangeSpendPolicy::default();
+        let filtered = change_spend_policy.filter_utxos(get_test_utxos().into_iter());
+
+        assert_eq!(filtered.len(), 2);
+    }
+
+    #[test]
+    fn test_change_spend_policy_no_internal() {
+        let change_spend_policy = ChangeSpendPolicy::ChangeForbidden;
+        let filtered = change_spend_policy.filter_utxos(get_test_utxos().into_iter());
+
+        assert_eq!(filtered.len(), 1);
+        assert_eq!(filtered[0].is_internal, false);
+    }
+
+    #[test]
+    fn test_change_spend_policy_only_internal() {
+        let change_spend_policy = ChangeSpendPolicy::OnlyChange;
+        let filtered = change_spend_policy.filter_utxos(get_test_utxos().into_iter());
+
+        assert_eq!(filtered.len(), 1);
+        assert_eq!(filtered[0].is_internal, true);
+    }
+
+    #[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/0.1.0-beta.1/src/bdk/wallet/utils.rs.html b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/utils.rs.html new file mode 100644 index 0000000000..7fda4f9243 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/utils.rs.html @@ -0,0 +1,311 @@ +utils.rs.html -- 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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use miniscript::{MiniscriptKey, Satisfier};
+
+// De-facto standard "dust limit" (even though it should change based on the output type)
+const DUST_LIMIT_SATOSHI: u64 = 546;
+
+/// Trait to check if a value is below the dust limit
+// we implement this trait to make sure we don't mess up the comparison with off-by-one like a <
+// instead of a <= etc. The constant value for the dust limit is not public on purpose, to
+// encourage the usage of this trait.
+pub trait IsDust {
+    /// Check whether or not a value is below dust limit
+    fn is_dust(&self) -> bool;
+}
+
+impl IsDust for u64 {
+    fn is_dust(&self) -> bool {
+        *self <= DUST_LIMIT_SATOSHI
+    }
+}
+
+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,
+        }
+    }
+}
+
+impl<Pk: MiniscriptKey> Satisfier<Pk> for After {
+    fn check_after(&self, n: u32) -> bool {
+        if let Some(current_height) = self.current_height {
+            current_height >= n
+        } 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> Satisfier<Pk> for Older {
+    fn check_older(&self, n: u32) -> bool {
+        if let Some(current_height) = self.current_height {
+            // TODO: test >= / >
+            current_height as u64 >= self.create_height.unwrap_or(0) as u64 + n as u64
+        } else {
+            self.assume_height_reached
+        }
+    }
+}
+
+pub struct ChunksIterator<I: Iterator> {
+    iter: I,
+    size: usize,
+}
+
+impl<I: Iterator> ChunksIterator<I> {
+    pub fn new(iter: I, size: usize) -> Self {
+        ChunksIterator { iter, size }
+    }
+}
+
+impl<I: Iterator> Iterator for ChunksIterator<I> {
+    type Item = Vec<<I as std::iter::Iterator>::Item>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let mut v = Vec::new();
+        for _ in 0..self.size {
+            let e = self.iter.next();
+
+            match e {
+                None => break,
+                Some(val) => v.push(val),
+            }
+        }
+
+        if v.is_empty() {
+            return None;
+        }
+
+        Some(v)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use crate::types::FeeRate;
+
+    #[test]
+    fn test_fee_from_btc_per_kb() {
+        let fee = FeeRate::from_btc_per_kvb(1e-5);
+        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
+    }
+
+    #[test]
+    fn test_fee_from_sats_vbyte() {
+        let fee = FeeRate::from_sat_per_vb(1.0);
+        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
+    }
+
+    #[test]
+    fn test_fee_default_min_relay_fee() {
+        let fee = FeeRate::default_min_relay_fee();
+        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/storage.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/storage.js new file mode 100644 index 0000000000..1b5225126f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/storage.js @@ -0,0 +1 @@ +var resourcesSuffix="";var currentTheme=document.getElementById("themeStyle");var mainTheme=document.getElementById("mainThemeStyle");var savedHref=[];function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(!elem||!elem.classList){return}elem.classList.add(className)}function removeClass(elem,className){if(!elem||!elem.classList){return}elem.classList.remove(className)}function onEach(arr,func,reversed){if(arr&&arr.length>0&&func){var length=arr.length;var i;if(reversed!==true){for(i=0;i=0;--i){if(func(arr[i])===true){return true}}}}return false}function onEachLazy(lazyArray,func,reversed){return onEach(Array.prototype.slice.call(lazyArray),func,reversed)}function hasOwnProperty(obj,property){return Object.prototype.hasOwnProperty.call(obj,property)}function usableLocalStorage(){if(typeof Storage==="undefined"){return false}try{return window.localStorage!==null&&window.localStorage!==undefined}catch(err){return false}}function updateLocalStorage(name,value){if(usableLocalStorage()){localStorage[name]=value}else{}}function getCurrentValue(name){if(usableLocalStorage()&&localStorage[name]!==undefined){return localStorage[name]}return null}function switchTheme(styleElem,mainStyleElem,newTheme,saveTheme){var fullBasicCss="rustdoc"+resourcesSuffix+".css";var fullNewTheme=newTheme+resourcesSuffix+".css";var newHref=mainStyleElem.href.replace(fullBasicCss,fullNewTheme);if(styleElem.href===newHref){return}var found=false;if(savedHref.length===0){onEachLazy(document.getElementsByTagName("link"),function(el){savedHref.push(el.href)})}onEach(savedHref,function(el){if(el===newHref){found=true;return true}});if(found===true){styleElem.href=newHref;if(saveTheme===true){updateLocalStorage("rustdoc-theme",newTheme)}}}function getSystemValue(){var property=getComputedStyle(document.documentElement).getPropertyValue('content');return property.replace(/[\"\']/g,"")}switchTheme(currentTheme,mainTheme,getCurrentValue("rustdoc-theme")||getSystemValue()||"light",false) \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/theme.js b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/theme.js new file mode 100644 index 0000000000..ebd1a87271 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/theme.js @@ -0,0 +1 @@ +var themes=document.getElementById("theme-choices");var themePicker=document.getElementById("theme-picker");function showThemeButtonState(){themes.style.display="block";themePicker.style.borderBottomRightRadius="0";themePicker.style.borderBottomLeftRadius="0"}function hideThemeButtonState(){themes.style.display="none";themePicker.style.borderBottomRightRadius="3px";themePicker.style.borderBottomLeftRadius="3px"}function switchThemeButtonState(){if(themes.style.display==="block"){hideThemeButtonState()}else{showThemeButtonState()}};function handleThemeButtonsBlur(e){var active=document.activeElement;var related=e.relatedTarget;if(active.id!=="themePicker"&&(!active.parentNode||active.parentNode.id!=="theme-choices")&&(!related||(related.id!=="themePicker"&&(!related.parentNode||related.parentNode.id!=="theme-choices")))){hideThemeButtonState()}}themePicker.onclick=switchThemeButtonState;themePicker.onblur=handleThemeButtonsBlur;["dark","light"].forEach(function(item){var but=document.createElement('button');but.textContent=item;but.onclick=function(el){switchTheme(currentTheme,mainTheme,item,true)};but.onblur=handleThemeButtonsBlur;themes.appendChild(but)}) \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/wheel.svg b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/wheel.svg new file mode 100644 index 0000000000..01da3b24c7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/0.1.0-beta.1/wheel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/index.html b/docs/.vuepress/public/docs-rs/bdk/index.html new file mode 100644 index 0000000000..2a1a8bba18 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/index.html @@ -0,0 +1,12 @@ + + + Redirect + + + +

+ You are being re-directed to the latest version.
+ If that doesn't happen click here. +

+ + diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/.lock b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/.lock new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/COPYRIGHT.txt b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/COPYRIGHT.txt new file mode 100644 index 0000000000..af77776cca --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/COPYRIGHT.txt @@ -0,0 +1,45 @@ +These documentation pages include resources by third parties. This copyright +file applies only to those resources. The following third party resources are +included, and carry their own copyright notices and license terms: + +* Fira Sans (FiraSans-Regular.woff, FiraSans-Medium.woff): + + Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ + with Reserved Font Name Fira Sans. + + Copyright (c) 2014, Telefonica S.A. + + Licensed under the SIL Open Font License, Version 1.1. + See FiraSans-LICENSE.txt. + +* rustdoc.css, main.js, and playpen.js: + + Copyright 2015 The Rust Developers. + Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or + the MIT license (LICENSE-MIT.txt) at your option. + +* normalize.css: + + Copyright (c) Nicolas Gallagher and Jonathan Neal. + Licensed under the MIT license (see LICENSE-MIT.txt). + +* Source Code Pro (SourceCodePro-Regular.woff, SourceCodePro-Semibold.woff): + + Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), + with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark + of Adobe Systems Incorporated in the United States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceCodePro-LICENSE.txt. + +* Source Serif Pro (SourceSerifPro-Regular.ttf.woff, + SourceSerifPro-Bold.ttf.woff, SourceSerifPro-It.ttf.woff): + + Copyright 2014 Adobe Systems Incorporated (http://www.adobe.com/), with + Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of + Adobe Systems Incorporated in the United States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceSerifPro-LICENSE.txt. + +This copyright file is intended to be distributed with rustdoc output. diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-LICENSE.txt b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-LICENSE.txt new file mode 100644 index 0000000000..d444ea92b6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-LICENSE.txt @@ -0,0 +1,94 @@ +Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. +with Reserved Font Name < Fira >, + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-Medium.woff b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-Medium.woff new file mode 100644 index 0000000000..7d742c5fb7 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-Medium.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-Regular.woff b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-Regular.woff new file mode 100644 index 0000000000..d8e0363f4e Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-Regular.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/LICENSE-APACHE.txt b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/LICENSE-APACHE.txt new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/LICENSE-APACHE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/LICENSE-MIT.txt b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/LICENSE-MIT.txt new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/LICENSE-MIT.txt @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-LICENSE.txt b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-LICENSE.txt new file mode 100644 index 0000000000..07542572e3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-LICENSE.txt @@ -0,0 +1,93 @@ +Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-Regular.woff b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-Regular.woff new file mode 100644 index 0000000000..5576670903 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-Regular.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-Semibold.woff b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-Semibold.woff new file mode 100644 index 0000000000..ca972a11dc Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-Semibold.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-Bold.ttf.woff b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-Bold.ttf.woff new file mode 100644 index 0000000000..ca254318fe Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-Bold.ttf.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-It.ttf.woff b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-It.ttf.woff new file mode 100644 index 0000000000..a287bbe6ed Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-It.ttf.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-LICENSE.md b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-LICENSE.md new file mode 100644 index 0000000000..22cb755f2f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-LICENSE.md @@ -0,0 +1,93 @@ +Copyright 2014-2018 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-Regular.ttf.woff b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-Regular.ttf.woff new file mode 100644 index 0000000000..a3d55cfdf2 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-Regular.ttf.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/ayu.css b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/ayu.css new file mode 100644 index 0000000000..ae61550be2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/ayu.css @@ -0,0 +1 @@ + body{background-color:#0f1419;color:#c5c5c5;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:white;}h1.fqn{border-bottom-color:#5c6773;}h1.fqn a{color:#fff;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod){border-bottom-color:#5c6773;}h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){border:none;}.in-band{background-color:#0f1419;}.invisible{background:rgba(0,0,0,0);}code{color:#ffb454;}h3>code,h4>code,h5>code{color:#e6e1cf;}pre>code{color:#e6e1cf;}span code{color:#e6e1cf;}.docblock a>code{color:#39AFD7 !important;}.docblock code,.docblock-short code{background-color:#191f26;}pre{color:#e6e1cf;background-color:#191f26;}.sidebar{background-color:#14191f;}.logo-container.rust-logo>img{filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);}*{scrollbar-color:#5c6773 transparent;}.sidebar{scrollbar-color:#5c6773 transparent;}::-webkit-scrollbar-track{background-color:transparent;}::-webkit-scrollbar-thumb{background-color:#5c6773;}.sidebar::-webkit-scrollbar-track{background-color:transparent;}.sidebar::-webkit-scrollbar-thumb{background-color:#5c6773;}.sidebar .current{background-color:transparent;color:#ffb44c;}.source .sidebar{background-color:#0f1419;}.sidebar .location{border-color:#000;background-color:#0f1419;color:#fff;}.sidebar-elems .location{color:#ff7733;}.sidebar-elems .location a{color:#fff;}.sidebar .version{border-bottom-color:#424c57;}.sidebar-title{border-top-color:#5c6773;border-bottom-color:#5c6773;}.block a:hover{background:transparent;color:#ffb44c;}.line-numbers span{color:#5c6773;}.line-numbers .line-highlighted{color:#708090;background-color:rgba(255,236,164,0.06);padding-right:4px;border-right:1px solid #ffb44c;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#5c6773;}.docblock table,.docblock table td,.docblock table th{border-color:#5c6773;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#c5c5c5;}.content .highlighted{color:#000 !important;background-color:#c6afb3;}.content .highlighted a,.content .highlighted span{color:#000 !important;}.content .highlighted{background-color:#c6afb3;}.search-results a{color:#0096cf;}.search-results a span.desc{color:#c5c5c5;}.content .item-info::before{color:#ccc;}.content span.foreigntype,.content a.foreigntype{color:#ef57ff;}.content span.union,.content a.union{color:#98a01c;}.content span.constant,.content a.constant,.content span.static,.content a.static{color:#6380a0;}.content span.primitive,.content a.primitive{color:#32889b;}.content span.traitalias,.content a.traitalias{color:#57d399;}.content span.keyword,.content a.keyword{color:#de5249;}.content span.externcrate,.content span.mod,.content a.mod{color:#acccf9;}.content span.struct,.content a.struct{color:#ffa0a5;}.content span.enum,.content a.enum{color:#99e0c9;}.content span.trait,.content a.trait{color:#39AFD7;}.content span.type,.content a.type{color:#cfbcf5;}.content span.fn,.content a.fn,.content span.method,.content a.method,.content span.tymethod,.content a.tymethod,.content .fnname{color:#fdd687;}.content span.attr,.content a.attr,.content span.derive,.content a.derive,.content span.macro,.content a.macro{color:#a37acc;}pre.rust .comment{color:#788797;}pre.rust .doccomment{color:#a1ac88;}nav:not(.sidebar){border-bottom-color:#424c57;}nav.main .current{border-top-color:#5c6773;border-bottom-color:#5c6773;}nav.main .separator{border:1px solid #5c6773;}a{color:#c5c5c5;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.item-info a,#help a{color:#39AFD7;}.collapse-toggle{color:#999;}#crate-search{color:#c5c5c5;background-color:#141920;box-shadow:0 0 0 1px #424c57,0 0 0 2px transparent;border-color:#424c57;}.search-input{color:#ffffff;background-color:#141920;box-shadow:0 0 0 1px #424c57,0 0 0 2px transparent;transition:box-shadow 150ms ease-in-out;}#crate-search+.search-input:focus{box-shadow:0 0 0 1px #148099,0 0 0 2px transparent;}.search-focus:disabled{color:#929292;}.module-item .stab{color:#000;}.stab.unstable,.stab.deprecated,.stab.portability{color:#c5c5c5;background:#314559 !important;border-style:none !important;border-radius:4px;padding:3px 6px 3px 6px;}.stab.portability>code{color:#e6e1cf;background-color:transparent;}#help>div{background:#14191f;box-shadow:0px 6px 20px 0px black;border:none;border-radius:4px;}#help>div>span{border-bottom-color:#5c6773;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:#788797;}.line-numbers :target{background-color:transparent;}pre.rust .number,pre.rust .string{color:#b8cc52;}pre.rust .kw,pre.rust .kw-2,pre.rust .prelude-ty,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .op,pre.rust .lifetime{color:#ff7733;}pre.rust .macro,pre.rust .macro-nonterminal{color:#a37acc;}pre.rust .question-mark{color:#ff9011;}pre.rust .self{color:#36a3d9;font-style:italic;}pre.rust .attribute{color:#e6e1cf;}pre.rust .attribute .ident,pre.rust .attribute .op{color:#e6e1cf;}.example-wrap>pre.line-number{color:#5c67736e;border:none;}a.test-arrow{font-size:100%;color:#788797;border-radius:4px;background-color:rgba(57,175,215,0.09);}a.test-arrow:hover{background-color:rgba(57,175,215,0.368);color:#c5c5c5;}.toggle-label{color:#999;}:target>code,:target>.in-band{background:rgba(255,236,164,0.06);border-right:3px solid rgba(255,180,76,0.85);}pre.compile_fail{border-left:2px solid rgba(255,0,0,.4);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.4);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.5);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#39AFD7;}.tooltip .tooltiptext{background-color:#314559;color:#c5c5c5;border:1px solid #5c6773;}.tooltip .tooltiptext::after{border-color:transparent #314559 transparent transparent;}.notable-traits-tooltiptext{background-color:#314559;border-color:#5c6773;}#titles>button.selected{background-color:#141920 !important;border-bottom:1px solid #ffb44c !important;border-top:none;}#titles>button:not(.selected){background-color:transparent !important;border:none;}#titles>button:hover{border-bottom:1px solid rgba(242,151,24,0.3);}#titles>button>div.count{color:#888;}.content .highlighted.mod,.content .highlighted.externcrate{}.search-input:focus{}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{}.content .highlighted.trait{}.content span.struct,.content a.struct,.block a.current.struct{}#titles>button:hover,#titles>button.selected{}.content .highlighted.traitalias{}.content span.type,.content a.type,.block a.current.type{}.content span.union,.content a.union,.block a.current.union{}.content .highlighted.foreigntype{}pre.rust .lifetime{}.content .highlighted.primitive{}.content .highlighted.constant,.content .highlighted.static{}.stab.unstable{}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){}.content span.enum,.content a.enum,.block a.current.enum{}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{}.content span.keyword,.content a.keyword,.block a.current.keyword{}pre.rust .comment{}.content .highlighted.enum{}.content .highlighted.struct{}.content .highlighted.keyword{}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{}pre.rust .kw{}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{}pre.rust .doccomment{}.stab.deprecated{}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{}.stab.portability{}.content .highlighted.union{}.content span.primitive,.content a.primitive,.block a.current.primitive{}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{}.content .highlighted.type{}pre.rust .kw-2,pre.rust .prelude-ty{}.content span.trait,.content a.trait,.block a.current.trait{}@media (max-width:700px){.sidebar-menu{background-color:#14191f;border-bottom-color:#5c6773;border-right-color:#5c6773;}.sidebar-elems{background-color:#14191f;border-right-color:#5c6773;}#sidebar-filler{background-color:#14191f;border-bottom-color:#5c6773;}}kbd{color:#c5c5c5;background-color:#314559;border-color:#5c6773;border-bottom-color:#5c6773;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu,.help-button{border-color:#5c6773;background-color:#0f1419;color:#fff;}#theme-picker>img,#settings-menu>img{filter:invert(100);}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus,.help-button:hover,.help-button:focus{border-color:#e0e0e0;}#theme-choices{border-color:#5c6773;background-color:#0f1419;}#theme-choices>button:not(:first-child){border-top-color:#5c6773;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:rgba(110,110,110,0.33);}@media (max-width:700px){#theme-picker{background:#0f1419;}}#all-types{background-color:#14191f;}#all-types:hover{background-color:rgba(70,70,70,0.33);}.search-results td span.alias{color:#c5c5c5;}.search-results td span.grey{color:#999;}#sidebar-toggle{background-color:#14191f;}#sidebar-toggle:hover{background-color:rgba(70,70,70,0.33);}#source-sidebar{background-color:#14191f;}#source-sidebar>.title{color:#fff;border-bottom-color:#5c6773;}div.files>a:hover,div.name:hover{background-color:#14191f;color:#ffb44c;}div.files>.selected{background-color:#14191f;color:#ffb44c;}.setting-line>.title{border-bottom-color:#5c6773;}input:checked+.slider{background-color:#ffb454 !important;} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/all.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/all.html new file mode 100644 index 0000000000..35d47a2b03 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/all.html @@ -0,0 +1,6 @@ +List of all items in this crate + +

[] + + List of all items

Structs

Enums

Traits

Macros

Functions

Typedefs

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/enum.AnyBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/enum.AnyBlockchain.html new file mode 100644 index 0000000000..916f07b121 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/enum.AnyBlockchain.html @@ -0,0 +1,52 @@ +bdk::blockchain::any::AnyBlockchain - Rust + +

[][src]Enum bdk::blockchain::any::AnyBlockchain

pub enum AnyBlockchain {
+    Electrum(ElectrumBlockchain),
+    Esplora(EsploraBlockchain),
+    CompactFilters(CompactFiltersBlockchain),
+}

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

+

It allows switching backend at runtime

+

See this module's documentation for a usage example.

+

+ Variants

+
This is supported on crate feature electrum only.

Electrum client

+
This is supported on crate feature esplora only.

Esplora client

+
CompactFilters(CompactFiltersBlockchain)
This is supported on crate feature compact_filters only.

Compact filters client

+

Trait Implementations

impl Blockchain for AnyBlockchain[src]

impl ConfigurableBlockchain for AnyBlockchain[src]

type Config = AnyBlockchainConfig

Type that contains the configuration

+

impl From<CompactFiltersBlockchain> for AnyBlockchain[src]

impl From<ElectrumBlockchain> for AnyBlockchain[src]

impl From<EsploraBlockchain> for AnyBlockchain[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> BlockchainMarker for T where
    T: Blockchain
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/enum.AnyBlockchainConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/enum.AnyBlockchainConfig.html new file mode 100644 index 0000000000..a034ec2a32 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/enum.AnyBlockchainConfig.html @@ -0,0 +1,47 @@ +bdk::blockchain::any::AnyBlockchainConfig - Rust + +

[][src]Enum bdk::blockchain::any::AnyBlockchainConfig

pub enum AnyBlockchainConfig {
+    Electrum(ElectrumBlockchainConfig),
+    Esplora(EsploraBlockchainConfig),
+    CompactFilters(CompactFiltersBlockchainConfig),
+}

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

+

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

+

+ Variants

+
This is supported on crate feature electrum only.

Electrum client

+
This is supported on crate feature esplora only.

Esplora client

+
This is supported on crate feature compact_filters only.

Compact filters client

+

Trait Implementations

impl Debug for AnyBlockchainConfig[src]

impl<'de> Deserialize<'de> for AnyBlockchainConfig[src]

impl From<CompactFiltersBlockchainConfig> for AnyBlockchainConfig[src]

impl From<ElectrumBlockchainConfig> for AnyBlockchainConfig[src]

impl From<EsploraBlockchainConfig> for AnyBlockchainConfig[src]

impl Serialize for AnyBlockchainConfig[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/index.html new file mode 100644 index 0000000000..70a7a733eb --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/index.html @@ -0,0 +1,47 @@ +bdk::blockchain::any - Rust + +

[][src]Module bdk::blockchain::any

Runtime-checked blockchain types

+

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

+

Example

+

In this example both wallet_electrum and wallet_esplora have the same type of +Wallet<AnyBlockchain, MemoryDatabase>. This means that they could both, for instance, be +assigned to a struct member.

+ +
+let electrum_blockchain = ElectrumBlockchain::from(electrum_client::Client::new("...")?);
+let wallet_electrum: Wallet<AnyBlockchain, _> = Wallet::new(
+    "...",
+    None,
+    Network::Testnet,
+    MemoryDatabase::default(),
+    electrum_blockchain.into(),
+)?;
+
+let esplora_blockchain = EsploraBlockchain::new("...", None);
+let wallet_esplora: Wallet<AnyBlockchain, _> = Wallet::new(
+    "...",
+    None,
+    Network::Testnet,
+    MemoryDatabase::default(),
+    esplora_blockchain.into(),
+)?;
+
+

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

+ +
+let config = serde_json::from_str("...")?;
+let blockchain = AnyBlockchain::from_config(&config)?;
+let wallet = Wallet::new(
+    "...",
+    None,
+    Network::Testnet,
+    MemoryDatabase::default(),
+    blockchain,
+)?;
+

Enums

+
AnyBlockchain

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

+
AnyBlockchainConfig

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

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/sidebar-items.js new file mode 100644 index 0000000000..14144cf693 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["AnyBlockchain","Type that can contain any of the [`Blockchain`] types defined by the library"],["AnyBlockchainConfig","Type that can contain any of the blockchain configurations defined by the library"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/enum.CompactFiltersError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/enum.CompactFiltersError.html new file mode 100644 index 0000000000..3fba9f11c4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/enum.CompactFiltersError.html @@ -0,0 +1,73 @@ +bdk::blockchain::compact_filters::CompactFiltersError - Rust + +

[][src]Enum bdk::blockchain::compact_filters::CompactFiltersError

pub enum CompactFiltersError {
+    InvalidResponse,
+    InvalidHeaders,
+    InvalidFilterHeader,
+    InvalidFilter,
+    MissingBlock,
+    DataCorruption,
+    NotConnected,
+    Timeout,
+    NoPeers,
+    DB(Error),
+    IO(Error),
+    BIP158(Error),
+    Time(SystemTimeError),
+    Global(Box<Error>),
+}
This is supported on crate feature compact_filters only.

An error that can occur during sync with a CompactFiltersBlockchain

+

+ Variants

+
InvalidResponse

A peer sent an invalid or unexpected response

+
InvalidHeaders

The headers returned are invalid

+
InvalidFilterHeader

The compact filter headers returned are invalid

+
InvalidFilter

The compact filter returned is invalid

+
MissingBlock

The peer is missing a block in the valid chain

+
DataCorruption

The data stored in the block filters storage are corrupted

+
NotConnected

A peer is not connected

+
Timeout

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

+
NoPeers

No peers have been specified

+
DB(Error)

Internal database error

+
IO(Error)

Internal I/O error

+
BIP158(Error)

Invalid BIP158 filter

+

Internal system time error

+
Global(Box<Error>)

Wrapper for crate::error::Error

+

Trait Implementations

impl Debug for CompactFiltersError[src]

impl Display for CompactFiltersError[src]

impl Error for CompactFiltersError[src]

impl From<CompactFiltersError> for Error[src]

impl From<Error> for CompactFiltersError[src]

impl From<Error> for CompactFiltersError[src]

impl From<Error> for CompactFiltersError[src]

impl From<Error> for CompactFiltersError[src]

impl From<SystemTimeError> for CompactFiltersError[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/index.html new file mode 100644 index 0000000000..53f3f770e2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/index.html @@ -0,0 +1,39 @@ +bdk::blockchain::compact_filters - Rust + +

[][src]Module bdk::blockchain::compact_filters

This is supported on crate feature compact_filters only.

Compact Filters

+

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

+

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

+

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

+

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

+

Example

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

Structs

+
BitcoinPeerConfig

Data to connect to a Bitcoin P2P peer

+
CompactFiltersBlockchain

Structure implementing the required blockchain traits

+
CompactFiltersBlockchainConfig

Configuration for a CompactFiltersBlockchain

+
Mempool

Container for unconfirmed, but valid Bitcoin transactions

+
Peer

A Bitcoin peer

+

Enums

+
CompactFiltersError

An error that can occur during sync with a CompactFiltersBlockchain

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/peer/struct.Mempool.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/peer/struct.Mempool.html new file mode 100644 index 0000000000..cd04378cbe --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/peer/struct.Mempool.html @@ -0,0 +1,10 @@ + + + + + + +

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

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/peer/struct.Peer.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/peer/struct.Peer.html new file mode 100644 index 0000000000..11332c3bdb --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/peer/struct.Peer.html @@ -0,0 +1,10 @@ + + + + + + +

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

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/sidebar-items.js new file mode 100644 index 0000000000..187af79563 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["CompactFiltersError","An error that can occur during sync with a [`CompactFiltersBlockchain`]"]],"struct":[["BitcoinPeerConfig","Data to connect to a Bitcoin P2P peer"],["CompactFiltersBlockchain","Structure implementing the required blockchain traits"],["CompactFiltersBlockchainConfig","Configuration for a [`CompactFiltersBlockchain`]"],["Mempool","Container for unconfirmed, but valid Bitcoin transactions"],["Peer","A Bitcoin peer"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.BitcoinPeerConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.BitcoinPeerConfig.html new file mode 100644 index 0000000000..822c73d161 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.BitcoinPeerConfig.html @@ -0,0 +1,40 @@ +bdk::blockchain::compact_filters::BitcoinPeerConfig - Rust + +

[][src]Struct bdk::blockchain::compact_filters::BitcoinPeerConfig

pub struct BitcoinPeerConfig {
+    pub address: String,
+    pub socks5: Option<String>,
+    pub socks5_credentials: Option<(String, String)>,
+}
This is supported on crate feature compact_filters only.

Data to connect to a Bitcoin P2P peer

+

+ Fields

address: String

Peer address such as 127.0.0.1:18333

+
socks5: Option<String>

Optional socks5 proxy

+
socks5_credentials: Option<(String, String)>

Optional socks5 proxy credentials

+

Trait Implementations

impl Debug for BitcoinPeerConfig[src]

impl<'de> Deserialize<'de> for BitcoinPeerConfig[src]

impl Serialize for BitcoinPeerConfig[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html new file mode 100644 index 0000000000..c99aa78694 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html @@ -0,0 +1,49 @@ +bdk::blockchain::compact_filters::CompactFiltersBlockchain - Rust + +

[][src]Struct bdk::blockchain::compact_filters::CompactFiltersBlockchain

pub struct CompactFiltersBlockchain { /* fields omitted */ }
This is supported on crate feature compact_filters only.

Structure implementing the required blockchain traits

+

Example

+

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

+

Implementations

impl CompactFiltersBlockchain[src]

pub fn new<P: AsRef<Path>>(
    peers: Vec<Peer>,
    storage_dir: P,
    skip_blocks: Option<usize>
) -> Result<Self, CompactFiltersError>
[src]

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

+

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

+

Trait Implementations

impl Blockchain for CompactFiltersBlockchain[src]

impl ConfigurableBlockchain for CompactFiltersBlockchain[src]

type Config = CompactFiltersBlockchainConfig

Type that contains the configuration

+

impl Debug for CompactFiltersBlockchain[src]

impl From<CompactFiltersBlockchain> for AnyBlockchain[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> BlockchainMarker for T where
    T: Blockchain
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchainConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchainConfig.html new file mode 100644 index 0000000000..0d8ad732f9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchainConfig.html @@ -0,0 +1,43 @@ +bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig - Rust + +

[][src]Struct bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig

pub struct CompactFiltersBlockchainConfig {
+    pub peers: Vec<BitcoinPeerConfig>,
+    pub network: Network,
+    pub storage_dir: String,
+    pub skip_blocks: Option<usize>,
+}
This is supported on crate feature compact_filters only.

Configuration for a CompactFiltersBlockchain

+

+ Fields

peers: Vec<BitcoinPeerConfig>

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

+
network: Network

Network used

+
storage_dir: String

Storage dir to save partially downloaded headers and full blocks

+
skip_blocks: Option<usize>

Optionally skip initial skip_blocks blocks (default: 0)

+

Trait Implementations

impl Debug for CompactFiltersBlockchainConfig[src]

impl<'de> Deserialize<'de> for CompactFiltersBlockchainConfig[src]

impl From<CompactFiltersBlockchainConfig> for AnyBlockchainConfig[src]

impl Serialize for CompactFiltersBlockchainConfig[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.Mempool.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.Mempool.html new file mode 100644 index 0000000000..e03a70996f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.Mempool.html @@ -0,0 +1,39 @@ +bdk::blockchain::compact_filters::Mempool - Rust + +

[][src]Struct bdk::blockchain::compact_filters::Mempool

pub struct Mempool { /* fields omitted */ }
This is supported on crate feature compact_filters only.

Container for unconfirmed, but valid Bitcoin transactions

+

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

+

Implementations

impl Mempool[src]

pub fn add_tx(&self, tx: Transaction)[src]

Add a transaction to the mempool

+

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

+

pub fn get_tx(&self, inventory: &Inventory) -> Option<Transaction>[src]

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

+

pub fn has_tx(&self, txid: &Txid) -> bool[src]

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

+

pub fn iter_txs(&self) -> Vec<Transaction>[src]

Return the list of transactions contained in the mempool

+

Trait Implementations

impl Debug for Mempool[src]

impl Default for Mempool[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.Peer.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.Peer.html new file mode 100644 index 0000000000..5c3eb0c9a9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.Peer.html @@ -0,0 +1,43 @@ +bdk::blockchain::compact_filters::Peer - Rust + +

[][src]Struct bdk::blockchain::compact_filters::Peer

pub struct Peer { /* fields omitted */ }
This is supported on crate feature compact_filters only.

A Bitcoin peer

+

Implementations

impl Peer[src]

pub fn connect<A: ToSocketAddrs>(
    address: A,
    mempool: Arc<Mempool>,
    network: Network
) -> Result<Self, CompactFiltersError>
[src]

Connect to a peer over a plaintext TCP connection

+

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

+

pub fn connect_proxy<T: ToTargetAddr, P: ToSocketAddrs>(
    target: T,
    proxy: P,
    credentials: Option<(&str, &str)>,
    mempool: Arc<Mempool>,
    network: Network
) -> Result<Self, CompactFiltersError>
[src]

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

+

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

+

pub fn get_version(&self) -> &VersionMessage[src]

Return the [VersionMessage] sent by the peer

+

pub fn get_network(&self) -> Network[src]

Return the Bitcoin [Network] in use

+

pub fn get_mempool(&self) -> Arc<Mempool>[src]

Return the mempool used by this peer

+

pub fn is_connected(&self) -> bool[src]

Return whether or not the peer is still connected

+

pub fn send(&self, payload: NetworkMessage) -> Result<(), CompactFiltersError>[src]

Send a raw Bitcoin message to the peer

+

pub fn recv(
    &self,
    wait_for: &'static str,
    timeout: Option<Duration>
) -> Result<Option<NetworkMessage>, CompactFiltersError>
[src]

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

+

Trait Implementations

impl Debug for Peer[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/index.html new file mode 100644 index 0000000000..10b5f8a1cd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/index.html @@ -0,0 +1,15 @@ +bdk::blockchain::electrum - Rust + +

[][src]Module bdk::blockchain::electrum

This is supported on crate feature electrum only.

Electrum

+

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

+

Example

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

Structs

+
ElectrumBlockchain

Wrapper over an Electrum Client that implements the required blockchain traits

+
ElectrumBlockchainConfig

Configuration for an ElectrumBlockchain

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/sidebar-items.js new file mode 100644 index 0000000000..1bd5458912 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["ElectrumBlockchain","Wrapper over an Electrum Client that implements the required blockchain traits"],["ElectrumBlockchainConfig","Configuration for an [`ElectrumBlockchain`]"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/struct.ElectrumBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/struct.ElectrumBlockchain.html new file mode 100644 index 0000000000..1d0542e6fe --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/struct.ElectrumBlockchain.html @@ -0,0 +1,42 @@ +bdk::blockchain::electrum::ElectrumBlockchain - Rust + +

[][src]Struct bdk::blockchain::electrum::ElectrumBlockchain

pub struct ElectrumBlockchain(_);
This is supported on crate feature electrum only.

Wrapper over an Electrum Client that implements the required blockchain traits

+

Example

+

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

+

Trait Implementations

impl Blockchain for ElectrumBlockchain[src]

impl ConfigurableBlockchain for ElectrumBlockchain[src]

type Config = ElectrumBlockchainConfig

Type that contains the configuration

+

impl From<Client> for ElectrumBlockchain[src]

impl From<ElectrumBlockchain> for AnyBlockchain[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> BlockchainMarker for T where
    T: Blockchain
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/struct.ElectrumBlockchainConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/struct.ElectrumBlockchainConfig.html new file mode 100644 index 0000000000..f15a951de2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/struct.ElectrumBlockchainConfig.html @@ -0,0 +1,44 @@ +bdk::blockchain::electrum::ElectrumBlockchainConfig - Rust + +

[][src]Struct bdk::blockchain::electrum::ElectrumBlockchainConfig

pub struct ElectrumBlockchainConfig {
+    pub url: String,
+    pub socks5: Option<String>,
+    pub retry: u8,
+    pub timeout: u8,
+}
This is supported on crate feature electrum only.

Configuration for an ElectrumBlockchain

+

+ Fields

url: String

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

+

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

+
socks5: Option<String>

URL of the socks5 proxy server or a Tor service

+
retry: u8

Request retry count

+
timeout: u8

Request timeout (seconds)

+

Trait Implementations

impl Debug for ElectrumBlockchainConfig[src]

impl<'de> Deserialize<'de> for ElectrumBlockchainConfig[src]

impl From<ElectrumBlockchainConfig> for AnyBlockchainConfig[src]

impl Serialize for ElectrumBlockchainConfig[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/enum.Capability.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/enum.Capability.html new file mode 100644 index 0000000000..613d781903 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/enum.Capability.html @@ -0,0 +1,51 @@ +bdk::blockchain::Capability - Rust + +

[][src]Enum bdk::blockchain::Capability

pub enum Capability {
+    FullHistory,
+    GetAnyTx,
+    AccurateFees,
+}

Capabilities that can be supported by a Blockchain backend

+

+ Variants

+
FullHistory

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

+
GetAnyTx

Can fetch any historical transaction given its txid

+
AccurateFees

Can compute accurate fees for the transactions found during sync

+

Trait Implementations

impl Clone for Capability[src]

impl Copy for Capability[src]

impl Debug for Capability[src]

impl Eq for Capability[src]

impl Hash for Capability[src]

impl PartialEq<Capability> for Capability[src]

impl StructuralEq for Capability[src]

impl StructuralPartialEq for Capability[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/enum.EsploraError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/enum.EsploraError.html new file mode 100644 index 0000000000..3a45d9599c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/enum.EsploraError.html @@ -0,0 +1,58 @@ +bdk::blockchain::esplora::EsploraError - Rust + +

[][src]Enum bdk::blockchain::esplora::EsploraError

pub enum EsploraError {
+    Reqwest(Error),
+    Parsing(ParseIntError),
+    BitcoinEncoding(Error),
+    Hex(Error),
+    TransactionNotFound(Txid),
+    HeaderHeightNotFound(u32),
+    HeaderHashNotFound(BlockHash),
+}
This is supported on crate feature esplora only.

Errors that can happen during a sync with EsploraBlockchain

+

+ Variants

+
Reqwest(Error)

Error with the HTTP call

+
Parsing(ParseIntError)

Invalid number returned

+
BitcoinEncoding(Error)

Invalid Bitcoin data returned

+
Hex(Error)

Invalid Hex data returned

+
TransactionNotFound(Txid)

Transaction not found

+
HeaderHeightNotFound(u32)

Header height not found

+
HeaderHashNotFound(BlockHash)

Header hash not found

+

Trait Implementations

impl Debug for EsploraError[src]

impl Display for EsploraError[src]

impl Error for EsploraError[src]

impl From<Error> for EsploraError[src]

impl From<Error> for EsploraError[src]

impl From<Error> for EsploraError[src]

impl From<EsploraError> for Error[src]

impl From<ParseIntError> for EsploraError[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/index.html new file mode 100644 index 0000000000..d6ed3b9df2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/index.html @@ -0,0 +1,15 @@ +bdk::blockchain::esplora - Rust + +

[][src]Module bdk::blockchain::esplora

This is supported on crate feature esplora only.

Esplora

+

This module defines a Blockchain struct that can query an Esplora backend +populate the wallet's database by

+

Example

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

Structs

+
EsploraBlockchain

Structure that implements the logic to sync with Esplora

+
EsploraBlockchainConfig

Configuration for an EsploraBlockchain

+

Enums

+
EsploraError

Errors that can happen during a sync with EsploraBlockchain

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/sidebar-items.js new file mode 100644 index 0000000000..d4d17db97b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["EsploraError","Errors that can happen during a sync with [`EsploraBlockchain`]"]],"struct":[["EsploraBlockchain","Structure that implements the logic to sync with Esplora"],["EsploraBlockchainConfig","Configuration for an [`EsploraBlockchain`]"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/struct.EsploraBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/struct.EsploraBlockchain.html new file mode 100644 index 0000000000..b645d65ca6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/struct.EsploraBlockchain.html @@ -0,0 +1,43 @@ +bdk::blockchain::esplora::EsploraBlockchain - Rust + +

[][src]Struct bdk::blockchain::esplora::EsploraBlockchain

pub struct EsploraBlockchain(_);
This is supported on crate feature esplora only.

Structure that implements the logic to sync with Esplora

+

Example

+

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

+

Implementations

impl EsploraBlockchain[src]

pub fn new(base_url: &str, concurrency: Option<u8>) -> Self[src]

Create a new instance of the client from a base URL

+

Trait Implementations

impl Blockchain for EsploraBlockchain[src]

impl ConfigurableBlockchain for EsploraBlockchain[src]

type Config = EsploraBlockchainConfig

Type that contains the configuration

+

impl Debug for EsploraBlockchain[src]

impl From<EsploraBlockchain> for AnyBlockchain[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> BlockchainMarker for T where
    T: Blockchain
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/struct.EsploraBlockchainConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/struct.EsploraBlockchainConfig.html new file mode 100644 index 0000000000..3f00c32c65 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/struct.EsploraBlockchainConfig.html @@ -0,0 +1,40 @@ +bdk::blockchain::esplora::EsploraBlockchainConfig - Rust + +

[][src]Struct bdk::blockchain::esplora::EsploraBlockchainConfig

pub struct EsploraBlockchainConfig {
+    pub base_url: String,
+    pub concurrency: Option<u8>,
+}
This is supported on crate feature esplora only.

Configuration for an EsploraBlockchain

+

+ Fields

base_url: String

Base URL of the esplora service

+

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

+
concurrency: Option<u8>

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

+

Trait Implementations

impl Debug for EsploraBlockchainConfig[src]

impl<'de> Deserialize<'de> for EsploraBlockchainConfig[src]

impl From<EsploraBlockchainConfig> for AnyBlockchainConfig[src]

impl Serialize for EsploraBlockchainConfig[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.log_progress.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.log_progress.html new file mode 100644 index 0000000000..8f223b1af9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.log_progress.html @@ -0,0 +1,5 @@ +bdk::blockchain::log_progress - Rust + +

[][src]Function bdk::blockchain::log_progress

pub fn log_progress() -> LogProgress

Create a nwe instance of LogProgress

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.noop_progress.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.noop_progress.html new file mode 100644 index 0000000000..07602022d5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.noop_progress.html @@ -0,0 +1,5 @@ +bdk::blockchain::noop_progress - Rust + +

[][src]Function bdk::blockchain::noop_progress

pub fn noop_progress() -> NoopProgress

Create a new instance of NoopProgress

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

[][src]Function bdk::blockchain::progress

pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>)

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

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/index.html new file mode 100644 index 0000000000..15f7341c86 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/index.html @@ -0,0 +1,33 @@ +bdk::blockchain - Rust + +

[][src]Module bdk::blockchain

Blockchain backends

+

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

+

Re-exports

+
pub use any::AnyBlockchain;
pub use any::AnyBlockchainConfig;
pub use self::electrum::ElectrumBlockchain;
pub use self::electrum::ElectrumBlockchainConfig;
pub use self::esplora::EsploraBlockchain;
pub use self::compact_filters::CompactFiltersBlockchain;

Modules

+
any

Runtime-checked blockchain types

+
compact_filterscompact_filters

Compact Filters

+
electrumelectrum

Electrum

+
esploraesplora

Esplora

+

Structs

+
LogProgress

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

+
NoopProgress

Type that implements Progress and drops every update received

+
OfflineBlockchain

Type that only implements BlockchainMarker and is always "offline"

+

Enums

+
Capability

Capabilities that can be supported by a Blockchain backend

+

Traits

+
Blockchain

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

+
BlockchainMarker

Marker trait for a blockchain backend

+
ConfigurableBlockchain

Trait for Blockchain types that can be created given a configuration

+
Progress

Trait for types that can receive and process progress updates during Blockchain::sync and +Blockchain::setup

+

Functions

+
log_progress

Create a nwe instance of LogProgress

+
noop_progress

Create a new instance of NoopProgress

+
progress

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

+

Type Definitions

+
ProgressData

Data sent with a progress update over a channel

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/sidebar-items.js new file mode 100644 index 0000000000..7e42516826 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["Capability","Capabilities that can be supported by a [`Blockchain`] backend"]],"fn":[["log_progress","Create a nwe instance of [`LogProgress`]"],["noop_progress","Create a new instance of [`NoopProgress`]"],["progress","Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]"]],"mod":[["any","Runtime-checked blockchain types"],["compact_filters","Compact Filters"],["electrum","Electrum"],["esplora","Esplora"]],"struct":[["LogProgress","Type that implements [`Progress`] and logs at level `INFO` every update received"],["NoopProgress","Type that implements [`Progress`] and drops every update received"],["OfflineBlockchain","Type that only implements [`BlockchainMarker`] and is always \"offline\""]],"trait":[["Blockchain","Trait that defines the actions that must be supported by a blockchain backend"],["BlockchainMarker","Marker trait for a blockchain backend"],["ConfigurableBlockchain","Trait for [`Blockchain`] types that can be created given a configuration"],["Progress","Trait for types that can receive and process progress updates during [`Blockchain::sync`] and [`Blockchain::setup`]"]],"type":[["ProgressData","Data sent with a progress update over a [`channel`]"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.LogProgress.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.LogProgress.html new file mode 100644 index 0000000000..37fecdf533 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.LogProgress.html @@ -0,0 +1,36 @@ +bdk::blockchain::LogProgress - Rust + +

[][src]Struct bdk::blockchain::LogProgress

pub struct LogProgress;

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

+

Trait Implementations

impl Clone for LogProgress[src]

impl Progress for LogProgress[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.NoopProgress.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.NoopProgress.html new file mode 100644 index 0000000000..32da05a48d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.NoopProgress.html @@ -0,0 +1,36 @@ +bdk::blockchain::NoopProgress - Rust + +

[][src]Struct bdk::blockchain::NoopProgress

pub struct NoopProgress;

Type that implements Progress and drops every update received

+

Trait Implementations

impl Clone for NoopProgress[src]

impl Progress for NoopProgress[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.OfflineBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.OfflineBlockchain.html new file mode 100644 index 0000000000..a828794792 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.OfflineBlockchain.html @@ -0,0 +1,29 @@ +bdk::blockchain::OfflineBlockchain - Rust + +

[][src]Struct bdk::blockchain::OfflineBlockchain

pub struct OfflineBlockchain;

Type that only implements BlockchainMarker and is always "offline"

+

Trait Implementations

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.Blockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.Blockchain.html new file mode 100644 index 0000000000..ccb3c3548b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.Blockchain.html @@ -0,0 +1,36 @@ +bdk::blockchain::Blockchain - Rust + +

[][src]Trait bdk::blockchain::Blockchain

pub trait Blockchain: BlockchainMarker {
+    pub fn get_capabilities(&self) -> HashSet<Capability>;
+
pub fn setup<D: BatchDatabase, P: 'static + Progress>(
        &self,
        stop_gap: Option<usize>,
        database: &mut D,
        progress_update: P
    ) -> Result<(), Error>; +
pub fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>; +
pub fn broadcast(&self, tx: &Transaction) -> Result<(), Error>; +
pub fn get_height(&self) -> Result<u32, Error>; +
pub fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>; + + pub fn sync<D: BatchDatabase, P: 'static + Progress>(
        &self,
        stop_gap: Option<usize>,
        database: &mut D,
        progress_update: P
    ) -> Result<(), Error> { ... } +}

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

+

Required methods

pub fn get_capabilities(&self) -> HashSet<Capability>[src]

Return the set of Capability supported by this backend

+

pub fn setup<D: BatchDatabase, P: 'static + Progress>(
    &self,
    stop_gap: Option<usize>,
    database: &mut D,
    progress_update: P
) -> Result<(), Error>
[src]

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

+

This method is the equivalent of Blockchain::sync, but it's guaranteed to only be +called once, at the first Wallet::sync.

+

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

+

For types that do not have that distinction, only this method can be implemented, since +Blockchain::sync defaults to calling this internally if not overridden.

+

pub fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>[src]

Fetch a transaction from the blockchain given its txid

+

pub fn broadcast(&self, tx: &Transaction) -> Result<(), Error>[src]

Broadcast a transaction

+

pub fn get_height(&self) -> Result<u32, Error>[src]

Return the current height

+

pub fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>[src]

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

+
Loading content...

Provided methods

pub fn sync<D: BatchDatabase, P: 'static + Progress>(
    &self,
    stop_gap: Option<usize>,
    database: &mut D,
    progress_update: P
) -> Result<(), Error>
[src]

Populate the internal database with transactions and UTXOs

+

If not overridden, it defaults to calling Blockchain::setup internally.

+

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

+

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

+

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

+
Loading content...

Implementations on Foreign Types

impl<T: Blockchain> Blockchain for Arc<T>[src]

Loading content...

Implementors

impl Blockchain for AnyBlockchain[src]

impl Blockchain for CompactFiltersBlockchain[src]

This is supported on crate feature compact_filters only.

impl Blockchain for ElectrumBlockchain[src]

This is supported on crate feature electrum only.

impl Blockchain for EsploraBlockchain[src]

This is supported on crate feature esplora only.
Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.BlockchainMarker.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.BlockchainMarker.html new file mode 100644 index 0000000000..6b7b52152c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.BlockchainMarker.html @@ -0,0 +1,14 @@ +bdk::blockchain::BlockchainMarker - Rust + +

[][src]Trait bdk::blockchain::BlockchainMarker

pub trait BlockchainMarker { }

Marker trait for a blockchain backend

+

This is a marker trait for blockchain types. It is automatically implemented for types that +implement Blockchain, so as a user of the library you won't have to implement this +manually.

+

Users of the library will probably never have to implement this trait manually, but they +could still need to import it to define types and structs with generics; +Implementing only the marker trait is pointless, since OfflineBlockchain +already does that, and whenever Blockchain is implemented, the marker trait is also +automatically implemented by the library.

+

Implementors

impl BlockchainMarker for OfflineBlockchain[src]

impl<T: Blockchain> BlockchainMarker for T[src]

The BlockchainMarker marker trait is automatically implemented for Blockchain types

+
Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.ConfigurableBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.ConfigurableBlockchain.html new file mode 100644 index 0000000000..131ce0ecec --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.ConfigurableBlockchain.html @@ -0,0 +1,10 @@ +bdk::blockchain::ConfigurableBlockchain - Rust + +

[][src]Trait bdk::blockchain::ConfigurableBlockchain

pub trait ConfigurableBlockchain: Blockchain + Sized {
+    type Config: Debug;
+    pub fn from_config(config: &Self::Config) -> Result<Self, Error>;
+}

Trait for Blockchain types that can be created given a configuration

+

Associated Types

type Config: Debug[src]

Type that contains the configuration

+
Loading content...

Required methods

pub fn from_config(config: &Self::Config) -> Result<Self, Error>[src]

Create a new instance given a configuration

+
Loading content...

Implementors

impl ConfigurableBlockchain for AnyBlockchain[src]

type Config = AnyBlockchainConfig

impl ConfigurableBlockchain for CompactFiltersBlockchain[src]

This is supported on crate feature compact_filters only.

impl ConfigurableBlockchain for ElectrumBlockchain[src]

This is supported on crate feature electrum only.

type Config = ElectrumBlockchainConfig

impl ConfigurableBlockchain for EsploraBlockchain[src]

This is supported on crate feature esplora only.

type Config = EsploraBlockchainConfig

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.Progress.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.Progress.html new file mode 100644 index 0000000000..f2d54223cd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.Progress.html @@ -0,0 +1,11 @@ +bdk::blockchain::Progress - Rust + +

[][src]Trait bdk::blockchain::Progress

pub trait Progress: Send {
+    pub fn update(
        &self,
        progress: f32,
        message: Option<String>
    ) -> Result<(), Error>; +}

Trait for types that can receive and process progress updates during Blockchain::sync and +Blockchain::setup

+

Required methods

pub fn update(
    &self,
    progress: f32,
    message: Option<String>
) -> Result<(), Error>
[src]

Send a new progress update

+

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

+
Loading content...

Implementations on Foreign Types

impl Progress for Sender<ProgressData>[src]

Loading content...

Implementors

impl Progress for LogProgress[src]

impl Progress for NoopProgress[src]

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/type.ProgressData.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/type.ProgressData.html new file mode 100644 index 0000000000..43b5347cb5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/type.ProgressData.html @@ -0,0 +1,5 @@ +bdk::blockchain::ProgressData - Rust + +

[][src]Type Definition bdk::blockchain::ProgressData

type ProgressData = (f32, Option<String>);

Data sent with a progress update over a channel

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyBatch.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyBatch.html new file mode 100644 index 0000000000..2780dfa143 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyBatch.html @@ -0,0 +1,50 @@ +bdk::database::any::AnyBatch - Rust + +

[][src]Enum bdk::database::any::AnyBatch

pub enum AnyBatch {
+    Memory(<MemoryDatabase as BatchDatabase>::Batch),
+    Sled(<Tree as BatchDatabase>::Batch),
+}

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

+

+ Variants

+

In-memory ephemeral database

+
Sled(<Tree as BatchDatabase>::Batch)
This is supported on crate feature key-value-db only.

Simple key-value embedded database based on [sled]

+

Trait Implementations

impl BatchOperations for AnyBatch[src]

impl From<<MemoryDatabase as BatchDatabase>::Batch> for AnyBatch[src]

impl From<<Tree as BatchDatabase>::Batch> for AnyBatch[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyDatabase.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyDatabase.html new file mode 100644 index 0000000000..ba702ed155 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyDatabase.html @@ -0,0 +1,70 @@ +bdk::database::any::AnyDatabase - Rust + +

[][src]Enum bdk::database::any::AnyDatabase

pub enum AnyDatabase {
+    Memory(MemoryDatabase),
+    Sled(Tree),
+}

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

+

It allows switching database type at runtime.

+

See this module's documentation for a usage example.

+

+ Variants

+

In-memory ephemeral database

+
Sled(Tree)
This is supported on crate feature key-value-db only.

Simple key-value embedded database based on [sled]

+

Trait Implementations

impl BatchDatabase for AnyDatabase[src]

type Batch = AnyBatch

Container for the operations

+

impl BatchOperations for AnyDatabase[src]

impl ConfigurableDatabase for AnyDatabase[src]

type Config = AnyDatabaseConfig

Type that contains the configuration

+

impl Database for AnyDatabase[src]

impl Debug for AnyDatabase[src]

impl From<MemoryDatabase> for AnyDatabase[src]

impl From<Tree> for AnyDatabase[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyDatabaseConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyDatabaseConfig.html new file mode 100644 index 0000000000..c880a327c7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyDatabaseConfig.html @@ -0,0 +1,44 @@ +bdk::database::any::AnyDatabaseConfig - Rust + +

[][src]Enum bdk::database::any::AnyDatabaseConfig

pub enum AnyDatabaseConfig {
+    Memory(()),
+    Sled(SledDbConfiguration),
+}

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

+

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

+

+ Variants

+
Memory(())

Memory database has no config

+
This is supported on crate feature key-value-db only.

Simple key-value embedded database based on [sled]

+

Trait Implementations

impl Debug for AnyDatabaseConfig[src]

impl<'de> Deserialize<'de> for AnyDatabaseConfig[src]

impl From<()> for AnyDatabaseConfig[src]

impl From<SledDbConfiguration> for AnyDatabaseConfig[src]

impl Serialize for AnyDatabaseConfig[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/index.html new file mode 100644 index 0000000000..abe18b01fd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/index.html @@ -0,0 +1,31 @@ +bdk::database::any - Rust + +

[][src]Module bdk::database::any

Runtime-checked database types

+

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

+

Example

+

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

+ +
+let memory = MemoryDatabase::default().into();
+let wallet_memory: OfflineWallet<AnyDatabase> =
+    Wallet::new_offline("...", None, Network::Testnet, memory)?;
+
+let sled = sled::open("my-database")?.open_tree("default_tree")?.into();
+let wallet_sled: OfflineWallet<AnyDatabase> =
+    Wallet::new_offline("...", None, Network::Testnet, sled)?;
+

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

+ +
+let config = serde_json::from_str("...")?;
+let database = AnyDatabase::from_config(&config)?;
+let wallet: OfflineWallet<_> = Wallet::new_offline("...", None, Network::Testnet, database)?;
+

Structs

+
SledDbConfiguration

Configuration type for a [sled::Tree] database

+

Enums

+
AnyBatch

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

+
AnyDatabase

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

+
AnyDatabaseConfig

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

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/sidebar-items.js new file mode 100644 index 0000000000..c0fb4445df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["AnyBatch","Type that contains any of the [`BatchDatabase::Batch`] types defined by the library"],["AnyDatabase","Type that can contain any of the [`Database`] types defined by the library"],["AnyDatabaseConfig","Type that can contain any of the database configurations defined by the library"]],"struct":[["SledDbConfiguration","Configuration type for a [`sled::Tree`] database"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/struct.SledDbConfiguration.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/struct.SledDbConfiguration.html new file mode 100644 index 0000000000..634abca3dd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/struct.SledDbConfiguration.html @@ -0,0 +1,39 @@ +bdk::database::any::SledDbConfiguration - Rust + +

[][src]Struct bdk::database::any::SledDbConfiguration

pub struct SledDbConfiguration {
+    pub path: String,
+    pub tree_name: String,
+}

Configuration type for a [sled::Tree] database

+

+ Fields

path: String

Main directory of the db

+
tree_name: String

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

+

Trait Implementations

impl Debug for SledDbConfiguration[src]

impl<'de> Deserialize<'de> for SledDbConfiguration[src]

impl From<SledDbConfiguration> for AnyDatabaseConfig[src]

impl Serialize for SledDbConfiguration[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/index.html new file mode 100644 index 0000000000..fb5d1a74e7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/index.html @@ -0,0 +1,22 @@ +bdk::database - Rust + +

[][src]Module bdk::database

Database types

+

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

+

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

+

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

+

Re-exports

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

Modules

+
any

Runtime-checked database types

+
memory

In-memory ephemeral database

+

Traits

+
BatchDatabase

Trait for a database that supports batch operations

+
BatchOperations

Trait for operations that can be batched

+
ConfigurableDatabase

Trait for Database types that can be created given a configuration

+
Database

Trait for reading data from a database

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/index.html new file mode 100644 index 0000000000..ca05a688e0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/index.html @@ -0,0 +1,9 @@ +bdk::database::memory - Rust + +

[][src]Module bdk::database::memory

In-memory ephemeral database

+

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

+

Structs

+
MemoryDatabase

In-memory ephemeral database

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/sidebar-items.js new file mode 100644 index 0000000000..665f6718d0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["MemoryDatabase","In-memory ephemeral database"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/struct.MemoryDatabase.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/struct.MemoryDatabase.html new file mode 100644 index 0000000000..a50d11bfaf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/struct.MemoryDatabase.html @@ -0,0 +1,68 @@ +bdk::database::memory::MemoryDatabase - Rust + +

[][src]Struct bdk::database::memory::MemoryDatabase

pub struct MemoryDatabase { /* fields omitted */ }

In-memory ephemeral database

+

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

+

Once it's dropped its content will be lost.

+

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

+

Implementations

impl MemoryDatabase[src]

pub fn new() -> Self[src]

Create a new empty database

+

Trait Implementations

impl BatchDatabase for MemoryDatabase[src]

type Batch = Self

Container for the operations

+

impl BatchOperations for MemoryDatabase[src]

impl ConfigurableDatabase for MemoryDatabase[src]

type Config = ()

Type that contains the configuration

+

impl Database for MemoryDatabase[src]

impl Debug for MemoryDatabase[src]

impl Default for MemoryDatabase[src]

impl From<<MemoryDatabase as BatchDatabase>::Batch> for AnyBatch[src]

impl From<MemoryDatabase> for AnyDatabase[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/sidebar-items.js new file mode 100644 index 0000000000..8349d566b5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"mod":[["any","Runtime-checked database types"],["memory","In-memory ephemeral database"]],"trait":[["BatchDatabase","Trait for a database that supports batch operations"],["BatchOperations","Trait for operations that can be batched"],["ConfigurableDatabase","Trait for [`Database`] types that can be created given a configuration"],["Database","Trait for reading data from a database"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.BatchDatabase.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.BatchDatabase.html new file mode 100644 index 0000000000..4edc4e5295 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.BatchDatabase.html @@ -0,0 +1,13 @@ +bdk::database::BatchDatabase - Rust + +

[][src]Trait bdk::database::BatchDatabase

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

Trait for a database that supports batch operations

+

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

+

Associated Types

type Batch: BatchOperations[src]

Container for the operations

+
Loading content...

Required methods

pub fn begin_batch(&self) -> Self::Batch[src]

Create a new batch container

+

pub fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>[src]

Consume and apply a batch of operations

+
Loading content...

Implementations on Foreign Types

impl BatchDatabase for Tree[src]

type Batch = Batch

Loading content...

Implementors

impl BatchDatabase for AnyDatabase[src]

type Batch = AnyBatch

impl BatchDatabase for MemoryDatabase[src]

type Batch = Self

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.BatchOperations.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.BatchOperations.html new file mode 100644 index 0000000000..43cec5ac1a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.BatchOperations.html @@ -0,0 +1,31 @@ +bdk::database::BatchOperations - Rust + +

[][src]Trait bdk::database::BatchOperations

pub trait BatchOperations {
+    pub fn set_script_pubkey(
        &mut self,
        script: &Script,
        keychain: KeychainKind,
        child: u32
    ) -> Result<(), Error>; +
pub fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>; +
pub fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>; +
pub fn set_tx(
        &mut self,
        transaction: &TransactionDetails
    ) -> Result<(), Error>; +
pub fn set_last_index(
        &mut self,
        keychain: KeychainKind,
        value: u32
    ) -> Result<(), Error>; +
pub fn del_script_pubkey_from_path(
        &mut self,
        keychain: KeychainKind,
        child: u32
    ) -> Result<Option<Script>, Error>; +
pub fn del_path_from_script_pubkey(
        &mut self,
        script: &Script
    ) -> Result<Option<(KeychainKind, u32)>, Error>; +
pub fn del_utxo(
        &mut self,
        outpoint: &OutPoint
    ) -> Result<Option<UTXO>, Error>; +
pub fn del_raw_tx(
        &mut self,
        txid: &Txid
    ) -> Result<Option<Transaction>, Error>; +
pub fn del_tx(
        &mut self,
        txid: &Txid,
        include_raw: bool
    ) -> Result<Option<TransactionDetails>, Error>; +
pub fn del_last_index(
        &mut self,
        keychain: KeychainKind
    ) -> Result<Option<u32>, Error>; +}

Trait for operations that can be batched

+

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

+

Required methods

pub fn set_script_pubkey(
    &mut self,
    script: &Script,
    keychain: KeychainKind,
    child: u32
) -> Result<(), Error>
[src]

Store a script_pubkey along with its keychain and child number.

+

pub fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>[src]

Store a UTXO

+

pub fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>[src]

Store a raw transaction

+

pub fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>[src]

Store the metadata of a transaction

+

pub fn set_last_index(
    &mut self,
    keychain: KeychainKind,
    value: u32
) -> Result<(), Error>
[src]

Store the last derivation index for a given keychain.

+

pub fn del_script_pubkey_from_path(
    &mut self,
    keychain: KeychainKind,
    child: u32
) -> Result<Option<Script>, Error>
[src]

Delete a script_pubkey given the keychain and its child number.

+

pub fn del_path_from_script_pubkey(
    &mut self,
    script: &Script
) -> Result<Option<(KeychainKind, u32)>, Error>
[src]

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

+

pub fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>[src]

Delete a UTXO given its [OutPoint]

+

pub fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>[src]

Delete a raw transaction given its [Txid]

+

pub fn del_tx(
    &mut self,
    txid: &Txid,
    include_raw: bool
) -> Result<Option<TransactionDetails>, Error>
[src]

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

+

pub fn del_last_index(
    &mut self,
    keychain: KeychainKind
) -> Result<Option<u32>, Error>
[src]

Delete the last derivation index for a keychain.

+
Loading content...

Implementations on Foreign Types

impl BatchOperations for Tree[src]

impl BatchOperations for Batch[src]

Loading content...

Implementors

impl BatchOperations for AnyBatch[src]

impl BatchOperations for AnyDatabase[src]

impl BatchOperations for MemoryDatabase[src]

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.ConfigurableDatabase.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.ConfigurableDatabase.html new file mode 100644 index 0000000000..463d548462 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.ConfigurableDatabase.html @@ -0,0 +1,10 @@ +bdk::database::ConfigurableDatabase - Rust + +

[][src]Trait bdk::database::ConfigurableDatabase

pub trait ConfigurableDatabase: Database + Sized {
+    type Config: Debug;
+    pub fn from_config(config: &Self::Config) -> Result<Self, Error>;
+}

Trait for Database types that can be created given a configuration

+

Associated Types

type Config: Debug[src]

Type that contains the configuration

+
Loading content...

Required methods

pub fn from_config(config: &Self::Config) -> Result<Self, Error>[src]

Create a new instance given a configuration

+
Loading content...

Implementations on Foreign Types

impl ConfigurableDatabase for Tree[src]

type Config = SledDbConfiguration

Loading content...

Implementors

impl ConfigurableDatabase for AnyDatabase[src]

type Config = AnyDatabaseConfig

impl ConfigurableDatabase for MemoryDatabase[src]

type Config = ()

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.Database.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.Database.html new file mode 100644 index 0000000000..c776d70675 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.Database.html @@ -0,0 +1,35 @@ +bdk::database::Database - Rust + +

[][src]Trait bdk::database::Database

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

Trait for reading data from a database

+

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

+

Required methods

pub fn check_descriptor_checksum<B: AsRef<[u8]>>(
    &mut self,
    keychain: KeychainKind,
    bytes: B
) -> Result<(), Error>
[src]

Read and checks the descriptor checksum for a given keychain.

+

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

+

pub fn iter_script_pubkeys(
    &self,
    keychain: Option<KeychainKind>
) -> Result<Vec<Script>, Error>
[src]

Return the list of script_pubkeys

+

pub fn iter_utxos(&self) -> Result<Vec<UTXO>, Error>[src]

Return the list of UTXOs

+

pub fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>[src]

Return the list of raw transactions

+

pub fn iter_txs(
    &self,
    include_raw: bool
) -> Result<Vec<TransactionDetails>, Error>
[src]

Return the list of transactions metadata

+

pub fn get_script_pubkey_from_path(
    &self,
    keychain: KeychainKind,
    child: u32
) -> Result<Option<Script>, Error>
[src]

Fetch a script_pubkey given the child number of a keychain.

+

pub fn get_path_from_script_pubkey(
    &self,
    script: &Script
) -> Result<Option<(KeychainKind, u32)>, Error>
[src]

Fetch the keychain and child number of a given script_pubkey

+

pub fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>[src]

Fetch a UTXO given its [OutPoint]

+

pub fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>[src]

Fetch a raw transaction given its [Txid]

+

pub fn get_tx(
    &self,
    txid: &Txid,
    include_raw: bool
) -> Result<Option<TransactionDetails>, Error>
[src]

Fetch the transaction metadata and optionally also the raw transaction

+

pub fn get_last_index(
    &self,
    keychain: KeychainKind
) -> Result<Option<u32>, Error>
[src]

Return the last defivation index for a keychain.

+

pub fn increment_last_index(
    &mut self,
    keychain: KeychainKind
) -> Result<u32, Error>
[src]

Increment the last derivation index for a keychain and return it

+

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

+
Loading content...

Implementations on Foreign Types

impl Database for Tree[src]

Loading content...

Implementors

impl Database for AnyDatabase[src]

impl Database for MemoryDatabase[src]

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/fn.get_checksum.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/fn.get_checksum.html new file mode 100644 index 0000000000..6b9e25e90a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/fn.get_checksum.html @@ -0,0 +1,5 @@ +bdk::descriptor::checksum::get_checksum - Rust + +

[][src]Function bdk::descriptor::checksum::get_checksum

pub fn get_checksum(desc: &str) -> Result<String, Error>

Compute the checksum of a descriptor

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/index.html new file mode 100644 index 0000000000..0c7f9bb96d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/index.html @@ -0,0 +1,9 @@ +bdk::descriptor::checksum - Rust + +

[][src]Module bdk::descriptor::checksum

Descriptor checksum

+

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

+

Functions

+
get_checksum

Compute the checksum of a descriptor

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/sidebar-items.js new file mode 100644 index 0000000000..e1add094a5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"fn":[["get_checksum","Compute the checksum of a descriptor"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Descriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Descriptor.html new file mode 100644 index 0000000000..42300b0891 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Descriptor.html @@ -0,0 +1,156 @@ +bdk::descriptor::Descriptor - Rust + +

[]Enum bdk::descriptor::Descriptor

pub enum Descriptor<Pk> where
    Pk: MiniscriptKey
{ + Bare(Miniscript<Pk, Bare>), + Pk(Pk), + Pkh(Pk), + Wpkh(Pk), + ShWpkh(Pk), + Sh(Miniscript<Pk, Legacy>), + Wsh(Miniscript<Pk, Segwitv0>), + ShWsh(Miniscript<Pk, Segwitv0>), + ShSortedMulti(SortedMultiVec<Pk, Legacy>), + WshSortedMulti(SortedMultiVec<Pk, Segwitv0>), + ShWshSortedMulti(SortedMultiVec<Pk, Segwitv0>), +}

Script descriptor

+

+ Variants

+
Bare(Miniscript<Pk, Bare>)

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

+
Pk(Pk)

Pay-to-Pubkey

+
Pkh(Pk)

Pay-to-PubKey-Hash

+
Wpkh(Pk)

Pay-to-Witness-PubKey-Hash

+
ShWpkh(Pk)

Pay-to-Witness-PubKey-Hash inside P2SH

+

Pay-to-ScriptHash with Legacy context

+

Pay-to-Witness-ScriptHash with Segwitv0 context

+
ShWsh(Miniscript<Pk, Segwitv0>)

P2SH-P2WSH with Segwitv0 context

+
ShSortedMulti(SortedMultiVec<Pk, Legacy>)

Sortedmulti under P2SH

+
WshSortedMulti(SortedMultiVec<Pk, Segwitv0>)

Sortedmulti under P2WSH

+
ShWshSortedMulti(SortedMultiVec<Pk, Segwitv0>)

Sortedmulti under P2SH-P2WSH

+

Implementations

impl<Pk> Descriptor<Pk> where
    Pk: MiniscriptKey

pub fn translate_pk<Fpk, Fpkh, Q, E>(
    &self,
    translatefpk: Fpk,
    translatefpkh: Fpkh
) -> Result<Descriptor<Q>, E> where
    Fpk: FnMut(&Pk) -> Result<Q, E>,
    Fpkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, E>,
    Q: MiniscriptKey

Convert a descriptor using abstract keys to one using specific keys +This will panic if translatefpk returns an uncompressed key when +converting to a Segwit descriptor. To prevent this panic, ensure +translatefpk returns an error in this case instead.

+

pub fn sanity_check(&self) -> Result<(), Error>

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 signauture on all spend paths +And whether the script is malleable. +In general, all the guarantees of miniscript hold only for safe scripts. +All the analysis guarantees of miniscript only hold safe scripts. +The signer may not be able to find satisfactions even if one exists

+

impl<Pk> Descriptor<Pk> where
    Pk: MiniscriptKey

pub fn address<ToPkCtx>(
    &self,
    network: Network,
    to_pk_ctx: ToPkCtx
) -> Option<Address> where
    Pk: ToPublicKey<ToPkCtx>,
    ToPkCtx: Copy

Computes the Bitcoin address of the descriptor, if one exists +to_pk_ctx denotes the ToPkCtx required for deriving bitcoin::PublicKey +from MiniscriptKey using ToPublicKey. +If MiniscriptKey is already is [bitcoin::PublicKey], then the context +would be [NullCtx] and [descriptor.DescriptorPublicKeyCtx] if MiniscriptKey is [descriptor.DescriptorPublicKey]

+

In general, this is defined by generic for the trait [trait.ToPublicKey]

+

pub fn script_pubkey<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> Script where
    Pk: ToPublicKey<ToPkCtx>,
    ToPkCtx: Copy

Computes the scriptpubkey of the descriptor +to_pk_ctx denotes the ToPkCtx required for deriving bitcoin::PublicKey +from MiniscriptKey using ToPublicKey. +If MiniscriptKey is already is [bitcoin::PublicKey], then the context +would be [NullCtx] and [descriptor.DescriptorPublicKeyCtx] if MiniscriptKey is [descriptor.DescriptorPublicKey]

+

In general, this is defined by generic for the trait ToPublicKey

+

pub fn unsigned_script_sig<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> Script where
    Pk: ToPublicKey<ToPkCtx>,
    ToPkCtx: Copy

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). +to_pk_ctx denotes the ToPkCtx required for deriving bitcoin::PublicKey +from MiniscriptKey using ToPublicKey. +If MiniscriptKey is already is [bitcoin::PublicKey], then the context +would be [NullCtx] and [descriptor.DescriptorPublicKeyCtx] if MiniscriptKey is [descriptor.DescriptorPublicKey]

+

In general, this is defined by generic for the trait ToPublicKey

+

pub fn witness_script<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> Script where
    Pk: ToPublicKey<ToPkCtx>,
    ToPkCtx: Copy

Computes the "witness script" of the descriptor, i.e. 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. +to_pk_ctx denotes the ToPkCtx required for deriving bitcoin::PublicKey +from MiniscriptKey using ToPublicKey. +If MiniscriptKey is already is [bitcoin::PublicKey], then the context +would be [NullCtx] and [descriptor.DescriptorPublicKeyCtx] if MiniscriptKey is [descriptor.DescriptorPublicKey]

+

In general, this is defined by generic for the trait ToPublicKey

+

pub fn get_satisfication<ToPkCtx, S>(
    &self,
    satisfier: S,
    to_pk_ctx: ToPkCtx
) -> Result<(Vec<Vec<u8, Global>, Global>, Script), Error> where
    Pk: ToPublicKey<ToPkCtx>,
    S: Satisfier<ToPkCtx, Pk>,
    ToPkCtx: Copy

Returns satisfying witness and scriptSig to spend an +output controlled by the given descriptor if it possible to +construct one using the satisfier S. +to_pk_ctx denotes the ToPkCtx required for deriving bitcoin::PublicKey +from MiniscriptKey using ToPublicKey. +If MiniscriptKey is already is [bitcoin::PublicKey], then the context +would be [NullCtx] and [descriptor.DescriptorPublicKeyCtx] if MiniscriptKey is [descriptor.DescriptorPublicKey]

+

In general, this is defined by generic for the trait ToPublicKey

+

pub fn satisfy<ToPkCtx, S>(
    &self,
    txin: &mut TxIn,
    satisfier: S,
    to_pk_ctx: ToPkCtx
) -> Result<(), Error> where
    Pk: ToPublicKey<ToPkCtx>,
    S: Satisfier<ToPkCtx, Pk>,
    ToPkCtx: Copy

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

+

pub fn max_satisfaction_weight<ToPkCtx>(
    &self,
    to_pk_ctx: ToPkCtx
) -> Option<usize> where
    Pk: ToPublicKey<ToPkCtx>,
    ToPkCtx: Copy

Computes an upper bound on the weight of a satisfying witness to the +transaction. Assumes all signatures are 73 bytes, including push opcode +and sighash suffix. Includes the weight of the VarInts encoding the +scriptSig and witness stack length.

+

pub fn script_code<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> Script where
    Pk: ToPublicKey<ToPkCtx>,
    ToPkCtx: Copy

Get 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. +to_pk_ctx denotes the ToPkCtx required for deriving bitcoin::PublicKey +from MiniscriptKey using ToPublicKey. +If MiniscriptKey is already is [bitcoin::PublicKey], then the context +would be [NullCtx] and [descriptor.DescriptorPublicKeyCtx] if MiniscriptKey is [descriptor.DescriptorPublicKey]

+

In general, this is defined by generic for the trait ToPublicKey

+

impl Descriptor<DescriptorPublicKey>

pub fn derive(
    &self,
    child_number: ChildNumber
) -> Descriptor<DescriptorPublicKey>

Derives all wildcard keys in the descriptor using the supplied child_number

+

pub fn parse_descriptor(
    s: &str
) -> Result<(Descriptor<DescriptorPublicKey>, HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>), Error>

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.

+

pub fn to_string_with_secret(
    &self,
    key_map: &HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>
) -> String

Serialize a descriptor to string with its secret keys

+

Trait Implementations

impl<Pk> Clone for Descriptor<Pk> where
    Pk: MiniscriptKey + Clone

impl<Pk> Debug for Descriptor<Pk> where
    Pk: MiniscriptKey

impl<Pk> Display for Descriptor<Pk> where
    Pk: MiniscriptKey

impl<Pk> Eq for Descriptor<Pk> where
    Pk: MiniscriptKey + Eq

impl ExtractPolicy for Descriptor<DescriptorPublicKey>[src]

impl<Pk> FromStr for Descriptor<Pk> where
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

type Err = Error

The associated error which can be returned from parsing.

+

impl<Pk> FromTree for Descriptor<Pk> where
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

pub fn from_tree(top: &Tree<'_>) -> Result<Descriptor<Pk>, Error>

Parse an expression tree into a descriptor

+

impl<Pk> Liftable<Pk> for Descriptor<Pk> where
    Pk: MiniscriptKey

impl<Pk> Ord for Descriptor<Pk> where
    Pk: MiniscriptKey + Ord

impl<Pk> PartialEq<Descriptor<Pk>> for Descriptor<Pk> where
    Pk: MiniscriptKey + PartialEq<Pk>, 

impl<Pk> PartialOrd<Descriptor<Pk>> for Descriptor<Pk> where
    Pk: MiniscriptKey + PartialOrd<Pk>, 

impl<Pk> StructuralEq for Descriptor<Pk> where
    Pk: MiniscriptKey

impl<Pk> StructuralPartialEq for Descriptor<Pk> where
    Pk: MiniscriptKey

Auto Trait Implementations

impl<Pk> RefUnwindSafe for Descriptor<Pk> where
    Pk: RefUnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe
[src]

impl<Pk> Send for Descriptor<Pk> where
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync
[src]

impl<Pk> Sync for Descriptor<Pk> where
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync
[src]

impl<Pk> Unpin for Descriptor<Pk> where
    Pk: Unpin,
    <Pk as MiniscriptKey>::Hash: Unpin
[src]

impl<Pk> UnwindSafe for Descriptor<Pk> where
    Pk: RefUnwindSafe + UnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Legacy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Legacy.html new file mode 100644 index 0000000000..ffb2ec62ab --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Legacy.html @@ -0,0 +1,103 @@ +bdk::descriptor::Legacy - Rust + +

[]Enum bdk::descriptor::Legacy

pub enum Legacy {}

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

+

Trait Implementations

impl Clone for Legacy

impl Debug for Legacy

impl Eq for Legacy

impl Ord for Legacy

impl PartialEq<Legacy> for Legacy

impl PartialOrd<Legacy> for Legacy

impl ScriptContext for Legacy

impl StructuralEq for Legacy

impl StructuralPartialEq for Legacy

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<Ctx> ExtScriptContext for Ctx where
    Ctx: 'static + ScriptContext
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Segwitv0.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Segwitv0.html new file mode 100644 index 0000000000..8d6af85ba0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Segwitv0.html @@ -0,0 +1,100 @@ +bdk::descriptor::Segwitv0 - Rust + +

[]Enum bdk::descriptor::Segwitv0

pub enum Segwitv0 {}

Segwitv0 ScriptContext

+

Trait Implementations

impl Clone for Segwitv0

impl Debug for Segwitv0

impl Eq for Segwitv0

impl Ord for Segwitv0

impl PartialEq<Segwitv0> for Segwitv0

impl PartialOrd<Segwitv0> for Segwitv0

impl ScriptContext for Segwitv0

impl StructuralEq for Segwitv0

impl StructuralPartialEq for Segwitv0

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<Ctx> ExtScriptContext for Ctx where
    Ctx: 'static + ScriptContext
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Terminal.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Terminal.html new file mode 100644 index 0000000000..1cf838dcc4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Terminal.html @@ -0,0 +1,124 @@ +bdk::descriptor::Terminal - Rust + +

[]Enum bdk::descriptor::Terminal

pub enum Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey
{ + True, + False, + PkK(Pk), + PkH(<Pk as MiniscriptKey>::Hash), + After(u32), + Older(u32), + Sha256(Hash), + Hash256(Hash), + Ripemd160(Hash), + Hash160(Hash), + Alt(Arc<Miniscript<Pk, Ctx>>), + Swap(Arc<Miniscript<Pk, Ctx>>), + Check(Arc<Miniscript<Pk, Ctx>>), + DupIf(Arc<Miniscript<Pk, Ctx>>), + Verify(Arc<Miniscript<Pk, Ctx>>), + NonZero(Arc<Miniscript<Pk, Ctx>>), + ZeroNotEqual(Arc<Miniscript<Pk, Ctx>>), + AndV(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + AndB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + AndOr(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + OrB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + OrD(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + OrC(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + OrI(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), + Thresh(usizeVec<Arc<Miniscript<Pk, Ctx>>, Global>), + Multi(usizeVec<Pk, Global>), +}

All AST elements

+

+ Variants

+
True

1

+
False

0

+
PkK(Pk)

<key>

+
PkH(<Pk as MiniscriptKey>::Hash)

DUP HASH160 <keyhash> EQUALVERIFY

+
After(u32)

n CHECKLOCKTIMEVERIFY

+
Older(u32)

n CHECKSEQUENCEVERIFY

+
Sha256(Hash)

SIZE 32 EQUALVERIFY SHA256 <hash> EQUAL

+
Hash256(Hash)

SIZE 32 EQUALVERIFY HASH256 <hash> EQUAL

+
Ripemd160(Hash)

SIZE 32 EQUALVERIFY RIPEMD160 <hash> EQUAL

+
Hash160(Hash)

SIZE 32 EQUALVERIFY HASH160 <hash> EQUAL

+
Alt(Arc<Miniscript<Pk, Ctx>>)

TOALTSTACK [E] FROMALTSTACK

+
Swap(Arc<Miniscript<Pk, Ctx>>)

SWAP [E1]

+
Check(Arc<Miniscript<Pk, Ctx>>)

[Kt]/[Ke] CHECKSIG

+
DupIf(Arc<Miniscript<Pk, Ctx>>)

DUP IF [V] ENDIF

+
Verify(Arc<Miniscript<Pk, Ctx>>)

[T] VERIFY

+
NonZero(Arc<Miniscript<Pk, Ctx>>)

SIZE 0NOTEQUAL IF Fn ENDIF

+
ZeroNotEqual(Arc<Miniscript<Pk, Ctx>>)

[X] 0NOTEQUAL

+
AndV(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[V] [T]/[V]/[F]/[Kt]

+
AndB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[E] [W] BOOLAND

+
AndOr(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[various] NOTIF [various] ELSE [various] ENDIF

+
OrB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[E] [W] BOOLOR

+
OrD(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[E] IFDUP NOTIF [T]/[E] ENDIF

+
OrC(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

[E] NOTIF [V] ENDIF

+
OrI(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

IF [various] ELSE [various] ENDIF

+
Thresh(usizeVec<Arc<Miniscript<Pk, Ctx>>, Global>)

[E] ([W] ADD)* k EQUAL

+
Multi(usizeVec<Pk, Global>)

k ()* n CHECKMULTISIG

+

Implementations

impl<Pk, Ctx> Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn translate_pk<FPk, FPkh, Q, Error>(
    &self,
    translatefpk: &mut FPk,
    translatefpkh: &mut FPkh
) -> Result<Terminal<Q, Ctx>, Error> where
    FPk: FnMut(&Pk) -> Result<Q, Error>,
    FPkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, Error>,
    Q: MiniscriptKey

Convert an AST element with one public key type to one of another +public key type .This will panic while converting to +Segwit Miniscript using uncompressed public keys

+

impl<Pk, Ctx> Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn encode<ToPkCtx>(&self, builder: Builder, to_pk_ctx: ToPkCtx) -> Builder where
    Pk: ToPublicKey<ToPkCtx>,
    ToPkCtx: Copy

Encode the element as a fragment of Bitcoin Script. The inverse +function, from Script to an AST element, is implemented in the +parse module.

+

pub fn script_size<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> usize where
    Pk: ToPublicKey<ToPkCtx>,
    ToPkCtx: Copy

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.

+

Trait Implementations

impl<Pk, Ctx> Clone for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + Clone,
    Pk: MiniscriptKey + Clone,
    <Pk as MiniscriptKey>::Hash: Clone

impl<Pk, Ctx> Debug for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Display for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Eq for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + Eq,
    Pk: MiniscriptKey + Eq,
    <Pk as MiniscriptKey>::Hash: Eq

impl<Pk, Ctx> FromTree for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

impl<Pk, Ctx> Hash for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + Hash,
    Pk: MiniscriptKey + Hash,
    <Pk as MiniscriptKey>::Hash: Hash

impl<Pk, Ctx> Liftable<Pk> for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Ord for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + Ord,
    Pk: MiniscriptKey + Ord,
    <Pk as MiniscriptKey>::Hash: Ord

impl<Pk, Ctx> PartialEq<Terminal<Pk, Ctx>> for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + PartialEq<Ctx>,
    Pk: MiniscriptKey + PartialEq<Pk>,
    <Pk as MiniscriptKey>::Hash: PartialEq<<Pk as MiniscriptKey>::Hash>, 

impl<Pk, Ctx> PartialOrd<Terminal<Pk, Ctx>> for Terminal<Pk, Ctx> where
    Ctx: ScriptContext + PartialOrd<Ctx>,
    Pk: MiniscriptKey + PartialOrd<Pk>,
    <Pk as MiniscriptKey>::Hash: PartialOrd<<Pk as MiniscriptKey>::Hash>, 

impl<Pk, Ctx> StructuralEq for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> StructuralPartialEq for Terminal<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Auto Trait Implementations

impl<Pk, Ctx> RefUnwindSafe for Terminal<Pk, Ctx> where
    Ctx: RefUnwindSafe,
    Pk: RefUnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe
[src]

impl<Pk, Ctx> Send for Terminal<Pk, Ctx> where
    Ctx: Send + Sync,
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync
[src]

impl<Pk, Ctx> Sync for Terminal<Pk, Ctx> where
    Ctx: Send + Sync,
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync
[src]

impl<Pk, Ctx> Unpin for Terminal<Pk, Ctx> where
    Pk: Unpin,
    <Pk as MiniscriptKey>::Hash: Unpin
[src]

impl<Pk, Ctx> UnwindSafe for Terminal<Pk, Ctx> where
    Ctx: RefUnwindSafe,
    Pk: RefUnwindSafe + UnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/enum.Error.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/enum.Error.html new file mode 100644 index 0000000000..f85b978722 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/enum.Error.html @@ -0,0 +1,65 @@ +bdk::descriptor::error::Error - Rust + +

[][src]Enum bdk::descriptor::error::Error

pub enum Error {
+    InvalidHDKeyPath,
+    Key(KeyError),
+    Policy(PolicyError),
+    InvalidDescriptorCharacter(char),
+    BIP32(Error),
+    Base58(Error),
+    PK(Error),
+    Miniscript(Error),
+    Hex(Error),
+}

Errors related to the parsing and usage of descriptors

+

+ Variants

+
InvalidHDKeyPath

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

+

Error thrown while working with keys

+
Policy(PolicyError)

Error while extracting and manipulating policies

+
InvalidDescriptorCharacter(char)

Invalid character 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(Error)

Hex decoding error

+

Trait Implementations

impl Debug for Error[src]

impl Display for Error[src]

impl Error for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<KeyError> for Error[src]

impl From<PolicyError> for Error[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/index.html new file mode 100644 index 0000000000..7f40f8e520 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/index.html @@ -0,0 +1,7 @@ +bdk::descriptor::error - Rust + +

[][src]Module bdk::descriptor::error

Descriptor errors

+

Enums

+
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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/sidebar-items.js new file mode 100644 index 0000000000..1ad99d4faf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/index.html new file mode 100644 index 0000000000..ccb74e27c0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/index.html @@ -0,0 +1,39 @@ +bdk::descriptor - Rust + +

[][src]Module bdk::descriptor

Descriptors

+

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

+

Re-exports

+
pub use self::checksum::get_checksum;
pub use self::policy::Policy;

Modules

+
checksum

Descriptor checksum

+
error

Descriptor errors

+
policy

Descriptor policy

+
template

Descriptor templates

+

Structs

+
Miniscript

Top-level script AST type

+

Enums

+
Descriptor

Script descriptor

+
Legacy

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

+
Segwitv0

Segwitv0 ScriptContext

+
Terminal

All AST elements

+

Traits

+
ExtractPolicy

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

+
MiniscriptKey

Public key trait which can be converted to Hash type

+
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

+
ToPublicKey

Trait describing public key types which can be converted to bitcoin pubkeys +The trait relies on Copy trait because in all practical usecases ToPkCtx +should contain references to objects which should be cheap to Copy.

+
ToWalletDescriptor

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

+

Type Definitions

+
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

+
KeyMap

Alias type for a map of public key to secret key

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.PolicyError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.PolicyError.html new file mode 100644 index 0000000000..c514b71eff --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.PolicyError.html @@ -0,0 +1,55 @@ +bdk::descriptor::policy::PolicyError - Rust + +

[][src]Enum bdk::descriptor::policy::PolicyError

pub enum PolicyError {
+    NotEnoughItemsSelected(String),
+    TooManyItemsSelected(String),
+    IndexOutOfRange(usize),
+    AddOnLeaf,
+    AddOnPartialComplete,
+    MixedTimelockUnits,
+    IncompatibleConditions,
+}

Errors that can happen while extracting and manipulating policies

+

+ Variants

+
NotEnoughItemsSelected(String)

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

+
TooManyItemsSelected(String)

Too many items are selected to satisfy a SatisfiableItem::Thresh

+
IndexOutOfRange(usize)

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

+
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

impl Debug for PolicyError[src]

impl Display for PolicyError[src]

impl Error for PolicyError[src]

impl From<PolicyError> for Error[src]

impl From<PolicyError> for Error[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.Satisfaction.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.Satisfaction.html new file mode 100644 index 0000000000..5c56c8e9b8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.Satisfaction.html @@ -0,0 +1,75 @@ +bdk::descriptor::policy::Satisfaction - Rust + +

[][src]Enum bdk::descriptor::policy::Satisfaction

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,
+}

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

+

+ Variants

+
Partial

Only a partial satisfaction of some kind of threshold policy

+

Fields of Partial

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

Extra conditions that also need to be satisfied

+
PartialComplete

Can reach the threshold of some kind of threshold policy

+

Fields of PartialComplete

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

+
Complete

Can satisfy the policy item

+

Fields of Complete

condition: Condition

Extra conditions that also need to be satisfied

+
None

Cannot satisfy or contribute to the policy item

+

Implementations

impl Satisfaction[src]

pub fn is_leaf(&self) -> bool[src]

Returns whether the Satisfaction is a leaf item

+

Trait Implementations

impl Clone for Satisfaction[src]

impl Debug for Satisfaction[src]

impl From<bool> for Satisfaction[src]

impl Serialize for Satisfaction[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.SatisfiableItem.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.SatisfiableItem.html new file mode 100644 index 0000000000..e5fa6b2346 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.SatisfiableItem.html @@ -0,0 +1,91 @@ +bdk::descriptor::policy::SatisfiableItem - Rust + +

[][src]Enum bdk::descriptor::policy::SatisfiableItem

pub enum SatisfiableItem {
+    Signature(PKOrF),
+    SignatureKey(PKOrF),
+    SHA256Preimage {
+        hash: Hash,
+    },
+    HASH256Preimage {
+        hash: Hash,
+    },
+    RIPEMD160Preimage {
+        hash: Hash,
+    },
+    HASH160Preimage {
+        hash: Hash,
+    },
+    AbsoluteTimelock {
+        value: u32,
+    },
+    RelativeTimelock {
+        value: u32,
+    },
+    Multisig {
+        keys: Vec<PKOrF>,
+        threshold: usize,
+    },
+    Thresh {
+        items: Vec<Policy>,
+        threshold: usize,
+    },
+}

An item that needs to be satisfied

+

+ Variants

+
Signature(PKOrF)

Signature for a raw public key

+
SignatureKey(PKOrF)

Signature for an extended key fingerprint

+
SHA256Preimage

SHA256 preimage hash

+

Fields of SHA256Preimage

hash: Hash

The digest value

+
HASH256Preimage

Double SHA256 preimage hash

+

Fields of HASH256Preimage

hash: Hash

The digest value

+
RIPEMD160Preimage

RIPEMD160 preimage hash

+

Fields of RIPEMD160Preimage

hash: Hash

The digest value

+
HASH160Preimage

SHA256 then RIPEMD160 preimage hash

+

Fields of HASH160Preimage

hash: Hash

The digest value

+
AbsoluteTimelock

Absolute timeclock timestamp

+

Fields of AbsoluteTimelock

value: u32

The timestamp value

+
RelativeTimelock

Relative timelock locktime

+

Fields of RelativeTimelock

value: u32

The locktime value

+
Multisig

Multi-signature public keys with threshold count

+

Fields of Multisig

keys: Vec<PKOrF>

The raw public key or extended key fingerprint

+
threshold: usize

The required threshold count

+
Thresh

Threshold items with threshold count

+

Fields of Thresh

items: Vec<Policy>

The policy items

+
threshold: usize

The required threshold count

+

Implementations

impl SatisfiableItem[src]

pub fn is_leaf(&self) -> bool[src]

Returns whether the SatisfiableItem is a leaf item

+

pub fn id(&self) -> String[src]

Returns a unique id for the SatisfiableItem

+

Trait Implementations

impl Clone for SatisfiableItem[src]

impl Debug for SatisfiableItem[src]

impl From<SatisfiableItem> for Policy[src]

impl Serialize for SatisfiableItem[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/index.html new file mode 100644 index 0000000000..b63abf9c5b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/index.html @@ -0,0 +1,30 @@ +bdk::descriptor::policy - Rust + +

[][src]Module bdk::descriptor::policy

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

+
+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(desc)?;
+println!("{:?}", extended_desc);
+
+let signers = Arc::new(key_map.into());
+let policy = extended_desc.extract_policy(&signers, &secp)?;
+println!("policy: {}", serde_json::to_string(&policy)?);
+

Structs

+
Condition

An extra condition that must be satisfied but that is out of control of the user

+
PKOrF

Raw public key or extended key fingerprint

+
Policy

Descriptor spending policy

+

Enums

+
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

+

Type Definitions

+
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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/sidebar-items.js new file mode 100644 index 0000000000..4a150396ce --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["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"],["PKOrF","Raw public key or extended key fingerprint"],["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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.Condition.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.Condition.html new file mode 100644 index 0000000000..494ddc412f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.Condition.html @@ -0,0 +1,62 @@ +bdk::descriptor::policy::Condition - Rust + +

[][src]Struct bdk::descriptor::policy::Condition

pub struct Condition {
+    pub csv: Option<u32>,
+    pub timelock: Option<u32>,
+}

An extra condition that must be satisfied but that is out of control of the user

+

+ Fields

csv: Option<u32>

Optional CheckSequenceVerify condition

+
timelock: Option<u32>

Optional timelock condition

+

Implementations

impl Condition[src]

pub fn is_null(&self) -> bool[src]

Returns true if there are no extra conditions to verify

+

Trait Implementations

impl Clone for Condition[src]

impl Copy for Condition[src]

impl Debug for Condition[src]

impl Default for Condition[src]

impl Eq for Condition[src]

impl Hash for Condition[src]

impl Ord for Condition[src]

impl PartialEq<Condition> for Condition[src]

impl PartialOrd<Condition> for Condition[src]

impl Serialize for Condition[src]

impl StructuralEq for Condition[src]

impl StructuralPartialEq for Condition[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.PKOrF.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.PKOrF.html new file mode 100644 index 0000000000..2033adda15 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.PKOrF.html @@ -0,0 +1,38 @@ +bdk::descriptor::policy::PKOrF - Rust + +

[][src]Struct bdk::descriptor::policy::PKOrF

pub struct PKOrF { /* fields omitted */ }

Raw public key or extended key fingerprint

+

Trait Implementations

impl Clone for PKOrF[src]

impl Debug for PKOrF[src]

impl Default for PKOrF[src]

impl Serialize for PKOrF[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.Policy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.Policy.html new file mode 100644 index 0000000000..edb84dab4d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.Policy.html @@ -0,0 +1,55 @@ +bdk::descriptor::policy::Policy - Rust + +

[][src]Struct bdk::descriptor::policy::Policy

pub struct Policy {
+    pub id: String,
+    pub item: SatisfiableItem,
+    pub satisfaction: Satisfaction,
+    pub contribution: Satisfaction,
+}

Descriptor spending policy

+

+ Fields

id: String

Identifier for this policy node

+
item: SatisfiableItem

Type of this policy node

+
satisfaction: Satisfaction

How a much given PSBT already satisfies this polcy node (currently unused)

+
contribution: Satisfaction

How the wallet's descriptor can satisfy this policy node

+

Implementations

impl Policy[src]

pub fn requires_path(&self) -> bool[src]

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 get_condition(
    &self,
    path: &BTreeMap<String, Vec<usize>>
) -> Result<Condition, PolicyError>
[src]

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

+

Trait Implementations

impl Clone for Policy[src]

impl Debug for Policy[src]

impl From<SatisfiableItem> for Policy[src]

impl Serialize for Policy[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/type.ConditionMap.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/type.ConditionMap.html new file mode 100644 index 0000000000..04cdc96053 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/type.ConditionMap.html @@ -0,0 +1,5 @@ +bdk::descriptor::policy::ConditionMap - Rust + +

[][src]Type Definition bdk::descriptor::policy::ConditionMap

type ConditionMap = BTreeMap<usize, HashSet<Condition>>;

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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/type.FoldedConditionMap.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/type.FoldedConditionMap.html new file mode 100644 index 0000000000..d677ccbae2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/type.FoldedConditionMap.html @@ -0,0 +1,5 @@ +bdk::descriptor::policy::FoldedConditionMap - Rust + +

[][src]Type Definition bdk::descriptor::policy::FoldedConditionMap

type FoldedConditionMap = BTreeMap<Vec<usize>, HashSet<Condition>>;

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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/sidebar-items.js new file mode 100644 index 0000000000..91b23d7fe1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["Descriptor","Script descriptor"],["Legacy","Legacy ScriptContext To be used as P2SH scripts For creation of Bare scriptpubkeys, construct the Miniscript under `Bare` ScriptContext"],["Segwitv0","Segwitv0 ScriptContext"],["Terminal","All AST elements"]],"mod":[["checksum","Descriptor checksum"],["error","Descriptor errors"],["policy","Descriptor policy"],["template","Descriptor templates"]],"struct":[["Miniscript","Top-level script AST type"]],"trait":[["ExtractPolicy","Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]"],["MiniscriptKey","Public key trait which can be converted to Hash type"],["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"],["ToPublicKey","Trait describing public key types which can be converted to bitcoin pubkeys The trait relies on Copy trait because in all practical usecases `ToPkCtx` should contain references to objects which should be cheap to `Copy`."],["ToWalletDescriptor","Trait for types which can be converted into an [`ExtendedDescriptor`] and a [`KeyMap`] usable by a wallet in a specific [`Network`]"]],"type":[["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`"],["KeyMap","Alias type for a map of public key to secret key"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/struct.Miniscript.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/struct.Miniscript.html new file mode 100644 index 0000000000..1c5121d486 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/struct.Miniscript.html @@ -0,0 +1,206 @@ +bdk::descriptor::Miniscript - Rust + +

[]Struct bdk::descriptor::Miniscript

pub struct Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey
{ + pub node: Terminal<Pk, Ctx>, + pub ty: Type, + pub ext: ExtData, + // some fields omitted +}

Top-level script AST type

+

+ Fields

node: Terminal<Pk, Ctx>

A node in the Abstract Syntax Tree(

+
ty: Type

The correctness and malleability type information for the AST node

+
ext: ExtData

Additional information helpful for extra analysis.

+

Implementations

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn requires_sig(&self) -> bool

Whether all spend paths of miniscript require a signature

+

pub fn is_non_malleable(&self) -> bool

Whether the miniscript is malleable

+

pub fn within_resource_limits(&self) -> bool

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

+

pub fn has_mixed_timelocks(&self) -> bool

Whether the miniscript contains a combination of timelocks

+

pub fn has_repeated_keys(&self) -> bool

Whether the miniscript has repeated Pk or Pkh

+

pub fn sanity_check(&self) -> Result<(), AnalysisError>

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

+

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Iterator-related extensions for Miniscript

+

pub fn iter(&self) -> Iter<'_, Pk, Ctx>

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.

+

pub fn iter_pk(&self) -> PkIter<'_, Pk, Ctx>

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.

+

pub fn iter_pkh(&self) -> PkhIter<'_, Pk, Ctx>

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

+

pub fn iter_pk_pkh(&self) -> PkPkhIter<'_, Pk, Ctx>

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

+

pub fn branches(&self) -> Vec<&Miniscript<Pk, Ctx>, Global>

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

+

pub fn get_nth_child(&self, n: usize) -> Option<&Miniscript<Pk, Ctx>>

Returns child node with given index, if any

+

pub fn get_leaf_pk(&self) -> Vec<Pk, Global>

Returns Vec with cloned version of all public keys from the current miniscript item, +if any. Otherwise returns an empty Vec.

+

NB: The function analyzes only single miniscript item and not any of its descendants in AST. +To obtain a list of all public keys within AST use [fn.iter_pk()] function, for example +miniscript.iter_pubkeys().collect().

+

pub fn get_leaf_pkh(&self) -> Vec<<Pk as MiniscriptKey>::Hash, Global>

Returns Vec with hashes of all public keys from the current miniscript item, if any. +Otherwise returns an empty Vec.

+

For each public key the function computes hash; for each hash of the public key the function +returns its cloned copy.

+

NB: The function analyzes only single miniscript item and not any of its descendants in AST. +To obtain a list of all public key hashes within AST use [fn.iter_pkh()] function, +for example miniscript.iter_pubkey_hashes().collect().

+

pub fn get_leaf_pk_pkh(&self) -> Vec<PkPkh<Pk>, Global>

Returns Vec of [PkPkh] entries, representing either public keys or public key +hashes, depending on the data from the current miniscript item. If there is no public +keys or hashes, the function returns an empty Vec.

+

NB: The function analyzes only single miniscript item and not any of its descendants in AST. +To obtain a list of all public keys or hashes within AST use [fn.iter_pk_pkh()] +function, for example miniscript.iter_pubkeys_and_hashes().collect().

+

pub fn get_nth_pk(&self, n: usize) -> Option<Pk>

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.

+

pub fn get_nth_pkh(&self, n: usize) -> Option<<Pk as MiniscriptKey>::Hash>

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

+

For each public key the function computes hash; for each hash of the public key the function +returns it cloned copy.

+

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

+

pub fn get_nth_pk_pkh(&self, n: usize) -> Option<PkPkh<Pk>>

Returns Option::Some with hash of n'th public key or hash 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.

+

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn from_ast(t: Terminal<Pk, Ctx>) -> Result<Miniscript<Pk, Ctx>, Error>

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.

+

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn into_inner(self) -> Terminal<Pk, Ctx>

Extracts the AstElem representing the root of the miniscript

+

pub fn as_inner(&self) -> &Terminal<Pk, Ctx>

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

+

impl<Ctx> Miniscript<PublicKey, Ctx> where
    Ctx: ScriptContext

pub fn parse_insane(
    script: &Script
) -> Result<Miniscript<PublicKey, Ctx>, Error>

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.

+

pub fn parse(script: &Script) -> Result<Miniscript<PublicKey, Ctx>, Error>

Attempt to parse a Script into Miniscript representation. +This function will fail parsing for scripts that do not clear +the [fn.analyzable.sanity_check] checks. Use [fn.parse_insane] to +parse such scripts.

+

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn encode<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> Script where
    Pk: ToPublicKey<ToPkCtx>,
    ToPkCtx: Copy

Encode as a Bitcoin script

+

pub fn script_size<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> usize where
    Pk: ToPublicKey<ToPkCtx>,
    ToPkCtx: Copy

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.

+

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn max_satisfaction_witness_elements(&self) -> Option<usize>

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 return None on malformed Miniscript objects which do +not correspond to semantically sane Scripts. (Such scripts should be +rejected at parse time. Any exceptions are bugs.)

+

pub fn max_satisfaction_size(&self) -> Option<usize>

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.

+

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn translate_pk<FPk, FPkh, Q, FuncError>(
    &self,
    translatefpk: &mut FPk,
    translatefpkh: &mut FPkh
) -> Result<Miniscript<Q, Ctx>, FuncError> where
    FPk: FnMut(&Pk) -> Result<Q, FuncError>,
    FPkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, FuncError>,
    Q: MiniscriptKey

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

+

pub fn from_str_insane(s: &str) -> Result<Miniscript<Pk, Ctx>, Error> where
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

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.

+

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn satisfy<ToPkCtx, S>(
    &self,
    satisfier: S,
    to_pk_ctx: ToPkCtx
) -> Result<Vec<Vec<u8, Global>, Global>, Error> where
    Pk: ToPublicKey<ToPkCtx>,
    S: Satisfier<ToPkCtx, Pk>,
    ToPkCtx: Copy

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

+

pub fn satisfy_malleable<ToPkCtx, S>(
    &self,
    satisfier: S,
    to_pk_ctx: ToPkCtx
) -> Result<Vec<Vec<u8, Global>, Global>, Error> where
    Pk: ToPublicKey<ToPkCtx>,
    S: Satisfier<ToPkCtx, Pk>,
    ToPkCtx: Copy

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

+

impl<Pk, Ctx> Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn lift_check(&self) -> Result<(), LiftError>

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

+
    +
  1. Timelock combination
  2. +
  3. Contains a spend that exceeds resource limits
  4. +
+

Trait Implementations

impl<Pk, Ctx> Clone for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext + Clone,
    Pk: MiniscriptKey + Clone

impl<Pk, Ctx> Debug for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Display for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Eq for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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

+

impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx>[src]

impl<Pk, Ctx> FromStr for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

type Err = Error

The associated error which can be returned from parsing.

+

pub fn from_str(s: &str) -> Result<Miniscript<Pk, Ctx>, Error>

Parse a Miniscript from string and perform sanity checks +See [fn.from_str_insane] to parse scripts from string that +do not clear the [fn.analyzable.sanity_check] checks.

+

impl<Pk, Ctx> FromTree for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey,
    <Pk as FromStr>::Err: ToString,
    <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

pub fn from_tree(top: &Tree<'_>) -> Result<Miniscript<Pk, Ctx>, Error>

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

+

impl<Pk, Ctx> Hash for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext + Hash,
    Pk: MiniscriptKey + Hash

impl<Pk, Ctx> Liftable<Pk> for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Ord for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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

+

impl<Pk, Ctx> PartialEq<Miniscript<Pk, Ctx>> for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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

+

impl<Pk, Ctx> PartialOrd<Miniscript<Pk, Ctx>> for Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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

+

Auto Trait Implementations

impl<Pk, Ctx> RefUnwindSafe for Miniscript<Pk, Ctx> where
    Ctx: RefUnwindSafe,
    Pk: RefUnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe
[src]

impl<Pk, Ctx> Send for Miniscript<Pk, Ctx> where
    Ctx: Send + Sync,
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync
[src]

impl<Pk, Ctx> Sync for Miniscript<Pk, Ctx> where
    Ctx: Send + Sync,
    Pk: Send + Sync,
    <Pk as MiniscriptKey>::Hash: Send + Sync
[src]

impl<Pk, Ctx> Unpin for Miniscript<Pk, Ctx> where
    Ctx: Unpin,
    Pk: Unpin,
    <Pk as MiniscriptKey>::Hash: Unpin
[src]

impl<Pk, Ctx> UnwindSafe for Miniscript<Pk, Ctx> where
    Ctx: RefUnwindSafe + UnwindSafe,
    Pk: RefUnwindSafe + UnwindSafe,
    <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/index.html new file mode 100644 index 0000000000..a701f40721 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/index.html @@ -0,0 +1,21 @@ +bdk::descriptor::template - Rust + +

[][src]Module bdk::descriptor::template

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

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

+
BIP44Public

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

+
BIP49

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

+
BIP49Public

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

+
BIP84

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

+
BIP84Public

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

+
P2PKH

P2PKH template. Expands to a descriptor pkh(key)

+
P2WPKH

P2WPKH template. Expands to a descriptor wpkh(key)

+
P2WPKH_P2SH

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

+

Traits

+
DescriptorTemplate

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

+

Type Definitions

+
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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/sidebar-items.js new file mode 100644 index 0000000000..1e10991c5b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["BIP44","BIP44 template. Expands to `pkh(key/44'/0'/0'/{0,1}/*)`"],["BIP44Public","BIP44 public template. Expands to `pkh(key/{0,1}/*)`"],["BIP49","BIP49 template. Expands to `sh(wpkh(key/49'/0'/0'/{0,1}/*))`"],["BIP49Public","BIP49 public template. Expands to `sh(wpkh(key/{0,1}/*))`"],["BIP84","BIP84 template. Expands to `wpkh(key/84'/0'/0'/{0,1}/*)`"],["BIP84Public","BIP84 public template. Expands to `wpkh(key/{0,1}/*)`"],["P2PKH","P2PKH template. Expands to a descriptor `pkh(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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP44.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP44.html new file mode 100644 index 0000000000..e1665c341e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP44.html @@ -0,0 +1,47 @@ +bdk::descriptor::template::BIP44 - Rust + +

[][src]Struct bdk::descriptor::template::BIP44

pub struct BIP44<K: DerivableKey<Legacy>>(pub K, pub KeychainKind);

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

+

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

+

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

+

Example

+
+use bdk::template::BIP44;
+
+let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+let wallet: OfflineWallet<_> = Wallet::new_offline(
+    BIP44(key.clone(), KeychainKind::External),
+    Some(BIP44(key, KeychainKind::Internal)),
+    Network::Testnet,
+    MemoryDatabase::default()
+)?;
+
+assert_eq!(wallet.get_new_address()?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
+assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)");
+

Trait Implementations

impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44<K>[src]

Auto Trait Implementations

impl<K> RefUnwindSafe for BIP44<K> where
    K: RefUnwindSafe
[src]

impl<K> Send for BIP44<K> where
    K: Send
[src]

impl<K> Sync for BIP44<K> where
    K: Sync
[src]

impl<K> Unpin for BIP44<K> where
    K: Unpin
[src]

impl<K> UnwindSafe for BIP44<K> where
    K: UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToWalletDescriptor for T where
    T: DescriptorTemplate
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP44Public.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP44Public.html new file mode 100644 index 0000000000..6eb406b0a5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP44Public.html @@ -0,0 +1,50 @@ +bdk::descriptor::template::BIP44Public - Rust + +

[][src]Struct bdk::descriptor::template::BIP44Public

pub struct BIP44Public<K: DerivableKey<Legacy>>(pub K, pub Fingerprint, pub KeychainKind);

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

+

This assumes that the key used has already been derived with m/44'/0'/0'.

+

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::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
+let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
+let wallet: OfflineWallet<_> = Wallet::new_offline(
+    BIP44Public(key.clone(), fingerprint, KeychainKind::External),
+    Some(BIP44Public(key, fingerprint, KeychainKind::Internal)),
+    Network::Testnet,
+    MemoryDatabase::default()
+)?;
+
+assert_eq!(wallet.get_new_address()?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
+assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)");
+

Trait Implementations

impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44Public<K>[src]

Auto Trait Implementations

impl<K> RefUnwindSafe for BIP44Public<K> where
    K: RefUnwindSafe
[src]

impl<K> Send for BIP44Public<K> where
    K: Send
[src]

impl<K> Sync for BIP44Public<K> where
    K: Sync
[src]

impl<K> Unpin for BIP44Public<K> where
    K: Unpin
[src]

impl<K> UnwindSafe for BIP44Public<K> where
    K: UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToWalletDescriptor for T where
    T: DescriptorTemplate
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP49.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP49.html new file mode 100644 index 0000000000..2efbae9d75 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP49.html @@ -0,0 +1,47 @@ +bdk::descriptor::template::BIP49 - Rust + +

[][src]Struct bdk::descriptor::template::BIP49

pub struct BIP49<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);

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

+

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

+

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

+

Example

+
+use bdk::template::BIP49;
+
+let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+let wallet: OfflineWallet<_> = Wallet::new_offline(
+    BIP49(key.clone(), KeychainKind::External),
+    Some(BIP49(key, KeychainKind::Internal)),
+    Network::Testnet,
+    MemoryDatabase::default()
+)?;
+
+assert_eq!(wallet.get_new_address()?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
+assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))");
+

Trait Implementations

impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49<K>[src]

Auto Trait Implementations

impl<K> RefUnwindSafe for BIP49<K> where
    K: RefUnwindSafe
[src]

impl<K> Send for BIP49<K> where
    K: Send
[src]

impl<K> Sync for BIP49<K> where
    K: Sync
[src]

impl<K> Unpin for BIP49<K> where
    K: Unpin
[src]

impl<K> UnwindSafe for BIP49<K> where
    K: UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToWalletDescriptor for T where
    T: DescriptorTemplate
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP49Public.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP49Public.html new file mode 100644 index 0000000000..7fff60cfd4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP49Public.html @@ -0,0 +1,50 @@ +bdk::descriptor::template::BIP49Public - Rust + +

[][src]Struct bdk::descriptor::template::BIP49Public

pub struct BIP49Public<K: DerivableKey<Segwitv0>>(pub K, pub Fingerprint, pub KeychainKind);

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

+

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::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
+let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
+let wallet: OfflineWallet<_> = Wallet::new_offline(
+    BIP49Public(key.clone(), fingerprint, KeychainKind::External),
+    Some(BIP49Public(key, fingerprint, KeychainKind::Internal)),
+    Network::Testnet,
+    MemoryDatabase::default()
+)?;
+
+assert_eq!(wallet.get_new_address()?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
+assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))");
+

Trait Implementations

impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49Public<K>[src]

Auto Trait Implementations

impl<K> RefUnwindSafe for BIP49Public<K> where
    K: RefUnwindSafe
[src]

impl<K> Send for BIP49Public<K> where
    K: Send
[src]

impl<K> Sync for BIP49Public<K> where
    K: Sync
[src]

impl<K> Unpin for BIP49Public<K> where
    K: Unpin
[src]

impl<K> UnwindSafe for BIP49Public<K> where
    K: UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToWalletDescriptor for T where
    T: DescriptorTemplate
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP84.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP84.html new file mode 100644 index 0000000000..934b4dc733 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP84.html @@ -0,0 +1,47 @@ +bdk::descriptor::template::BIP84 - Rust + +

[][src]Struct bdk::descriptor::template::BIP84

pub struct BIP84<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);

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

+

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

+

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

+

Example

+
+use bdk::template::BIP84;
+
+let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+let wallet: OfflineWallet<_> = Wallet::new_offline(
+    BIP84(key.clone(), KeychainKind::External),
+    Some(BIP84(key, KeychainKind::Internal)),
+    Network::Testnet,
+    MemoryDatabase::default()
+)?;
+
+assert_eq!(wallet.get_new_address()?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
+assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)");
+

Trait Implementations

impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP84<K>[src]

Auto Trait Implementations

impl<K> RefUnwindSafe for BIP84<K> where
    K: RefUnwindSafe
[src]

impl<K> Send for BIP84<K> where
    K: Send
[src]

impl<K> Sync for BIP84<K> where
    K: Sync
[src]

impl<K> Unpin for BIP84<K> where
    K: Unpin
[src]

impl<K> UnwindSafe for BIP84<K> where
    K: UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToWalletDescriptor for T where
    T: DescriptorTemplate
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP84Public.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP84Public.html new file mode 100644 index 0000000000..632706f146 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP84Public.html @@ -0,0 +1,50 @@ +bdk::descriptor::template::BIP84Public - Rust + +

[][src]Struct bdk::descriptor::template::BIP84Public

pub struct BIP84Public<K: DerivableKey<Segwitv0>>(pub K, pub Fingerprint, pub KeychainKind);

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

+

This assumes that the key used has already been derived with m/84'/0'/0'.

+

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::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
+let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
+let wallet: OfflineWallet<_> = Wallet::new_offline(
+    BIP84Public(key.clone(), fingerprint, KeychainKind::External),
+    Some(BIP84Public(key, fingerprint, KeychainKind::Internal)),
+    Network::Testnet,
+    MemoryDatabase::default()
+)?;
+
+assert_eq!(wallet.get_new_address()?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
+assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)");
+

Trait Implementations

impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP84Public<K>[src]

Auto Trait Implementations

impl<K> RefUnwindSafe for BIP84Public<K> where
    K: RefUnwindSafe
[src]

impl<K> Send for BIP84Public<K> where
    K: Send
[src]

impl<K> Sync for BIP84Public<K> where
    K: Sync
[src]

impl<K> Unpin for BIP84Public<K> where
    K: Unpin
[src]

impl<K> UnwindSafe for BIP84Public<K> where
    K: UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToWalletDescriptor for T where
    T: DescriptorTemplate
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2PKH.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2PKH.html new file mode 100644 index 0000000000..0678bdd7e4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2PKH.html @@ -0,0 +1,48 @@ +bdk::descriptor::template::P2PKH - Rust + +

[][src]Struct bdk::descriptor::template::P2PKH

pub struct P2PKH<K: ToDescriptorKey<Legacy>>(pub K);

P2PKH template. Expands to a descriptor pkh(key)

+

Example

+
+use bdk::template::P2PKH;
+
+let key =
+    bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+let wallet: OfflineWallet<_> = Wallet::new_offline(
+    P2PKH(key),
+    None,
+    Network::Testnet,
+    MemoryDatabase::default(),
+)?;
+
+assert_eq!(
+    wallet.get_new_address()?.to_string(),
+    "mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"
+);
+

Trait Implementations

impl<K: ToDescriptorKey<Legacy>> DescriptorTemplate for P2PKH<K>[src]

Auto Trait Implementations

impl<K> RefUnwindSafe for P2PKH<K> where
    K: RefUnwindSafe
[src]

impl<K> Send for P2PKH<K> where
    K: Send
[src]

impl<K> Sync for P2PKH<K> where
    K: Sync
[src]

impl<K> Unpin for P2PKH<K> where
    K: Unpin
[src]

impl<K> UnwindSafe for P2PKH<K> where
    K: UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToWalletDescriptor for T where
    T: DescriptorTemplate
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2WPKH.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2WPKH.html new file mode 100644 index 0000000000..4766fc25f8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2WPKH.html @@ -0,0 +1,48 @@ +bdk::descriptor::template::P2WPKH - Rust + +

[][src]Struct bdk::descriptor::template::P2WPKH

pub struct P2WPKH<K: ToDescriptorKey<Segwitv0>>(pub K);

P2WPKH template. Expands to a descriptor wpkh(key)

+

Example

+
+use bdk::template::P2WPKH;
+
+let key =
+    bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+let wallet: OfflineWallet<_> = Wallet::new_offline(
+    P2WPKH(key),
+    None,
+    Network::Testnet,
+    MemoryDatabase::default(),
+)?;
+
+assert_eq!(
+    wallet.get_new_address()?.to_string(),
+    "tb1q4525hmgw265tl3drrl8jjta7ayffu6jf68ltjd"
+);
+

Trait Implementations

impl<K: ToDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH<K>[src]

Auto Trait Implementations

impl<K> RefUnwindSafe for P2WPKH<K> where
    K: RefUnwindSafe
[src]

impl<K> Send for P2WPKH<K> where
    K: Send
[src]

impl<K> Sync for P2WPKH<K> where
    K: Sync
[src]

impl<K> Unpin for P2WPKH<K> where
    K: Unpin
[src]

impl<K> UnwindSafe for P2WPKH<K> where
    K: UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToWalletDescriptor for T where
    T: DescriptorTemplate
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2WPKH_P2SH.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2WPKH_P2SH.html new file mode 100644 index 0000000000..74f62aeac6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2WPKH_P2SH.html @@ -0,0 +1,48 @@ +bdk::descriptor::template::P2WPKH_P2SH - Rust + +

[][src]Struct bdk::descriptor::template::P2WPKH_P2SH

pub struct P2WPKH_P2SH<K: ToDescriptorKey<Segwitv0>>(pub K);

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

+

Example

+
+use bdk::template::P2WPKH_P2SH;
+
+let key =
+    bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+let wallet: OfflineWallet<_> = Wallet::new_offline(
+    P2WPKH_P2SH(key),
+    None,
+    Network::Testnet,
+    MemoryDatabase::default(),
+)?;
+
+assert_eq!(
+    wallet.get_new_address()?.to_string(),
+    "2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"
+);
+

Trait Implementations

impl<K: ToDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH_P2SH<K>[src]

Auto Trait Implementations

impl<K> RefUnwindSafe for P2WPKH_P2SH<K> where
    K: RefUnwindSafe
[src]

impl<K> Send for P2WPKH_P2SH<K> where
    K: Send
[src]

impl<K> Sync for P2WPKH_P2SH<K> where
    K: Sync
[src]

impl<K> Unpin for P2WPKH_P2SH<K> where
    K: Unpin
[src]

impl<K> UnwindSafe for P2WPKH_P2SH<K> where
    K: UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToWalletDescriptor for T where
    T: DescriptorTemplate
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/trait.DescriptorTemplate.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/trait.DescriptorTemplate.html new file mode 100644 index 0000000000..8f3a721057 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/trait.DescriptorTemplate.html @@ -0,0 +1,23 @@ +bdk::descriptor::template::DescriptorTemplate - Rust + +

[][src]Trait bdk::descriptor::template::DescriptorTemplate

pub trait DescriptorTemplate {
+    pub fn build(self) -> Result<DescriptorTemplateOut, KeyError>;
+}

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

+

Since ToWalletDescriptor is implemented for any DescriptorTemplate, they can also be +passed directly to the Wallet constructor.

+

Example

+
+use bdk::keys::{KeyError, ToDescriptorKey};
+use bdk::miniscript::Legacy;
+use bdk::template::{DescriptorTemplate, DescriptorTemplateOut};
+
+struct MyP2PKH<K: ToDescriptorKey<Legacy>>(K);
+
+impl<K: ToDescriptorKey<Legacy>> DescriptorTemplate for MyP2PKH<K> {
+    fn build(self) -> Result<DescriptorTemplateOut, KeyError> {
+        Ok(bdk::descriptor!(pkh(self.0))?)
+    }
+}
+

Required methods

pub fn build(self) -> Result<DescriptorTemplateOut, KeyError>[src]

Build the complete descriptor

+
Loading content...

Implementors

impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44<K>[src]

impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44Public<K>[src]

impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49<K>[src]

impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49Public<K>[src]

impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP84<K>[src]

impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP84Public<K>[src]

impl<K: ToDescriptorKey<Legacy>> DescriptorTemplate for P2PKH<K>[src]

impl<K: ToDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH<K>[src]

impl<K: ToDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH_P2SH<K>[src]

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/type.DescriptorTemplateOut.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/type.DescriptorTemplateOut.html new file mode 100644 index 0000000000..2dc811d4f4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/type.DescriptorTemplateOut.html @@ -0,0 +1,6 @@ +bdk::descriptor::template::DescriptorTemplateOut - Rust + +

[][src]Type Definition bdk::descriptor::template::DescriptorTemplateOut

type DescriptorTemplateOut = (ExtendedDescriptor, KeyMap, ValidNetworks);

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

+

Trait Implementations

impl ToWalletDescriptor for DescriptorTemplateOut[src]

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ExtractPolicy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ExtractPolicy.html new file mode 100644 index 0000000000..1012bebadf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ExtractPolicy.html @@ -0,0 +1,8 @@ +bdk::descriptor::ExtractPolicy - Rust + +

[][src]Trait bdk::descriptor::ExtractPolicy

pub trait ExtractPolicy {
+    pub fn extract_policy(
        &self,
        signers: &SignersContainer,
        secp: &Secp256k1<All>
    ) -> Result<Option<Policy>, Error>; +}

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

+

Required methods

pub fn extract_policy(
    &self,
    signers: &SignersContainer,
    secp: &Secp256k1<All>
) -> Result<Option<Policy>, Error>
[src]

Extract the spending policy

+
Loading content...

Implementors

impl ExtractPolicy for Descriptor<DescriptorPublicKey>[src]

impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx>[src]

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.MiniscriptKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.MiniscriptKey.html new file mode 100644 index 0000000000..45e2f12a24 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.MiniscriptKey.html @@ -0,0 +1,16 @@ +bdk::descriptor::MiniscriptKey - Rust + +

[]Trait bdk::descriptor::MiniscriptKey

pub trait MiniscriptKey: Clone + Eq + Ord + Debug + Display + Hash + FromStr {
+    type Hash: Clone + Eq + Ord + Debug + Display + Hash + FromStr;
+    pub fn to_pubkeyhash(&self) -> Self::Hash;
+
+    pub fn is_uncompressed(&self) -> bool { ... }
+}

Public key trait which can be converted to Hash type

+

Associated Types

type Hash: Clone + Eq + Ord + Debug + Display + Hash + FromStr

The associated Hash type with the publicKey

+
Loading content...

Required methods

pub fn to_pubkeyhash(&self) -> Self::Hash

Converts an object to PublicHash

+
Loading content...

Provided methods

pub fn is_uncompressed(&self) -> bool

Check if the publicKey is uncompressed. The default +implementation returns false

+
Loading content...

Implementations on Foreign Types

impl MiniscriptKey for String

type Hash = String

impl MiniscriptKey for DummyKey

type Hash = DummyKeyHash

impl MiniscriptKey for PublicKey

pub fn is_uncompressed(&self) -> bool

is_uncompressed returns true only for +bitcoin::Publickey type if the underlying key is uncompressed.

+

type Hash = Hash

Loading content...

Implementors

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ScriptContext.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ScriptContext.html new file mode 100644 index 0000000000..c2bd80c5da --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ScriptContext.html @@ -0,0 +1,78 @@ +bdk::descriptor::ScriptContext - Rust + +

[]Trait bdk::descriptor::ScriptContext

pub trait ScriptContext: Sealed + Clone + PartialEq<Self> + Eq + Ord + PartialOrd<Self> + Debug {
+    pub fn check_terminal_non_malleable<Pk, Ctx>(
        _frag: &Terminal<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
; +
pub fn max_satisfaction_size<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Option<usize>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
; + + pub fn check_witness<Pk, Ctx>(
        _witness: &[Vec<u8, Global>]
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn check_global_consensus_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn check_global_policy_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn check_local_consensus_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn check_local_policy_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn check_global_validity<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn check_local_validity<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn top_level_type_check<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), Error>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn other_top_level_checks<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), Error>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn top_level_checks<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), Error>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +}

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 methods

pub fn check_terminal_non_malleable<Pk, Ctx>(
    _frag: &Terminal<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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.

+

pub fn max_satisfaction_size<Pk, Ctx>(ms: &Miniscript<Pk, Ctx>) -> Option<usize> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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

+
Loading content...

Provided methods

pub fn check_witness<Pk, Ctx>(
    _witness: &[Vec<u8, Global>]
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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.

+

pub fn check_global_consensus_validity<Pk, Ctx>(
    _ms: &Miniscript<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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.

+

pub fn check_global_policy_validity<Pk, Ctx>(
    _ms: &Miniscript<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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.

+

pub fn check_local_consensus_validity<Pk, Ctx>(
    _ms: &Miniscript<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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.

+

pub fn check_local_policy_validity<Pk, Ctx>(
    _ms: &Miniscript<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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

+

pub fn check_global_validity<Pk, Ctx>(
    ms: &Miniscript<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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

+

pub fn check_local_validity<Pk, Ctx>(
    ms: &Miniscript<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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

+

pub fn top_level_type_check<Pk, Ctx>(
    ms: &Miniscript<Pk, Ctx>
) -> Result<(), Error> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Check whether the top-level is type B

+

pub fn other_top_level_checks<Pk, Ctx>(
    _ms: &Miniscript<Pk, Ctx>
) -> Result<(), Error> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Other top level checks that are context specific

+

pub fn top_level_checks<Pk, Ctx>(ms: &Miniscript<Pk, Ctx>) -> Result<(), Error> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Check top level consensus rules.

+
Loading content...

Implementations on Foreign Types

impl ScriptContext for Bare

Loading content...

Implementors

impl ScriptContext for Legacy

impl ScriptContext for Segwitv0

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ToPublicKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ToPublicKey.html new file mode 100644 index 0000000000..1c2cfde4f4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ToPublicKey.html @@ -0,0 +1,25 @@ +bdk::descriptor::ToPublicKey - Rust + +

[]Trait bdk::descriptor::ToPublicKey

pub trait ToPublicKey<ToPkCtx>: MiniscriptKey where
    ToPkCtx: Copy
{ + pub fn to_public_key(&self, to_pk_ctx: ToPkCtx) -> PublicKey; +
pub fn hash_to_hash160(hash: &Self::Hash, to_pk_ctx: ToPkCtx) -> Hash; + + pub fn serialized_len(&self, to_pk_ctx: ToPkCtx) -> usize { ... } +}

Trait describing public key types which can be converted to bitcoin pubkeys +The trait relies on Copy trait because in all practical usecases ToPkCtx +should contain references to objects which should be cheap to Copy.

+

Required methods

pub fn to_public_key(&self, to_pk_ctx: ToPkCtx) -> PublicKey

Converts an object to a public key +C represents additional context information that maybe +required for deriving a bitcoin::PublicKey from MiniscriptKey +You may require secp context for crypto operations +or additional information for substituting the wildcard in +extended pubkeys

+

pub fn hash_to_hash160(hash: &Self::Hash, to_pk_ctx: ToPkCtx) -> Hash

Converts a hashed version of the public key to a hash160 hash.

+

This method must be consistent with to_public_key, in the sense +that calling MiniscriptKey::to_pubkeyhash followed by this function +should give the same result as calling to_public_key and hashing +the result directly.

+
Loading content...

Provided methods

pub fn serialized_len(&self, to_pk_ctx: ToPkCtx) -> usize

Computes the size of a public key when serialized in a script, +including the length bytes

+
Loading content...

Implementations on Foreign Types

impl ToPublicKey<NullCtx> for DummyKey

impl ToPublicKey<NullCtx> for PublicKey

Loading content...

Implementors

impl<'secp, C> ToPublicKey<DescriptorPublicKeyCtx<'secp, C>> for DescriptorPublicKey where
    C: Verification, 

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ToWalletDescriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ToWalletDescriptor.html new file mode 100644 index 0000000000..e748fbf297 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ToWalletDescriptor.html @@ -0,0 +1,10 @@ +bdk::descriptor::ToWalletDescriptor - Rust + +

[][src]Trait bdk::descriptor::ToWalletDescriptor

pub trait ToWalletDescriptor {
+    pub fn to_wallet_descriptor(
        self,
        network: Network
    ) -> Result<(ExtendedDescriptor, KeyMap), KeyError>; +}

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

+

Required methods

pub fn to_wallet_descriptor(
    self,
    network: Network
) -> Result<(ExtendedDescriptor, KeyMap), KeyError>
[src]

Convert to wallet descriptor

+
Loading content...

Implementations on Foreign Types

impl<'_> ToWalletDescriptor for &'_ str[src]

impl<'_> ToWalletDescriptor for &'_ String[src]

impl ToWalletDescriptor for (ExtendedDescriptor, KeyMap)[src]

Loading content...

Implementors

impl ToWalletDescriptor for DescriptorTemplateOut[src]

impl ToWalletDescriptor for ExtendedDescriptor[src]

impl<T: DescriptorTemplate> ToWalletDescriptor for T[src]

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

+
Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.ExtendedDescriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.ExtendedDescriptor.html new file mode 100644 index 0000000000..846b405272 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.ExtendedDescriptor.html @@ -0,0 +1,6 @@ +bdk::descriptor::ExtendedDescriptor - Rust + +

[][src]Type Definition bdk::descriptor::ExtendedDescriptor

type ExtendedDescriptor = Descriptor<DescriptorPublicKey>;

Alias for a Descriptor that can contain extended keys using DescriptorPublicKey

+

Trait Implementations

impl ToWalletDescriptor for ExtendedDescriptor[src]

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.HDKeyPaths.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.HDKeyPaths.html new file mode 100644 index 0000000000..25850ae841 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.HDKeyPaths.html @@ -0,0 +1,6 @@ +bdk::descriptor::HDKeyPaths - Rust + +

[][src]Type Definition bdk::descriptor::HDKeyPaths

type HDKeyPaths = BTreeMap<PublicKey, KeySource>;

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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.KeyMap.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.KeyMap.html new file mode 100644 index 0000000000..bfe0522027 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.KeyMap.html @@ -0,0 +1,9 @@ +bdk::descriptor::KeyMap - Rust + +

[]Type Definition bdk::descriptor::KeyMap

type KeyMap = HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>;

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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.Error.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.Error.html new file mode 100644 index 0000000000..a6f2f695e6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.Error.html @@ -0,0 +1,148 @@ +bdk::Error - Rust + +

[][src]Enum bdk::Error

pub enum Error {
+    InvalidU32Bytes(Vec<u8>),
+    Generic(String),
+    ScriptDoesntHaveAddressForm,
+    SingleRecipientMultipleOutputs,
+    SingleRecipientNoInputs,
+    NoRecipients,
+    NoUtxosSelected,
+    OutputBelowDustLimit(usize),
+    InsufficientFunds,
+    BnBTotalTriesExceeded,
+    BnBNoExactMatch,
+    UnknownUTXO,
+    TransactionNotFound,
+    TransactionConfirmed,
+    IrreplaceableTransaction,
+    FeeRateTooLow {
+        required: FeeRate,
+    },
+    FeeTooLow {
+        required: u64,
+    },
+    MissingKeyOrigin(String),
+    Key(KeyError),
+    ChecksumMismatch,
+    SpendingPolicyRequired(KeychainKind),
+    InvalidPolicyPathError(PolicyError),
+    Signer(SignerError),
+    OfflineClient,
+    InvalidProgressValue(f32),
+    ProgressUpdateError,
+    InvalidOutpoint(OutPoint),
+    Descriptor(Error),
+    AddressValidator(AddressValidatorError),
+    Encode(Error),
+    Miniscript(Error),
+    BIP32(Error),
+    Secp256k1(Error),
+    JSON(Error),
+    Hex(Error),
+    PSBT(Error),
+    Electrum(Error),
+    Esplora(EsploraError),
+    CompactFilters(CompactFiltersError),
+    Sled(Error),
+}

Errors that can be thrown by the Wallet

+

+ Variants

+
InvalidU32Bytes(Vec<u8>)

Wrong number of bytes found when trying to convert to u32

+
Generic(String)

Generic error

+
ScriptDoesntHaveAddressForm

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

+
SingleRecipientMultipleOutputs

Found multiple outputs when single_recipient option has been specified

+
SingleRecipientNoInputs

single_recipient option is selected but neither drain_wallet nor manually_selected_only are

+
NoRecipients

Cannot build a tx without recipients

+
NoUtxosSelected

manually_selected_only option is selected but no utxo has been passed

+
OutputBelowDustLimit(usize)

Output created is under the dust limit, 546 satoshis

+
InsufficientFunds

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

+
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

+
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

+
UnknownUTXO

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

+
TransactionNotFound

Thrown when a tx is not found in the internal database

+
TransactionConfirmed

Happens when trying to bump a transaction that is already confirmed

+
IrreplaceableTransaction

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

+
FeeRateTooLow

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

+

Fields of FeeRateTooLow

required: FeeRate

Required fee rate (satoshi/vbyte)

+
FeeTooLow

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

+

Fields of FeeTooLow

required: u64

Required fee absolute value (satoshi)

+
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

+

Error while working with keys

+
ChecksumMismatch

Descriptor checksum mismatch

+
SpendingPolicyRequired(KeychainKind)

Spending policy is not compatible with this KeychainKind

+
InvalidPolicyPathError(PolicyError)

Error while extracting and manipulating policies

+
Signer(SignerError)

Signing error

+
OfflineClient

Thrown when trying to call a method that requires a network connection, Wallet::sync and Wallet::broadcast +This error is thrown when creating the Client for the first time, while recovery attempts are tried +during the sync

+
InvalidProgressValue(f32)

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

+
ProgressUpdateError

Progress update error (maybe the channel has been closed)

+
InvalidOutpoint(OutPoint)

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

+
Descriptor(Error)

Error related to the parsing and usage of descriptors

+
AddressValidator(AddressValidatorError)

Error that can be returned to fail the validation of an address

+
Encode(Error)

Encoding error

+
Miniscript(Error)

Miniscript error

+
BIP32(Error)

BIP32 error

+
Secp256k1(Error)

An ECDSA error

+
JSON(Error)

Error serializing or deserializing JSON data

+
Hex(Error)

Hex decoding error

+
PSBT(Error)

Partially signed bitcoin transaction error

+
Electrum(Error)

Electrum client error

+
Esplora(EsploraError)

Esplora client error

+
CompactFilters(CompactFiltersError)

Compact filters client error)

+
Sled(Error)

Sled database error

+

Trait Implementations

impl Debug for Error[src]

impl Display for Error[src]

impl Error for Error[src]

impl From<AddressValidatorError> for Error[src]

impl From<CompactFiltersError> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for CompactFiltersError[src]

This is supported on crate feature compact_filters only.

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<Error> for Error[src]

impl From<EsploraError> for Error[src]

impl From<KeyError> for Error[src]

impl From<PolicyError> for Error[src]

impl From<SignerError> for Error[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.KeychainKind.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.KeychainKind.html new file mode 100644 index 0000000000..491efbac18 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.KeychainKind.html @@ -0,0 +1,59 @@ +bdk::KeychainKind - Rust + +

[][src]Enum bdk::KeychainKind

pub enum KeychainKind {
+    External,
+    Internal,
+}

Types of keychains

+

+ Variants

+
External

External

+
Internal

Internal, usually used for change outputs

+

Implementations

impl KeychainKind[src]

pub fn as_byte(&self) -> u8[src]

Return KeychainKind as a byte

+

Trait Implementations

impl AsRef<[u8]> for KeychainKind[src]

impl Clone for KeychainKind[src]

impl Copy for KeychainKind[src]

impl Debug for KeychainKind[src]

impl<'de> Deserialize<'de> for KeychainKind[src]

impl Eq for KeychainKind[src]

impl Hash for KeychainKind[src]

impl PartialEq<KeychainKind> for KeychainKind[src]

impl Serialize for KeychainKind[src]

impl StructuralEq for KeychainKind[src]

impl StructuralPartialEq for KeychainKind[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Base32Len for T where
    T: AsRef<[u8]>, 

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<'f, T> CheckBase32<Vec<u5, Global>> for T where
    T: AsRef<[u8]>, 

type Err = Error

Error type if conversion fails

+

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToBase32 for T where
    T: AsRef<[u8]>, 

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.ScriptType.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.ScriptType.html new file mode 100644 index 0000000000..fac96f212c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.ScriptType.html @@ -0,0 +1,58 @@ +bdk::ScriptType - Rust + +

[][src]Enum bdk::ScriptType

pub enum ScriptType {
+    External,
+    Internal,
+}

Types of script

+

+ Variants

+
External

External

+
Internal

Internal, usually used for change outputs

+

Implementations

impl ScriptType[src]

pub fn as_byte(&self) -> u8[src]

Trait Implementations

impl AsRef<[u8]> for ScriptType[src]

impl Clone for ScriptType[src]

impl Copy for ScriptType[src]

impl Debug for ScriptType[src]

impl<'de> Deserialize<'de> for ScriptType[src]

impl Eq for ScriptType[src]

impl Hash for ScriptType[src]

impl PartialEq<ScriptType> for ScriptType[src]

impl Serialize for ScriptType[src]

impl StructuralEq for ScriptType[src]

impl StructuralPartialEq for ScriptType[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Base32Len for T where
    T: AsRef<[u8]>, 

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<'f, T> CheckBase32<Vec<u5, Global>> for T where
    T: AsRef<[u8]>, 

type Err = Error

Error type if conversion fails

+

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToBase32 for T where
    T: AsRef<[u8]>, 

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/error/enum.Error.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/error/enum.Error.html new file mode 100644 index 0000000000..113a951037 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/error/enum.Error.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../bdk/enum.Error.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/index.html new file mode 100644 index 0000000000..8323289c69 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/index.html @@ -0,0 +1,167 @@ +bdk - Rust + +

[][src]Crate bdk

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

+

About

+

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

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

A Tour of BDK

+

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

+

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

+
bdk = "0.2.0"
+
+

Sync the balance of a descriptor

Example

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

Generate a few addresses

Example

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

Create a transaction

Example

+
ⓘThis example is not tested
+use base64::decode;
+use bdk::{FeeRate, TxBuilder, Wallet};
+use bdk::database::MemoryDatabase;
+use bdk::blockchain::{noop_progress, ElectrumBlockchain};
+
+use bdk::electrum_client::Client;
+
+use bitcoin::consensus::serialize;
+
+fn main() -> Result<(), bdk::Error> {
+    let client = Client::new("ssl://electrum.blockstream.info:60002")?;
+    let wallet = Wallet::new(
+        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
+        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
+        bitcoin::Network::Testnet,
+        MemoryDatabase::default(),
+        ElectrumBlockchain::from(client)
+    )?;
+
+    wallet.sync(noop_progress(), None)?;
+
+    let send_to = wallet.get_new_address()?;
+    let (psbt, details) = wallet.create_tx(
+        TxBuilder::with_recipients(vec![(send_to.script_pubkey(), 50_000)])
+            .enable_rbf()
+            .do_not_spend_change()
+            .fee_rate(FeeRate::from_sat_per_vb(5.0))
+    )?;
+
+    println!("Transaction details: {:#?}", details);
+    println!("Unsigned PSBT: {}", base64::encode(&serialize(&psbt)));
+
+    Ok(())
+}
+

Sign a transaction

Example

+
ⓘThis example is not tested
+use base64::decode;
+use bdk::{Wallet, OfflineWallet};
+use bdk::database::MemoryDatabase;
+
+use bitcoin::consensus::deserialize;
+
+fn main() -> Result<(), bdk::Error> {
+    let wallet: OfflineWallet<_> = Wallet::new_offline(
+        "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
+        Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
+        bitcoin::Network::Testnet,
+        MemoryDatabase::default(),
+    )?;
+
+    let psbt = "...";
+    let psbt = deserialize(&base64::decode(psbt).unwrap())?;
+
+    let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
+
+    Ok(())
+}
+

Feature flags

+

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

+

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

+
    +
  • all-keys: all features for working with bitcoin keys
  • +
  • async-interface: async functions in bdk traits
  • +
  • cli-utils: utilities for creating a command line interface wallet
  • +
  • keys-bip39: BIP-39 mnemonic codes for generating deterministic keys
  • +
+

Internal features

+

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

+
    +
  • compact_filters: compact_filters client protocol for interacting with the bitcoin P2P network
  • +
  • electrum: electrum client protocol for interacting with electrum servers
  • +
  • esplora: esplora client protocol for interacting with blockstream electrs servers
  • +
  • key-value-db: key value database based on sled for caching blockchain data
  • +
+

Re-exports

+
pub extern crate bitcoin;
pub extern crate miniscript;
pub extern crate electrum_client;
pub extern crate reqwest;
pub extern crate sled;
pub use descriptor::template;
pub use descriptor::HDKeyPaths;
pub use wallet::address_validator;
pub use wallet::signer;
pub use wallet::tx_builder::TxBuilder;
pub use wallet::OfflineWallet;
pub use wallet::Wallet;

Modules

+
blockchain

Blockchain backends

+
database

Database types

+
descriptor

Descriptors

+
keys

Key formats

+
wallet

Wallet

+

Macros

+
descriptor

Macro to write full descriptors with code

+
fragment

Macro to write descriptor fragments with code

+

Structs

+
FeeRate

Fee rate

+
TransactionDetails

A wallet transaction

+
UTXO

A wallet unspent output

+

Enums

+
Error

Errors that can be thrown by the Wallet

+
KeychainKind

Types of keychains

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/index.html new file mode 100644 index 0000000000..7beb4dcbbd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/index.html @@ -0,0 +1,7 @@ +bdk::keys::bip39 - Rust + +

[][src]Module bdk::keys::bip39

This is supported on crate feature keys-bip39 only.

BIP-0039

+

Type Definitions

+
MnemonicWithPassphrase

Type for a BIP39 mnemonic with an optional passphrase

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/sidebar-items.js new file mode 100644 index 0000000000..e3212ff208 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"type":[["MnemonicWithPassphrase","Type for a BIP39 mnemonic with an optional passphrase"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/type.MnemonicWithPassphrase.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/type.MnemonicWithPassphrase.html new file mode 100644 index 0000000000..64af95a2d4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/type.MnemonicWithPassphrase.html @@ -0,0 +1,6 @@ +bdk::keys::bip39::MnemonicWithPassphrase - Rust + +

[][src]Type Definition bdk::keys::bip39::MnemonicWithPassphrase

type MnemonicWithPassphrase = (Mnemonic, Option<String>);
This is supported on crate feature keys-bip39 only.

Type for a BIP39 mnemonic with an optional passphrase

+

Trait Implementations

impl<Ctx: ScriptContext> DerivableKey<Ctx> for MnemonicWithPassphrase[src]

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorKey.html new file mode 100644 index 0000000000..8e38293842 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorKey.html @@ -0,0 +1,37 @@ +bdk::keys::DescriptorKey - Rust + +

[][src]Enum bdk::keys::DescriptorKey

pub enum DescriptorKey<Ctx: ScriptContext> {
+    // some variants omitted
+}

Container for public or secret keys

+

Implementations

impl<Ctx: ScriptContext> DescriptorKey<Ctx>[src]

pub fn from_public(public: DescriptorPublicKey, networks: ValidNetworks) -> Self[src]

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

+

pub fn from_secret(secret: DescriptorSecretKey, networks: ValidNetworks) -> Self[src]

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

+

pub fn override_valid_networks(self, networks: ValidNetworks) -> Self[src]

Override the computed set of valid networks

+

Trait Implementations

impl<Ctx: Debug + ScriptContext> Debug for DescriptorKey<Ctx>[src]

impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorKey<Ctx>[src]

The "identity" conversion is used internally by some bdk::fragments

+

Auto Trait Implementations

impl<Ctx> RefUnwindSafe for DescriptorKey<Ctx> where
    Ctx: RefUnwindSafe
[src]

impl<Ctx> Send for DescriptorKey<Ctx> where
    Ctx: Send
[src]

impl<Ctx> Sync for DescriptorKey<Ctx> where
    Ctx: Sync
[src]

impl<Ctx> Unpin for DescriptorKey<Ctx> where
    Ctx: Unpin
[src]

impl<Ctx> UnwindSafe for DescriptorKey<Ctx> where
    Ctx: UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorPublicKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorPublicKey.html new file mode 100644 index 0000000000..38c6c9e90c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorPublicKey.html @@ -0,0 +1,81 @@ +bdk::keys::DescriptorPublicKey - Rust + +

[]Enum bdk::keys::DescriptorPublicKey

pub enum DescriptorPublicKey {
+    SinglePub(DescriptorSinglePub),
+    XPub(DescriptorXKey<ExtendedPubKey>),
+}

The MiniscriptKey corresponding to Descriptors. This can +either be Single public key or a Xpub

+

+ Variants

+

Single Public Key

+
XPub(DescriptorXKey<ExtendedPubKey>)

Xpub

+

Implementations

impl DescriptorPublicKey

pub fn derive(self, child_number: ChildNumber) -> DescriptorPublicKey

Derives the specified child key if self is a wildcard xpub. Otherwise returns self.

+

Panics if given a hardened child number

+

Trait Implementations

impl Clone for DescriptorPublicKey

impl Debug for DescriptorPublicKey

impl Display for DescriptorPublicKey

impl Eq for DescriptorPublicKey

impl FromStr for DescriptorPublicKey

type Err = DescriptorKeyParseError

The associated error which can be returned from parsing.

+

impl Hash for DescriptorPublicKey

impl MiniscriptKey for DescriptorPublicKey

type Hash = DescriptorPublicKey

The associated Hash type with the publicKey

+

impl Ord for DescriptorPublicKey

impl PartialEq<DescriptorPublicKey> for DescriptorPublicKey

impl PartialOrd<DescriptorPublicKey> for DescriptorPublicKey

impl StructuralEq for DescriptorPublicKey

impl StructuralPartialEq for DescriptorPublicKey

impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorPublicKey[src]

impl<'secp, C> ToPublicKey<DescriptorPublicKeyCtx<'secp, C>> for DescriptorPublicKey where
    C: Verification, 

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorSecretKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorSecretKey.html new file mode 100644 index 0000000000..77ee6bed66 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorSecretKey.html @@ -0,0 +1,48 @@ +bdk::keys::DescriptorSecretKey - Rust + +

[]Enum bdk::keys::DescriptorSecretKey

pub enum DescriptorSecretKey {
+    SinglePriv(DescriptorSinglePriv),
+    XPrv(DescriptorXKey<ExtendedPrivKey>),
+}

A Secret Key that can be either a single key or an Xprv

+

+ Variants

+

Single Secret Key

+
XPrv(DescriptorXKey<ExtendedPrivKey>)

Xprv

+

Implementations

impl DescriptorSecretKey

pub fn as_public<C>(
    &self,
    secp: &Secp256k1<C>
) -> Result<DescriptorPublicKey, DescriptorKeyParseError> where
    C: Signing, 

Return the public version of this key, by applying either +DescriptorSinglePriv::as_public or [DescriptorXKey<bip32::ExtendedPrivKey>::as_public] +depending on the type of key.

+

If the key is an "XPrv", the hardened derivation steps will be applied before converting it +to a public key. See the documentation of [DescriptorXKey<bip32::ExtendedPrivKey>::as_public] +for more details.

+

Trait Implementations

impl Debug for DescriptorSecretKey

impl Display for DescriptorSecretKey

impl FromStr for DescriptorSecretKey

type Err = DescriptorKeyParseError

The associated error which can be returned from parsing.

+

impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorSecretKey[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.KeyError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.KeyError.html new file mode 100644 index 0000000000..ef3178668e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.KeyError.html @@ -0,0 +1,55 @@ +bdk::keys::KeyError - Rust + +

[][src]Enum bdk::keys::KeyError

pub enum KeyError {
+    InvalidScriptContext,
+    InvalidNetwork,
+    InvalidChecksum,
+    Message(String),
+    BIP32(Error),
+    Miniscript(Error),
+}

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

impl Debug for KeyError[src]

impl Display for KeyError[src]

impl Error for KeyError[src]

impl From<Error> for KeyError[src]

impl From<Error> for KeyError[src]

impl From<KeyError> for Error[src]

impl From<KeyError> for Error[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.ScriptContextEnum.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.ScriptContextEnum.html new file mode 100644 index 0000000000..9e93778129 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.ScriptContextEnum.html @@ -0,0 +1,49 @@ +bdk::keys::ScriptContextEnum - Rust + +

[][src]Enum bdk::keys::ScriptContextEnum

pub enum ScriptContextEnum {
+    Legacy,
+    Segwitv0,
+}

Enum representation of the known valid ScriptContexts

+

+ Variants

+
Legacy

Legacy scripts

+
Segwitv0

Segwitv0 scripts

+

Implementations

impl ScriptContextEnum[src]

pub fn is_legacy(&self) -> bool[src]

Returns whether the script context is ScriptContextEnum::Legacy

+

pub fn is_segwit_v0(&self) -> bool[src]

Returns whether the script context is ScriptContextEnum::Segwitv0

+

Trait Implementations

impl Clone for ScriptContextEnum[src]

impl Copy for ScriptContextEnum[src]

impl Debug for ScriptContextEnum[src]

impl Eq for ScriptContextEnum[src]

impl PartialEq<ScriptContextEnum> for ScriptContextEnum[src]

impl StructuralEq for ScriptContextEnum[src]

impl StructuralPartialEq for ScriptContextEnum[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.any_network.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.any_network.html new file mode 100644 index 0000000000..76ff654177 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.any_network.html @@ -0,0 +1,5 @@ +bdk::keys::any_network - Rust + +

[][src]Function bdk::keys::any_network

pub fn any_network() -> ValidNetworks

Create a set containing mainnet, testnet and regtest

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.mainnet_network.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.mainnet_network.html new file mode 100644 index 0000000000..d0807b41c8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.mainnet_network.html @@ -0,0 +1,5 @@ +bdk::keys::mainnet_network - Rust + +

[][src]Function bdk::keys::mainnet_network

pub fn mainnet_network() -> ValidNetworks

Create a set only containing mainnet

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.merge_networks.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.merge_networks.html new file mode 100644 index 0000000000..86a3528a58 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.merge_networks.html @@ -0,0 +1,5 @@ +bdk::keys::merge_networks - Rust + +

[][src]Function bdk::keys::merge_networks

pub fn merge_networks(a: &ValidNetworks, b: &ValidNetworks) -> ValidNetworks

Compute the intersection of two sets

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.test_networks.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.test_networks.html new file mode 100644 index 0000000000..4071c41fd5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.test_networks.html @@ -0,0 +1,5 @@ +bdk::keys::test_networks - Rust + +

[][src]Function bdk::keys::test_networks

pub fn test_networks() -> ValidNetworks

Create a set containing testnet and regtest

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/index.html new file mode 100644 index 0000000000..7442d78e48 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/index.html @@ -0,0 +1,37 @@ +bdk::keys - Rust + +

[][src]Module bdk::keys

Key formats

+

Modules

+
bip39keys-bip39

BIP-0039

+

Structs

+
DescriptorSinglePriv

A Single Descriptor Secret Key with optional origin information

+
DescriptorSinglePub

A Single Descriptor Key with optional origin information

+
GeneratedKey

Output of a GeneratableKey key generation

+
PrivateKeyGenerateOptions

Options for generating a [PrivateKey]

+
SortedMultiVec

Contents of a "sortedmulti" descriptor

+

Enums

+
DescriptorKey

Container for public or secret keys

+
DescriptorPublicKey

The MiniscriptKey corresponding to Descriptors. This can +either be Single public key or a Xpub

+
DescriptorSecretKey

A Secret Key that can be either a single key or an Xprv

+
KeyError

Errors thrown while working with keys

+
ScriptContextEnum

Enum representation of the known valid ScriptContexts

+

Traits

+
DerivableKey

Trait for keys that can be derived.

+
ExtScriptContext

Trait that adds extra useful methods to ScriptContexts

+
GeneratableDefaultOptions

Trait that allows generating a key with the default options

+
GeneratableKey

Trait for keys that can be generated

+
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

+
ToDescriptorKey

Trait for objects that can be turned into a public or secret DescriptorKey

+

Functions

+
any_network

Create a set containing mainnet, testnet 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

+

Type Definitions

+
ValidNetworks

Set of valid networks for a key

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/sidebar-items.js new file mode 100644 index 0000000000..9ba16e1f5e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["DescriptorKey","Container for public or secret keys"],["DescriptorPublicKey","The MiniscriptKey corresponding to Descriptors. This can either be Single public key or a Xpub"],["DescriptorSecretKey","A Secret Key that can be either a single key or an Xprv"],["KeyError","Errors thrown while working with `keys`"],["ScriptContextEnum","Enum representation of the known valid [`ScriptContext`]s"]],"fn":[["any_network","Create a set containing mainnet, testnet and regtest"],["mainnet_network","Create a set only containing mainnet"],["merge_networks","Compute the intersection of two sets"],["test_networks","Create a set containing testnet and regtest"]],"mod":[["bip39","BIP-0039"]],"struct":[["DescriptorSinglePriv","A Single Descriptor Secret Key with optional origin information"],["DescriptorSinglePub","A Single Descriptor Key with optional origin information"],["GeneratedKey","Output of a [`GeneratableKey`] key generation"],["PrivateKeyGenerateOptions","Options for generating a [`PrivateKey`]"],["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"],["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"],["ToDescriptorKey","Trait for objects that can be turned into a public or secret [`DescriptorKey`]"]],"type":[["ValidNetworks","Set of valid networks for a key"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.DescriptorSinglePriv.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.DescriptorSinglePriv.html new file mode 100644 index 0000000000..13fd899c3a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.DescriptorSinglePriv.html @@ -0,0 +1,36 @@ +bdk::keys::DescriptorSinglePriv - Rust + +

[]Struct bdk::keys::DescriptorSinglePriv

pub struct DescriptorSinglePriv {
+    pub origin: Option<(Fingerprint, DerivationPath)>,
+    pub key: PrivateKey,
+}

A Single Descriptor Secret Key with optional origin information

+

+ Fields

origin: Option<(Fingerprint, DerivationPath)>

Origin information

+
key: PrivateKey

The key

+

Trait Implementations

impl Debug for DescriptorSinglePriv

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.DescriptorSinglePub.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.DescriptorSinglePub.html new file mode 100644 index 0000000000..6a9b79d215 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.DescriptorSinglePub.html @@ -0,0 +1,59 @@ +bdk::keys::DescriptorSinglePub - Rust + +

[]Struct bdk::keys::DescriptorSinglePub

pub struct DescriptorSinglePub {
+    pub origin: Option<(Fingerprint, DerivationPath)>,
+    pub key: PublicKey,
+}

A Single Descriptor Key with optional origin information

+

+ Fields

origin: Option<(Fingerprint, DerivationPath)>

Origin information

+
key: PublicKey

The key

+

Trait Implementations

impl Clone for DescriptorSinglePub

impl Debug for DescriptorSinglePub

impl Eq for DescriptorSinglePub

impl Hash for DescriptorSinglePub

impl Ord for DescriptorSinglePub

impl PartialEq<DescriptorSinglePub> for DescriptorSinglePub

impl PartialOrd<DescriptorSinglePub> for DescriptorSinglePub

impl StructuralEq for DescriptorSinglePub

impl StructuralPartialEq for DescriptorSinglePub

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.GeneratedKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.GeneratedKey.html new file mode 100644 index 0000000000..d92eab815c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.GeneratedKey.html @@ -0,0 +1,34 @@ +bdk::keys::GeneratedKey - Rust + +

[][src]Struct bdk::keys::GeneratedKey

pub struct GeneratedKey<K, Ctx: ScriptContext> { /* fields omitted */ }

Output of a GeneratableKey key generation

+

Implementations

impl<K, Ctx: ScriptContext> GeneratedKey<K, Ctx>[src]

pub fn into_key(self) -> K[src]

Consumes self and returns the key

+

Trait Implementations

impl<K, Ctx: ScriptContext> Deref for GeneratedKey<K, Ctx>[src]

type Target = K

The resulting type after dereferencing.

+

impl<Ctx, K> DerivableKey<Ctx> for GeneratedKey<K, Ctx> where
    Ctx: ScriptContext,
    K: DerivableKey<Ctx>, 
[src]

impl<Ctx, K> ToDescriptorKey<Ctx> for GeneratedKey<K, Ctx> where
    Ctx: ScriptContext,
    K: ToDescriptorKey<Ctx>, 
[src]

Auto Trait Implementations

impl<K, Ctx> RefUnwindSafe for GeneratedKey<K, Ctx> where
    Ctx: RefUnwindSafe,
    K: RefUnwindSafe
[src]

impl<K, Ctx> Send for GeneratedKey<K, Ctx> where
    Ctx: Send,
    K: Send
[src]

impl<K, Ctx> Sync for GeneratedKey<K, Ctx> where
    Ctx: Sync,
    K: Sync
[src]

impl<K, Ctx> Unpin for GeneratedKey<K, Ctx> where
    Ctx: Unpin,
    K: Unpin
[src]

impl<K, Ctx> UnwindSafe for GeneratedKey<K, Ctx> where
    Ctx: UnwindSafe,
    K: UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.PrivateKeyGenerateOptions.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.PrivateKeyGenerateOptions.html new file mode 100644 index 0000000000..af5794738a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.PrivateKeyGenerateOptions.html @@ -0,0 +1,42 @@ +bdk::keys::PrivateKeyGenerateOptions - Rust + +

[][src]Struct bdk::keys::PrivateKeyGenerateOptions

pub struct PrivateKeyGenerateOptions {
+    pub compressed: bool,
+}

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

impl Clone for PrivateKeyGenerateOptions[src]

impl Copy for PrivateKeyGenerateOptions[src]

impl Debug for PrivateKeyGenerateOptions[src]

impl Default for PrivateKeyGenerateOptions[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.SortedMultiVec.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.SortedMultiVec.html new file mode 100644 index 0000000000..82ea82db66 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.SortedMultiVec.html @@ -0,0 +1,96 @@ +bdk::keys::SortedMultiVec - Rust + +

[]Struct bdk::keys::SortedMultiVec

pub struct SortedMultiVec<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey
{ + pub k: usize, + pub pks: Vec<Pk, Global>, + // some fields omitted +}

Contents of a "sortedmulti" descriptor

+

+ Fields

k: usize

signatures required

+
pks: Vec<Pk, Global>

public keys inside sorted Multi

+

Implementations

impl<Pk, Ctx> SortedMultiVec<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn new(
    k: usize,
    pks: Vec<Pk, Global>
) -> Result<SortedMultiVec<Pk, Ctx>, Error>

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.

+

impl<Pk, Ctx> SortedMultiVec<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn translate_pk<FPk, Q, FuncError>(
    &self,
    translatefpk: &mut FPk
) -> Result<SortedMultiVec<Q, Ctx>, FuncError> where
    FPk: FnMut(&Pk) -> Result<Q, FuncError>,
    Q: MiniscriptKey

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

+

impl<Pk, Ctx> SortedMultiVec<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

pub fn sorted_node<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> Terminal<Pk, Ctx> where
    Pk: ToPublicKey<ToPkCtx>,
    ToPkCtx: Copy

Create Terminal::Multi containing sorted pubkeys

+

pub fn encode<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> Script where
    Pk: ToPublicKey<ToPkCtx>,
    ToPkCtx: Copy

Encode as a Bitcoin script

+

pub fn satisfy<ToPkCtx, S>(
    &self,
    satisfier: S,
    to_pk_ctx: ToPkCtx
) -> Result<Vec<Vec<u8, Global>, Global>, Error> where
    Pk: ToPublicKey<ToPkCtx>,
    S: Satisfier<ToPkCtx, Pk>,
    ToPkCtx: Copy

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

+

pub fn script_size<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> usize where
    Pk: ToPublicKey<ToPkCtx>,
    ToPkCtx: Copy

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.

+

pub fn max_satisfaction_witness_elements(&self) -> usize

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

+

pub fn max_satisfaction_size(&self, usize) -> usize

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.

+

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

+

Trait Implementations

impl<Pk, Ctx> Clone for SortedMultiVec<Pk, Ctx> where
    Ctx: ScriptContext + Clone,
    Pk: MiniscriptKey + Clone

impl<Pk, Ctx> Debug for SortedMultiVec<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Display for SortedMultiVec<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Eq for SortedMultiVec<Pk, Ctx> where
    Ctx: ScriptContext + Eq,
    Pk: MiniscriptKey + Eq

impl<Pk, Ctx> Liftable<Pk> for SortedMultiVec<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> Ord for SortedMultiVec<Pk, Ctx> where
    Ctx: ScriptContext + Ord,
    Pk: MiniscriptKey + Ord

impl<Pk, Ctx> PartialEq<SortedMultiVec<Pk, Ctx>> for SortedMultiVec<Pk, Ctx> where
    Ctx: ScriptContext + PartialEq<Ctx>,
    Pk: MiniscriptKey + PartialEq<Pk>, 

impl<Pk, Ctx> PartialOrd<SortedMultiVec<Pk, Ctx>> for SortedMultiVec<Pk, Ctx> where
    Ctx: ScriptContext + PartialOrd<Ctx>,
    Pk: MiniscriptKey + PartialOrd<Pk>, 

impl<Pk, Ctx> StructuralEq for SortedMultiVec<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

impl<Pk, Ctx> StructuralPartialEq for SortedMultiVec<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Auto Trait Implementations

impl<Pk, Ctx> RefUnwindSafe for SortedMultiVec<Pk, Ctx> where
    Ctx: RefUnwindSafe,
    Pk: RefUnwindSafe
[src]

impl<Pk, Ctx> Send for SortedMultiVec<Pk, Ctx> where
    Ctx: Send,
    Pk: Send
[src]

impl<Pk, Ctx> Sync for SortedMultiVec<Pk, Ctx> where
    Ctx: Sync,
    Pk: Sync
[src]

impl<Pk, Ctx> Unpin for SortedMultiVec<Pk, Ctx> where
    Ctx: Unpin,
    Pk: Unpin
[src]

impl<Pk, Ctx> UnwindSafe for SortedMultiVec<Pk, Ctx> where
    Ctx: UnwindSafe,
    Pk: UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.DerivableKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.DerivableKey.html new file mode 100644 index 0000000000..e5228642f7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.DerivableKey.html @@ -0,0 +1,15 @@ +bdk::keys::DerivableKey - Rust + +

[][src]Trait bdk::keys::DerivableKey

pub trait DerivableKey<Ctx: ScriptContext> {
+    pub fn add_metadata(
        self,
        origin: Option<KeySource>,
        derivation_path: DerivationPath
    ) -> Result<DescriptorKey<Ctx>, KeyError>; +}

Trait for keys that can be derived.

+

When extra metadata are provided, a DerivableKey can be transofrmed into a +DescriptorKey: the trait ToDescriptorKey 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 implemented this trait instead of ToDescriptorKey. The same +rules regarding script context and valid networks apply.

+

Required methods

pub fn add_metadata(
    self,
    origin: Option<KeySource>,
    derivation_path: DerivationPath
) -> Result<DescriptorKey<Ctx>, KeyError>
[src]

Add a extra metadata, consume self and turn it into a DescriptorKey

+
Loading content...

Implementations on Foreign Types

impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed[src]

This is supported on crate feature keys-bip39 only.

impl<Ctx: ScriptContext> DerivableKey<Ctx> for Mnemonic[src]

This is supported on crate feature keys-bip39 only.

impl<Ctx: ScriptContext> DerivableKey<Ctx> for ExtendedPubKey[src]

impl<Ctx: ScriptContext> DerivableKey<Ctx> for ExtendedPrivKey[src]

Loading content...

Implementors

impl<Ctx, K> DerivableKey<Ctx> for GeneratedKey<K, Ctx> where
    Ctx: ScriptContext,
    K: DerivableKey<Ctx>, 
[src]

impl<Ctx: ScriptContext> DerivableKey<Ctx> for MnemonicWithPassphrase[src]

This is supported on crate feature keys-bip39 only.
Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ExtScriptContext.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ExtScriptContext.html new file mode 100644 index 0000000000..f22a12511a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ExtScriptContext.html @@ -0,0 +1,13 @@ +bdk::keys::ExtScriptContext - Rust + +

[][src]Trait bdk::keys::ExtScriptContext

pub trait ExtScriptContext: ScriptContext {
+    pub fn as_enum() -> ScriptContextEnum;
+
+    pub fn is_legacy() -> bool { ... }
+
pub fn is_segwit_v0() -> bool { ... } +}

Trait that adds extra useful methods to ScriptContexts

+

Required methods

Loading content...

Provided methods

pub fn is_legacy() -> bool[src]

Returns whether the script context is Legacy

+

pub fn is_segwit_v0() -> bool[src]

Returns whether the script context is Segwitv0

+
Loading content...

Implementors

impl<Ctx: ScriptContext + 'static> ExtScriptContext for Ctx[src]

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.GeneratableDefaultOptions.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.GeneratableDefaultOptions.html new file mode 100644 index 0000000000..17759d7720 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.GeneratableDefaultOptions.html @@ -0,0 +1,13 @@ +bdk::keys::GeneratableDefaultOptions - Rust + +

[][src]Trait bdk::keys::GeneratableDefaultOptions

pub trait GeneratableDefaultOptions<Ctx>: GeneratableKey<Ctx> where
    Ctx: ScriptContext,
    Self::Options: Default
{ + pub fn generate_with_entropy_default(
        entropy: Self::Entropy
    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> { ... } +
pub fn generate_default() -> Result<GeneratedKey<Self, Ctx>, Self::Error> { ... } +}

Trait that allows generating a key with the default options

+

This trait is automatically implemented if the GeneratableKey::Options implements Default.

+

Provided methods

pub fn generate_with_entropy_default(
    entropy: Self::Entropy
) -> Result<GeneratedKey<Self, Ctx>, Self::Error>
[src]

Generate a key with the default options and a given entropy

+

pub fn generate_default() -> Result<GeneratedKey<Self, Ctx>, Self::Error>[src]

Generate a key with the default options and a random entropy

+
Loading content...

Implementors

impl<Ctx, K> GeneratableDefaultOptions<Ctx> for K where
    Ctx: ScriptContext,
    K: GeneratableKey<Ctx>,
    <K as GeneratableKey<Ctx>>::Options: Default
[src]

Automatic implementation of GeneratableDefaultOptions for GeneratableKeys where +Options implements Default

+
Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.GeneratableKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.GeneratableKey.html new file mode 100644 index 0000000000..5812454c1e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.GeneratableKey.html @@ -0,0 +1,22 @@ +bdk::keys::GeneratableKey - Rust + +

[][src]Trait bdk::keys::GeneratableKey

pub trait GeneratableKey<Ctx: ScriptContext>: Sized {
+    type Entropy: AsMut<[u8]> + Default;
+    type Options;
+    type Error: Debug;
+    pub fn generate_with_entropy(
        options: Self::Options,
        entropy: Self::Entropy
    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error>; + + pub fn generate(
        options: Self::Options
    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> { ... } +}

Trait for keys that can be generated

+

The same rules about ScriptContext and ValidNetworks from ToDescriptorKey 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 +ToDescriptorKey: the generated keys can be directly used in descriptors if Self is also +ToDescriptorKey.

+

Associated Types

type Entropy: AsMut<[u8]> + Default[src]

Type specifying the amount of entropy required e.g. [u8;32]

+

type Options[src]

Extra options required by the generate_with_entropy

+

type Error: Debug[src]

Returned error in case of failure

+
Loading content...

Required methods

pub fn generate_with_entropy(
    options: Self::Options,
    entropy: Self::Entropy
) -> Result<GeneratedKey<Self, Ctx>, Self::Error>
[src]

Generate a key given the extra options and the entropy

+
Loading content...

Provided methods

pub fn generate(
    options: Self::Options
) -> Result<GeneratedKey<Self, Ctx>, Self::Error>
[src]

Generate a key given the options with a random entropy

+
Loading content...

Implementations on Foreign Types

impl<Ctx: ScriptContext> GeneratableKey<Ctx> for Mnemonic[src]

This is supported on crate feature keys-bip39 only.

type Entropy = [u8; 32]

type Options = (MnemonicType, Language)

type Error = Option<ErrorKind>

impl<Ctx: ScriptContext> GeneratableKey<Ctx> for ExtendedPrivKey[src]

type Entropy = [u8; 32]

type Options = ()

type Error = Error

impl<Ctx: ScriptContext> GeneratableKey<Ctx> for PrivateKey[src]

type Entropy = [u8; 32]

type Options = PrivateKeyGenerateOptions

type Error = Error

Loading content...

Implementors

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ScriptContext.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ScriptContext.html new file mode 100644 index 0000000000..c81e63ce76 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ScriptContext.html @@ -0,0 +1,78 @@ +bdk::keys::ScriptContext - Rust + +

[]Trait bdk::keys::ScriptContext

pub trait ScriptContext: Sealed + Clone + PartialEq<Self> + Eq + Ord + PartialOrd<Self> + Debug {
+    pub fn check_terminal_non_malleable<Pk, Ctx>(
        _frag: &Terminal<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
; +
pub fn max_satisfaction_size<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Option<usize>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
; + + pub fn check_witness<Pk, Ctx>(
        _witness: &[Vec<u8, Global>]
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn check_global_consensus_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn check_global_policy_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn check_local_consensus_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn check_local_policy_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn check_global_validity<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn check_local_validity<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn top_level_type_check<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), Error>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn other_top_level_checks<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), Error>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
pub fn top_level_checks<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), Error>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +}

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 methods

pub fn check_terminal_non_malleable<Pk, Ctx>(
    _frag: &Terminal<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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.

+

pub fn max_satisfaction_size<Pk, Ctx>(ms: &Miniscript<Pk, Ctx>) -> Option<usize> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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

+
Loading content...

Provided methods

pub fn check_witness<Pk, Ctx>(
    _witness: &[Vec<u8, Global>]
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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.

+

pub fn check_global_consensus_validity<Pk, Ctx>(
    _ms: &Miniscript<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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.

+

pub fn check_global_policy_validity<Pk, Ctx>(
    _ms: &Miniscript<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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.

+

pub fn check_local_consensus_validity<Pk, Ctx>(
    _ms: &Miniscript<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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.

+

pub fn check_local_policy_validity<Pk, Ctx>(
    _ms: &Miniscript<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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

+

pub fn check_global_validity<Pk, Ctx>(
    ms: &Miniscript<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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

+

pub fn check_local_validity<Pk, Ctx>(
    ms: &Miniscript<Pk, Ctx>
) -> Result<(), ScriptContextError> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

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

+

pub fn top_level_type_check<Pk, Ctx>(
    ms: &Miniscript<Pk, Ctx>
) -> Result<(), Error> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Check whether the top-level is type B

+

pub fn other_top_level_checks<Pk, Ctx>(
    _ms: &Miniscript<Pk, Ctx>
) -> Result<(), Error> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Other top level checks that are context specific

+

pub fn top_level_checks<Pk, Ctx>(ms: &Miniscript<Pk, Ctx>) -> Result<(), Error> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey

Check top level consensus rules.

+
Loading content...

Implementations on Foreign Types

impl ScriptContext for Bare

Loading content...

Implementors

impl ScriptContext for Legacy

impl ScriptContext for Segwitv0

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ToDescriptorKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ToDescriptorKey.html new file mode 100644 index 0000000000..54802814ca --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ToDescriptorKey.html @@ -0,0 +1,112 @@ +bdk::keys::ToDescriptorKey - Rust + +

[][src]Trait bdk::keys::ToDescriptorKey

pub trait ToDescriptorKey<Ctx: ScriptContext>: Sized {
+    pub fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError>;
+}

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, KeyError, ScriptContext, ToDescriptorKey};
+
+pub struct MyKeyType {
+    pubkey: PublicKey,
+}
+
+impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for MyKeyType {
+    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        self.pubkey.to_descriptor_key()
+    }
+}
+

Key type that is only valid on mainnet:

+ +
+use bdk::bitcoin::PublicKey;
+
+use bdk::keys::{
+    mainnet_network, DescriptorKey, DescriptorPublicKey, DescriptorSinglePub, KeyError,
+    ScriptContext, ToDescriptorKey,
+};
+
+pub struct MyKeyType {
+    pubkey: PublicKey,
+}
+
+impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for MyKeyType {
+    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        Ok(DescriptorKey::from_public(
+            DescriptorPublicKey::SinglePub(DescriptorSinglePub {
+                origin: None,
+                key: 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, KeyError, ScriptContext, ToDescriptorKey};
+
+pub struct MyKeyType {
+    is_legacy: bool,
+    pubkey: PublicKey,
+}
+
+impl<Ctx: ScriptContext + 'static> ToDescriptorKey<Ctx> for MyKeyType {
+    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        if Ctx::is_legacy() == self.is_legacy {
+            self.pubkey.to_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.

+ +
ⓘThis example deliberately fails to compile
+use bdk::bitcoin::PublicKey;
+use std::str::FromStr;
+
+use bdk::keys::{DescriptorKey, KeyError, ToDescriptorKey};
+
+pub struct MySegwitOnlyKeyType {
+    pubkey: PublicKey,
+}
+
+impl ToDescriptorKey<bdk::miniscript::Segwitv0> for MySegwitOnlyKeyType {
+    fn to_descriptor_key(self) -> Result<DescriptorKey<bdk::miniscript::Segwitv0>, KeyError> {
+        self.pubkey.to_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

pub fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError>[src]

Turn the key into a DescriptorKey within the requested ScriptContext

+
Loading content...

Implementations on Foreign Types

impl<Ctx: ScriptContext, T: DerivableKey<Ctx>> ToDescriptorKey<Ctx> for (T, DerivationPath)[src]

impl<Ctx: ScriptContext, T: DerivableKey<Ctx>> ToDescriptorKey<Ctx> for (T, KeySource, DerivationPath)[src]

impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for PublicKey[src]

impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for PrivateKey[src]

Loading content...

Implementors

impl<Ctx, K> ToDescriptorKey<Ctx> for GeneratedKey<K, Ctx> where
    Ctx: ScriptContext,
    K: ToDescriptorKey<Ctx>, 
[src]

impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorKey<Ctx>[src]

The "identity" conversion is used internally by some bdk::fragments

+

impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorPublicKey[src]

impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorSecretKey[src]

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/type.ValidNetworks.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/type.ValidNetworks.html new file mode 100644 index 0000000000..9156edfb16 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/type.ValidNetworks.html @@ -0,0 +1,5 @@ +bdk::keys::ValidNetworks - Rust + +

[][src]Type Definition bdk::keys::ValidNetworks

type ValidNetworks = HashSet<Network>;

Set of valid networks for a key

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.descriptor!.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.descriptor!.html new file mode 100644 index 0000000000..990e1ba2f8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.descriptor!.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to macro.descriptor.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.descriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.descriptor.html new file mode 100644 index 0000000000..58bf25b1ab --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.descriptor.html @@ -0,0 +1,76 @@ +bdk::descriptor - Rust + +

[][src]Macro bdk::descriptor

+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 )* ) ) => { ... };
+}
+

Macro to write full descriptors with code

+

This macro expands to a Result of +DescriptorTemplateOut and Error

+

Example

+

Signature plus timelock, equivalent to: sh(wsh(and_v(v:pk(...), older(...))))

+ +
+let my_key = bitcoin::PublicKey::from_str("02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c")?;
+let my_timelock = 50;
+let (my_descriptor, my_keys_map, networks) = bdk::descriptor!(sh ( wsh ( and_v (+v pk my_key), ( older my_timelock ))))?;
+
+

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(...),sdv: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+d+v older my_timelock)
+    )
+}?;
+
+let b_items = vec![
+    bdk::fragment!(pk my_key_1)?,
+    bdk::fragment!(+s pk my_key_2)?,
+    bdk::fragment!(+s+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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.fragment!.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.fragment!.html new file mode 100644 index 0000000000..1dbdb1fdc8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.fragment!.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to macro.fragment.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.fragment.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.fragment.html new file mode 100644 index 0000000000..d1031f5d0c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.fragment.html @@ -0,0 +1,44 @@ +bdk::fragment - Rust + +

[][src]Macro bdk::fragment

+macro_rules! fragment {
+    ( +a $( $inner:tt )* ) => { ... };
+    ( +s $( $inner:tt )* ) => { ... };
+    ( +c $( $inner:tt )* ) => { ... };
+    ( +d $( $inner:tt )* ) => { ... };
+    ( +v $( $inner:tt )* ) => { ... };
+    ( +j $( $inner:tt )* ) => { ... };
+    ( +n $( $inner:tt )* ) => { ... };
+    ( +t $( $inner:tt )* ) => { ... };
+    ( +l $( $inner:tt )* ) => { ... };
+    ( +u $( $inner:tt )* ) => { ... };
+    ( true ) => { ... };
+    ( false ) => { ... };
+    ( pk_k $key:expr ) => { ... };
+    ( pk $key:expr ) => { ... };
+    ( pk_h $key_hash:expr ) => { ... };
+    ( after $value:expr ) => { ... };
+    ( older $value:expr ) => { ... };
+    ( sha256 $hash:expr ) => { ... };
+    ( hash256 $hash:expr ) => { ... };
+    ( ripemd160 $hash:expr ) => { ... };
+    ( hash160 $hash:expr ) => { ... };
+    ( and_v ( $( $a:tt )* ), ( $( $b:tt )* ) ) => { ... };
+    ( and_b ( $( $a:tt )* ), ( $( $b:tt )* ) ) => { ... };
+    ( and_or ( $( $a:tt )* ), ( $( $b:tt )* ), ( $( $c:tt )* ) ) => { ... };
+    ( or_b ( $( $a:tt )* ), ( $( $b:tt )* ) ) => { ... };
+    ( or_d ( $( $a:tt )* ), ( $( $b:tt )* ) ) => { ... };
+    ( or_c ( $( $a:tt )* ), ( $( $b:tt )* ) ) => { ... };
+    ( or_i ( $( $a:tt )* ), ( $( $b:tt )* ) ) => { ... };
+    ( thresh_vec $thresh:expr, $items:expr ) => { ... };
+    ( thresh $thresh:expr $(, ( $( $item:tt )* ) )+ ) => { ... };
+    ( multi_vec $thresh:expr, $keys:expr ) => { ... };
+    ( multi $thresh:expr $(, $key:expr )+ ) => { ... };
+    ( sortedmulti $( $inner:tt )* ) => { ... };
+    ( sortedmulti_vec $( $inner:tt )* ) => { ... };
+}
+

Macro to write descriptor fragments with code

+

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

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/sidebar-items.js new file mode 100644 index 0000000000..bc49a753f3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["Error","Errors that can be thrown by the `Wallet`"],["KeychainKind","Types of keychains"]],"macro":[["descriptor","Macro to write full descriptors with code"],["fragment","Macro to write descriptor fragments with code"]],"mod":[["blockchain","Blockchain backends"],["database","Database types"],["descriptor","Descriptors"],["keys","Key formats"],["wallet","Wallet"]],"struct":[["FeeRate","Fee rate"],["TransactionDetails","A wallet transaction"],["UTXO","A wallet unspent output"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.FeeRate.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.FeeRate.html new file mode 100644 index 0000000000..23ab6fa059 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.FeeRate.html @@ -0,0 +1,51 @@ +bdk::FeeRate - Rust + +

[][src]Struct bdk::FeeRate

pub struct FeeRate(_);

Fee rate

+

Implementations

impl FeeRate[src]

pub fn from_btc_per_kvb(btc_per_kvb: f32) -> Self[src]

Create a new instance of FeeRate given a float fee rate in btc/kvbytes

+

pub fn from_sat_per_vb(sat_per_vb: f32) -> Self[src]

Create a new instance of FeeRate given a float fee rate in satoshi/vbyte

+

pub fn default_min_relay_fee() -> Self[src]

Create a new FeeRate with the default min relay fee value

+

pub fn as_sat_vb(&self) -> f32[src]

Return the value as satoshi/vbyte

+

Trait Implementations

impl Clone for FeeRate[src]

impl Copy for FeeRate[src]

impl Debug for FeeRate[src]

impl Default for FeeRate[src]

impl PartialEq<FeeRate> for FeeRate[src]

impl PartialOrd<FeeRate> for FeeRate[src]

impl StructuralPartialEq for FeeRate[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.TransactionDetails.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.TransactionDetails.html new file mode 100644 index 0000000000..52089b9ae3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.TransactionDetails.html @@ -0,0 +1,59 @@ +bdk::TransactionDetails - Rust + +

[][src]Struct bdk::TransactionDetails

pub struct TransactionDetails {
+    pub transaction: Option<Transaction>,
+    pub txid: Txid,
+    pub timestamp: u64,
+    pub received: u64,
+    pub sent: u64,
+    pub fees: u64,
+    pub height: Option<u32>,
+}

A wallet transaction

+

+ Fields

transaction: Option<Transaction>

Optional transaction

+
txid: Txid

Transaction id

+
timestamp: u64

Timestamp

+
received: u64

Received value (sats)

+
sent: u64

Sent value (sats)

+
fees: u64

Fee value (sats)

+
height: Option<u32>

Confirmed in block height, None means unconfirmed

+

Trait Implementations

impl Clone for TransactionDetails[src]

impl Debug for TransactionDetails[src]

impl Default for TransactionDetails[src]

impl<'de> Deserialize<'de> for TransactionDetails[src]

impl Eq for TransactionDetails[src]

impl PartialEq<TransactionDetails> for TransactionDetails[src]

impl Serialize for TransactionDetails[src]

impl StructuralEq for TransactionDetails[src]

impl StructuralPartialEq for TransactionDetails[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.UTXO.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.UTXO.html new file mode 100644 index 0000000000..cbdf664fe6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.UTXO.html @@ -0,0 +1,50 @@ +bdk::UTXO - Rust + +

[][src]Struct bdk::UTXO

pub struct UTXO {
+    pub outpoint: OutPoint,
+    pub txout: TxOut,
+    pub keychain: KeychainKind,
+}

A wallet unspent output

+

+ Fields

outpoint: OutPoint

Reference to a transaction output

+
txout: TxOut

Transaction output

+
keychain: KeychainKind

Type of keychain

+

Trait Implementations

impl Clone for UTXO[src]

impl Debug for UTXO[src]

impl<'de> Deserialize<'de> for UTXO[src]

impl Eq for UTXO[src]

impl PartialEq<UTXO> for UTXO[src]

impl Serialize for UTXO[src]

impl StructuralEq for UTXO[src]

impl StructuralPartialEq for UTXO[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/enum.KeychainKind.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/enum.KeychainKind.html new file mode 100644 index 0000000000..8b0b5f9399 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/enum.KeychainKind.html @@ -0,0 +1,10 @@ + + + + + + +

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

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/enum.ScriptType.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/enum.ScriptType.html new file mode 100644 index 0000000000..b10e9a3fe6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/enum.ScriptType.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../bdk/enum.ScriptType.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.FeeRate.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.FeeRate.html new file mode 100644 index 0000000000..c8b0ec4f98 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.FeeRate.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../bdk/struct.FeeRate.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.TransactionDetails.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.TransactionDetails.html new file mode 100644 index 0000000000..5db5e06868 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.TransactionDetails.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../bdk/struct.TransactionDetails.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.UTXO.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.UTXO.html new file mode 100644 index 0000000000..1517bb40f5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.UTXO.html @@ -0,0 +1,10 @@ + + + + + + +

Redirecting to ../../bdk/struct.UTXO.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/enum.AddressValidatorError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/enum.AddressValidatorError.html new file mode 100644 index 0000000000..19c2ae0bf1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/enum.AddressValidatorError.html @@ -0,0 +1,60 @@ +bdk::wallet::address_validator::AddressValidatorError - Rust + +

[][src]Enum bdk::wallet::address_validator::AddressValidatorError

pub enum AddressValidatorError {
+    UserRejected,
+    ConnectionError,
+    TimeoutError,
+    InvalidScript,
+    Message(String),
+}

Errors that can be returned to fail the validation of an address

+

+ Variants

+
UserRejected

User rejected the address

+
ConnectionError

Network connection error

+
TimeoutError

Network request timeout error

+
InvalidScript

Invalid script

+
Message(String)

A custom error message

+

Trait Implementations

impl Clone for AddressValidatorError[src]

impl Debug for AddressValidatorError[src]

impl Display for AddressValidatorError[src]

impl Eq for AddressValidatorError[src]

impl Error for AddressValidatorError[src]

impl From<AddressValidatorError> for Error[src]

impl PartialEq<AddressValidatorError> for AddressValidatorError[src]

impl StructuralEq for AddressValidatorError[src]

impl StructuralPartialEq for AddressValidatorError[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/index.html new file mode 100644 index 0000000000..8779ce0ce5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/index.html @@ -0,0 +1,47 @@ +bdk::wallet::address_validator - Rust + +

[][src]Module bdk::wallet::address_validator

Address validation callbacks

+

The typical usage of those callbacks is for displaying the newly-generated address on a +hardware wallet, so that the user can cross-check its correctness.

+

More generally speaking though, these callbacks can also be used to "do something" every time +an address is generated, without necessarily checking or validating it.

+

An address validator can be attached to a Wallet by using the +Wallet::add_address_validator method, and +whenever a new address is generated (either explicitly by the user with +Wallet::get_new_address or internally to create a change +address) all the attached validators will be polled, in sequence. All of them must complete +successfully to continue.

+

Example

+
+struct PrintAddressAndContinue;
+
+impl AddressValidator for PrintAddressAndContinue {
+    fn validate(
+        &self,
+        keychain: KeychainKind,
+        hd_keypaths: &HDKeyPaths,
+        script: &Script
+    ) -> Result<(), AddressValidatorError> {
+        let address = Address::from_script(script, Network::Testnet)
+            .as_ref()
+            .map(Address::to_string)
+            .unwrap_or(script.to_string());
+        println!("New address of type {:?}: {}", keychain, address);
+        println!("HD keypaths: {:#?}", hd_keypaths);
+
+        Ok(())
+    }
+}
+
+let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+wallet.add_address_validator(Arc::new(PrintAddressAndContinue));
+
+let address = wallet.get_new_address()?;
+println!("Address: {}", address);
+

Enums

+
AddressValidatorError

Errors that can be returned to fail the validation of an address

+

Traits

+
AddressValidator

Trait to build address validators

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/sidebar-items.js new file mode 100644 index 0000000000..58959ba340 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["AddressValidatorError","Errors that can be returned to fail the validation of an address"]],"trait":[["AddressValidator","Trait to build address validators"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/trait.AddressValidator.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/trait.AddressValidator.html new file mode 100644 index 0000000000..ccd57983bc --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/trait.AddressValidator.html @@ -0,0 +1,12 @@ +bdk::wallet::address_validator::AddressValidator - Rust + +

[][src]Trait bdk::wallet::address_validator::AddressValidator

pub trait AddressValidator: Send + Sync {
+    pub fn validate(
        &self,
        keychain: KeychainKind,
        hd_keypaths: &HDKeyPaths,
        script: &Script
    ) -> Result<(), AddressValidatorError>; +}

Trait to build address validators

+

All the address validators attached to a wallet with Wallet::add_address_validator will be polled +every time an address (external or internal) is generated by the wallet. Errors returned in the +validator will be propagated up to the original caller that triggered the address generation.

+

For a usage example see this module's documentation.

+

Required methods

pub fn validate(
    &self,
    keychain: KeychainKind,
    hd_keypaths: &HDKeyPaths,
    script: &Script
) -> Result<(), AddressValidatorError>
[src]

Validate or inspect an address

+
Loading content...

Implementors

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/constant.TXIN_BASE_WEIGHT.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/constant.TXIN_BASE_WEIGHT.html new file mode 100644 index 0000000000..424e9ede75 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/constant.TXIN_BASE_WEIGHT.html @@ -0,0 +1,4 @@ +bdk::wallet::coin_selection::TXIN_BASE_WEIGHT - Rust + +

[][src]Constant bdk::wallet::coin_selection::TXIN_BASE_WEIGHT

pub const TXIN_BASE_WEIGHT: usize = (32 + 4 + 4 + 1) * 4; // 0x0_000_000_000_000_0a4usize
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/index.html new file mode 100644 index 0000000000..6c2eea8d97 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/index.html @@ -0,0 +1,72 @@ +bdk::wallet::coin_selection - Rust + +

[][src]Module bdk::wallet::coin_selection

Coin selection

+

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

+

The coin selection algorithm is not globally part of a Wallet, instead it +is selected whenever a Wallet::create_tx call is made, through +the use of the TxBuilder structure, specifically with +TxBuilder::coin_selection method.

+

The DefaultCoinSelectionAlgorithm selects the default coin selection algorithm that +TxBuilder uses, if it's not explicitly overridden.

+

Example

+
+#[derive(Debug)]
+struct AlwaysSpendEverything;
+
+impl<D: Database> CoinSelectionAlgorithm<D> for AlwaysSpendEverything {
+    fn coin_select(
+        &self,
+        database: &D,
+        required_utxos: Vec<(UTXO, usize)>,
+        optional_utxos: Vec<(UTXO, usize)>,
+        fee_rate: FeeRate,
+        amount_needed: u64,
+        fee_amount: f32,
+    ) -> Result<CoinSelectionResult, bdk::Error> {
+        let mut selected_amount = 0;
+        let mut additional_weight = 0;
+        let all_utxos_selected = required_utxos
+            .into_iter().chain(optional_utxos)
+            .scan((&mut selected_amount, &mut additional_weight), |(selected_amount, additional_weight), (utxo, weight)| {
+                **selected_amount += utxo.txout.value;
+                **additional_weight += TXIN_BASE_WEIGHT + weight;
+
+                Some(utxo)
+            })
+            .collect::<Vec<_>>();
+        let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0;
+
+        if (fee_amount + additional_fees).ceil() as u64 + amount_needed > selected_amount {
+            return Err(bdk::Error::InsufficientFunds);
+        }
+
+        Ok(CoinSelectionResult {
+            selected: all_utxos_selected,
+            selected_amount,
+            fee_amount: fee_amount + additional_fees,
+        })
+    }
+}
+
+// create wallet, sync, ...
+
+let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+let (psbt, details) = wallet.create_tx(
+    TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+        .coin_selection(AlwaysSpendEverything),
+)?;
+
+// inspect, sign, broadcast, ...
+
+

Structs

+
BranchAndBoundCoinSelection

Branch and bound coin selection

+
CoinSelectionResult

Result of a successful coin selection

+
LargestFirstCoinSelection

Simple and dumb coin selection

+

Traits

+
CoinSelectionAlgorithm

Trait for generalized coin selection algorithms

+

Type Definitions

+
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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/sidebar-items.js new file mode 100644 index 0000000000..8e7e293b89 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["BranchAndBoundCoinSelection","Branch and bound coin selection"],["CoinSelectionResult","Result of a successful coin selection"],["LargestFirstCoinSelection","Simple and dumb coin selection"]],"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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html new file mode 100644 index 0000000000..3bab787572 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html @@ -0,0 +1,34 @@ +bdk::wallet::coin_selection::BranchAndBoundCoinSelection - Rust + +

[][src]Struct bdk::wallet::coin_selection::BranchAndBoundCoinSelection

pub struct BranchAndBoundCoinSelection { /* fields omitted */ }

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

impl BranchAndBoundCoinSelection[src]

pub fn new(size_of_change: u64) -> Self[src]

Create new instance with target size for change output

+

Trait Implementations

impl<D: Database> CoinSelectionAlgorithm<D> for BranchAndBoundCoinSelection[src]

impl Debug for BranchAndBoundCoinSelection[src]

impl Default for BranchAndBoundCoinSelection[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.CoinSelectionResult.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.CoinSelectionResult.html new file mode 100644 index 0000000000..ac4969b233 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.CoinSelectionResult.html @@ -0,0 +1,38 @@ +bdk::wallet::coin_selection::CoinSelectionResult - Rust + +

[][src]Struct bdk::wallet::coin_selection::CoinSelectionResult

pub struct CoinSelectionResult {
+    pub selected: Vec<UTXO>,
+    pub selected_amount: u64,
+    pub fee_amount: f32,
+}

Result of a successful coin selection

+

+ Fields

selected: Vec<UTXO>

List of outputs selected for use as inputs

+
selected_amount: u64

Sum of the selected inputs' value

+
fee_amount: f32

Total fee amount in satoshi

+

Trait Implementations

impl Debug for CoinSelectionResult[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html new file mode 100644 index 0000000000..3694261e76 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html @@ -0,0 +1,34 @@ +bdk::wallet::coin_selection::LargestFirstCoinSelection - Rust + +

[][src]Struct bdk::wallet::coin_selection::LargestFirstCoinSelection

pub struct LargestFirstCoinSelection;

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

impl<D: Database> CoinSelectionAlgorithm<D> for LargestFirstCoinSelection[src]

impl Debug for LargestFirstCoinSelection[src]

impl Default for LargestFirstCoinSelection[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html new file mode 100644 index 0000000000..d7b7b57eeb --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html @@ -0,0 +1,23 @@ +bdk::wallet::coin_selection::CoinSelectionAlgorithm - Rust + +

[][src]Trait bdk::wallet::coin_selection::CoinSelectionAlgorithm

pub trait CoinSelectionAlgorithm<D: Database>: Debug {
+    pub fn coin_select(
        &self,
        database: &D,
        required_utxos: Vec<(UTXO, usize)>,
        optional_utxos: Vec<(UTXO, usize)>,
        fee_rate: FeeRate,
        amount_needed: u64,
        fee_amount: f32
    ) -> Result<CoinSelectionResult, Error>; +}

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

pub fn coin_select(
    &self,
    database: &D,
    required_utxos: Vec<(UTXO, usize)>,
    optional_utxos: Vec<(UTXO, usize)>,
    fee_rate: FeeRate,
    amount_needed: u64,
    fee_amount: f32
) -> Result<CoinSelectionResult, Error>
[src]

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 amount_needed with their +weight cost
  • +
  • optional_utxos: the remaining available utxos to satisfy amount_needed with their +weight cost
  • +
  • fee_rate: fee rate to use
  • +
  • amount_needed: the amount in satoshi to select
  • +
  • fee_amount: the amount of fees in satoshi already accumulated from adding outputs and +the transaction's header
  • +
+
Loading content...

Implementors

impl<D: Database> CoinSelectionAlgorithm<D> for BranchAndBoundCoinSelection[src]

impl<D: Database> CoinSelectionAlgorithm<D> for LargestFirstCoinSelection[src]

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html new file mode 100644 index 0000000000..0cb914590e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html @@ -0,0 +1,6 @@ +bdk::wallet::coin_selection::DefaultCoinSelectionAlgorithm - Rust + +

[][src]Type Definition bdk::wallet::coin_selection::DefaultCoinSelectionAlgorithm

type DefaultCoinSelectionAlgorithm = BranchAndBoundCoinSelection;

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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/index.html new file mode 100644 index 0000000000..bb91aa33f1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/index.html @@ -0,0 +1,36 @@ +bdk::wallet::export - Rust + +

[][src]Module bdk::wallet::export

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 = WalletExport::from_str(import)?;
+let wallet: OfflineWallet<_> = Wallet::new_offline(
+    &import.descriptor(),
+    import.change_descriptor().as_ref(),
+    Network::Testnet,
+    MemoryDatabase::default(),
+)?;
+

Export a Wallet

+
+let wallet: OfflineWallet<_> = Wallet::new_offline(
+    "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
+    Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
+    Network::Testnet,
+    MemoryDatabase::default()
+)?;
+let export = WalletExport::export_wallet(&wallet, "exported wallet", true)
+    .map_err(ToString::to_string)
+    .map_err(bdk::Error::Generic)?;
+
+println!("Exported: {}", export.to_string());
+

Structs

+
WalletExport

Structure that contains the export of a wallet

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/sidebar-items.js new file mode 100644 index 0000000000..06abb3c4ee --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["WalletExport","Structure that contains the export of a wallet"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/struct.WalletExport.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/struct.WalletExport.html new file mode 100644 index 0000000000..cdef818514 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/struct.WalletExport.html @@ -0,0 +1,53 @@ +bdk::wallet::export::WalletExport - Rust + +

[][src]Struct bdk::wallet::export::WalletExport

pub struct WalletExport {
+    pub blockheight: u32,
+    pub label: String,
+    // some fields omitted
+}

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

impl WalletExport[src]

pub fn export_wallet<B: BlockchainMarker, D: BatchDatabase>(
    wallet: &Wallet<B, D>,
    label: &str,
    include_blockheight: bool
) -> Result<Self, &'static str>
[src]

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 descriptor(&self) -> String[src]

Return the external descriptor

+

pub fn change_descriptor(&self) -> Option<String>[src]

Return the internal descriptor, if present

+

Trait Implementations

impl Debug for WalletExport[src]

impl<'de> Deserialize<'de> for WalletExport[src]

impl FromStr for WalletExport[src]

type Err = Error

The associated error which can be returned from parsing.

+

impl Serialize for WalletExport[src]

impl ToString for WalletExport[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> DeserializeOwned for T where
    T: for<'de> Deserialize<'de>, 
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/index.html new file mode 100644 index 0000000000..7f20cd4daf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/index.html @@ -0,0 +1,19 @@ +bdk::wallet - Rust + +

[][src]Module bdk::wallet

Wallet

+

This module defines the Wallet structure.

+

Modules

+
address_validator

Address validation callbacks

+
coin_selection

Coin selection

+
export

Wallet export

+
signer

Generalized signers

+
time

Cross-platform time

+
tx_builder

Transaction builder

+

Structs

+
Wallet

A Bitcoin wallet

+

Traits

+
IsDust

Trait to check if a value is below the dust limit

+

Type Definitions

+
OfflineWallet

Type alias for a Wallet that uses OfflineBlockchain

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/sidebar-items.js new file mode 100644 index 0000000000..811ec3c2b5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"mod":[["address_validator","Address validation callbacks"],["coin_selection","Coin selection"],["export","Wallet export"],["signer","Generalized signers"],["time","Cross-platform time"],["tx_builder","Transaction builder"]],"struct":[["Wallet","A Bitcoin wallet"]],"trait":[["IsDust","Trait to check if a value is below the dust limit"]],"type":[["OfflineWallet","Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/enum.SignerError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/enum.SignerError.html new file mode 100644 index 0000000000..7f44c5c3b9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/enum.SignerError.html @@ -0,0 +1,68 @@ +bdk::wallet::signer::SignerError - Rust + +

[][src]Enum bdk::wallet::signer::SignerError

pub enum SignerError {
+    MissingKey,
+    InvalidKey,
+    UserCanceled,
+    InputIndexOutOfRange,
+    MissingNonWitnessUtxo,
+    InvalidNonWitnessUtxo,
+    MissingWitnessUtxo,
+    MissingWitnessScript,
+    MissingHDKeypath,
+}

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 requied to sign this input

+
MissingHDKeypath

The fingerprint and derivation path are missing from the psbt input

+

Trait Implementations

impl Clone for SignerError[src]

impl Debug for SignerError[src]

impl Display for SignerError[src]

impl Eq for SignerError[src]

impl Error for SignerError[src]

impl From<SignerError> for Error[src]

impl PartialEq<SignerError> for SignerError[src]

impl StructuralEq for SignerError[src]

impl StructuralPartialEq for SignerError[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T> ToString for T where
    T: Display + ?Sized
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/enum.SignerId.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/enum.SignerId.html new file mode 100644 index 0000000000..1a404225cd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/enum.SignerId.html @@ -0,0 +1,63 @@ +bdk::wallet::signer::SignerId - Rust + +

[][src]Enum bdk::wallet::signer::SignerId

pub enum SignerId {
+    PkHash(Hash),
+    Fingerprint(Fingerprint),
+}

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

+

Trait Implementations

impl Clone for SignerId[src]

impl Debug for SignerId[src]

impl Eq for SignerId[src]

impl From<Fingerprint> for SignerId[src]

impl From<Hash> for SignerId[src]

impl Hash for SignerId[src]

impl Ord for SignerId[src]

impl PartialEq<SignerId> for SignerId[src]

impl PartialOrd<SignerId> for SignerId[src]

impl StructuralEq for SignerId[src]

impl StructuralPartialEq for SignerId[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/index.html new file mode 100644 index 0000000000..fee170e531 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/index.html @@ -0,0 +1,58 @@ +bdk::wallet::signer - Rust + +

[][src]Module bdk::wallet::signer

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 Signer for CustomSigner {
+    fn sign(
+        &self,
+        psbt: &mut psbt::PartiallySignedTransaction,
+        input_index: Option<usize>,
+        _secp: &Secp256k1<All>,
+    ) -> Result<(), SignerError> {
+        let input_index = input_index.ok_or(SignerError::InputIndexOutOfRange)?;
+        self.device.sign_input(psbt, input_index)?;
+
+        Ok(())
+    }
+
+    fn sign_whole_tx(&self) -> bool {
+        false
+    }
+}
+
+let custom_signer = CustomSigner::connect();
+
+let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+wallet.add_signer(
+    KeychainKind::External,
+    Fingerprint::from_str("e30f11b8").unwrap().into(),
+    SignerOrdering(200),
+    Arc::new(custom_signer)
+);
+
+

Structs

+
SignerOrdering

Defines the order in which signers are called

+
SignersContainer

Container for multiple signers

+

Enums

+
SignerError

Signing error

+
SignerId

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

+

Traits

+
Signer

Trait for signers

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/sidebar-items.js new file mode 100644 index 0000000000..8f3e3d79b6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["SignerError","Signing error"],["SignerId","Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among multiple of them"]],"struct":[["SignerOrdering","Defines the order in which signers are called"],["SignersContainer","Container for multiple signers"]],"trait":[["Signer","Trait for signers"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/struct.SignerOrdering.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/struct.SignerOrdering.html new file mode 100644 index 0000000000..6bd85ccaf8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/struct.SignerOrdering.html @@ -0,0 +1,55 @@ +bdk::wallet::signer::SignerOrdering - Rust + +

[][src]Struct bdk::wallet::signer::SignerOrdering

pub struct SignerOrdering(pub usize);

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.

+

Trait Implementations

impl Clone for SignerOrdering[src]

impl Debug for SignerOrdering[src]

impl Default for SignerOrdering[src]

impl Eq for SignerOrdering[src]

impl Ord for SignerOrdering[src]

impl PartialEq<SignerOrdering> for SignerOrdering[src]

impl PartialOrd<SignerOrdering> for SignerOrdering[src]

impl StructuralEq for SignerOrdering[src]

impl StructuralPartialEq for SignerOrdering[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/struct.SignersContainer.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/struct.SignersContainer.html new file mode 100644 index 0000000000..ebd6434357 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/struct.SignersContainer.html @@ -0,0 +1,46 @@ +bdk::wallet::signer::SignersContainer - Rust + +

[][src]Struct bdk::wallet::signer::SignersContainer

pub struct SignersContainer(_);

Container for multiple signers

+

Implementations

impl SignersContainer[src]

pub fn as_key_map(&self, secp: &Secp256k1<All>) -> KeyMap[src]

Create a map of public keys to secret keys

+

impl SignersContainer[src]

pub fn new() -> Self[src]

Default constructor

+

pub fn add_external(
    &mut self,
    id: SignerId,
    ordering: SignerOrdering,
    signer: Arc<dyn Signer>
) -> Option<Arc<dyn Signer>>
[src]

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 remove(
    &mut self,
    id: SignerId,
    ordering: SignerOrdering
) -> Option<Arc<dyn Signer>>
[src]

Removes a signer from the container and returns it

+

pub fn ids(&self) -> Vec<&SignerId>[src]

Returns the list of identifiers of all the signers in the container

+

pub fn signers(&self) -> Vec<&Arc<dyn Signer>>[src]

Returns the list of signers in the container, sorted by lowest to highest ordering

+

pub fn find(&self, id: SignerId) -> Option<&Arc<dyn Signer>>[src]

Finds the signer with lowest ordering for a given id in the container.

+

Trait Implementations

impl Clone for SignersContainer[src]

impl Debug for SignersContainer[src]

impl Default for SignersContainer[src]

impl From<HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>> for SignersContainer[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/trait.Signer.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/trait.Signer.html new file mode 100644 index 0000000000..95e96eab96 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/trait.Signer.html @@ -0,0 +1,22 @@ +bdk::wallet::signer::Signer - Rust + +

[][src]Trait bdk::wallet::signer::Signer

pub trait Signer: Debug + Send + Sync {
+    pub fn sign(
        &self,
        psbt: &mut PartiallySignedTransaction,
        input_index: Option<usize>,
        secp: &Secp256k1<All>
    ) -> Result<(), SignerError>; +
pub fn sign_whole_tx(&self) -> bool; + + pub fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> { ... } +}

Trait for signers

+

This trait can be implemented to provide customized signers to the wallet. For an example see +this module's documentation.

+

Required methods

pub fn sign(
    &self,
    psbt: &mut PartiallySignedTransaction,
    input_index: Option<usize>,
    secp: &Secp256k1<All>
) -> Result<(), SignerError>
[src]

Sign a PSBT

+

The input_index argument is only provided if the wallet doesn't declare to sign the whole +transaction in one go (see Signer::sign_whole_tx). Otherwise its value is None and +can be ignored.

+

pub fn sign_whole_tx(&self) -> bool[src]

Return whether or not the signer signs the whole transaction in one go instead of every +input individually

+
Loading content...

Provided methods

pub fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey>[src]

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

+
Loading content...

Implementations on Foreign Types

impl Signer for DescriptorXKey<ExtendedPrivKey>[src]

impl Signer for PrivateKey[src]

Loading content...

Implementors

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html new file mode 100644 index 0000000000..9d76dc92f8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html @@ -0,0 +1,92 @@ +bdk::wallet::Wallet - Rust + +

[][src]Struct bdk::wallet::Wallet

pub struct Wallet<B, D> { /* fields omitted */ }

A Bitcoin wallet

+

A wallet takes descriptors, a database and a +blockchain and implements the basic functions that a Bitcoin wallets +needs to operate, like generating addresses, returning the balance, +creating transactions, etc.

+

A wallet can be either "online" if the blockchain type provided +implements Blockchain, or "offline" OfflineBlockchain is used. Offline wallets only expose +methods that don't need any interaction with the blockchain to work.

+

Implementations

impl<B, D> Wallet<B, D> where
    B: BlockchainMarker,
    D: BatchDatabase
[src]

pub fn new_offline<E: ToWalletDescriptor>(
    descriptor: E,
    change_descriptor: Option<E>,
    network: Network,
    database: D
) -> Result<Self, Error>
[src]

Create a new "offline" wallet

+

pub fn get_new_address(&self) -> Result<Address, Error>[src]

Return a newly generated address using the external descriptor

+

pub fn is_mine(&self, script: &Script) -> Result<bool, Error>[src]

Return whether or not a script is part of this wallet (either internal or external)

+

pub fn list_unspent(&self) -> Result<Vec<UTXO>, Error>[src]

Return the list of unspent outputs of this wallet

+

Note that this methods only operate on the internal database, which first needs to be +Wallet::sync manually.

+

pub fn list_transactions(
    &self,
    include_raw: bool
) -> Result<Vec<TransactionDetails>, Error>
[src]

Return the list of transactions made and received by the wallet

+

Optionally fill the TransactionDetails::transaction field with the raw transaction if +include_raw is true.

+

Note that this methods only operate on the internal database, which first needs to be +Wallet::sync manually.

+

pub fn get_balance(&self) -> Result<u64, Error>[src]

Return the balance, meaning the sum of this wallet's unspent outputs' values

+

Note that this methods only operate on the internal database, which first needs to be +Wallet::sync manually.

+

pub fn add_signer(
    &mut self,
    keychain: KeychainKind,
    id: SignerId,
    ordering: SignerOrdering,
    signer: Arc<dyn Signer>
)
[src]

Add an external signer

+

See the signer module for an example.

+

pub fn add_address_validator(&mut self, validator: Arc<dyn AddressValidator>)[src]

Add an address validator

+

See the address_validator module for an example.

+

pub fn create_tx<Cs: CoinSelectionAlgorithm<D>>(
    &self,
    builder: TxBuilder<D, Cs, CreateTx>
) -> Result<(PSBT, TransactionDetails), Error>
[src]

Create a new transaction following the options specified in the builder

+

Example

+
+let (psbt, details) = wallet.create_tx(
+    TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+)?;
+// sign and broadcast ...
+

pub fn bump_fee<Cs: CoinSelectionAlgorithm<D>>(
    &self,
    txid: &Txid,
    builder: TxBuilder<D, Cs, BumpFee>
) -> Result<(PSBT, TransactionDetails), Error>
[src]

Bump the fee of a transaction following the options specified in the builder

+

Return an error if the transaction is already confirmed or doesn't explicitly signal RBF.

+

NOTE: if the original transaction was made with TxBuilder::set_single_recipient, +the TxBuilder::maintain_single_recipient flag should be enabled to correctly reduce the +only output's value in order to increase the fees.

+

If the builder specifies some utxos that must be spent, they will be added to the +transaction regardless of whether they are necessary or not to cover additional fees.

+

Example

+
+let txid = Txid::from_str("faff0a466b70f5d5f92bd757a92c1371d4838bdd5bc53a06764e2488e51ce8f8").unwrap();
+let (psbt, details) = wallet.bump_fee(
+    &txid,
+    TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(5.0)),
+)?;
+// sign and broadcast ...
+

pub fn sign(
    &self,
    psbt: PSBT,
    assume_height: Option<u32>
) -> Result<(PSBT, bool), Error>
[src]

Sign a transaction with all the wallet's signers, in the order specified by every signer's +SignerOrdering

+

Example

+
+let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
+

pub fn policies(&self, keychain: KeychainKind) -> Result<Option<Policy>, Error>[src]

Return the spending policies for the wallet's descriptor

+

pub fn public_descriptor(
    &self,
    keychain: KeychainKind
) -> Result<Option<ExtendedDescriptor>, Error>
[src]

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 finalize_psbt(
    &self,
    psbt: PSBT,
    assume_height: Option<u32>
) -> Result<(PSBT, bool), Error>
[src]

Try to finalize a PSBT

+

pub fn secp_ctx(&self) -> &Secp256k1<All>[src]

Return the secp256k1 context used for all signing operations

+

impl<B, D> Wallet<B, D> where
    B: Blockchain,
    D: BatchDatabase
[src]

pub fn new<E: ToWalletDescriptor>(
    descriptor: E,
    change_descriptor: Option<E>,
    network: Network,
    database: D,
    client: B
) -> Result<Self, Error>
[src]

Create a new "online" wallet

+

pub fn sync<P: 'static + Progress>(
    &self,
    progress_update: P,
    max_address_param: Option<u32>
) -> Result<(), Error>
[src]

Sync the internal database with the blockchain

+

pub fn client(&self) -> Option<&B>[src]

Return a reference to the internal blockchain client

+

pub fn network(&self) -> Network[src]

Get the Bitcoin network the wallet is using.

+

pub fn broadcast(&self, tx: Transaction) -> Result<Txid, Error>[src]

Broadcast a transaction to the network

+

Auto Trait Implementations

impl<B, D> !RefUnwindSafe for Wallet<B, D>[src]

impl<B, D> Send for Wallet<B, D> where
    B: Send,
    D: Send
[src]

impl<B, D> !Sync for Wallet<B, D>[src]

impl<B, D> Unpin for Wallet<B, D> where
    B: Unpin,
    D: Unpin
[src]

impl<B, D> !UnwindSafe for Wallet<B, D>[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/fn.get_timestamp.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/fn.get_timestamp.html new file mode 100644 index 0000000000..7d78ed14eb --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/fn.get_timestamp.html @@ -0,0 +1,5 @@ +bdk::wallet::time::get_timestamp - Rust + +

[][src]Function bdk::wallet::time::get_timestamp

pub fn get_timestamp() -> u64

Return the current timestamp in seconds

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/index.html new file mode 100644 index 0000000000..29b8cd1da8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/index.html @@ -0,0 +1,11 @@ +bdk::wallet::time - Rust + +

[][src]Module bdk::wallet::time

Cross-platform time

+

This module provides a function to get the current timestamp that works on all the platforms +supported by the library.

+

It can be useful to compare it with the timestamps found in +TransactionDetails.

+

Functions

+
get_timestamp

Return the current timestamp in seconds

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/sidebar-items.js new file mode 100644 index 0000000000..22164ef49f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"fn":[["get_timestamp","Return the current timestamp in seconds"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/trait.IsDust.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/trait.IsDust.html new file mode 100644 index 0000000000..dade076dc1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/trait.IsDust.html @@ -0,0 +1,8 @@ +bdk::wallet::IsDust - Rust + +

[][src]Trait bdk::wallet::IsDust

pub trait IsDust {
+    pub fn is_dust(&self) -> bool;
+}

Trait to check if a value is below the dust limit

+

Required methods

pub fn is_dust(&self) -> bool[src]

Check whether or not a value is below dust limit

+
Loading content...

Implementations on Foreign Types

impl IsDust for u64[src]

Loading content...

Implementors

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html new file mode 100644 index 0000000000..2bfd8fc4f6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html @@ -0,0 +1,63 @@ +bdk::wallet::tx_builder::ChangeSpendPolicy - Rust + +

[][src]Enum bdk::wallet::tx_builder::ChangeSpendPolicy

pub enum ChangeSpendPolicy {
+    ChangeAllowed,
+    OnlyChange,
+    ChangeForbidden,
+}

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

impl Clone for ChangeSpendPolicy[src]

impl Copy for ChangeSpendPolicy[src]

impl Debug for ChangeSpendPolicy[src]

impl Default for ChangeSpendPolicy[src]

impl Eq for ChangeSpendPolicy[src]

impl Hash for ChangeSpendPolicy[src]

impl Ord for ChangeSpendPolicy[src]

impl PartialEq<ChangeSpendPolicy> for ChangeSpendPolicy[src]

impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy[src]

impl StructuralEq for ChangeSpendPolicy[src]

impl StructuralPartialEq for ChangeSpendPolicy[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/enum.TxOrdering.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/enum.TxOrdering.html new file mode 100644 index 0000000000..26672be49f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/enum.TxOrdering.html @@ -0,0 +1,64 @@ +bdk::wallet::tx_builder::TxOrdering - Rust + +

[][src]Enum bdk::wallet::tx_builder::TxOrdering

pub enum TxOrdering {
+    Shuffle,
+    Untouched,
+    BIP69Lexicographic,
+}

Ordering of the transaction's inputs and outputs

+

+ Variants

+
Shuffle

Randomized (default)

+
Untouched

Unchanged

+
BIP69Lexicographic

BIP69 / Lexicographic

+

Implementations

impl TxOrdering[src]

pub fn sort_tx(&self, tx: &mut Transaction)[src]

Sort transaction inputs and outputs by TxOrdering variant

+

Trait Implementations

impl Clone for TxOrdering[src]

impl Copy for TxOrdering[src]

impl Debug for TxOrdering[src]

impl Default for TxOrdering[src]

impl Eq for TxOrdering[src]

impl Hash for TxOrdering[src]

impl Ord for TxOrdering[src]

impl PartialEq<TxOrdering> for TxOrdering[src]

impl PartialOrd<TxOrdering> for TxOrdering[src]

impl StructuralEq for TxOrdering[src]

impl StructuralPartialEq for TxOrdering[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<Q, K> Equivalent<K> for Q where
    K: Borrow<Q> + ?Sized,
    Q: Eq + ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/index.html new file mode 100644 index 0000000000..ae1593ff1b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/index.html @@ -0,0 +1,23 @@ +bdk::wallet::tx_builder - Rust + +

[][src]Module bdk::wallet::tx_builder

Transaction builder

+

Example

+
+// Create a transaction with one output to `to_address` of 50_000 satoshi, with a custom fee rate
+// of 5.0 satoshi/vbyte, only spending non-change outputs and with RBF signaling
+// enabled
+let builder = TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+    .fee_rate(FeeRate::from_sat_per_vb(5.0))
+    .do_not_spend_change()
+    .enable_rbf();
+

Structs

+
BumpFee

Wallet::bump_fee context

+
CreateTx

Wallet::create_tx context

+
TxBuilder

A transaction builder

+

Enums

+
ChangeSpendPolicy

Policy regarding the use of change outputs when creating a transaction

+
TxOrdering

Ordering of the transaction's inputs and outputs

+

Traits

+
TxBuilderContext

Context in which the TxBuilder is valid

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/sidebar-items.js new file mode 100644 index 0000000000..76461e4a13 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["ChangeSpendPolicy","Policy regarding the use of change outputs when creating a transaction"],["TxOrdering","Ordering of the transaction's inputs and outputs"]],"struct":[["BumpFee","`Wallet::bump_fee` context"],["CreateTx","`Wallet::create_tx` context"],["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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.BumpFee.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.BumpFee.html new file mode 100644 index 0000000000..f7a5030e23 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.BumpFee.html @@ -0,0 +1,37 @@ +bdk::wallet::tx_builder::BumpFee - Rust + +

[][src]Struct bdk::wallet::tx_builder::BumpFee

pub struct BumpFee;

Trait Implementations

impl Clone for BumpFee[src]

impl Debug for BumpFee[src]

impl Default for BumpFee[src]

impl TxBuilderContext for BumpFee[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.CreateTx.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.CreateTx.html new file mode 100644 index 0000000000..e333ecd81b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.CreateTx.html @@ -0,0 +1,37 @@ +bdk::wallet::tx_builder::CreateTx - Rust + +

[][src]Struct bdk::wallet::tx_builder::CreateTx

pub struct CreateTx;

Trait Implementations

impl Clone for CreateTx[src]

impl Debug for CreateTx[src]

impl Default for CreateTx[src]

impl TxBuilderContext for CreateTx[src]

Auto Trait Implementations

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.TxBuilder.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.TxBuilder.html new file mode 100644 index 0000000000..dfad991d27 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.TxBuilder.html @@ -0,0 +1,152 @@ +bdk::wallet::tx_builder::TxBuilder - Rust + +

[][src]Struct bdk::wallet::tx_builder::TxBuilder

pub struct TxBuilder<D: Database, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext> { /* fields omitted */ }

A transaction builder

+

This structure contains the configuration that the wallet must follow to build a transaction.

+

For an example see this module's documentation;

+

Implementations

impl<D: Database, Ctx: TxBuilderContext> TxBuilder<D, DefaultCoinSelectionAlgorithm, Ctx>[src]

pub fn new() -> Self[src]

Create an empty builder

+

impl<D: Database, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext> TxBuilder<D, Cs, Ctx>[src]

pub fn fee_rate(self, fee_rate: FeeRate) -> Self[src]

Set a custom fee rate

+

pub fn fee_absolute(self, fee_amount: u64) -> Self[src]

Set an absolute fee

+

pub fn policy_path(
    self,
    policy_path: BTreeMap<String, Vec<usize>>,
    keychain: KeychainKind
) -> Self
[src]

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.

+ +
+let mut path = BTreeMap::new();
+path.insert("aabbccdd".to_string(), vec![0, 1]);
+
+let builder = TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+    .policy_path(path, KeychainKind::External);
+

pub fn utxos(self, utxos: Vec<OutPoint>) -> Self[src]

Replace the internal list of utxos that must be spent with a new list

+

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(self, utxo: OutPoint) -> Self[src]

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 manually_selected_only(self) -> Self[src]

Only spend utxos added by add_utxo and utxos.

+

The wallet will not add additional utxos to the transaction even if they are needed to +make the transaction valid.

+

pub fn unspendable(self, unspendable: Vec<OutPoint>) -> Self[src]

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::utxos and +TxBuilder::add_utxo have priority over these. See the docs of the two linked methods +for more details.

+

pub fn add_unspendable(self, unspendable: OutPoint) -> Self[src]

Add a utxo to the internal list of unspendable utxos

+

It's important to note that the "must-be-spent" utxos added with TxBuilder::utxos and +TxBuilder::add_utxo have priority over this. See the docs of the two linked methods +for more details.

+

pub fn sighash(self, sighash: SigHashType) -> Self[src]

Sign with a specific sig hash

+

Use this option very carefully

+

pub fn ordering(self, ordering: TxOrdering) -> Self[src]

Choose the ordering for inputs and outputs of the transaction

+

pub fn nlocktime(self, locktime: u32) -> Self[src]

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 version(self, version: i32) -> Self[src]

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 do_not_spend_change(self) -> Self[src]

Do not spend change outputs

+

This effectively adds all the change outputs to the "unspendable" list. See +TxBuilder::unspendable.

+

pub fn only_spend_change(self) -> Self[src]

Only spend change outputs

+

This effectively adds all the non-change outputs to the "unspendable" list. See +TxBuilder::unspendable.

+

pub fn change_policy(self, change_policy: ChangeSpendPolicy) -> Self[src]

pub fn force_non_witness_utxo(self) -> Self[src]

Fill-in the psbt::Input::non_witness_utxo field even if the wallet only has SegWit +descriptors.

+

This is useful for signers which always require it, like Trezor hardware wallets.

+

pub fn include_output_redeem_witness_script(self) -> Self[src]

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.

+

pub fn add_global_xpubs(self) -> Self[src]

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 drain_wallet(self) -> Self[src]

Spend all the available inputs. This respects filters like TxBuilder::unspendable and the change policy.

+

pub fn coin_selection<P: CoinSelectionAlgorithm<D>>(
    self,
    coin_selection: P
) -> TxBuilder<D, P, Ctx>
[src]

Choose the coin selection algorithm

+

Overrides the DefaultCoinSelectionAlgorithm.

+

impl<D: Database> TxBuilder<D, DefaultCoinSelectionAlgorithm, CreateTx>[src]

pub fn with_recipients(recipients: Vec<(Script, u64)>) -> Self[src]

Create a builder starting from a list of recipients

+

impl<D: Database, Cs: CoinSelectionAlgorithm<D>> TxBuilder<D, Cs, CreateTx>[src]

pub fn set_recipients(self, recipients: Vec<(Script, u64)>) -> Self[src]

Replace the recipients already added with a new list

+

pub fn add_recipient(self, script_pubkey: Script, amount: u64) -> Self[src]

Add a recipient to the internal list

+

pub fn set_single_recipient(self, recipient: Script) -> Self[src]

Set a single recipient that will get all the selected funds minus the fee. No change will +be created

+

This method overrides any recipient set with set_recipients or +add_recipient.

+

It can only be used in conjunction with drain_wallet to send the +entire content of the wallet (minus filters) to a single recipient or with a +list of manually selected UTXOs by enabling manually_selected_only +and selecting them with utxos or add_utxo.

+

When bumping the fees of a transaction made with this option, the user should remeber to +add maintain_single_recipient to correctly update the +single output instead of adding one more for the change.

+

pub fn enable_rbf(self) -> Self[src]

Enable signaling RBF

+

This will use the default nSequence value of 0xFFFFFFFD.

+

pub fn enable_rbf_with_sequence(self, nsequence: u32) -> Self[src]

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.

+

impl<D: Database> TxBuilder<D, DefaultCoinSelectionAlgorithm, BumpFee>[src]

pub fn maintain_single_recipient(self) -> Self[src]

Bump the fees of a transaction made with set_single_recipient

+

Unless extra inputs are specified with add_utxo or utxos, this flag will make +bump_fee reduce the value of the existing output, or fail if it would be consumed +entirely given the higher new fee rate.

+

If extra inputs are added and they are not entirely consumed in fees, a change output will not +be added; the existing output will simply grow in value.

+

Fails if the transaction has more than one outputs.

+

Trait Implementations

impl<D: Debug + Database, Cs: Debug + CoinSelectionAlgorithm<D>, Ctx: Debug + TxBuilderContext> Debug for TxBuilder<D, Cs, Ctx>[src]

impl<D: Database, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext> Default for TxBuilder<D, Cs, Ctx> where
    Cs: Default
[src]

Auto Trait Implementations

impl<D, Cs, Ctx> RefUnwindSafe for TxBuilder<D, Cs, Ctx> where
    Cs: RefUnwindSafe,
    Ctx: RefUnwindSafe,
    D: RefUnwindSafe
[src]

impl<D, Cs, Ctx> Send for TxBuilder<D, Cs, Ctx> where
    Cs: Send,
    Ctx: Send,
    D: Send
[src]

impl<D, Cs, Ctx> Sync for TxBuilder<D, Cs, Ctx> where
    Cs: Sync,
    Ctx: Sync,
    D: Sync
[src]

impl<D, Cs, Ctx> Unpin for TxBuilder<D, Cs, Ctx> where
    Cs: Unpin,
    Ctx: Unpin,
    D: Unpin
[src]

impl<D, Cs, Ctx> UnwindSafe for TxBuilder<D, Cs, Ctx> where
    Cs: UnwindSafe,
    Ctx: UnwindSafe,
    D: UnwindSafe
[src]

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T> Instrument for T[src]

impl<T> Instrument for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> Pointable for T

type Init = T

The type for initializers.

+

impl<T> Same<T> for T

type Output = T

Should always be Self

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+

impl<V, T> VZip<V> for T where
    V: MultiLane<T>, 

\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/trait.TxBuilderContext.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/trait.TxBuilderContext.html new file mode 100644 index 0000000000..081df97ad3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/trait.TxBuilderContext.html @@ -0,0 +1,5 @@ +bdk::wallet::tx_builder::TxBuilderContext - Rust + +

[][src]Trait bdk::wallet::tx_builder::TxBuilderContext

pub trait TxBuilderContext: Debug + Default + Clone { }

Context in which the TxBuilder is valid

+

Implementors

impl TxBuilderContext for BumpFee[src]

impl TxBuilderContext for CreateTx[src]

Loading content...
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/type.OfflineWallet.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/type.OfflineWallet.html new file mode 100644 index 0000000000..cdc5549ea9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/type.OfflineWallet.html @@ -0,0 +1,5 @@ +bdk::wallet::OfflineWallet - Rust + +

[][src]Type Definition bdk::wallet::OfflineWallet

type OfflineWallet<D> = Wallet<OfflineBlockchain, D>;

Type alias for a Wallet that uses OfflineBlockchain

+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/utils/trait.IsDust.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/utils/trait.IsDust.html new file mode 100644 index 0000000000..71ab5675d6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/utils/trait.IsDust.html @@ -0,0 +1,10 @@ + + + + + + +

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

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/brush.svg b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/brush.svg new file mode 100644 index 0000000000..ea266e856a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/brush.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/dark.css b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/dark.css new file mode 100644 index 0000000000..774d43d747 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/dark.css @@ -0,0 +1 @@ +body{background-color:#353535;color:#ddd;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:#ddd;}h1.fqn{border-bottom-color:#d2d2d2;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){border-bottom-color:#d2d2d2;}.in-band{background-color:#353535;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#2A2A2A;}pre{background-color:#2A2A2A;}.sidebar{background-color:#505050;}.logo-container.rust-logo>img{filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff)}*{scrollbar-color:rgb(64,65,67) #717171;}.sidebar{scrollbar-color:rgba(32,34,37,.6) transparent;}::-webkit-scrollbar-track{background-color:#717171;}::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar::-webkit-scrollbar-track{background-color:#717171;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar .current{background-color:#333;}.source .sidebar{background-color:#353535;}.sidebar .location{border-color:#fff;background:#575757;color:#DDD;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#444;}.line-numbers span{color:#3B91E2;}.line-numbers .line-highlighted{background-color:#0a042f !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#DDD;}.docblock table,.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#ddd;}.content .highlighted{color:#eee !important;background-color:#616161;}.content .highlighted a,.content .highlighted span{color:#eee !important;}.content .highlighted.trait{background-color:#013191;}.content .highlighted.traitalias{background-color:#013191;}.content .highlighted.mod,.content .highlighted.externcrate{background-color:#afc6e4;}.content .highlighted.mod{background-color:#803a1b;}.content .highlighted.externcrate{background-color:#396bac;}.content .highlighted.enum{background-color:#5b4e68;}.content .highlighted.struct{background-color:#194e9f;}.content .highlighted.union{background-color:#b7bd49;}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{background-color:#4950ed;}.content .highlighted.type{background-color:#38902c;}.content .highlighted.foreigntype{background-color:#b200d6;}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{background-color:#217d1c;}.content .highlighted.constant,.content .highlighted.static{background-color:#0063cc;}.content .highlighted.primitive{background-color:#00708a;}.content .highlighted.keyword{background-color:#884719;}.content .item-info::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#82b089;}.content span.struct,.content a.struct,.block a.current.struct{color:#2dbfb8;}.content span.type,.content a.type,.block a.current.type{color:#ff7f00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#dd7de8;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#09bd00;}.content span.union,.content a.union,.block a.current.union{color:#a6ae37;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#82a5c9;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#43aec7;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#bda000;}.content span.trait,.content a.trait,.block a.current.trait{color:#b78cf2;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#b397da;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#2BAB63;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}pre.rust .comment{color:#8d8d8b;}pre.rust .doccomment{color:#8ca375;}nav:not(.sidebar){border-bottom-color:#4e4e4e;}nav.main .current{border-top-color:#eee;border-bottom-color:#eee;}nav.main .separator{border-color:#eee;}a{color:#ddd;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.item-info a,#help a{color:#D2991D;}a.test-arrow{color:#dedede;}.collapse-toggle{color:#999;}#crate-search{color:#111;background-color:#f0f0f0;border-color:#000;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input{color:#111;background-color:#f0f0f0;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input:focus{border-color:#008dfd;}.search-focus:disabled{background-color:#c5c4c4;}#crate-search+.search-input:focus{box-shadow:0 0 8px 4px #078dd8;}.module-item .stab{color:#ddd;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;color:#2f2f2f;}.stab.deprecated{background:#F3DFFF;border-color:#7F0087;color:#2f2f2f;}.stab.portability{background:#C4ECFF;border-color:#7BA5DB;color:#2f2f2f;}.stab.portability>code{color:#ddd;}#help>div{background:#4d4d4d;border-color:#bfbfbf;}#help>div>span{border-bottom-color:#bfbfbf;}#help dt{border-color:#bfbfbf;background:rgba(0,0,0,0);color:black;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:#ddd;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#ab8ac1;}pre.rust .kw-2,pre.rust .prelude-ty{color:#769acb;}pre.rust .number,pre.rust .string{color:#83a300;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#ee6868;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#d97f26;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#4a4949;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label{color:#999;}:target>code,:target>.in-band{background-color:#494a3d;border-right:3px solid #bb7410;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.8);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.8);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.8);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.8);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip .tooltiptext{background-color:#000;color:#fff;border-color:#000;}.tooltip .tooltiptext::after{border-color:transparent black transparent transparent;}.notable-traits-tooltiptext{background-color:#111;border-color:#777;}#titles>button:not(.selected){background-color:#252525;border-top-color:#252525;}#titles>button:hover,#titles>button.selected{border-top-color:#0089ff;background-color:#353535;}#titles>button>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#505050;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#505050;border-right-color:#000;}#sidebar-filler{background-color:#505050;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu,.help-button{border-color:#e0e0e0;background:#f0f0f0;color:#000;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus,.help-button:hover,.help-button:focus{border-color:#ffb900;}#theme-choices{border-color:#e0e0e0;background-color:#353535;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#4e4e4e;}@media (max-width:700px){#theme-picker{background:#f0f0f0;}}#all-types{background-color:#505050;}#all-types:hover{background-color:#606060;}.search-results td span.alias{color:#fff;}.search-results td span.grey{color:#ccc;}#sidebar-toggle{background-color:#565656;}#sidebar-toggle:hover{background-color:#676767;}#source-sidebar{background-color:#565656;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#444;}div.files>.selected{background-color:#333;}.setting-line>.title{border-bottom-color:#ddd;} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/down-arrow.svg b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/down-arrow.svg new file mode 100644 index 0000000000..35437e77a7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/down-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon-16x16.png b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon-16x16.png new file mode 100644 index 0000000000..7cfe6c1355 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon-16x16.png differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon-32x32.png b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon-32x32.png new file mode 100644 index 0000000000..5109c1de8b Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon-32x32.png differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon.svg b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon.svg new file mode 100644 index 0000000000..8b34b51198 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon.svg @@ -0,0 +1,24 @@ + + + + + diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/alloc/string/trait.ToString.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/alloc/string/trait.ToString.js new file mode 100644 index 0000000000..5f6129873e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/alloc/string/trait.ToString.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl ToString for WalletExport","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.Blockchain.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.Blockchain.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.Blockchain.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.BlockchainMarker.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.BlockchainMarker.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.BlockchainMarker.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.ConfigurableBlockchain.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.ConfigurableBlockchain.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.ConfigurableBlockchain.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.Progress.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.Progress.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.Progress.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.BatchDatabase.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.BatchDatabase.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.BatchDatabase.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.BatchOperations.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.BatchOperations.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.BatchOperations.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.ConfigurableDatabase.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.ConfigurableDatabase.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.ConfigurableDatabase.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.Database.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.Database.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.Database.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/template/trait.DescriptorTemplate.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/template/trait.DescriptorTemplate.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/template/trait.DescriptorTemplate.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ExtractPolicy.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ExtractPolicy.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ExtractPolicy.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.MiniscriptKey.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.MiniscriptKey.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.MiniscriptKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ToPublicKey.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ToPublicKey.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ToPublicKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ToWalletDescriptor.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ToWalletDescriptor.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ToWalletDescriptor.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.DerivableKey.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.DerivableKey.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.DerivableKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ExtScriptContext.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ExtScriptContext.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ExtScriptContext.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.GeneratableDefaultOptions.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.GeneratableDefaultOptions.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.GeneratableDefaultOptions.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.GeneratableKey.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.GeneratableKey.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.GeneratableKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ScriptContext.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ScriptContext.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ScriptContext.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ToDescriptorKey.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ToDescriptorKey.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ToDescriptorKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/signer/trait.Signer.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/signer/trait.Signer.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/signer/trait.Signer.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/trait.IsDust.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/trait.IsDust.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/trait.IsDust.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/tx_builder/trait.TxBuilderContext.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/tx_builder/trait.TxBuilderContext.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/tx_builder/trait.TxBuilderContext.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/clone/trait.Clone.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/clone/trait.Clone.js new file mode 100644 index 0000000000..a7ef0cbabd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/clone/trait.Clone.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Clone for Capability","synthetic":false,"types":[]},{"text":"impl Clone for NoopProgress","synthetic":false,"types":[]},{"text":"impl Clone for LogProgress","synthetic":false,"types":[]},{"text":"impl Clone for PKOrF","synthetic":false,"types":[]},{"text":"impl Clone for SatisfiableItem","synthetic":false,"types":[]},{"text":"impl Clone for Satisfaction","synthetic":false,"types":[]},{"text":"impl Clone for Policy","synthetic":false,"types":[]},{"text":"impl Clone for Condition","synthetic":false,"types":[]},{"text":"impl Clone for ScriptContextEnum","synthetic":false,"types":[]},{"text":"impl Clone for PrivateKeyGenerateOptions","synthetic":false,"types":[]},{"text":"impl Clone for KeychainKind","synthetic":false,"types":[]},{"text":"impl Clone for FeeRate","synthetic":false,"types":[]},{"text":"impl Clone for UTXO","synthetic":false,"types":[]},{"text":"impl Clone for TransactionDetails","synthetic":false,"types":[]},{"text":"impl Clone for AddressValidatorError","synthetic":false,"types":[]},{"text":"impl Clone for SignerId","synthetic":false,"types":[]},{"text":"impl Clone for SignerError","synthetic":false,"types":[]},{"text":"impl Clone for SignerOrdering","synthetic":false,"types":[]},{"text":"impl Clone for SignersContainer","synthetic":false,"types":[]},{"text":"impl Clone for CreateTx","synthetic":false,"types":[]},{"text":"impl Clone for BumpFee","synthetic":false,"types":[]},{"text":"impl Clone for TxOrdering","synthetic":false,"types":[]},{"text":"impl Clone for ChangeSpendPolicy","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.Eq.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.Eq.js new file mode 100644 index 0000000000..7e8d7dc356 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.Eq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Eq for Capability","synthetic":false,"types":[]},{"text":"impl Eq for Condition","synthetic":false,"types":[]},{"text":"impl Eq for ScriptContextEnum","synthetic":false,"types":[]},{"text":"impl Eq for KeychainKind","synthetic":false,"types":[]},{"text":"impl Eq for UTXO","synthetic":false,"types":[]},{"text":"impl Eq for TransactionDetails","synthetic":false,"types":[]},{"text":"impl Eq for AddressValidatorError","synthetic":false,"types":[]},{"text":"impl Eq for SignerId","synthetic":false,"types":[]},{"text":"impl Eq for SignerError","synthetic":false,"types":[]},{"text":"impl Eq for SignerOrdering","synthetic":false,"types":[]},{"text":"impl Eq for TxOrdering","synthetic":false,"types":[]},{"text":"impl Eq for ChangeSpendPolicy","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.Ord.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.Ord.js new file mode 100644 index 0000000000..66d7a0f62f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.Ord.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Ord for Condition","synthetic":false,"types":[]},{"text":"impl Ord for SignerId","synthetic":false,"types":[]},{"text":"impl Ord for SignerOrdering","synthetic":false,"types":[]},{"text":"impl Ord for TxOrdering","synthetic":false,"types":[]},{"text":"impl Ord for ChangeSpendPolicy","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.PartialEq.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.PartialEq.js new file mode 100644 index 0000000000..31a908a5b9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.PartialEq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl PartialEq<Capability> for Capability","synthetic":false,"types":[]},{"text":"impl PartialEq<Condition> for Condition","synthetic":false,"types":[]},{"text":"impl PartialEq<ScriptContextEnum> for ScriptContextEnum","synthetic":false,"types":[]},{"text":"impl PartialEq<KeychainKind> for KeychainKind","synthetic":false,"types":[]},{"text":"impl PartialEq<FeeRate> for FeeRate","synthetic":false,"types":[]},{"text":"impl PartialEq<UTXO> for UTXO","synthetic":false,"types":[]},{"text":"impl PartialEq<TransactionDetails> for TransactionDetails","synthetic":false,"types":[]},{"text":"impl PartialEq<AddressValidatorError> for AddressValidatorError","synthetic":false,"types":[]},{"text":"impl PartialEq<SignerId> for SignerId","synthetic":false,"types":[]},{"text":"impl PartialEq<SignerError> for SignerError","synthetic":false,"types":[]},{"text":"impl PartialEq<SignerOrdering> for SignerOrdering","synthetic":false,"types":[]},{"text":"impl PartialEq<TxOrdering> for TxOrdering","synthetic":false,"types":[]},{"text":"impl PartialEq<ChangeSpendPolicy> for ChangeSpendPolicy","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.PartialOrd.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.PartialOrd.js new file mode 100644 index 0000000000..dd7d82b585 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.PartialOrd.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl PartialOrd<Condition> for Condition","synthetic":false,"types":[]},{"text":"impl PartialOrd<FeeRate> for FeeRate","synthetic":false,"types":[]},{"text":"impl PartialOrd<SignerId> for SignerId","synthetic":false,"types":[]},{"text":"impl PartialOrd<SignerOrdering> for SignerOrdering","synthetic":false,"types":[]},{"text":"impl PartialOrd<TxOrdering> for TxOrdering","synthetic":false,"types":[]},{"text":"impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/convert/trait.AsRef.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/convert/trait.AsRef.js new file mode 100644 index 0000000000..5b2db4abf7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/convert/trait.AsRef.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl AsRef<[u8]> for KeychainKind","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/convert/trait.From.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/convert/trait.From.js new file mode 100644 index 0000000000..3d6411eda8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/convert/trait.From.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<AddressValidatorError> for Error","synthetic":false,"types":[]},{"text":"impl From<PolicyError> for Error","synthetic":false,"types":[]},{"text":"impl From<SignerError> for Error","synthetic":false,"types":[]},{"text":"impl From<KeyError> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<EsploraError> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<CompactFiltersError> for Error","synthetic":false,"types":[]},{"text":"impl From<ElectrumBlockchain> for AnyBlockchain","synthetic":false,"types":[]},{"text":"impl From<EsploraBlockchain> for AnyBlockchain","synthetic":false,"types":[]},{"text":"impl From<CompactFiltersBlockchain> for AnyBlockchain","synthetic":false,"types":[]},{"text":"impl From<ElectrumBlockchainConfig> for AnyBlockchainConfig","synthetic":false,"types":[]},{"text":"impl From<EsploraBlockchainConfig> for AnyBlockchainConfig","synthetic":false,"types":[]},{"text":"impl From<CompactFiltersBlockchainConfig> for AnyBlockchainConfig","synthetic":false,"types":[]},{"text":"impl From<Client> for ElectrumBlockchain","synthetic":false,"types":[]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":[]},{"text":"impl From<ParseIntError> for EsploraError","synthetic":false,"types":[]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":[]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":[]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":[]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":[]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":[]},{"text":"impl From<SystemTimeError> for CompactFiltersError","synthetic":false,"types":[]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":[]},{"text":"impl From<MemoryDatabase> for AnyDatabase","synthetic":false,"types":[]},{"text":"impl From<Tree> for AnyDatabase","synthetic":false,"types":[]},{"text":"impl From<<MemoryDatabase as BatchDatabase>::Batch> for AnyBatch","synthetic":false,"types":[]},{"text":"impl From<<Tree as BatchDatabase>::Batch> for AnyBatch","synthetic":false,"types":[]},{"text":"impl From<()> for AnyDatabaseConfig","synthetic":false,"types":[]},{"text":"impl From<SledDbConfiguration> for AnyDatabaseConfig","synthetic":false,"types":[]},{"text":"impl From<KeyError> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<PolicyError> for Error","synthetic":false,"types":[]},{"text":"impl From<bool> for Satisfaction","synthetic":false,"types":[]},{"text":"impl From<SatisfiableItem> for Policy","synthetic":false,"types":[]},{"text":"impl From<Error> for KeyError","synthetic":false,"types":[]},{"text":"impl From<Error> for KeyError","synthetic":false,"types":[]},{"text":"impl From<Hash> for SignerId","synthetic":false,"types":[]},{"text":"impl From<Fingerprint> for SignerId","synthetic":false,"types":[]},{"text":"impl From<HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>> for SignersContainer","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/default/trait.Default.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/default/trait.Default.js new file mode 100644 index 0000000000..748e3f274e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/default/trait.Default.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Default for Mempool","synthetic":false,"types":[]},{"text":"impl Default for MemoryDatabase","synthetic":false,"types":[]},{"text":"impl Default for PKOrF","synthetic":false,"types":[]},{"text":"impl Default for Condition","synthetic":false,"types":[]},{"text":"impl Default for PrivateKeyGenerateOptions","synthetic":false,"types":[]},{"text":"impl Default for FeeRate","synthetic":false,"types":[]},{"text":"impl Default for TransactionDetails","synthetic":false,"types":[]},{"text":"impl Default for LargestFirstCoinSelection","synthetic":false,"types":[]},{"text":"impl Default for BranchAndBoundCoinSelection","synthetic":false,"types":[]},{"text":"impl Default for SignerOrdering","synthetic":false,"types":[]},{"text":"impl Default for SignersContainer","synthetic":false,"types":[]},{"text":"impl Default for CreateTx","synthetic":false,"types":[]},{"text":"impl Default for BumpFee","synthetic":false,"types":[]},{"text":"impl<D: Database, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext> Default for TxBuilder<D, Cs, Ctx> where
    Cs: Default, 
","synthetic":false,"types":[]},{"text":"impl Default for TxOrdering","synthetic":false,"types":[]},{"text":"impl Default for ChangeSpendPolicy","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/fmt/trait.Debug.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/fmt/trait.Debug.js new file mode 100644 index 0000000000..b3638c12d9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/fmt/trait.Debug.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Debug for Error","synthetic":false,"types":[]},{"text":"impl Debug for AnyBlockchainConfig","synthetic":false,"types":[]},{"text":"impl Debug for ElectrumBlockchainConfig","synthetic":false,"types":[]},{"text":"impl Debug for EsploraBlockchain","synthetic":false,"types":[]},{"text":"impl Debug for EsploraBlockchainConfig","synthetic":false,"types":[]},{"text":"impl Debug for EsploraError","synthetic":false,"types":[]},{"text":"impl Debug for Mempool","synthetic":false,"types":[]},{"text":"impl Debug for Peer","synthetic":false,"types":[]},{"text":"impl Debug for CompactFiltersBlockchain","synthetic":false,"types":[]},{"text":"impl Debug for BitcoinPeerConfig","synthetic":false,"types":[]},{"text":"impl Debug for CompactFiltersBlockchainConfig","synthetic":false,"types":[]},{"text":"impl Debug for CompactFiltersError","synthetic":false,"types":[]},{"text":"impl Debug for Capability","synthetic":false,"types":[]},{"text":"impl Debug for AnyDatabase","synthetic":false,"types":[]},{"text":"impl Debug for SledDbConfiguration","synthetic":false,"types":[]},{"text":"impl Debug for AnyDatabaseConfig","synthetic":false,"types":[]},{"text":"impl Debug for MemoryDatabase","synthetic":false,"types":[]},{"text":"impl Debug for Error","synthetic":false,"types":[]},{"text":"impl Debug for PKOrF","synthetic":false,"types":[]},{"text":"impl Debug for SatisfiableItem","synthetic":false,"types":[]},{"text":"impl Debug for Satisfaction","synthetic":false,"types":[]},{"text":"impl Debug for Policy","synthetic":false,"types":[]},{"text":"impl Debug for Condition","synthetic":false,"types":[]},{"text":"impl Debug for PolicyError","synthetic":false,"types":[]},{"text":"impl<Ctx: Debug + ScriptContext> Debug for DescriptorKey<Ctx>","synthetic":false,"types":[]},{"text":"impl Debug for ScriptContextEnum","synthetic":false,"types":[]},{"text":"impl Debug for PrivateKeyGenerateOptions","synthetic":false,"types":[]},{"text":"impl Debug for KeyError","synthetic":false,"types":[]},{"text":"impl Debug for KeychainKind","synthetic":false,"types":[]},{"text":"impl Debug for FeeRate","synthetic":false,"types":[]},{"text":"impl Debug for UTXO","synthetic":false,"types":[]},{"text":"impl Debug for TransactionDetails","synthetic":false,"types":[]},{"text":"impl Debug for AddressValidatorError","synthetic":false,"types":[]},{"text":"impl Debug for CoinSelectionResult","synthetic":false,"types":[]},{"text":"impl Debug for LargestFirstCoinSelection","synthetic":false,"types":[]},{"text":"impl Debug for BranchAndBoundCoinSelection","synthetic":false,"types":[]},{"text":"impl Debug for WalletExport","synthetic":false,"types":[]},{"text":"impl Debug for SignerId","synthetic":false,"types":[]},{"text":"impl Debug for SignerError","synthetic":false,"types":[]},{"text":"impl Debug for SignerOrdering","synthetic":false,"types":[]},{"text":"impl Debug for SignersContainer","synthetic":false,"types":[]},{"text":"impl Debug for CreateTx","synthetic":false,"types":[]},{"text":"impl Debug for BumpFee","synthetic":false,"types":[]},{"text":"impl<D: Debug + Database, Cs: Debug + CoinSelectionAlgorithm<D>, Ctx: Debug + TxBuilderContext> Debug for TxBuilder<D, Cs, Ctx>","synthetic":false,"types":[]},{"text":"impl Debug for TxOrdering","synthetic":false,"types":[]},{"text":"impl Debug for ChangeSpendPolicy","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/fmt/trait.Display.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/fmt/trait.Display.js new file mode 100644 index 0000000000..ce37b5523e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/fmt/trait.Display.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Display for Error","synthetic":false,"types":[]},{"text":"impl Display for EsploraError","synthetic":false,"types":[]},{"text":"impl Display for CompactFiltersError","synthetic":false,"types":[]},{"text":"impl Display for Error","synthetic":false,"types":[]},{"text":"impl Display for PolicyError","synthetic":false,"types":[]},{"text":"impl Display for KeyError","synthetic":false,"types":[]},{"text":"impl Display for AddressValidatorError","synthetic":false,"types":[]},{"text":"impl Display for SignerError","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/hash/trait.Hash.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/hash/trait.Hash.js new file mode 100644 index 0000000000..64f360015e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/hash/trait.Hash.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Hash for Capability","synthetic":false,"types":[]},{"text":"impl Hash for Condition","synthetic":false,"types":[]},{"text":"impl Hash for KeychainKind","synthetic":false,"types":[]},{"text":"impl Hash for SignerId","synthetic":false,"types":[]},{"text":"impl Hash for TxOrdering","synthetic":false,"types":[]},{"text":"impl Hash for ChangeSpendPolicy","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Copy.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Copy.js new file mode 100644 index 0000000000..243d52c881 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Copy.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Copy for Capability","synthetic":false,"types":[]},{"text":"impl Copy for Condition","synthetic":false,"types":[]},{"text":"impl Copy for ScriptContextEnum","synthetic":false,"types":[]},{"text":"impl Copy for PrivateKeyGenerateOptions","synthetic":false,"types":[]},{"text":"impl Copy for KeychainKind","synthetic":false,"types":[]},{"text":"impl Copy for FeeRate","synthetic":false,"types":[]},{"text":"impl Copy for TxOrdering","synthetic":false,"types":[]},{"text":"impl Copy for ChangeSpendPolicy","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Freeze.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Freeze.js new file mode 100644 index 0000000000..d8ca791082 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Freeze.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Freeze for Error","synthetic":true,"types":[]},{"text":"impl !Freeze for AnyBlockchain","synthetic":true,"types":[]},{"text":"impl Freeze for AnyBlockchainConfig","synthetic":true,"types":[]},{"text":"impl !Freeze for ElectrumBlockchain","synthetic":true,"types":[]},{"text":"impl Freeze for ElectrumBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Freeze for EsploraBlockchain","synthetic":true,"types":[]},{"text":"impl Freeze for EsploraBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Freeze for EsploraError","synthetic":true,"types":[]},{"text":"impl !Freeze for Mempool","synthetic":true,"types":[]},{"text":"impl Freeze for Peer","synthetic":true,"types":[]},{"text":"impl Freeze for CompactFiltersBlockchain","synthetic":true,"types":[]},{"text":"impl Freeze for BitcoinPeerConfig","synthetic":true,"types":[]},{"text":"impl Freeze for CompactFiltersBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Freeze for CompactFiltersError","synthetic":true,"types":[]},{"text":"impl Freeze for Capability","synthetic":true,"types":[]},{"text":"impl Freeze for OfflineBlockchain","synthetic":true,"types":[]},{"text":"impl Freeze for NoopProgress","synthetic":true,"types":[]},{"text":"impl Freeze for LogProgress","synthetic":true,"types":[]},{"text":"impl Freeze for AnyDatabase","synthetic":true,"types":[]},{"text":"impl Freeze for AnyBatch","synthetic":true,"types":[]},{"text":"impl Freeze for SledDbConfiguration","synthetic":true,"types":[]},{"text":"impl Freeze for AnyDatabaseConfig","synthetic":true,"types":[]},{"text":"impl Freeze for MemoryDatabase","synthetic":true,"types":[]},{"text":"impl Freeze for Error","synthetic":true,"types":[]},{"text":"impl Freeze for PKOrF","synthetic":true,"types":[]},{"text":"impl Freeze for SatisfiableItem","synthetic":true,"types":[]},{"text":"impl Freeze for Satisfaction","synthetic":true,"types":[]},{"text":"impl Freeze for Policy","synthetic":true,"types":[]},{"text":"impl Freeze for Condition","synthetic":true,"types":[]},{"text":"impl Freeze for PolicyError","synthetic":true,"types":[]},{"text":"impl<K> Freeze for P2PKH<K> where
    K: Freeze, 
","synthetic":true,"types":[]},{"text":"impl<K> Freeze for P2WPKH_P2SH<K> where
    K: Freeze, 
","synthetic":true,"types":[]},{"text":"impl<K> Freeze for P2WPKH<K> where
    K: Freeze, 
","synthetic":true,"types":[]},{"text":"impl<K> Freeze for BIP44<K> where
    K: Freeze, 
","synthetic":true,"types":[]},{"text":"impl<K> Freeze for BIP44Public<K> where
    K: Freeze, 
","synthetic":true,"types":[]},{"text":"impl<K> Freeze for BIP49<K> where
    K: Freeze, 
","synthetic":true,"types":[]},{"text":"impl<K> Freeze for BIP49Public<K> where
    K: Freeze, 
","synthetic":true,"types":[]},{"text":"impl<K> Freeze for BIP84<K> where
    K: Freeze, 
","synthetic":true,"types":[]},{"text":"impl<K> Freeze for BIP84Public<K> where
    K: Freeze, 
","synthetic":true,"types":[]},{"text":"impl<Ctx> Freeze for DescriptorKey<Ctx>","synthetic":true,"types":[]},{"text":"impl Freeze for ScriptContextEnum","synthetic":true,"types":[]},{"text":"impl<K, Ctx> Freeze for GeneratedKey<K, Ctx> where
    K: Freeze, 
","synthetic":true,"types":[]},{"text":"impl Freeze for PrivateKeyGenerateOptions","synthetic":true,"types":[]},{"text":"impl Freeze for KeyError","synthetic":true,"types":[]},{"text":"impl Freeze for KeychainKind","synthetic":true,"types":[]},{"text":"impl Freeze for FeeRate","synthetic":true,"types":[]},{"text":"impl Freeze for UTXO","synthetic":true,"types":[]},{"text":"impl Freeze for TransactionDetails","synthetic":true,"types":[]},{"text":"impl Freeze for AddressValidatorError","synthetic":true,"types":[]},{"text":"impl Freeze for CoinSelectionResult","synthetic":true,"types":[]},{"text":"impl Freeze for LargestFirstCoinSelection","synthetic":true,"types":[]},{"text":"impl Freeze for BranchAndBoundCoinSelection","synthetic":true,"types":[]},{"text":"impl Freeze for WalletExport","synthetic":true,"types":[]},{"text":"impl Freeze for SignerId","synthetic":true,"types":[]},{"text":"impl Freeze for SignerError","synthetic":true,"types":[]},{"text":"impl Freeze for SignerOrdering","synthetic":true,"types":[]},{"text":"impl Freeze for SignersContainer","synthetic":true,"types":[]},{"text":"impl Freeze for CreateTx","synthetic":true,"types":[]},{"text":"impl Freeze for BumpFee","synthetic":true,"types":[]},{"text":"impl<D, Cs, Ctx> Freeze for TxBuilder<D, Cs, Ctx> where
    Cs: Freeze, 
","synthetic":true,"types":[]},{"text":"impl Freeze for TxOrdering","synthetic":true,"types":[]},{"text":"impl Freeze for ChangeSpendPolicy","synthetic":true,"types":[]},{"text":"impl<B, D> !Freeze for Wallet<B, D>","synthetic":true,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Send.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Send.js new file mode 100644 index 0000000000..b500695f51 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Send.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Send for Error","synthetic":true,"types":[]},{"text":"impl Send for AnyBlockchain","synthetic":true,"types":[]},{"text":"impl Send for AnyBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Send for ElectrumBlockchain","synthetic":true,"types":[]},{"text":"impl Send for ElectrumBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Send for EsploraBlockchain","synthetic":true,"types":[]},{"text":"impl Send for EsploraBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Send for EsploraError","synthetic":true,"types":[]},{"text":"impl Send for Mempool","synthetic":true,"types":[]},{"text":"impl Send for Peer","synthetic":true,"types":[]},{"text":"impl Send for CompactFiltersBlockchain","synthetic":true,"types":[]},{"text":"impl Send for BitcoinPeerConfig","synthetic":true,"types":[]},{"text":"impl Send for CompactFiltersBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Send for CompactFiltersError","synthetic":true,"types":[]},{"text":"impl Send for Capability","synthetic":true,"types":[]},{"text":"impl Send for OfflineBlockchain","synthetic":true,"types":[]},{"text":"impl Send for NoopProgress","synthetic":true,"types":[]},{"text":"impl Send for LogProgress","synthetic":true,"types":[]},{"text":"impl !Send for AnyDatabase","synthetic":true,"types":[]},{"text":"impl !Send for AnyBatch","synthetic":true,"types":[]},{"text":"impl Send for SledDbConfiguration","synthetic":true,"types":[]},{"text":"impl Send for AnyDatabaseConfig","synthetic":true,"types":[]},{"text":"impl !Send for MemoryDatabase","synthetic":true,"types":[]},{"text":"impl Send for Error","synthetic":true,"types":[]},{"text":"impl Send for PKOrF","synthetic":true,"types":[]},{"text":"impl Send for SatisfiableItem","synthetic":true,"types":[]},{"text":"impl Send for Satisfaction","synthetic":true,"types":[]},{"text":"impl Send for Policy","synthetic":true,"types":[]},{"text":"impl Send for Condition","synthetic":true,"types":[]},{"text":"impl Send for PolicyError","synthetic":true,"types":[]},{"text":"impl<K> Send for P2PKH<K> where
    K: Send, 
","synthetic":true,"types":[]},{"text":"impl<K> Send for P2WPKH_P2SH<K> where
    K: Send, 
","synthetic":true,"types":[]},{"text":"impl<K> Send for P2WPKH<K> where
    K: Send, 
","synthetic":true,"types":[]},{"text":"impl<K> Send for BIP44<K> where
    K: Send, 
","synthetic":true,"types":[]},{"text":"impl<K> Send for BIP44Public<K> where
    K: Send, 
","synthetic":true,"types":[]},{"text":"impl<K> Send for BIP49<K> where
    K: Send, 
","synthetic":true,"types":[]},{"text":"impl<K> Send for BIP49Public<K> where
    K: Send, 
","synthetic":true,"types":[]},{"text":"impl<K> Send for BIP84<K> where
    K: Send, 
","synthetic":true,"types":[]},{"text":"impl<K> Send for BIP84Public<K> where
    K: Send, 
","synthetic":true,"types":[]},{"text":"impl<Ctx> Send for DescriptorKey<Ctx> where
    Ctx: Send, 
","synthetic":true,"types":[]},{"text":"impl Send for ScriptContextEnum","synthetic":true,"types":[]},{"text":"impl<K, Ctx> Send for GeneratedKey<K, Ctx> where
    Ctx: Send,
    K: Send, 
","synthetic":true,"types":[]},{"text":"impl Send for PrivateKeyGenerateOptions","synthetic":true,"types":[]},{"text":"impl Send for KeyError","synthetic":true,"types":[]},{"text":"impl Send for KeychainKind","synthetic":true,"types":[]},{"text":"impl Send for FeeRate","synthetic":true,"types":[]},{"text":"impl Send for UTXO","synthetic":true,"types":[]},{"text":"impl Send for TransactionDetails","synthetic":true,"types":[]},{"text":"impl Send for AddressValidatorError","synthetic":true,"types":[]},{"text":"impl Send for CoinSelectionResult","synthetic":true,"types":[]},{"text":"impl Send for LargestFirstCoinSelection","synthetic":true,"types":[]},{"text":"impl Send for BranchAndBoundCoinSelection","synthetic":true,"types":[]},{"text":"impl Send for WalletExport","synthetic":true,"types":[]},{"text":"impl Send for SignerId","synthetic":true,"types":[]},{"text":"impl Send for SignerError","synthetic":true,"types":[]},{"text":"impl Send for SignerOrdering","synthetic":true,"types":[]},{"text":"impl Send for SignersContainer","synthetic":true,"types":[]},{"text":"impl Send for CreateTx","synthetic":true,"types":[]},{"text":"impl Send for BumpFee","synthetic":true,"types":[]},{"text":"impl<D, Cs, Ctx> Send for TxBuilder<D, Cs, Ctx> where
    Cs: Send,
    Ctx: Send,
    D: Send, 
","synthetic":true,"types":[]},{"text":"impl Send for TxOrdering","synthetic":true,"types":[]},{"text":"impl Send for ChangeSpendPolicy","synthetic":true,"types":[]},{"text":"impl<B, D> Send for Wallet<B, D> where
    B: Send,
    D: Send, 
","synthetic":true,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.StructuralEq.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.StructuralEq.js new file mode 100644 index 0000000000..f127d77e7c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.StructuralEq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl StructuralEq for Capability","synthetic":false,"types":[]},{"text":"impl StructuralEq for Condition","synthetic":false,"types":[]},{"text":"impl StructuralEq for ScriptContextEnum","synthetic":false,"types":[]},{"text":"impl StructuralEq for KeychainKind","synthetic":false,"types":[]},{"text":"impl StructuralEq for UTXO","synthetic":false,"types":[]},{"text":"impl StructuralEq for TransactionDetails","synthetic":false,"types":[]},{"text":"impl StructuralEq for AddressValidatorError","synthetic":false,"types":[]},{"text":"impl StructuralEq for SignerId","synthetic":false,"types":[]},{"text":"impl StructuralEq for SignerError","synthetic":false,"types":[]},{"text":"impl StructuralEq for SignerOrdering","synthetic":false,"types":[]},{"text":"impl StructuralEq for TxOrdering","synthetic":false,"types":[]},{"text":"impl StructuralEq for ChangeSpendPolicy","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.StructuralPartialEq.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.StructuralPartialEq.js new file mode 100644 index 0000000000..76d66b9984 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.StructuralPartialEq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl StructuralPartialEq for Capability","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for Condition","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for ScriptContextEnum","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for KeychainKind","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for FeeRate","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for UTXO","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for TransactionDetails","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for AddressValidatorError","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for SignerId","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for SignerError","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for SignerOrdering","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for TxOrdering","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for ChangeSpendPolicy","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Sync.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Sync.js new file mode 100644 index 0000000000..a66b5513b1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Sync.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Sync for Error","synthetic":true,"types":[]},{"text":"impl Sync for AnyBlockchain","synthetic":true,"types":[]},{"text":"impl Sync for AnyBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Sync for ElectrumBlockchain","synthetic":true,"types":[]},{"text":"impl Sync for ElectrumBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Sync for EsploraBlockchain","synthetic":true,"types":[]},{"text":"impl Sync for EsploraBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Sync for EsploraError","synthetic":true,"types":[]},{"text":"impl Sync for Mempool","synthetic":true,"types":[]},{"text":"impl Sync for Peer","synthetic":true,"types":[]},{"text":"impl Sync for CompactFiltersBlockchain","synthetic":true,"types":[]},{"text":"impl Sync for BitcoinPeerConfig","synthetic":true,"types":[]},{"text":"impl Sync for CompactFiltersBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Sync for CompactFiltersError","synthetic":true,"types":[]},{"text":"impl Sync for Capability","synthetic":true,"types":[]},{"text":"impl Sync for OfflineBlockchain","synthetic":true,"types":[]},{"text":"impl Sync for NoopProgress","synthetic":true,"types":[]},{"text":"impl Sync for LogProgress","synthetic":true,"types":[]},{"text":"impl !Sync for AnyDatabase","synthetic":true,"types":[]},{"text":"impl !Sync for AnyBatch","synthetic":true,"types":[]},{"text":"impl Sync for SledDbConfiguration","synthetic":true,"types":[]},{"text":"impl Sync for AnyDatabaseConfig","synthetic":true,"types":[]},{"text":"impl !Sync for MemoryDatabase","synthetic":true,"types":[]},{"text":"impl Sync for Error","synthetic":true,"types":[]},{"text":"impl Sync for PKOrF","synthetic":true,"types":[]},{"text":"impl Sync for SatisfiableItem","synthetic":true,"types":[]},{"text":"impl Sync for Satisfaction","synthetic":true,"types":[]},{"text":"impl Sync for Policy","synthetic":true,"types":[]},{"text":"impl Sync for Condition","synthetic":true,"types":[]},{"text":"impl Sync for PolicyError","synthetic":true,"types":[]},{"text":"impl<K> Sync for P2PKH<K> where
    K: Sync, 
","synthetic":true,"types":[]},{"text":"impl<K> Sync for P2WPKH_P2SH<K> where
    K: Sync, 
","synthetic":true,"types":[]},{"text":"impl<K> Sync for P2WPKH<K> where
    K: Sync, 
","synthetic":true,"types":[]},{"text":"impl<K> Sync for BIP44<K> where
    K: Sync, 
","synthetic":true,"types":[]},{"text":"impl<K> Sync for BIP44Public<K> where
    K: Sync, 
","synthetic":true,"types":[]},{"text":"impl<K> Sync for BIP49<K> where
    K: Sync, 
","synthetic":true,"types":[]},{"text":"impl<K> Sync for BIP49Public<K> where
    K: Sync, 
","synthetic":true,"types":[]},{"text":"impl<K> Sync for BIP84<K> where
    K: Sync, 
","synthetic":true,"types":[]},{"text":"impl<K> Sync for BIP84Public<K> where
    K: Sync, 
","synthetic":true,"types":[]},{"text":"impl<Ctx> Sync for DescriptorKey<Ctx> where
    Ctx: Sync, 
","synthetic":true,"types":[]},{"text":"impl Sync for ScriptContextEnum","synthetic":true,"types":[]},{"text":"impl<K, Ctx> Sync for GeneratedKey<K, Ctx> where
    Ctx: Sync,
    K: Sync, 
","synthetic":true,"types":[]},{"text":"impl Sync for PrivateKeyGenerateOptions","synthetic":true,"types":[]},{"text":"impl Sync for KeyError","synthetic":true,"types":[]},{"text":"impl Sync for KeychainKind","synthetic":true,"types":[]},{"text":"impl Sync for FeeRate","synthetic":true,"types":[]},{"text":"impl Sync for UTXO","synthetic":true,"types":[]},{"text":"impl Sync for TransactionDetails","synthetic":true,"types":[]},{"text":"impl Sync for AddressValidatorError","synthetic":true,"types":[]},{"text":"impl Sync for CoinSelectionResult","synthetic":true,"types":[]},{"text":"impl Sync for LargestFirstCoinSelection","synthetic":true,"types":[]},{"text":"impl Sync for BranchAndBoundCoinSelection","synthetic":true,"types":[]},{"text":"impl Sync for WalletExport","synthetic":true,"types":[]},{"text":"impl Sync for SignerId","synthetic":true,"types":[]},{"text":"impl Sync for SignerError","synthetic":true,"types":[]},{"text":"impl Sync for SignerOrdering","synthetic":true,"types":[]},{"text":"impl Sync for SignersContainer","synthetic":true,"types":[]},{"text":"impl Sync for CreateTx","synthetic":true,"types":[]},{"text":"impl Sync for BumpFee","synthetic":true,"types":[]},{"text":"impl<D, Cs, Ctx> Sync for TxBuilder<D, Cs, Ctx> where
    Cs: Sync,
    Ctx: Sync,
    D: Sync, 
","synthetic":true,"types":[]},{"text":"impl Sync for TxOrdering","synthetic":true,"types":[]},{"text":"impl Sync for ChangeSpendPolicy","synthetic":true,"types":[]},{"text":"impl<B, D> !Sync for Wallet<B, D>","synthetic":true,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Unpin.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Unpin.js new file mode 100644 index 0000000000..4897f83303 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Unpin.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Unpin for Error","synthetic":true,"types":[]},{"text":"impl Unpin for AnyBlockchain","synthetic":true,"types":[]},{"text":"impl Unpin for AnyBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Unpin for ElectrumBlockchain","synthetic":true,"types":[]},{"text":"impl Unpin for ElectrumBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Unpin for EsploraBlockchain","synthetic":true,"types":[]},{"text":"impl Unpin for EsploraBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Unpin for EsploraError","synthetic":true,"types":[]},{"text":"impl Unpin for Mempool","synthetic":true,"types":[]},{"text":"impl Unpin for Peer","synthetic":true,"types":[]},{"text":"impl Unpin for CompactFiltersBlockchain","synthetic":true,"types":[]},{"text":"impl Unpin for BitcoinPeerConfig","synthetic":true,"types":[]},{"text":"impl Unpin for CompactFiltersBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Unpin for CompactFiltersError","synthetic":true,"types":[]},{"text":"impl Unpin for Capability","synthetic":true,"types":[]},{"text":"impl Unpin for OfflineBlockchain","synthetic":true,"types":[]},{"text":"impl Unpin for NoopProgress","synthetic":true,"types":[]},{"text":"impl Unpin for LogProgress","synthetic":true,"types":[]},{"text":"impl Unpin for AnyDatabase","synthetic":true,"types":[]},{"text":"impl Unpin for AnyBatch","synthetic":true,"types":[]},{"text":"impl Unpin for SledDbConfiguration","synthetic":true,"types":[]},{"text":"impl Unpin for AnyDatabaseConfig","synthetic":true,"types":[]},{"text":"impl Unpin for MemoryDatabase","synthetic":true,"types":[]},{"text":"impl Unpin for Error","synthetic":true,"types":[]},{"text":"impl Unpin for PKOrF","synthetic":true,"types":[]},{"text":"impl Unpin for SatisfiableItem","synthetic":true,"types":[]},{"text":"impl Unpin for Satisfaction","synthetic":true,"types":[]},{"text":"impl Unpin for Policy","synthetic":true,"types":[]},{"text":"impl Unpin for Condition","synthetic":true,"types":[]},{"text":"impl Unpin for PolicyError","synthetic":true,"types":[]},{"text":"impl<K> Unpin for P2PKH<K> where
    K: Unpin, 
","synthetic":true,"types":[]},{"text":"impl<K> Unpin for P2WPKH_P2SH<K> where
    K: Unpin, 
","synthetic":true,"types":[]},{"text":"impl<K> Unpin for P2WPKH<K> where
    K: Unpin, 
","synthetic":true,"types":[]},{"text":"impl<K> Unpin for BIP44<K> where
    K: Unpin, 
","synthetic":true,"types":[]},{"text":"impl<K> Unpin for BIP44Public<K> where
    K: Unpin, 
","synthetic":true,"types":[]},{"text":"impl<K> Unpin for BIP49<K> where
    K: Unpin, 
","synthetic":true,"types":[]},{"text":"impl<K> Unpin for BIP49Public<K> where
    K: Unpin, 
","synthetic":true,"types":[]},{"text":"impl<K> Unpin for BIP84<K> where
    K: Unpin, 
","synthetic":true,"types":[]},{"text":"impl<K> Unpin for BIP84Public<K> where
    K: Unpin, 
","synthetic":true,"types":[]},{"text":"impl<Ctx> Unpin for DescriptorKey<Ctx> where
    Ctx: Unpin, 
","synthetic":true,"types":[]},{"text":"impl Unpin for ScriptContextEnum","synthetic":true,"types":[]},{"text":"impl<K, Ctx> Unpin for GeneratedKey<K, Ctx> where
    Ctx: Unpin,
    K: Unpin, 
","synthetic":true,"types":[]},{"text":"impl Unpin for PrivateKeyGenerateOptions","synthetic":true,"types":[]},{"text":"impl Unpin for KeyError","synthetic":true,"types":[]},{"text":"impl Unpin for KeychainKind","synthetic":true,"types":[]},{"text":"impl Unpin for FeeRate","synthetic":true,"types":[]},{"text":"impl Unpin for UTXO","synthetic":true,"types":[]},{"text":"impl Unpin for TransactionDetails","synthetic":true,"types":[]},{"text":"impl Unpin for AddressValidatorError","synthetic":true,"types":[]},{"text":"impl Unpin for CoinSelectionResult","synthetic":true,"types":[]},{"text":"impl Unpin for LargestFirstCoinSelection","synthetic":true,"types":[]},{"text":"impl Unpin for BranchAndBoundCoinSelection","synthetic":true,"types":[]},{"text":"impl Unpin for WalletExport","synthetic":true,"types":[]},{"text":"impl Unpin for SignerId","synthetic":true,"types":[]},{"text":"impl Unpin for SignerError","synthetic":true,"types":[]},{"text":"impl Unpin for SignerOrdering","synthetic":true,"types":[]},{"text":"impl Unpin for SignersContainer","synthetic":true,"types":[]},{"text":"impl Unpin for CreateTx","synthetic":true,"types":[]},{"text":"impl Unpin for BumpFee","synthetic":true,"types":[]},{"text":"impl<D, Cs, Ctx> Unpin for TxBuilder<D, Cs, Ctx> where
    Cs: Unpin,
    Ctx: Unpin,
    D: Unpin, 
","synthetic":true,"types":[]},{"text":"impl Unpin for TxOrdering","synthetic":true,"types":[]},{"text":"impl Unpin for ChangeSpendPolicy","synthetic":true,"types":[]},{"text":"impl<B, D> Unpin for Wallet<B, D> where
    B: Unpin,
    D: Unpin, 
","synthetic":true,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/ops/deref/trait.Deref.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/ops/deref/trait.Deref.js new file mode 100644 index 0000000000..2f7bc5e869 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/ops/deref/trait.Deref.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl<K, Ctx: ScriptContext> Deref for GeneratedKey<K, Ctx>","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/str/traits/trait.FromStr.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/str/traits/trait.FromStr.js new file mode 100644 index 0000000000..b5dbd1e30a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/str/traits/trait.FromStr.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl FromStr for WalletExport","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/serde/de/trait.Deserialize.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/serde/de/trait.Deserialize.js new file mode 100644 index 0000000000..209a5d4358 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/serde/de/trait.Deserialize.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl<'de> Deserialize<'de> for AnyBlockchainConfig","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for ElectrumBlockchainConfig","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for EsploraBlockchainConfig","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for BitcoinPeerConfig","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for CompactFiltersBlockchainConfig","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for SledDbConfiguration","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for AnyDatabaseConfig","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for KeychainKind","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for UTXO","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for TransactionDetails","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for WalletExport","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/serde/ser/trait.Serialize.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/serde/ser/trait.Serialize.js new file mode 100644 index 0000000000..9429b901e9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/serde/ser/trait.Serialize.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Serialize for AnyBlockchainConfig","synthetic":false,"types":[]},{"text":"impl Serialize for ElectrumBlockchainConfig","synthetic":false,"types":[]},{"text":"impl Serialize for EsploraBlockchainConfig","synthetic":false,"types":[]},{"text":"impl Serialize for BitcoinPeerConfig","synthetic":false,"types":[]},{"text":"impl Serialize for CompactFiltersBlockchainConfig","synthetic":false,"types":[]},{"text":"impl Serialize for SledDbConfiguration","synthetic":false,"types":[]},{"text":"impl Serialize for AnyDatabaseConfig","synthetic":false,"types":[]},{"text":"impl Serialize for PKOrF","synthetic":false,"types":[]},{"text":"impl Serialize for SatisfiableItem","synthetic":false,"types":[]},{"text":"impl Serialize for Satisfaction","synthetic":false,"types":[]},{"text":"impl Serialize for Policy","synthetic":false,"types":[]},{"text":"impl Serialize for Condition","synthetic":false,"types":[]},{"text":"impl Serialize for KeychainKind","synthetic":false,"types":[]},{"text":"impl Serialize for UTXO","synthetic":false,"types":[]},{"text":"impl Serialize for TransactionDetails","synthetic":false,"types":[]},{"text":"impl Serialize for WalletExport","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/error/trait.Error.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/error/trait.Error.js new file mode 100644 index 0000000000..70a9b18acb --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/error/trait.Error.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Error for Error","synthetic":false,"types":[]},{"text":"impl Error for EsploraError","synthetic":false,"types":[]},{"text":"impl Error for CompactFiltersError","synthetic":false,"types":[]},{"text":"impl Error for Error","synthetic":false,"types":[]},{"text":"impl Error for PolicyError","synthetic":false,"types":[]},{"text":"impl Error for KeyError","synthetic":false,"types":[]},{"text":"impl Error for AddressValidatorError","synthetic":false,"types":[]},{"text":"impl Error for SignerError","synthetic":false,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/panic/trait.RefUnwindSafe.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/panic/trait.RefUnwindSafe.js new file mode 100644 index 0000000000..c48e9d7209 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/panic/trait.RefUnwindSafe.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl !RefUnwindSafe for Error","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for AnyBlockchain","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for AnyBlockchainConfig","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for ElectrumBlockchain","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for ElectrumBlockchainConfig","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for EsploraBlockchain","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for EsploraBlockchainConfig","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for EsploraError","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for Mempool","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for Peer","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for CompactFiltersBlockchain","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for BitcoinPeerConfig","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for CompactFiltersBlockchainConfig","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for CompactFiltersError","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for Capability","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for OfflineBlockchain","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for NoopProgress","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for LogProgress","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for AnyDatabase","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for AnyBatch","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for SledDbConfiguration","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for AnyDatabaseConfig","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for MemoryDatabase","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for Error","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for PKOrF","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for SatisfiableItem","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for Satisfaction","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for Policy","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for Condition","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for PolicyError","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for P2PKH<K> where
    K: RefUnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for P2WPKH_P2SH<K> where
    K: RefUnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for P2WPKH<K> where
    K: RefUnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for BIP44<K> where
    K: RefUnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for BIP44Public<K> where
    K: RefUnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for BIP49<K> where
    K: RefUnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for BIP49Public<K> where
    K: RefUnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for BIP84<K> where
    K: RefUnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for BIP84Public<K> where
    K: RefUnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<Ctx> RefUnwindSafe for DescriptorKey<Ctx> where
    Ctx: RefUnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for ScriptContextEnum","synthetic":true,"types":[]},{"text":"impl<K, Ctx> RefUnwindSafe for GeneratedKey<K, Ctx> where
    Ctx: RefUnwindSafe,
    K: RefUnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for PrivateKeyGenerateOptions","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for KeyError","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for KeychainKind","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for FeeRate","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for UTXO","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for TransactionDetails","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for AddressValidatorError","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for CoinSelectionResult","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for LargestFirstCoinSelection","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for BranchAndBoundCoinSelection","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for WalletExport","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for SignerId","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for SignerError","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for SignerOrdering","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for SignersContainer","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for CreateTx","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for BumpFee","synthetic":true,"types":[]},{"text":"impl<D, Cs, Ctx> RefUnwindSafe for TxBuilder<D, Cs, Ctx> where
    Cs: RefUnwindSafe,
    Ctx: RefUnwindSafe,
    D: RefUnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for TxOrdering","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for ChangeSpendPolicy","synthetic":true,"types":[]},{"text":"impl<B, D> !RefUnwindSafe for Wallet<B, D>","synthetic":true,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/panic/trait.UnwindSafe.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/panic/trait.UnwindSafe.js new file mode 100644 index 0000000000..a18b454332 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/panic/trait.UnwindSafe.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl !UnwindSafe for Error","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for AnyBlockchain","synthetic":true,"types":[]},{"text":"impl UnwindSafe for AnyBlockchainConfig","synthetic":true,"types":[]},{"text":"impl UnwindSafe for ElectrumBlockchain","synthetic":true,"types":[]},{"text":"impl UnwindSafe for ElectrumBlockchainConfig","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for EsploraBlockchain","synthetic":true,"types":[]},{"text":"impl UnwindSafe for EsploraBlockchainConfig","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for EsploraError","synthetic":true,"types":[]},{"text":"impl UnwindSafe for Mempool","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for Peer","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for CompactFiltersBlockchain","synthetic":true,"types":[]},{"text":"impl UnwindSafe for BitcoinPeerConfig","synthetic":true,"types":[]},{"text":"impl UnwindSafe for CompactFiltersBlockchainConfig","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for CompactFiltersError","synthetic":true,"types":[]},{"text":"impl UnwindSafe for Capability","synthetic":true,"types":[]},{"text":"impl UnwindSafe for OfflineBlockchain","synthetic":true,"types":[]},{"text":"impl UnwindSafe for NoopProgress","synthetic":true,"types":[]},{"text":"impl UnwindSafe for LogProgress","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for AnyDatabase","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for AnyBatch","synthetic":true,"types":[]},{"text":"impl UnwindSafe for SledDbConfiguration","synthetic":true,"types":[]},{"text":"impl UnwindSafe for AnyDatabaseConfig","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for MemoryDatabase","synthetic":true,"types":[]},{"text":"impl UnwindSafe for Error","synthetic":true,"types":[]},{"text":"impl UnwindSafe for PKOrF","synthetic":true,"types":[]},{"text":"impl UnwindSafe for SatisfiableItem","synthetic":true,"types":[]},{"text":"impl UnwindSafe for Satisfaction","synthetic":true,"types":[]},{"text":"impl UnwindSafe for Policy","synthetic":true,"types":[]},{"text":"impl UnwindSafe for Condition","synthetic":true,"types":[]},{"text":"impl UnwindSafe for PolicyError","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for P2PKH<K> where
    K: UnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for P2WPKH_P2SH<K> where
    K: UnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for P2WPKH<K> where
    K: UnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for BIP44<K> where
    K: UnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for BIP44Public<K> where
    K: UnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for BIP49<K> where
    K: UnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for BIP49Public<K> where
    K: UnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for BIP84<K> where
    K: UnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for BIP84Public<K> where
    K: UnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl<Ctx> UnwindSafe for DescriptorKey<Ctx> where
    Ctx: UnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl UnwindSafe for ScriptContextEnum","synthetic":true,"types":[]},{"text":"impl<K, Ctx> UnwindSafe for GeneratedKey<K, Ctx> where
    Ctx: UnwindSafe,
    K: UnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl UnwindSafe for PrivateKeyGenerateOptions","synthetic":true,"types":[]},{"text":"impl UnwindSafe for KeyError","synthetic":true,"types":[]},{"text":"impl UnwindSafe for KeychainKind","synthetic":true,"types":[]},{"text":"impl UnwindSafe for FeeRate","synthetic":true,"types":[]},{"text":"impl UnwindSafe for UTXO","synthetic":true,"types":[]},{"text":"impl UnwindSafe for TransactionDetails","synthetic":true,"types":[]},{"text":"impl UnwindSafe for AddressValidatorError","synthetic":true,"types":[]},{"text":"impl UnwindSafe for CoinSelectionResult","synthetic":true,"types":[]},{"text":"impl UnwindSafe for LargestFirstCoinSelection","synthetic":true,"types":[]},{"text":"impl UnwindSafe for BranchAndBoundCoinSelection","synthetic":true,"types":[]},{"text":"impl UnwindSafe for WalletExport","synthetic":true,"types":[]},{"text":"impl UnwindSafe for SignerId","synthetic":true,"types":[]},{"text":"impl UnwindSafe for SignerError","synthetic":true,"types":[]},{"text":"impl UnwindSafe for SignerOrdering","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for SignersContainer","synthetic":true,"types":[]},{"text":"impl UnwindSafe for CreateTx","synthetic":true,"types":[]},{"text":"impl UnwindSafe for BumpFee","synthetic":true,"types":[]},{"text":"impl<D, Cs, Ctx> UnwindSafe for TxBuilder<D, Cs, Ctx> where
    Cs: UnwindSafe,
    Ctx: UnwindSafe,
    D: UnwindSafe, 
","synthetic":true,"types":[]},{"text":"impl UnwindSafe for TxOrdering","synthetic":true,"types":[]},{"text":"impl UnwindSafe for ChangeSpendPolicy","synthetic":true,"types":[]},{"text":"impl<B, D> !UnwindSafe for Wallet<B, D>","synthetic":true,"types":[]}]; +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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/light.css b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/light.css new file mode 100644 index 0000000000..5a9d516b52 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/light.css @@ -0,0 +1 @@ + body{background-color:white;color:black;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:black;}h1.fqn{border-bottom-color:#D5D5D5;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){border-bottom-color:#DDDDDD;}.in-band{background-color:white;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#F5F5F5;}pre{background-color:#F5F5F5;}.sidebar{background-color:#F1F1F1;}*{scrollbar-color:rgba(36,37,39,0.6) #e6e6e6;}.sidebar{scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;}.logo-container.rust-logo>img{}::-webkit-scrollbar-track{background-color:#ecebeb;}::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar::-webkit-scrollbar-track{background-color:#dcdcdc;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar .current{background-color:#fff;}.source .sidebar{background-color:#fff;}.sidebar .location{border-color:#000;background-color:#fff;color:#333;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#F5F5F5;}.line-numbers span{color:#c67e2d;}.line-numbers .line-highlighted{background-color:#f6fdb0 !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#ddd;}.docblock table,.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#4E4C4C;}.content .highlighted{color:#000 !important;background-color:#ccc;}.content .highlighted a,.content .highlighted span{color:#000 !important;}.content .highlighted.trait{background-color:#c7b6ff;}.content .highlighted.traitalias{background-color:#c7b6ff;}.content .highlighted.mod,.content .highlighted.externcrate{background-color:#afc6e4;}.content .highlighted.enum{background-color:#b4d1b9;}.content .highlighted.struct{background-color:#e7b1a0;}.content .highlighted.union{background-color:#b7bd49;}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{background-color:#c6afb3;}.content .highlighted.type{background-color:#ffc891;}.content .highlighted.foreigntype{background-color:#f5c4ff;}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{background-color:#8ce488;}.content .highlighted.constant,.content .highlighted.static{background-color:#c3e0ff;}.content .highlighted.primitive{background-color:#9aecff;}.content .highlighted.keyword{background-color:#f99650;}.content .item-info::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#508157;}.content span.struct,.content a.struct,.block a.current.struct{color:#ad448e;}.content span.type,.content a.type,.block a.current.type{color:#ba5d00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#cd00e2;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#068000;}.content span.union,.content a.union,.block a.current.union{color:#767b27;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#546e8a;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#2c8093;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#4d76ae;}.content span.trait,.content a.trait,.block a.current.trait{color:#7c5af3;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#6841f1;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#9a6e31;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}pre.rust .comment{color:#8E908C;}pre.rust .doccomment{color:#4D4D4C;}nav:not(.sidebar){border-bottom-color:#e0e0e0;}nav.main .current{border-top-color:#000;border-bottom-color:#000;}nav.main .separator{border:1px solid #000;}a{color:#000;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.item-info a,#help a{color:#3873AD;}a.test-arrow{color:#f5f5f5;}.collapse-toggle{color:#999;}#crate-search{color:#555;background-color:white;border-color:#e0e0e0;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input{color:#555;background-color:white;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input:focus{border-color:#66afe9;}.search-focus:disabled{background-color:#e6e6e6;}#crate-search+.search-input:focus{box-shadow:0 0 8px #078dd8;}.module-item .stab{color:#000;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;}.stab.deprecated{background:#F3DFFF;border-color:#7F0087;}.stab.portability{background:#C4ECFF;border-color:#7BA5DB;}.stab.portability>code{color:#000;}#help>div{background:#e9e9e9;border-color:#bfbfbf;}#help>div>span{border-bottom-color:#bfbfbf;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:black;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#8959A8;}pre.rust .kw-2,pre.rust .prelude-ty{color:#4271AE;}pre.rust .number,pre.rust .string{color:#718C00;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#C82829;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#B76514;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#c7c7c7;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label{color:#999;}:target>code,:target>.in-band{background:#FDFFD3;border-right:3px solid #ffb44c;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.5);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.5);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.5);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip .tooltiptext{background-color:#000;color:#fff;}.tooltip .tooltiptext::after{border-color:transparent black transparent transparent;}.notable-traits-tooltiptext{background-color:#eee;border-color:#999;}#titles>button:not(.selected){background-color:#e6e6e6;border-top-color:#e6e6e6;}#titles>button:hover,#titles>button.selected{background-color:#ffffff;border-top-color:#0089ff;}#titles>button>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#F1F1F1;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#F1F1F1;border-right-color:#000;}#sidebar-filler{background-color:#F1F1F1;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu,.help-button{border-color:#e0e0e0;background-color:#fff;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus,.help-button:hover,.help-button:focus{border-color:#717171;}#theme-choices{border-color:#ccc;background-color:#fff;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#eee;}@media (max-width:700px){#theme-picker{background:#fff;}}#all-types{background-color:#fff;}#all-types:hover{background-color:#f9f9f9;}.search-results td span.alias{color:#000;}.search-results td span.grey{color:#999;}#sidebar-toggle{background-color:#F1F1F1;}#sidebar-toggle:hover{background-color:#E0E0E0;}#source-sidebar{background-color:#F1F1F1;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#E0E0E0;}div.files>.selected{background-color:#fff;}.setting-line>.title{border-bottom-color:#D5D5D5;} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/main.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/main.js new file mode 100644 index 0000000000..03cfb2cc39 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/main.js @@ -0,0 +1,8 @@ +if(!String.prototype.startsWith){String.prototype.startsWith=function(searchString,position){position=position||0;return this.indexOf(searchString,position)===position}}if(!String.prototype.endsWith){String.prototype.endsWith=function(suffix,length){var l=length||this.length;return this.indexOf(suffix,l-suffix.length)!==-1}}if(!DOMTokenList.prototype.add){DOMTokenList.prototype.add=function(className){if(className&&!hasClass(this,className)){if(this.className&&this.className.length>0){this.className+=" "+className}else{this.className=className}}}}if(!DOMTokenList.prototype.remove){DOMTokenList.prototype.remove=function(className){if(className&&this.className){this.className=(" "+this.className+" ").replace(" "+className+" "," ").trim()}}}function getVirtualKey(ev){if("key"in ev&&typeof ev.key!="undefined"){return ev.key}var c=ev.charCode||ev.keyCode;if(c==27){return"Escape"}return String.fromCharCode(c)}function getSearchInput(){return document.getElementsByClassName("search-input")[0]}function getSearchElement(){return document.getElementById("search")}function getThemesElement(){return document.getElementById("theme-choices")}function getThemePickerElement(){return document.getElementById("theme-picker")}function focusSearchBar(){getSearchInput().focus()}function defocusSearchBar(){getSearchInput().blur()}(function(){"use strict";var itemTypes=["mod","externcrate","import","struct","enum","fn","type","static","trait","impl","tymethod","method","structfield","variant","macro","primitive","associatedtype","constant","associatedconstant","union","foreigntype","keyword","existential","attr","derive","traitalias"];var disableShortcuts=getSettingValue("disable-shortcuts")==="true";var search_input=getSearchInput();var searchTimeout=null;var toggleAllDocsId="toggle-all-docs";var currentTab=0;var mouseMovedAfterSearch=true;var titleBeforeSearch=document.title;var searchTitle=null;function clearInputTimeout(){if(searchTimeout!==null){clearTimeout(searchTimeout);searchTimeout=null}}function getPageId(){if(window.location.hash){var tmp=window.location.hash.replace(/^#/,"");if(tmp.length>0){return tmp}}return null}function showSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){addClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];if(sidebar){addClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(!filler){var div=document.createElement("div");div.id="sidebar-filler";sidebar.appendChild(div)}}}function hideSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){removeClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(filler){filler.remove()}document.getElementsByTagName("body")[0].style.marginTop=""}function showSearchResults(search){if(search===null||typeof search==='undefined'){search=getSearchElement()}addClass(main,"hidden");removeClass(search,"hidden");mouseMovedAfterSearch=false;document.title=searchTitle}function hideSearchResults(search){if(search===null||typeof search==='undefined'){search=getSearchElement()}addClass(search,"hidden");removeClass(main,"hidden");document.title=titleBeforeSearch}var TY_PRIMITIVE=itemTypes.indexOf("primitive");var TY_KEYWORD=itemTypes.indexOf("keyword");function getQueryStringParams(){var params={};window.location.search.substring(1).split("&").map(function(s){var pair=s.split("=");params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params}function browserSupportsHistoryApi(){return window.history&&typeof window.history.pushState==="function"}function isHidden(elem){return elem.offsetHeight===0}var main=document.getElementById("main");var savedHash="";function handleHashes(ev){var elem;var search=getSearchElement();if(ev!==null&&search&&!hasClass(search,"hidden")&&ev.newURL){hideSearchResults(search);var hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(browserSupportsHistoryApi()){history.replaceState(hash,"","?search=#"+hash)}elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}if(savedHash!==window.location.hash){savedHash=window.location.hash;if(savedHash.length===0){return}elem=document.getElementById(savedHash.slice(1));if(!elem||!isHidden(elem)){return}var parent=elem.parentNode;if(parent&&hasClass(parent,"impl-items")){onEachLazy(parent.getElementsByClassName("collapsed"),function(e){if(e.parentNode===parent){e.click();return true}});if(isHidden(elem)){if(hasClass(parent.lastElementChild,"collapse-toggle")){parent.lastElementChild.click()}}}}}function highlightSourceLines(match,ev){if(typeof match==="undefined"){hideSidebar();match=window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/)}if(!match){return}var from=parseInt(match[1],10);var to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(to0){collapseDocs(collapses[0],"show")}}}}function getHelpElement(){buildHelperPopup();return document.getElementById("help")}function displayHelp(display,ev,help){help=help?help:getHelpElement();if(display===true){if(hasClass(help,"hidden")){ev.preventDefault();removeClass(help,"hidden");addClass(document.body,"blur")}}else if(hasClass(help,"hidden")===false){ev.preventDefault();addClass(help,"hidden");removeClass(document.body,"blur")}}function handleEscape(ev){var help=getHelpElement();var search=getSearchElement();if(hasClass(help,"hidden")===false){displayHelp(false,ev,help)}else if(hasClass(search,"hidden")===false){clearInputTimeout();ev.preventDefault();hideSearchResults(search)}defocusSearchBar();hideThemeButtonState()}function handleShortcut(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts===true){return}if(document.activeElement.tagName==="INPUT"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":displayHelp(false,ev);ev.preventDefault();focusSearchBar();break;case"+":case"-":ev.preventDefault();toggleAllDocs();break;case"?":displayHelp(true,ev);break;case"t":case"T":displayHelp(false,ev);ev.preventDefault();var themePicker=getThemePickerElement();themePicker.click();themePicker.focus();break;default:var themePicker=getThemePickerElement();if(themePicker.parentNode.contains(ev.target)){handleThemeKeyDown(ev)}}}}function handleThemeKeyDown(ev){var active=document.activeElement;var themes=getThemesElement();switch(getVirtualKey(ev)){case"ArrowUp":ev.preventDefault();if(active.previousElementSibling&&ev.target.id!=="theme-picker"){active.previousElementSibling.focus()}else{showThemeButtonState();themes.lastElementChild.focus()}break;case"ArrowDown":ev.preventDefault();if(active.nextElementSibling&&ev.target.id!=="theme-picker"){active.nextElementSibling.focus()}else{showThemeButtonState();themes.firstElementChild.focus()}break;case"Enter":case"Return":case"Space":if(ev.target.id==="theme-picker"&&themes.style.display==="none"){ev.preventDefault();showThemeButtonState();themes.firstElementChild.focus()}break;case"Home":ev.preventDefault();themes.firstElementChild.focus();break;case"End":ev.preventDefault();themes.lastElementChild.focus();break}}function findParentElement(elem,tagName){do{if(elem&&elem.tagName===tagName){return elem}elem=elem.parentNode}while(elem);return null}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);function resetMouseMoved(ev){mouseMovedAfterSearch=true}document.addEventListener("mousemove",resetMouseMoved);var handleSourceHighlight=(function(){var prev_line_id=0;var set_fragment=function(name){var x=window.scrollX,y=window.scrollY;if(browserSupportsHistoryApi()){history.replaceState(null,null,"#"+name);highlightSourceLines()}else{location.replace("#"+name)}window.scrollTo(x,y)};return function(ev){var cur_line_id=parseInt(ev.target.id,10);ev.preventDefault();if(ev.shiftKey&&prev_line_id){if(prev_line_id>cur_line_id){var tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());document.addEventListener("click",function(ev){if(hasClass(ev.target,"help-button")){displayHelp(true,ev)}else if(hasClass(ev.target,"collapse-toggle")){collapseDocs(ev.target,"toggle")}else if(hasClass(ev.target.parentNode,"collapse-toggle")){collapseDocs(ev.target.parentNode,"toggle")}else if(ev.target.tagName==="SPAN"&&hasClass(ev.target.parentNode,"line-numbers")){handleSourceHighlight(ev)}else if(hasClass(getHelpElement(),"hidden")===false){var help=getHelpElement();var is_inside_help_popup=ev.target!==help&&help.contains(ev.target);if(is_inside_help_popup===false){addClass(help,"hidden");removeClass(document.body,"blur")}}else{var a=findParentElement(ev.target,"A");if(a&&a.hash){expandSection(a.hash.replace(/^#/,""))}}});(function(){var x=document.getElementsByClassName("version-selector");if(x.length>0){x[0].onchange=function(){var i,match,url=document.location.href,stripped="",len=rootPath.match(/\.\.\//g).length+1;for(i=0;i-1){var obj=searchIndex[results[i].id];obj.lev=results[i].lev;if(isType!==true||obj.type){var res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=obj.displayPath+obj.name;obj.fullPath+="|"+obj.ty;obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}}return out}function sortResults(results,isType){var ar=[];for(var entry in results){if(hasOwnProperty(results,entry)){ar.push(results[entry])}}results=ar;var i;var nresults=results.length;for(i=0;ib?+1:-1)}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}if((aaa.item.ty===TY_PRIMITIVE&&bbb.item.ty!==TY_KEYWORD)||(aaa.item.ty===TY_KEYWORD&&bbb.item.ty!==TY_PRIMITIVE)){return-1}if((bbb.item.ty===TY_PRIMITIVE&&aaa.item.ty!==TY_PRIMITIVE)||(bbb.item.ty===TY_KEYWORD&&aaa.item.ty!==TY_KEYWORD)){return 1}a=(aaa.item.desc==="");b=(bbb.item.desc==="");if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});var length=results.length;for(i=0;i"));return{name:val.substring(0,val.indexOf("<")),generics:values.split(/\s*,\s*/),}}return{name:val,generics:[],}}function getObjectFromId(id){if(typeof id==="number"){return searchIndex[id]}return{'name':id}}function checkGenerics(obj,val){var lev_distance=MAX_LEV_DISTANCE+1;if(val.generics.length>0){if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>=val.generics.length){var elems=obj[GENERICS_DATA].slice(0);var total=0;var done=0;var vlength=val.generics.length;for(var y=0;yGENERICS_DATA&&obj[GENERICS_DATA].length>=val.generics.length){var elems=obj[GENERICS_DATA].slice(0);var allFound=true;for(var y=0;allFound===true&&yGENERICS_DATA&&obj[GENERICS_DATA].length!==0){var tmp_lev=checkGenerics(obj,val);if(tmp_lev<=MAX_LEV_DISTANCE){return tmp_lev}}else{return 0}}if(literalSearch===true){if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>0){var length=obj[GENERICS_DATA].length;for(x=0;xGENERICS_DATA&&obj[GENERICS_DATA].length>0){var olength=obj[GENERICS_DATA].length;for(x=0;x0){var length=obj.type[INPUTS_DATA].length;for(var i=0;iOUTPUT_DATA){var ret=obj.type[OUTPUT_DATA];if(typeof ret[0]==="string"){ret=[ret]}for(var x=0;xlength){return MAX_LEV_DISTANCE+1}for(var i=0;ilength){break}var lev_total=0;var aborted=false;for(var x=0;xMAX_LEV_DISTANCE){aborted=true;break}lev_total+=lev}if(aborted===false){ret_lev=Math.min(ret_lev,Math.round(lev_total/clength))}}return ret_lev}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER)return true;if(filter===type)return true;var name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function generateId(ty){if(ty.parent&&ty.parent.name){return itemTypes[ty.ty]+ty.path+ty.parent.name+ty.name}return itemTypes[ty.ty]+ty.path+ty.name}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,desc:item.desc,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,}}function handleAliases(ret,query,filterCrates){var aliases=[];var crateAliases=[];var i;if(filterCrates!==undefined){if(ALIASES[filterCrates]&&ALIASES[filterCrates][query.search]){for(i=0;iMAX_RESULTS){ret.others.pop()}};onEach(aliases,pushFunc);onEach(crateAliases,pushFunc)}var nSearchWords=searchWords.length;var i;var ty;var fullId;var returned;var in_args;if((val.charAt(0)==="\""||val.charAt(0)==="'")&&val.charAt(val.length-1)===val.charAt(0)){val=extractGenerics(val.substr(1,val.length-2));for(i=0;i")>-1){var trimmer=function(s){return s.trim()};var parts=val.split("->").map(trimmer);var input=parts[0];var inputs=input.split(",").map(trimmer).sort();for(i=0;i1?paths.length-1:1);var lev;for(j=0;j1){lev=checkPath(contains,paths[paths.length-1],ty);if(lev>MAX_LEV_DISTANCE){continue}else if(lev>0){lev_add=lev/10}}returned=MAX_LEV_DISTANCE+1;in_args=MAX_LEV_DISTANCE+1;var index=-1;lev=MAX_LEV_DISTANCE+1;fullId=generateId(ty);if(searchWords[j].indexOf(split[i])>-1||searchWords[j].indexOf(val)>-1||searchWords[j].replace(/_/g,"").indexOf(val)>-1){if(typePassesFilter(typeFilter,ty.ty)&&results[fullId]===undefined){index=searchWords[j].replace(/_/g,"").indexOf(val)}}if((lev=levenshtein(searchWords[j],val))<=MAX_LEV_DISTANCE){if(typePassesFilter(typeFilter,ty.ty)===false){lev=MAX_LEV_DISTANCE+1}else{lev+=1}}in_args=findArg(ty,valGenerics,false,typeFilter);returned=checkReturned(ty,valGenerics,false,typeFilter);lev+=lev_add;if(lev>0&&val.length>3&&searchWords[j].indexOf(val)>-1){if(val.length<6){lev-=1}else{lev=0}}if(in_args<=MAX_LEV_DISTANCE){if(results_in_args[fullId]===undefined){results_in_args[fullId]={id:j,index:index,lev:in_args,}}results_in_args[fullId].lev=Math.min(results_in_args[fullId].lev,in_args)}if(returned<=MAX_LEV_DISTANCE){if(results_returned[fullId]===undefined){results_returned[fullId]={id:j,index:index,lev:returned,}}results_returned[fullId].lev=Math.min(results_returned[fullId].lev,returned)}if(index!==-1||lev<=MAX_LEV_DISTANCE){if(index!==-1&&paths.length<2){lev=0}if(results[fullId]===undefined){results[fullId]={id:j,index:index,lev:lev,}}results[fullId].lev=Math.min(results[fullId].lev,lev)}}}var ret={"in_args":sortResults(results_in_args,true),"returned":sortResults(results_returned,true),"others":sortResults(results),};handleAliases(ret,query,filterCrates);return ret}function validateResult(name,path,keys,parent){for(var i=0;i-1||path.indexOf(keys[i])>-1||(parent!==undefined&&parent.name!==undefined&&parent.name.toLowerCase().indexOf(keys[i])>-1)||levenshtein(name,keys[i])<=MAX_LEV_DISTANCE)){return false}}return true}function getQuery(raw){var matches,type,query;query=raw;matches=query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);if(matches){type=matches[1].replace(/^const$/,"constant");query=query.substring(matches[0].length)}return{raw:raw,query:query,type:type,id:query+type}}function initSearchNav(){var hoverTimeout;var click_func=function(e){var el=e.target;while(el.tagName!=="TR"){el=el.parentNode}var dst=e.target.getElementsByTagName("a");if(dst.length<1){return}dst=dst[0];if(window.location.pathname===dst.pathname){hideSearchResults();document.location.href=dst.href}};var mouseover_func=function(e){if(mouseMovedAfterSearch){var el=e.target;while(el.tagName!=="TR"){el=el.parentNode}clearTimeout(hoverTimeout);hoverTimeout=setTimeout(function(){onEachLazy(document.getElementsByClassName("search-results"),function(e){onEachLazy(e.getElementsByClassName("result"),function(i_e){removeClass(i_e,"highlighted")})});addClass(el,"highlighted")},20)}};onEachLazy(document.getElementsByClassName("search-results"),function(e){onEachLazy(e.getElementsByClassName("result"),function(i_e){i_e.onclick=click_func;i_e.onmouseover=mouseover_func})});search_input.onkeydown=function(e){var actives=[[],[],[]];var current=0;onEachLazy(document.getElementById("results").childNodes,function(e){onEachLazy(e.getElementsByClassName("highlighted"),function(h_e){actives[current].push(h_e)});current+=1});if(e.which===38){if(e.ctrlKey){printTab(currentTab>0?currentTab-1:2)}else{if(!actives[currentTab].length||!actives[currentTab][0].previousElementSibling){return}addClass(actives[currentTab][0].previousElementSibling,"highlighted");removeClass(actives[currentTab][0],"highlighted")}e.preventDefault()}else if(e.which===40){if(e.ctrlKey){printTab(currentTab>1?0:currentTab+1)}else if(!actives[currentTab].length){var results=document.getElementById("results").childNodes;if(results.length>0){var res=results[currentTab].getElementsByClassName("result");if(res.length>0){addClass(res[0],"highlighted")}}}else if(actives[currentTab][0].nextElementSibling){addClass(actives[currentTab][0].nextElementSibling,"highlighted");removeClass(actives[currentTab][0],"highlighted")}e.preventDefault()}else if(e.which===13){if(actives[currentTab].length){document.location.href=actives[currentTab][0].getElementsByTagName("a")[0].href}}else if(e.which===16){}else if(actives[currentTab].length>0){removeClass(actives[currentTab][0],"highlighted")}}}function buildHrefAndPath(item){var displayPath;var href;var type=itemTypes[item.ty];var name=item.name;var path=item.path;if(type==="mod"){displayPath=path+"::";href=rootPath+path.replace(/::/g,"/")+"/"+name+"/index.html"}else if(type==="primitive"||type==="keyword"){displayPath="";href=rootPath+path.replace(/::/g,"/")+"/"+type+"."+name+".html"}else if(type==="externcrate"){displayPath="";href=rootPath+name+"/index.html"}else if(item.parent!==undefined){var myparent=item.parent;var anchor="#"+type+"."+name;var parentType=itemTypes[myparent.ty];var pageType=parentType;var pageName=myparent.name;if(parentType==="primitive"){displayPath=myparent.name+"::"}else if(type==="structfield"&&parentType==="variant"){var splitPath=item.path.split("::");var enumName=splitPath.pop();path=splitPath.join("::");displayPath=path+"::"+enumName+"::"+myparent.name+"::";anchor="#variant."+myparent.name+".field."+name;pageType="enum";pageName=enumName}else{displayPath=path+"::"+myparent.name+"::"}href=rootPath+path.replace(/::/g,"/")+"/"+pageType+"."+pageName+".html"+anchor}else{displayPath=item.path+"::";href=rootPath+item.path.replace(/::/g,"/")+"/"+type+"."+name+".html"}return[displayPath,href]}function escape(content){var h1=document.createElement("h1");h1.textContent=content;return h1.innerHTML}function pathSplitter(path){var tmp=""+path.replace(/::/g,"::");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}function addTab(array,query,display){var extraStyle="";if(display===false){extraStyle=" style=\"display: none;\""}var output="";var duplicates={};var length=0;if(array.length>0){output="";array.forEach(function(item){var name,type;name=item.name;type=itemTypes[item.ty];if(item.is_alias!==true){if(duplicates[item.fullPath]){return}duplicates[item.fullPath]=true}length+=1;output+=""});output+="
"+""+(item.is_alias===true?(""+item.alias+"  - see "):"")+item.displayPath+""+name+""+""+""+item.desc+" 
"}else{output="
No results :(
"+"Try on DuckDuckGo?

"+"Or try looking in one of these:
"}return[output,length]}function makeTabHeader(tabNb,text,nbElems){if(currentTab===tabNb){return""}return""}function showResults(results){var search=getSearchElement();if(results.others.length===1&&getSettingValue("go-to-only-result")==="true"&&(!search.firstChild||search.firstChild.innerText!==getSearchLoadingText())){var elem=document.createElement("a");elem.href=results.others[0].href;elem.style.display="none";document.body.appendChild(elem);elem.click();return}var query=getQuery(search_input.value);currentResults=query.id;var ret_others=addTab(results.others,query);var ret_in_args=addTab(results.in_args,query,false);var ret_returned=addTab(results.returned,query,false);var output="

Results for "+escape(query.query)+(query.type?" (type: "+escape(query.type)+")":"")+"

"+"
"+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
"+ret_others[0]+ret_in_args[0]+ret_returned[0]+"
";search.innerHTML=output;showSearchResults(search);var tds=search.getElementsByTagName("td");var td_width=0;if(tds.length>0){td_width=tds[0].offsetWidth}var width=search.offsetWidth-40-td_width;onEachLazy(search.getElementsByClassName("desc"),function(e){e.style.width=width+"px"});initSearchNav();var elems=document.getElementById("titles").childNodes;elems[0].onclick=function(){printTab(0)};elems[1].onclick=function(){printTab(1)};elems[2].onclick=function(){printTab(2)};printTab(currentTab)}function execSearch(query,searchWords,filterCrates){function getSmallest(arrays,positions,notDuplicates){var start=null;for(var it=0;itpositions[it]&&(start===null||start>arrays[it][positions[it]].lev)&&!notDuplicates[arrays[it][positions[it]].fullPath]){start=arrays[it][positions[it]].lev}}return start}function mergeArrays(arrays){var ret=[];var positions=[];var notDuplicates={};for(var x=0;xpositions[x]&&arrays[x][positions[x]].lev===smallest&&!notDuplicates[arrays[x][positions[x]].fullPath]){ret.push(arrays[x][positions[x]]);notDuplicates[arrays[x][positions[x]].fullPath]=true;positions[x]+=1}}}return ret}var queries=query.raw.split(",");var results={"in_args":[],"returned":[],"others":[],};for(var i=0;i1){return{"in_args":mergeArrays(results.in_args),"returned":mergeArrays(results.returned),"others":mergeArrays(results.others),}}return{"in_args":results.in_args[0],"returned":results.returned[0],"others":results.others[0],}}function getFilterCrates(){var elem=document.getElementById("crate-search");if(elem&&elem.value!=="All crates"&&hasOwnProperty(rawSearchIndex,elem.value)){return elem.value}return undefined}function search(e,forced){var params=getQueryStringParams();var query=getQuery(search_input.value.trim());if(e){e.preventDefault()}if(query.query.length===0){return}if(forced!==true&&query.id===currentResults){if(query.query.length>0){putBackSearch(search_input)}return}searchTitle="Results for "+query.query+" - Rust";if(browserSupportsHistoryApi()){if(!history.state&&!params.search){history.pushState(query,"","?search="+encodeURIComponent(query.raw))}else{history.replaceState(query,"","?search="+encodeURIComponent(query.raw))}}var filterCrates=getFilterCrates();showResults(execSearch(query,index,filterCrates))}function buildIndex(rawSearchIndex){searchIndex=[];var searchWords=[];var i;var currentIndex=0;for(var crate in rawSearchIndex){if(!hasOwnProperty(rawSearchIndex,crate)){continue}var crateSize=0;searchWords.push(crate);searchIndex.push({crate:crate,ty:1,name:crate,path:"",desc:rawSearchIndex[crate].doc,type:null,});currentIndex+=1;var items=rawSearchIndex[crate].i;var paths=rawSearchIndex[crate].p;var aliases=rawSearchIndex[crate].a;var len=paths.length;for(i=0;i0){search_input.value=params.search;search(e)}else{search_input.value="";hideSearchResults()}})}search()}index=buildIndex(rawSearchIndex);startSearch();if(rootPath==="../"||rootPath==="./"){var sidebar=document.getElementsByClassName("sidebar-elems")[0];if(sidebar){var div=document.createElement("div");div.className="block crate";div.innerHTML="

Crates

";var ul=document.createElement("ul");div.appendChild(ul);var crates=[];for(var crate in rawSearchIndex){if(!hasOwnProperty(rawSearchIndex,crate)){continue}crates.push(crate)}crates.sort();for(var i=0;i','`').replace('','`');return x.innerText}window.initSidebarItems=function(items){var sidebar=document.getElementsByClassName("sidebar-elems")[0];var current=window.sidebarCurrent;function block(shortty,longty){var filtered=items[shortty];if(!filtered){return}var div=document.createElement("div");div.className="block "+shortty;var h3=document.createElement("h3");h3.textContent=longty;div.appendChild(h3);var ul=document.createElement("ul");var length=filtered.length;for(var i=0;i"+""+"
"+code.outerHTML+"
";list.appendChild(display)}}};if(window.pending_implementors){window.register_implementors(window.pending_implementors)}function labelForToggleButton(sectionIsCollapsed){if(sectionIsCollapsed){return"+"}return"\u2212"}function onEveryMatchingChild(elem,className,func){if(elem&&className&&func){var length=elem.childNodes.length;var nodes=elem.childNodes;for(var i=0;i"+labelForToggleButton(sectionIsCollapsed)+"
]";return toggle}function createToggle(toggle,otherMessage,fontSize,extraClass,show){var span=document.createElement("span");span.className="toggle-label";if(show){span.style.display="none"}if(!otherMessage){span.innerHTML=" Expand description"}else{span.innerHTML=otherMessage}if(fontSize){span.style.fontSize=fontSize}var mainToggle=toggle.cloneNode(true);mainToggle.appendChild(span);var wrapper=document.createElement("div");wrapper.className="toggle-wrapper";if(!show){addClass(wrapper,"collapsed");var inner=mainToggle.getElementsByClassName("inner");if(inner&&inner.length>0){inner[0].innerHTML="+"}}if(extraClass){addClass(wrapper,extraClass)}wrapper.appendChild(mainToggle);return wrapper}(function(){var toggles=document.getElementById(toggleAllDocsId);if(toggles){toggles.onclick=toggleAllDocs}var toggle=createSimpleToggle(false);var hideMethodDocs=getSettingValue("auto-hide-method-docs")==="true";var hideImplementors=getSettingValue("auto-collapse-implementors")!=="false";var pageId=getPageId();var func=function(e){var next=e.nextElementSibling;if(next&&hasClass(next,"item-info")){next=next.nextElementSibling}if(!next){return}if(hasClass(next,"docblock")){var newToggle=toggle.cloneNode(true);insertAfter(newToggle,e.childNodes[e.childNodes.length-1]);if(hideMethodDocs===true&&hasClass(e,"method")===true){collapseDocs(newToggle,"hide",pageId)}}};var funcImpl=function(e){var next=e.nextElementSibling;if(next&&hasClass(next,"item-info")){next=next.nextElementSibling}if(next&&hasClass(next,"docblock")){next=next.nextElementSibling}if(!next){return}if(hasClass(e,"impl")&&(next.getElementsByClassName("method").length>0||next.getElementsByClassName("associatedconstant").length>0)){var newToggle=toggle.cloneNode(true);insertAfter(newToggle,e.childNodes[e.childNodes.length-1]);if(hideImplementors===true&&e.parentNode.id==="implementors-list"){collapseDocs(newToggle,"hide",pageId)}}};onEachLazy(document.getElementsByClassName("method"),func);onEachLazy(document.getElementsByClassName("associatedconstant"),func);onEachLazy(document.getElementsByClassName("impl"),funcImpl);var impl_call=function(){};if(hideMethodDocs===true){impl_call=function(e,newToggle){if(e.id.match(/^impl(?:-\d+)?$/)===null){if(hasClass(e,"impl")===true){collapseDocs(newToggle,"hide",pageId)}}}}var newToggle=document.createElement("a");newToggle.href="javascript:void(0)";newToggle.className="collapse-toggle hidden-default collapsed";newToggle.innerHTML="["+labelForToggleButton(true)+"] Show hidden undocumented items";function toggleClicked(){if(hasClass(this,"collapsed")){removeClass(this,"collapsed");onEachLazy(this.parentNode.getElementsByClassName("hidden"),function(x){if(hasClass(x,"content")===false){removeClass(x,"hidden");addClass(x,"x")}},true);this.innerHTML="["+labelForToggleButton(false)+"] Hide undocumented items"}else{addClass(this,"collapsed");onEachLazy(this.parentNode.getElementsByClassName("x"),function(x){if(hasClass(x,"content")===false){addClass(x,"hidden");removeClass(x,"x")}},true);this.innerHTML="["+labelForToggleButton(true)+"] Show hidden undocumented items"}}onEachLazy(document.getElementsByClassName("impl-items"),function(e){onEachLazy(e.getElementsByClassName("associatedconstant"),func);var hiddenElems=e.getElementsByClassName("hidden");var needToggle=false;var hlength=hiddenElems.length;for(var i=0;i"+getSearchLoadingText()+"";showSearchResults(search)}var sidebar_menu=document.getElementsByClassName("sidebar-menu")[0];if(sidebar_menu){sidebar_menu.onclick=function(){var sidebar=document.getElementsByClassName("sidebar")[0];if(hasClass(sidebar,"mobile")===true){hideSidebar()}else{showSidebar()}}}if(main){onEachLazy(main.getElementsByClassName("loading-content"),function(e){e.remove()});onEachLazy(main.childNodes,function(e){if(e.tagName==="H2"||e.tagName==="H3"){var nextTagName=e.nextElementSibling.tagName;if(nextTagName=="H2"||nextTagName=="H3"){e.nextElementSibling.style.display="flex"}else{e.nextElementSibling.style.display="block"}}})}function enableSearchInput(){if(search_input){search_input.removeAttribute('disabled')}}window.addSearchOptions=function(crates){var elem=document.getElementById("crate-search");if(!elem){enableSearchInput();return}var crates_text=[];if(Object.keys(crates).length>1){for(var crate in crates){if(hasOwnProperty(crates,crate)){crates_text.push(crate)}}}crates_text.sort(function(a,b){var lower_a=a.toLowerCase();var lower_b=b.toLowerCase();if(lower_alower_b){return 1}return 0});var savedCrate=getSettingValue("saved-filter-crate");for(var i=0;ithe rustdoc book.";var container=document.createElement("div");var shortcuts=[["?","Show this help dialog"],["S","Focus the search field"],["T","Focus the theme picker menu"],["↑","Move up in search results"],["↓","Move down in search results"],["ctrl + ↑ / ↓","Switch result tab"],["⏎","Go to active search result"],["+","Expand all sections"],["-","Collapse all sections"],].map(x=>"
"+x[0].split(" ").map((y,index)=>(index&1)===0?""+y+"":y).join("")+"
"+x[1]+"
").join("");var div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

Keyboard Shortcuts

"+shortcuts+"
";var infos=["Prefix searches with a type followed by a colon (e.g., fn:) to \ + restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \ + enum, trait, type, macro, \ + and const.","Search functions by type signature (e.g., vec -> usize or \ + * -> vec)","Search multiple things at once by splitting your query with comma (e.g., \ + str,u8 or String,struct:Vec,test)","You can look for items with an exact name by putting double quotes around \ + your request: \"string\"","Look for items inside another one by searching for a path: vec::Vec",].map(x=>"

"+x+"

").join("");var div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

Search Tricks

"+infos;container.appendChild(book_info);container.appendChild(div_shortcuts);container.appendChild(div_infos);popup.appendChild(container);insertAfter(popup,getSearchElement());buildHelperPopup=function(){}}onHashChange(null);window.onhashchange=onHashChange}());window.onunload=function(){} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/normalize.css b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/normalize.css new file mode 100644 index 0000000000..6d692b50ca --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/normalize.css @@ -0,0 +1,2 @@ + /*! normalize.css v3.0.0 | MIT License | git.io/normalize */ +html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/noscript.css b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/noscript.css new file mode 100644 index 0000000000..5cbcb9016b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/noscript.css @@ -0,0 +1 @@ + #main>h2+div,#main>h2+h3,#main>h3+div{display:block;}.loading-content{display:none;}#main>h2+div,#main>h3+div{display:block;}#main>h2+h3{display:flex;}#main .impl-items .hidden{display:block !important;} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/rust-logo.png b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/rust-logo.png new file mode 100644 index 0000000000..74b4bd6950 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/rust-logo.png differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/rustdoc.css b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/rustdoc.css new file mode 100644 index 0000000000..061171efd1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/rustdoc.css @@ -0,0 +1 @@ + @font-face {font-family:'Fira Sans';font-style:normal;font-weight:400;src:local('Fira Sans'),url("FiraSans-Regular.woff") format('woff');}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:500;src:local('Fira Sans Medium'),url("FiraSans-Medium.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:normal;font-weight:400;src:local('Source Serif Pro'),url("SourceSerifPro-Regular.ttf.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:italic;font-weight:400;src:local('Source Serif Pro Italic'),url("SourceSerifPro-It.ttf.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:normal;font-weight:700;src:local('Source Serif Pro Bold'),url("SourceSerifPro-Bold.ttf.woff") format('woff');}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("SourceCodePro-Regular.woff") format('woff');}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("SourceCodePro-Semibold.woff") format('woff');}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}html{content:"";}@media (prefers-color-scheme:light){html{content:"light";}}@media (prefers-color-scheme:dark){html{content:"dark";}}body{font:16px/1.4 "Source Serif Pro",serif;margin:0;position:relative;padding:10px 15px 20px 15px;-webkit-font-feature-settings:"kern","liga";-moz-font-feature-settings:"kern","liga";font-feature-settings:"kern","liga";}h1{font-size:1.5em;}h2{font-size:1.4em;}h3{font-size:1.3em;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod):not(.notable),h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){font-weight:500;margin:20px 0 15px 0;padding-bottom:6px;}h1.fqn{border-bottom:1px dashed;margin-top:0;}h1.fqn>.in-band>a:hover{text-decoration:underline;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){border-bottom:1px solid;}h3.impl,h3.method,h4.method,h3.type,h4.type,h4.associatedconstant{flex-basis:100%;font-weight:600;margin-top:16px;margin-bottom:10px;position:relative;}h3.impl,h3.method,h3.type{padding-left:15px;}h1,h2,h3,h4,.sidebar,a.source,.search-input,.content table td:first-child>a,.collapse-toggle,div.item-list .out-of-band,#source-sidebar,#sidebar-toggle{font-family:"Fira Sans",sans-serif;}.content ul.crate a.crate{font:16px/1.6 "Fira Sans";}ol,ul{padding-left:25px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:.6em;}p{margin:0 0 .6em 0;}summary{outline:none;}code,pre,a.test-arrow{font-family:"Source Code Pro",monospace;}.docblock code,.docblock-short code{border-radius:3px;padding:0 0.1em;}.docblock pre code,.docblock-short pre code,.docblock code.spotlight{padding:0;}.docblock code.spotlight :last-child{padding-bottom:0.6em;}pre{padding:14px;}.source .content pre{padding:20px;}img{max-width:100%;}li{position:relative;}.source .content{margin-top:50px;max-width:none;overflow:visible;margin-left:0px;min-width:70em;}nav.sub{font-size:16px;text-transform:uppercase;}.sidebar{width:200px;position:fixed;left:0;top:0;bottom:0;overflow:auto;}*{scrollbar-width:initial;}.sidebar{scrollbar-width:thin;}::-webkit-scrollbar{width:12px;}.sidebar::-webkit-scrollbar{width:8px;}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0;}.sidebar .block>ul>li{margin-right:-10px;}.content,nav{max-width:960px;}.hidden{display:none !important;}.logo-container{height:100px;width:100px;position:relative;margin:20px auto;display:block;margin-top:10px;}.logo-container>img{max-width:100px;max-height:100px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);display:block;}.sidebar .location{border:1px solid;font-size:17px;margin:30px 10px 20px 10px;text-align:center;word-wrap:break-word;}.sidebar .version{font-size:15px;text-align:center;border-bottom:1px solid;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;}.location:empty{border:none;}.location a:first-child{font-weight:500;}.block{padding:0;margin-bottom:14px;}.block h2,.block h3{margin-top:0;margin-bottom:8px;text-align:center;}.block ul,.block li{margin:0 10px;padding:0;list-style:none;}.block a{display:block;text-overflow:ellipsis;overflow:hidden;line-height:15px;padding:7px 5px;font-size:14px;font-weight:300;transition:border 500ms ease-out;}.sidebar-title{border-top:1px solid;border-bottom:1px solid;text-align:center;font-size:17px;margin-bottom:5px;}.sidebar-links{margin-bottom:15px;}.sidebar-links>a{padding-left:10px;width:100%;}.sidebar-menu{display:none;}.content{padding:15px 0;}.source .content pre.rust{white-space:pre;overflow:auto;padding-left:0;}.rustdoc:not(.source) .example-wrap{display:inline-flex;margin-bottom:10px;position:relative;}.example-wrap{width:100%;}.example-wrap>pre.line-number{overflow:initial;border:1px solid;border-top-left-radius:5px;border-bottom-left-radius:5px;padding:13px 8px;text-align:right;}.rustdoc:not(.source) .example-wrap>pre.rust{width:100%;overflow-x:auto;}.rustdoc:not(.source) .example-wrap>pre{margin:0;}#search{margin-left:230px;position:relative;}#results{position:absolute;right:0;left:0;overflow:auto;}#results>table{width:100%;table-layout:fixed;margin-bottom:40px;}.content pre.line-numbers{float:left;border:none;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}.line-numbers span{cursor:pointer;}.docblock-short{overflow-wrap:anywhere;}.docblock-short p{display:inline;}.docblock-short p{overflow:hidden;text-overflow:ellipsis;margin:0;}.docblock code,.docblock-short code{white-space:pre-wrap;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom:1px solid;}#main>.docblock h1{font-size:1.3em;}#main>.docblock h2{font-size:1.15em;}#main>.docblock h3,#main>.docblock h4,#main>.docblock h5{font-size:1em;}#main>h2+div,#main>h2+h3,#main>h3+div{display:none;flex-wrap:wrap;}.docblock h1{font-size:1em;}.docblock h2{font-size:0.95em;}.docblock h3,.docblock h4,.docblock h5{font-size:0.9em;}.docblock{margin-left:24px;position:relative;}.content .out-of-band{float:right;font-size:23px;margin:0px;padding:0px;font-weight:normal;}h3.impl>.out-of-band{font-size:21px;}h4.method>.out-of-band{font-size:19px;}h4>code,h3>code,.invisible>code{max-width:calc(100% - 41px);display:block;}.invisible{width:100%;display:inline-block;}.content .in-band{margin:0px;padding:0px;}.in-band>code{display:inline-block;}#main{position:relative;}#main>.since{top:inherit;font-family:"Fira Sans",sans-serif;}.content table:not(.table-display){border-spacing:0 5px;}.content td{vertical-align:top;}.content td:first-child{padding-right:20px;}.content td p:first-child{margin-top:0;}.content td h1,.content td h2{margin-left:0;font-size:1.1em;}.content tr:first-child td{border-top:0;}.docblock table{margin:.5em 0;width:calc(100% - 2px);border:1px dashed;}.docblock table td{padding:.5em;border:1px dashed;}.docblock table th{padding:.5em;text-align:left;border:1px solid;}.fields+table{margin-bottom:1em;}.content .item-list{list-style-type:none;padding:0;}.content .multi-column{-moz-column-count:5;-moz-column-gap:2.5em;-webkit-column-count:5;-webkit-column-gap:2.5em;column-count:5;column-gap:2.5em;}.content .multi-column li{width:100%;display:inline-block;}.content .method{font-size:1em;position:relative;}.content .method .where,.content .fn .where,.content .where.fmt-newline{display:block;font-size:0.8em;}.content .methods>div:not(.notable-traits){margin-left:40px;margin-bottom:15px;}.content .docblock>.impl-items{margin-left:20px;margin-top:-34px;}.content .docblock>.impl-items>h4{border-bottom:0;}.content .docblock>.impl-items .table-display{margin:0;}.content .docblock>.impl-items table td{padding:0;}.toggle-wrapper.marg-left>.collapse-toggle{left:-24px;}.content .docblock>.impl-items .table-display,.impl-items table td{border:none;}.content .item-info code{font-size:90%;}.content .item-info{position:relative;margin-left:33px;margin-top:-13px;}.sub-variant>div>.item-info{margin-top:initial;}.content .item-info::before{content:'⬑';font-size:25px;position:absolute;top:-6px;left:-19px;}.content .impl-items .method,.content .impl-items>.type,.impl-items>.associatedconstant{margin-left:20px;}.content .impl-items .docblock,.content .impl-items .item-info{margin-bottom:.6em;}.content .impl-items>.item-info{margin-left:40px;}.methods>.item-info,.content .impl-items>.item-info{margin-top:-8px;}.impl-items{flex-basis:100%;}#main>.item-info{margin-top:0;}nav:not(.sidebar){border-bottom:1px solid;padding-bottom:10px;margin-bottom:10px;}nav.main{padding:20px 0;text-align:center;}nav.main .current{border-top:1px solid;border-bottom:1px solid;}nav.main .separator{border:1px solid;display:inline-block;height:23px;margin:0 20px;}nav.sum{text-align:right;}nav.sub form{display:inline;}nav.sub,.content{margin-left:230px;}a{text-decoration:none;background:transparent;}.small-section-header:hover>.anchor{display:initial;}.in-band:hover>.anchor,.impl:hover>.anchor{display:inline-block;position:absolute;}.anchor{display:none;position:absolute;left:-7px;}.anchor.field{left:-5px;}.small-section-header>.anchor{left:-28px;padding-right:10px;}.anchor:before{content:'\2002\00a7\2002';}.docblock a:not(.srclink):not(.test-arrow):hover,.docblock-short a:not(.srclink):not(.test-arrow):hover,.item-info a{text-decoration:underline;}.invisible>.srclink,h4>code+.srclink,h3>code+.srclink{position:absolute;top:0;right:0;font-size:17px;font-weight:normal;}.block a.current.crate{font-weight:500;}.search-container{position:relative;}.search-container>div{display:inline-flex;width:calc(100% - 63px);}#crate-search{margin-top:5px;padding:6px;padding-right:19px;flex:none;border:0;border-right:0;border-radius:4px 0 0 4px;outline:none;cursor:pointer;border-right:1px solid;-moz-appearance:none;-webkit-appearance:none;text-indent:0.01px;text-overflow:"";background-repeat:no-repeat;background-color:transparent;background-size:20px;background-position:calc(100% - 1px) 56%;}.search-container>.top-button{position:absolute;right:0;top:10px;}.search-input{-moz-box-sizing:border-box !important;box-sizing:border-box !important;outline:none;border:none;border-radius:1px;margin-top:5px;padding:10px 16px;font-size:17px;transition:border-color 300ms ease;transition:border-radius 300ms ease-in-out;transition:box-shadow 300ms ease-in-out;width:100%;}#crate-search+.search-input{border-radius:0 1px 1px 0;width:calc(100% - 32px);}.search-input:focus{border-radius:2px;border:0;outline:0;}.search-results .desc{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;display:block;}.search-results a{display:block;}.content .search-results td:first-child{padding-right:0;width:50%;}.content .search-results td:first-child a{padding-right:10px;}.content .search-results td:first-child a:after{clear:both;content:"";display:block;}.content .search-results td:first-child a span{float:left;}tr.result span.primitive::after{content:' (primitive type)';font-style:italic;}tr.result span.keyword::after{content:' (keyword)';font-style:italic;}body.blur>:not(#help){filter:blur(8px);-webkit-filter:blur(8px);opacity:.7;}#help{width:100%;height:100vh;position:fixed;top:0;left:0;display:flex;justify-content:center;align-items:center;}#help>div{flex:0 0 auto;box-shadow:0 0 6px rgba(0,0,0,.2);width:550px;height:auto;border:1px solid;}#help dt{float:left;clear:left;display:block;}#help>div>span{text-align:center;display:block;margin:10px 0;font-size:18px;border-bottom:1px solid #ccc;padding-bottom:4px;margin-bottom:6px;}#help dd{margin:5px 35px;}#help .infos{padding-left:0;}#help h1,#help h2{margin-top:0;}#help>div div{width:50%;float:left;padding:0 20px 20px 17px;;}.stab{display:table;border-width:1px;border-style:solid;padding:3px;margin-bottom:5px;font-size:90%;}.stab p{display:inline;}.stab summary{display:list-item;}.stab .emoji{font-size:1.5em;}.module-item .stab{border-radius:3px;display:inline-block;font-size:80%;line-height:1.2;margin-bottom:0;margin-right:.3em;padding:2px;vertical-align:text-bottom;}.module-item.unstable{opacity:0.65;}.since{font-weight:normal;font-size:initial;position:absolute;right:0;top:0;}.impl-items .since,.impl .since,.methods .since{flex-grow:0;padding-left:12px;padding-right:2px;position:initial;}.impl-items .srclink,.impl .srclink,.methods .srclink{flex-grow:0;font-size:17px;font-weight:normal;}.impl-items code,.impl code,.methods code{flex-grow:1;}.impl-items h4,h4.impl,h3.impl,.methods h3{display:flex;flex-basis:100%;font-size:16px;margin-bottom:12px;justify-content:space-between;}.variants_table{width:100%;}.variants_table tbody tr td:first-child{width:1%;}td.summary-column{width:100%;}.summary{padding-right:0px;}pre.rust .question-mark{font-weight:bold;}a.test-arrow{display:inline-block;position:absolute;padding:5px 10px 5px 10px;border-radius:5px;font-size:130%;top:5px;right:5px;z-index:1;}a.test-arrow:hover{text-decoration:none;}.section-header:hover a:before{position:absolute;left:-25px;padding-right:10px;content:'\2002\00a7\2002';}.section-header:hover a{text-decoration:none;}.section-header a{color:inherit;}.collapse-toggle{font-weight:300;position:absolute;left:-23px;top:0;}h3>.collapse-toggle,h4>.collapse-toggle{font-size:0.8em;top:5px;}.toggle-wrapper>.collapse-toggle{left:-24px;margin-top:0px;}.toggle-wrapper{position:relative;margin-top:0;}.toggle-wrapper.collapsed{height:25px;transition:height .2s;margin-bottom:.6em;}.collapse-toggle>.inner{display:inline-block;width:1.2ch;text-align:center;}.collapse-toggle.hidden-default{position:relative;margin-left:20px;}.since+.srclink{display:table-cell;padding-left:10px;}.item-spacer{width:100%;height:12px;}.out-of-band>span.since{position:initial;font-size:20px;margin-right:5px;}.toggle-wrapper>.collapse-toggle{left:0;}.variant+.toggle-wrapper+.docblock>p{margin-top:5px;}.sub-variant,.sub-variant>h3{margin-top:1px !important;}#main>.sub-variant>h3{font-size:15px;margin-left:25px;margin-bottom:5px;}.sub-variant>div{margin-left:20px;margin-bottom:10px;}.sub-variant>div>span{display:block;position:relative;}.toggle-label{display:inline-block;margin-left:4px;margin-top:3px;}.enum>.toggle-wrapper+.docblock,.struct>.toggle-wrapper+.docblock{margin-left:30px;margin-bottom:20px;margin-top:5px;}.docblock>.section-header:first-child{margin-left:15px;margin-top:0;}.docblock>.section-header:first-child:hover>a:before{left:-10px;}.enum>.collapsed,.struct>.collapsed{margin-bottom:25px;}#main>.variant,#main>.structfield{display:block;}.attributes{display:block;margin-top:0px !important;margin-right:0px;margin-bottom:0px !important;margin-left:30px;}.toggle-attributes.collapsed{margin-bottom:0;}.impl-items>.toggle-attributes{margin-left:20px;}.impl-items .attributes{font-weight:500;}:target>code{opacity:1;}.information{position:absolute;left:-25px;margin-top:7px;z-index:1;}.tooltip{position:relative;display:inline-block;cursor:pointer;}.tooltip .tooltiptext{width:120px;display:none;text-align:center;padding:5px 3px 3px 3px;border-radius:6px;margin-left:5px;top:-5px;left:105%;z-index:10;font-size:16px;}.tooltip .tooltiptext::after{content:" ";position:absolute;top:50%;left:16px;margin-top:-5px;border-width:5px;border-style:solid;}.tooltip:hover .tooltiptext{display:inline;}.tooltip.compile_fail,.tooltip.should_panic,.tooltip.ignore{font-weight:bold;font-size:20px;}.notable-traits-tooltip{display:inline-block;cursor:pointer;}.notable-traits:hover .notable-traits-tooltiptext,.notable-traits .notable-traits-tooltiptext.force-tooltip{display:inline-block;}.notable-traits .notable-traits-tooltiptext{display:none;padding:5px 3px 3px 3px;border-radius:6px;margin-left:5px;z-index:10;font-size:16px;cursor:default;position:absolute;border:1px solid;}.notable-traits-tooltip::after{content:"\00a0\00a0\00a0";}.notable-traits .notable,.notable-traits .docblock{margin:0;}.notable-traits .docblock code.content{margin:0;padding:0;font-size:20px;}pre.rust.rust-example-rendered{position:relative;}pre.rust{tab-size:4;-moz-tab-size:4;}.search-failed{text-align:center;margin-top:20px;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#titles{height:35px;}#titles>button{float:left;width:33.3%;text-align:center;font-size:18px;cursor:pointer;border:0;border-top:2px solid;}#titles>button:not(:last-child){margin-right:1px;width:calc(33.3% - 1px);}#titles>button>div.count{display:inline-block;font-size:16px;}.notable-traits{cursor:pointer;z-index:2;margin-left:5px;}h4>.notable-traits{position:absolute;left:-44px;top:2px;}#all-types{text-align:center;border:1px solid;margin:0 10px;margin-bottom:10px;display:block;border-radius:7px;}#all-types>p{margin:5px 0;}#sidebar-toggle{position:fixed;top:30px;left:300px;z-index:10;padding:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;cursor:pointer;font-weight:bold;transition:left .5s;font-size:1.2em;border:1px solid;border-left:0;}#source-sidebar{position:fixed;top:0;bottom:0;left:0;width:300px;z-index:1;overflow:auto;transition:left .5s;border-right:1px solid;}#source-sidebar>.title{font-size:1.5em;text-align:center;border-bottom:1px solid;margin-bottom:6px;}.theme-picker{position:absolute;left:211px;top:19px;}.theme-picker button{outline:none;}#settings-menu,.help-button{position:absolute;top:10px;}#settings-menu{right:0;outline:none;}.help-button{right:30px;font-family:"Fira Sans",sans-serif;text-align:center;font-size:17px;}#theme-picker,#settings-menu,.help-button{padding:4px;width:27px;height:29px;border:1px solid;border-radius:3px;cursor:pointer;}#theme-choices{display:none;position:absolute;left:0;top:28px;border:1px solid;border-radius:3px;z-index:1;cursor:pointer;}#theme-choices>button{border:none;width:100%;padding:4px 8px;text-align:center;background:rgba(0,0,0,0);}#theme-choices>button:not(:first-child){border-top:1px solid;}@media (min-width:701px){.information:first-child>.tooltip{margin-top:16px;}}@media (max-width:700px){body{padding-top:0px;}.rustdoc>.sidebar{height:45px;min-height:40px;margin:0;margin-left:-15px;padding:0 15px;position:static;z-index:11;}.sidebar>.location{float:right;margin:0px;margin-top:2px;padding:3px 10px 1px 10px;min-height:39px;background:inherit;text-align:left;font-size:24px;}.sidebar .location:empty{padding:0;}.sidebar .logo-container{width:35px;height:35px;margin-top:5px;margin-bottom:5px;float:left;margin-left:50px;}.sidebar .logo-container>img{max-width:35px;max-height:35px;}.sidebar-menu{position:fixed;z-index:10;font-size:2rem;cursor:pointer;width:45px;left:0;text-align:center;display:block;border-bottom:1px solid;border-right:1px solid;height:45px;}.rustdoc.source>.sidebar>.sidebar-menu{display:none;}.sidebar-elems{position:fixed;z-index:1;left:0;top:45px;bottom:0;overflow-y:auto;border-right:1px solid;display:none;}.sidebar>.block.version{border-bottom:none;margin-top:12px;}nav.sub{width:calc(100% - 32px);float:right;}.content{margin-left:0px;}#main{margin-top:45px;padding:0;}.content .in-band{width:100%;}.content h4>.out-of-band{position:inherit;}.toggle-wrapper>.collapse-toggle{left:0px;}.toggle-wrapper{height:1.5em;}#search{margin-left:0;}.content .impl-items .method,.content .impl-items>.type,.impl-items>.associatedconstant{display:flex;}.anchor{display:none !important;}h1.fqn{overflow:initial;}.theme-picker{left:10px;top:54px;z-index:1;}h4>.notable-traits{position:absolute;left:-22px;top:24px;}#titles>button>div.count{float:left;width:100%;}#titles{height:50px;}.sidebar.mobile{position:fixed;width:100%;margin-left:0;background-color:rgba(0,0,0,0);height:100%;}.sidebar{width:calc(100% + 30px);}.show-it{display:block;width:246px;}.show-it>.block.items{margin:8px 0;}.show-it>.block.items>ul{margin:0;}.show-it>.block.items>ul>li{text-align:center;margin:2px 0;}.show-it>.block.items>ul>li>a{font-size:21px;}#sidebar-filler{position:fixed;left:45px;width:calc(100% - 45px);top:0;height:45px;z-index:-1;border-bottom:1px solid;}.collapse-toggle{left:-20px;}.impl>.collapse-toggle{left:-10px;}#all-types{margin:10px;}#sidebar-toggle{top:100px;width:30px;font-size:1.5rem;text-align:center;padding:0;}#source-sidebar{z-index:11;}#main>.line-numbers{margin-top:0;}.notable-traits .notable-traits-tooltiptext{left:0;top:100%;}.help-button{display:none;}.search-container>div{width:calc(100% - 32px);}}@media print{nav.sub,.content .out-of-band,.collapse-toggle{display:none;}}@media (max-width:416px){#titles,#titles>button{height:73px;}#main{margin-top:100px;}#main>table:not(.table-display) td{word-break:break-word;width:50%;}.search-container>div{display:block;width:calc(100% - 37px);}#crate-search{width:100%;border-radius:4px;border:0;}#crate-search+.search-input{width:calc(100% + 71px);margin-left:-36px;}#theme-picker,#settings-menu{padding:5px;width:31px;height:31px;}#theme-picker{margin-top:-2px;}#settings-menu{top:7px;}}h3.notable{margin:0;margin-bottom:13px;font-size:19px;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px;border-radius:3px;box-shadow:inset 0 -1px 0;cursor:default;}.hidden-by-impl-hider,.hidden-by-usual-hider{display:none !important;}#implementations-list>h3>span.in-band{width:100%;}.table-display{width:100%;border:0;border-collapse:collapse;border-spacing:0;font-size:16px;}.table-display tr td:first-child{padding-right:0;}.table-display tr td:last-child{float:right;}.table-display .out-of-band{position:relative;font-size:19px;display:block;}#implementors-list>.impl-items .table-display .out-of-band{font-size:17px;}.table-display td:hover .anchor{display:block;top:2px;left:-5px;}#main>ul{padding-left:10px;}#main>ul>li{list-style:none;}.non-exhaustive{margin-bottom:1em;}div.children{padding-left:27px;display:none;}div.name{cursor:pointer;position:relative;margin-left:16px;}div.files>a{display:block;padding:0 3px;}div.files>a:hover,div.name:hover{background-color:#a14b4b;}div.name.expand+.children{display:block;}div.name::before{content:"\25B6";padding-left:4px;font-size:0.7em;position:absolute;left:-16px;top:4px;}div.name.expand::before{transform:rotate(90deg);left:-15px;top:2px;}.type-decl>pre>.toggle-wrapper.toggle-attributes.top-attr{margin-left:0 !important;}.type-decl>pre>.docblock.attributes.top-attr{margin-left:1.8em !important;}.type-decl>pre>.toggle-attributes{margin-left:2.2em;}.type-decl>pre>.docblock.attributes{margin-left:4em;} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/search-index.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/search-index.js new file mode 100644 index 0000000000..328e2f87cd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/search-index.js @@ -0,0 +1,4 @@ +var searchIndex = JSON.parse('{\ +"bdk":{"doc":"A modern, lightweight, descriptor-based wallet library …","i":[[0,"blockchain","bdk","Blockchain backends",null,null],[0,"any","bdk::blockchain","Runtime-checked blockchain types",null,null],[4,"AnyBlockchain","bdk::blockchain::any","Type that can contain any of the [Blockchain] types …",null,null],[13,"Electrum","","Electrum client",0,null],[13,"Esplora","","Esplora client",0,null],[13,"CompactFilters","","Compact filters client",0,null],[4,"AnyBlockchainConfig","","Type that can contain any of the blockchain …",null,null],[13,"Electrum","","Electrum client",1,null],[13,"Esplora","","Esplora client",1,null],[13,"CompactFilters","","Compact filters client",1,null],[0,"electrum","bdk::blockchain","Electrum",null,null],[3,"ElectrumBlockchain","bdk::blockchain::electrum","Wrapper over an Electrum Client that implements the …",null,null],[3,"ElectrumBlockchainConfig","","Configuration for an [ElectrumBlockchain]",null,null],[12,"url","","URL of the Electrum server (such as ElectrumX, Esplora, …",2,null],[12,"socks5","","URL of the socks5 proxy server or a Tor service",2,null],[12,"retry","","Request retry count",2,null],[12,"timeout","","Request timeout (seconds)",2,null],[0,"esplora","bdk::blockchain","Esplora",null,null],[3,"EsploraBlockchain","bdk::blockchain::esplora","Structure that implements the logic to sync with Esplora",null,null],[11,"new","","Create a new instance of the client from a base URL",3,[[["option",4]]]],[3,"EsploraBlockchainConfig","","Configuration for an [EsploraBlockchain]",null,null],[12,"base_url","","Base URL of the esplora service",4,null],[12,"concurrency","","Number of parallel requests sent to the esplora service …",4,null],[4,"EsploraError","","Errors that can happen during a sync with […",null,null],[13,"Reqwest","","Error with the HTTP call",5,null],[13,"Parsing","","Invalid number returned",5,null],[13,"BitcoinEncoding","","Invalid Bitcoin data returned",5,null],[13,"Hex","","Invalid Hex data returned",5,null],[13,"TransactionNotFound","","Transaction not found",5,null],[13,"HeaderHeightNotFound","","Header height not found",5,null],[13,"HeaderHashNotFound","","Header hash not found",5,null],[0,"compact_filters","bdk::blockchain","Compact Filters",null,null],[3,"Mempool","bdk::blockchain::compact_filters","Container for unconfirmed, but valid Bitcoin transactions",null,null],[3,"Peer","","A Bitcoin peer",null,null],[3,"CompactFiltersBlockchain","","Structure implementing the required blockchain traits",null,null],[11,"new","","Construct a new instance given a list of peers, a path to …",6,[[["peer",3],["asref",8],["option",4],["vec",3],["path",3]],[["compactfilterserror",4],["result",4]]]],[3,"BitcoinPeerConfig","","Data to connect to a Bitcoin P2P peer",null,null],[12,"address","","Peer address such as 127.0.0.1:18333",7,null],[12,"socks5","","Optional socks5 proxy",7,null],[12,"socks5_credentials","","Optional socks5 proxy credentials",7,null],[3,"CompactFiltersBlockchainConfig","","Configuration for a [CompactFiltersBlockchain]",null,null],[12,"peers","","List of peers to try to connect to for asking headers and …",8,null],[12,"network","","Network used",8,null],[12,"storage_dir","","Storage dir to save partially downloaded headers and full …",8,null],[12,"skip_blocks","","Optionally skip initial skip_blocks blocks (default: 0)",8,null],[4,"CompactFiltersError","","An error that can occur during sync with a […",null,null],[13,"InvalidResponse","","A peer sent an invalid or unexpected response",9,null],[13,"InvalidHeaders","","The headers returned are invalid",9,null],[13,"InvalidFilterHeader","","The compact filter headers returned are invalid",9,null],[13,"InvalidFilter","","The compact filter returned is invalid",9,null],[13,"MissingBlock","","The peer is missing a block in the valid chain",9,null],[13,"DataCorruption","","The data stored in the block filters storage are corrupted",9,null],[13,"NotConnected","","A peer is not connected",9,null],[13,"Timeout","","A peer took too long to reply to one of our messages",9,null],[13,"NoPeers","","No peers have been specified",9,null],[13,"DB","","Internal database error",9,null],[13,"IO","","Internal I/O error",9,null],[13,"BIP158","","Invalid BIP158 filter",9,null],[13,"Time","","Internal system time error",9,null],[13,"Global","","Wrapper for [crate::error::Error]",9,null],[4,"Capability","bdk::blockchain","Capabilities that can be supported by a [Blockchain] …",null,null],[13,"FullHistory","","Can recover the full history of a wallet and not only the …",10,null],[13,"GetAnyTx","","Can fetch any historical transaction given its txid",10,null],[13,"AccurateFees","","Can compute accurate fees for the transactions found …",10,null],[8,"BlockchainMarker","","Marker trait for a blockchain backend",null,null],[3,"OfflineBlockchain","","Type that only implements [BlockchainMarker] and is …",null,null],[8,"Blockchain","","Trait that defines the actions that must be supported by …",null,null],[10,"get_capabilities","","Return the set of [Capability] supported by this backend",11,[[],[["hashset",3],["capability",4]]]],[10,"setup","","Setup the backend and populate the internal database for …",11,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"sync","","Populate the internal database with transactions and UTXOs",11,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[10,"get_tx","","Fetch a transaction from the blockchain given its txid",11,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[10,"broadcast","","Broadcast a transaction",11,[[["transaction",3]],[["error",4],["result",4]]]],[10,"get_height","","Return the current height",11,[[],[["result",4],["error",4]]]],[10,"estimate_fee","","Estimate the fee rate required to confirm a transaction …",11,[[],[["feerate",3],["error",4],["result",4]]]],[8,"ConfigurableBlockchain","","Trait for [Blockchain] types that can be created given a …",null,null],[16,"Config","","Type that contains the configuration",12,null],[10,"from_config","","Create a new instance given a configuration",12,[[],[["result",4],["error",4]]]],[6,"ProgressData","","Data sent with a progress update over a [channel]",null,null],[8,"Progress","","Trait for types that can receive and process progress …",null,null],[10,"update","","Send a new progress update",13,[[["string",3],["option",4]],[["error",4],["result",4]]]],[5,"progress","","Shortcut to create a [channel] (pair of [Sender] and […",null,[[]]],[3,"NoopProgress","","Type that implements [Progress] and drops every update …",null,null],[5,"noop_progress","","Create a new instance of [NoopProgress]",null,[[],["noopprogress",3]]],[3,"LogProgress","","Type that implements [Progress] and logs at level INFO …",null,null],[5,"log_progress","","Create a nwe instance of [LogProgress]",null,[[],["logprogress",3]]],[0,"database","bdk","Database types",null,null],[0,"any","bdk::database","Runtime-checked database types",null,null],[4,"AnyDatabase","bdk::database::any","Type that can contain any of the [Database] types defined …",null,null],[13,"Memory","","In-memory ephemeral database",14,null],[13,"Sled","","Simple key-value embedded database based on [sled]",14,null],[4,"AnyBatch","","Type that contains any of the [BatchDatabase::Batch] …",null,null],[13,"Memory","","In-memory ephemeral database",15,null],[13,"Sled","","Simple key-value embedded database based on [sled]",15,null],[3,"SledDbConfiguration","","Configuration type for a [sled::Tree] database",null,null],[12,"path","","Main directory of the db",16,null],[12,"tree_name","","Name of the database tree, a separated namespace for the …",16,null],[4,"AnyDatabaseConfig","","Type that can contain any of the database configurations …",null,null],[13,"Memory","","Memory database has no config",17,null],[13,"Sled","","Simple key-value embedded database based on [sled]",17,null],[0,"memory","bdk::database","In-memory ephemeral database",null,null],[3,"MemoryDatabase","bdk::database::memory","In-memory ephemeral database",null,null],[11,"new","","Create a new empty database",18,[[]]],[8,"BatchOperations","bdk::database","Trait for operations that can be batched",null,null],[10,"set_script_pubkey","","Store a script_pubkey along with its keychain and child …",19,[[["script",3],["keychainkind",4]],[["error",4],["result",4]]]],[10,"set_utxo","","Store a [UTXO]",19,[[["utxo",3]],[["error",4],["result",4]]]],[10,"set_raw_tx","","Store a raw transaction",19,[[["transaction",3]],[["error",4],["result",4]]]],[10,"set_tx","","Store the metadata of a transaction",19,[[["transactiondetails",3]],[["error",4],["result",4]]]],[10,"set_last_index","","Store the last derivation index for a given keychain.",19,[[["keychainkind",4]],[["error",4],["result",4]]]],[10,"del_script_pubkey_from_path","","Delete a script_pubkey given the keychain and its child …",19,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[10,"del_path_from_script_pubkey","","Delete the data related to a specific script_pubkey, …",19,[[["script",3]],[["error",4],["result",4],["option",4]]]],[10,"del_utxo","","Delete a [UTXO] given its [OutPoint]",19,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[10,"del_raw_tx","","Delete a raw transaction given its [Txid]",19,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[10,"del_tx","","Delete the metadata of a transaction and optionally the …",19,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[10,"del_last_index","","Delete the last derivation index for a keychain.",19,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[8,"Database","","Trait for reading data from a database",null,null],[10,"check_descriptor_checksum","","Read and checks the descriptor checksum for a given …",20,[[["asref",8],["keychainkind",4]],[["error",4],["result",4]]]],[10,"iter_script_pubkeys","","Return the list of script_pubkeys",20,[[["option",4],["keychainkind",4]],[["vec",3],["result",4],["error",4]]]],[10,"iter_utxos","","Return the list of [UTXO]s",20,[[],[["result",4],["vec",3],["error",4]]]],[10,"iter_raw_txs","","Return the list of raw transactions",20,[[],[["vec",3],["result",4],["error",4]]]],[10,"iter_txs","","Return the list of transactions metadata",20,[[],[["error",4],["result",4],["vec",3]]]],[10,"get_script_pubkey_from_path","","Fetch a script_pubkey given the child number of a …",20,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[10,"get_path_from_script_pubkey","","Fetch the keychain and child number of a given …",20,[[["script",3]],[["error",4],["result",4],["option",4]]]],[10,"get_utxo","","Fetch a [UTXO] given its [OutPoint]",20,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[10,"get_raw_tx","","Fetch a raw transaction given its [Txid]",20,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[10,"get_tx","","Fetch the transaction metadata and optionally also the …",20,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[10,"get_last_index","","Return the last defivation index for a keychain.",20,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[10,"increment_last_index","","Increment the last derivation index for a keychain and …",20,[[["keychainkind",4]],[["result",4],["error",4]]]],[8,"BatchDatabase","","Trait for a database that supports batch operations",null,null],[16,"Batch","","Container for the operations",21,null],[10,"begin_batch","","Create a new batch container",21,[[]]],[10,"commit_batch","","Consume and apply a batch of operations",21,[[],[["error",4],["result",4]]]],[8,"ConfigurableDatabase","","Trait for [Database] types that can be created given a …",null,null],[16,"Config","","Type that contains the configuration",22,null],[10,"from_config","","Create a new instance given a configuration",22,[[],[["result",4],["error",4]]]],[0,"descriptor","bdk","Descriptors",null,null],[6,"KeyMap","bdk::descriptor","Alias type for a map of public key to secret key",null,null],[4,"Descriptor","","Script descriptor",null,null],[13,"Bare","","A raw scriptpubkey (including pay-to-pubkey) under Legacy …",23,null],[13,"Pk","","Pay-to-Pubkey",23,null],[13,"Pkh","","Pay-to-PubKey-Hash",23,null],[13,"Wpkh","","Pay-to-Witness-PubKey-Hash",23,null],[13,"ShWpkh","","Pay-to-Witness-PubKey-Hash inside P2SH",23,null],[13,"Sh","","Pay-to-ScriptHash with Legacy context",23,null],[13,"Wsh","","Pay-to-Witness-ScriptHash with Segwitv0 context",23,null],[13,"ShWsh","","P2SH-P2WSH with Segwitv0 context",23,null],[13,"ShSortedMulti","","Sortedmulti under P2SH",23,null],[13,"WshSortedMulti","","Sortedmulti under P2WSH",23,null],[13,"ShWshSortedMulti","","Sortedmulti under P2SH-P2WSH",23,null],[4,"Legacy","","Legacy ScriptContext To be used as P2SH scripts For …",null,null],[3,"Miniscript","","Top-level script AST type",null,null],[12,"node","","A node in the Abstract Syntax Tree(",24,null],[12,"ty","","The correctness and malleability type information for the …",24,null],[12,"ext","","Additional information helpful for extra analysis.",24,null],[8,"MiniscriptKey","","Public key trait which can be converted to Hash type",null,null],[11,"is_uncompressed","","Check if the publicKey is uncompressed. The default …",25,[[]]],[16,"Hash","","The associated Hash type with the publicKey",25,null],[10,"to_pubkeyhash","","Converts an object to PublicHash",25,[[]]],[8,"ScriptContext","","The ScriptContext for Miniscript. Additional type …",null,null],[10,"check_terminal_non_malleable","","Depending on ScriptContext, fragments can be malleable. …",26,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_witness","","Check whether the given satisfaction is valid under the …",26,[[],[["scriptcontexterror",4],["result",4]]]],[10,"max_satisfaction_size","","Depending on script context, the size of a satifaction …",26,[[["miniscript",3]],["option",4]]],[11,"check_global_consensus_validity","","Depending on script Context, some of the Terminals might …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_global_policy_validity","","Depending on script Context, some of the script resource …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_consensus_validity","","Consensus rules at the Miniscript satisfaction time. It …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_policy_validity","","Policy rules at the Miniscript satisfaction time. It is …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_global_validity","","Check the consensus + policy(if not disabled) rules that …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_validity","","Check the consensus + policy(if not disabled) rules …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"top_level_type_check","","Check whether the top-level is type B",26,[[["miniscript",3]],[["error",4],["result",4]]]],[11,"other_top_level_checks","","Other top level checks that are context specific",26,[[["miniscript",3]],[["error",4],["result",4]]]],[11,"top_level_checks","","Check top level consensus rules.",26,[[["miniscript",3]],[["error",4],["result",4]]]],[4,"Segwitv0","","Segwitv0 ScriptContext",null,null],[4,"Terminal","","All AST elements",null,null],[13,"True","","1",27,null],[13,"False","","0",27,null],[13,"PkK","","",27,null],[13,"PkH","","DUP HASH160 EQUALVERIFY",27,null],[13,"After","","n CHECKLOCKTIMEVERIFY",27,null],[13,"Older","","n CHECKSEQUENCEVERIFY",27,null],[13,"Sha256","","SIZE 32 EQUALVERIFY SHA256 EQUAL",27,null],[13,"Hash256","","SIZE 32 EQUALVERIFY HASH256 EQUAL",27,null],[13,"Ripemd160","","SIZE 32 EQUALVERIFY RIPEMD160 EQUAL",27,null],[13,"Hash160","","SIZE 32 EQUALVERIFY HASH160 EQUAL",27,null],[13,"Alt","","TOALTSTACK [E] FROMALTSTACK",27,null],[13,"Swap","","SWAP [E1]",27,null],[13,"Check","","[Kt]/[Ke] CHECKSIG",27,null],[13,"DupIf","","DUP IF [V] ENDIF",27,null],[13,"Verify","","[T] VERIFY",27,null],[13,"NonZero","","SIZE 0NOTEQUAL IF [Fn] ENDIF",27,null],[13,"ZeroNotEqual","","[X] 0NOTEQUAL",27,null],[13,"AndV","","[V] [T]/[V]/[F]/[Kt]",27,null],[13,"AndB","","[E] [W] BOOLAND",27,null],[13,"AndOr","","[various] NOTIF [various] ELSE [various] ENDIF",27,null],[13,"OrB","","[E] [W] BOOLOR",27,null],[13,"OrD","","[E] IFDUP NOTIF [T]/[E] ENDIF",27,null],[13,"OrC","","[E] NOTIF [V] ENDIF",27,null],[13,"OrI","","IF [various] ELSE [various] ENDIF",27,null],[13,"Thresh","","[E] ([W] ADD)* k EQUAL",27,null],[13,"Multi","","k ()* n CHECKMULTISIG",27,null],[8,"ToPublicKey","","Trait describing public key types which can be converted …",null,null],[10,"to_public_key","","Converts an object to a public key C represents …",28,[[],["publickey",3]]],[11,"serialized_len","","Computes the size of a public key when serialized in a …",28,[[]]],[10,"hash_to_hash160","","Converts a hashed version of the public key to a hash160 …",28,[[],["hash",3]]],[0,"checksum","","Descriptor checksum",null,null],[5,"get_checksum","bdk::descriptor::checksum","Compute the checksum of a descriptor",null,[[],[["result",4],["string",3],["error",4]]]],[0,"error","bdk::descriptor","Descriptor errors",null,null],[4,"Error","bdk::descriptor::error","Errors related to the parsing and usage of descriptors",null,null],[13,"InvalidHDKeyPath","","Invalid HD Key path, such as having a wildcard but a …",29,null],[13,"Key","","Error thrown while working with keys",29,null],[13,"Policy","","Error while extracting and manipulating policies",29,null],[13,"InvalidDescriptorCharacter","","Invalid character found in the descriptor checksum",29,null],[13,"BIP32","","BIP32 error",29,null],[13,"Base58","","Error during base58 decoding",29,null],[13,"PK","","Key-related error",29,null],[13,"Miniscript","","Miniscript error",29,null],[13,"Hex","","Hex decoding error",29,null],[0,"policy","bdk::descriptor","Descriptor policy",null,null],[3,"PKOrF","bdk::descriptor::policy","Raw public key or extended key fingerprint",null,null],[4,"SatisfiableItem","","An item that needs to be satisfied",null,null],[13,"Signature","","Signature for a raw public key",30,null],[13,"SignatureKey","","Signature for an extended key fingerprint",30,null],[13,"SHA256Preimage","","SHA256 preimage hash",30,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","The digest value",31,null],[13,"HASH256Preimage","bdk::descriptor::policy","Double SHA256 preimage hash",30,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","The digest value",32,null],[13,"RIPEMD160Preimage","bdk::descriptor::policy","RIPEMD160 preimage hash",30,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","The digest value",33,null],[13,"HASH160Preimage","bdk::descriptor::policy","SHA256 then RIPEMD160 preimage hash",30,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","The digest value",34,null],[13,"AbsoluteTimelock","bdk::descriptor::policy","Absolute timeclock timestamp",30,null],[12,"value","bdk::descriptor::policy::SatisfiableItem","The timestamp value",35,null],[13,"RelativeTimelock","bdk::descriptor::policy","Relative timelock locktime",30,null],[12,"value","bdk::descriptor::policy::SatisfiableItem","The locktime value",36,null],[13,"Multisig","bdk::descriptor::policy","Multi-signature public keys with threshold count",30,null],[12,"keys","bdk::descriptor::policy::SatisfiableItem","The raw public key or extended key fingerprint",37,null],[12,"threshold","","The required threshold count",37,null],[13,"Thresh","bdk::descriptor::policy","Threshold items with threshold count",30,null],[12,"items","bdk::descriptor::policy::SatisfiableItem","The policy items",38,null],[12,"threshold","","The required threshold count",38,null],[11,"is_leaf","bdk::descriptor::policy","Returns whether the [SatisfiableItem] is a leaf item",30,[[]]],[11,"id","","Returns a unique id for the [SatisfiableItem]",30,[[],["string",3]]],[6,"ConditionMap","","Type for a map of sets of [Condition] items keyed by each …",null,null],[6,"FoldedConditionMap","","Type for a map of folded sets of [Condition] items keyed …",null,null],[4,"Satisfaction","","Represent if and how much a policy item is satisfied by …",null,null],[13,"Partial","","Only a partial satisfaction of some kind of threshold …",39,null],[12,"n","bdk::descriptor::policy::Satisfaction","Total number of items",40,null],[12,"m","","Threshold",40,null],[12,"items","","The items that can be satisfied by the descriptor",40,null],[12,"sorted","","Whether the items are sorted in lexicographic order (used …",40,null],[12,"conditions","","Extra conditions that also need to be satisfied",40,null],[13,"PartialComplete","bdk::descriptor::policy","Can reach the threshold of some kind of threshold policy",39,null],[12,"n","bdk::descriptor::policy::Satisfaction","Total number of items",41,null],[12,"m","","Threshold",41,null],[12,"items","","The items that can be satisfied by the descriptor",41,null],[12,"sorted","","Whether the items are sorted in lexicographic order (used …",41,null],[12,"conditions","","Extra conditions that also need to be satisfied",41,null],[13,"Complete","bdk::descriptor::policy","Can satisfy the policy item",39,null],[12,"condition","bdk::descriptor::policy::Satisfaction","Extra conditions that also need to be satisfied",42,null],[13,"None","bdk::descriptor::policy","Cannot satisfy or contribute to the policy item",39,null],[11,"is_leaf","","Returns whether the [Satisfaction] is a leaf item",39,[[]]],[3,"Policy","","Descriptor spending policy",null,null],[12,"id","","Identifier for this policy node",43,null],[12,"item","","Type of this policy node",43,null],[12,"satisfaction","","How a much given PSBT already satisfies this polcy node …",43,null],[12,"contribution","","How the wallet\'s descriptor can satisfy this policy node",43,null],[3,"Condition","","An extra condition that must be satisfied but that is out …",null,null],[12,"csv","","Optional CheckSequenceVerify condition",44,null],[12,"timelock","","Optional timelock condition",44,null],[11,"is_null","","Returns true if there are no extra conditions to verify",44,[[]]],[4,"PolicyError","","Errors that can happen while extracting and manipulating …",null,null],[13,"NotEnoughItemsSelected","","Not enough items are selected to satisfy a […",45,null],[13,"TooManyItemsSelected","","Too many items are selected to satisfy a […",45,null],[13,"IndexOutOfRange","","Index out of range for an item to satisfy a […",45,null],[13,"AddOnLeaf","","Can not add to an item that is [Satisfaction::None] or […",45,null],[13,"AddOnPartialComplete","","Can not add to an item that is […",45,null],[13,"MixedTimelockUnits","","Can not merge CSV or timelock values unless both are less …",45,null],[13,"IncompatibleConditions","","Incompatible conditions (not currently used)",45,null],[11,"requires_path","","Return whether or not a specific path in the policy tree …",43,[[]]],[11,"get_condition","","Return the conditions that are set by the spending policy …",43,[[["btreemap",3]],[["condition",3],["result",4],["policyerror",4]]]],[0,"template","bdk::descriptor","Descriptor templates",null,null],[6,"DescriptorTemplateOut","bdk::descriptor::template","Type alias for the return type of [DescriptorTemplate], …",null,null],[8,"DescriptorTemplate","","Trait for descriptor templates that can be built into a …",null,null],[10,"build","","Build the complete descriptor",46,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[3,"P2PKH","","P2PKH template. Expands to a descriptor pkh(key)",null,null],[12,"0","","",47,null],[3,"P2WPKH_P2SH","","P2WPKH-P2SH template. Expands to a descriptor …",null,null],[12,"0","","",48,null],[3,"P2WPKH","","P2WPKH template. Expands to a descriptor wpkh(key)",null,null],[12,"0","","",49,null],[3,"BIP44","","BIP44 template. Expands to pkh(key/44\'/0\'/0\'/{0,1}/*)",null,null],[12,"0","","",50,null],[12,"1","","",50,null],[3,"BIP44Public","","BIP44 public template. Expands to pkh(key/{0,1}/*)",null,null],[12,"0","","",51,null],[12,"1","","",51,null],[12,"2","","",51,null],[3,"BIP49","","BIP49 template. Expands to sh(wpkh(key/49\'/0\'/0\'/{0,1}/*))",null,null],[12,"0","","",52,null],[12,"1","","",52,null],[3,"BIP49Public","","BIP49 public template. Expands to sh(wpkh(key/{0,1}/*))",null,null],[12,"0","","",53,null],[12,"1","","",53,null],[12,"2","","",53,null],[3,"BIP84","","BIP84 template. Expands to wpkh(key/84\'/0\'/0\'/{0,1}/*)",null,null],[12,"0","","",54,null],[12,"1","","",54,null],[3,"BIP84Public","","BIP84 public template. Expands to wpkh(key/{0,1}/*)",null,null],[12,"0","","",55,null],[12,"1","","",55,null],[12,"2","","",55,null],[6,"ExtendedDescriptor","bdk::descriptor","Alias for a [Descriptor] that can contain extended keys …",null,null],[6,"HDKeyPaths","","Alias for the type of maps that represent derivation …",null,null],[8,"ToWalletDescriptor","","Trait for types which can be converted into an […",null,null],[10,"to_wallet_descriptor","","Convert to wallet descriptor",56,[[["network",4]],[["result",4],["keyerror",4]]]],[8,"ExtractPolicy","","Trait implemented on [Descriptor]s to add a method to …",null,null],[10,"extract_policy","","Extract the spending [policy]",57,[[["signerscontainer",3],["secp256k1",3]],[["result",4],["error",4],["option",4]]]],[0,"keys","bdk","Key formats",null,null],[4,"DescriptorPublicKey","bdk::keys","The MiniscriptKey corresponding to Descriptors. This can …",null,null],[13,"SinglePub","","Single Public Key",58,null],[13,"XPub","","Xpub",58,null],[4,"DescriptorSecretKey","","A Secret Key that can be either a single key or an Xprv",null,null],[13,"SinglePriv","","Single Secret Key",59,null],[13,"XPrv","","Xprv",59,null],[3,"DescriptorSinglePriv","","A Single Descriptor Secret Key with optional origin …",null,null],[12,"origin","","Origin information",60,null],[12,"key","","The key",60,null],[3,"DescriptorSinglePub","","A Single Descriptor Key with optional origin information",null,null],[12,"origin","","Origin information",61,null],[12,"key","","The key",61,null],[3,"SortedMultiVec","","Contents of a \\\"sortedmulti\\\" descriptor",null,null],[12,"k","","signatures required",62,null],[12,"pks","","public keys inside sorted Multi",62,null],[8,"ScriptContext","","The ScriptContext for Miniscript. Additional type …",null,null],[10,"check_terminal_non_malleable","","Depending on ScriptContext, fragments can be malleable. …",26,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_witness","","Check whether the given satisfaction is valid under the …",26,[[],[["scriptcontexterror",4],["result",4]]]],[10,"max_satisfaction_size","","Depending on script context, the size of a satifaction …",26,[[["miniscript",3]],["option",4]]],[11,"check_global_consensus_validity","","Depending on script Context, some of the Terminals might …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_global_policy_validity","","Depending on script Context, some of the script resource …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_consensus_validity","","Consensus rules at the Miniscript satisfaction time. It …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_policy_validity","","Policy rules at the Miniscript satisfaction time. It is …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_global_validity","","Check the consensus + policy(if not disabled) rules that …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_validity","","Check the consensus + policy(if not disabled) rules …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"top_level_type_check","","Check whether the top-level is type B",26,[[["miniscript",3]],[["error",4],["result",4]]]],[11,"other_top_level_checks","","Other top level checks that are context specific",26,[[["miniscript",3]],[["error",4],["result",4]]]],[11,"top_level_checks","","Check top level consensus rules.",26,[[["miniscript",3]],[["error",4],["result",4]]]],[0,"bip39","","BIP-0039",null,null],[6,"MnemonicWithPassphrase","bdk::keys::bip39","Type for a BIP39 mnemonic with an optional passphrase",null,null],[6,"ValidNetworks","bdk::keys","Set of valid networks for a key",null,null],[5,"any_network","","Create a set containing mainnet, testnet and regtest",null,[[],["validnetworks",6]]],[5,"mainnet_network","","Create a set only containing mainnet",null,[[],["validnetworks",6]]],[5,"test_networks","","Create a set containing testnet and regtest",null,[[],["validnetworks",6]]],[5,"merge_networks","","Compute the intersection of two sets",null,[[["validnetworks",6]],["validnetworks",6]]],[4,"DescriptorKey","","Container for public or secret keys",null,null],[11,"from_public","","Create an instance given a public key and a set of valid …",63,[[["descriptorpublickey",4],["validnetworks",6]]]],[11,"from_secret","","Create an instance given a secret key and a set of valid …",63,[[["descriptorsecretkey",4],["validnetworks",6]]]],[11,"override_valid_networks","","Override the computed set of valid networks",63,[[["validnetworks",6]]]],[4,"ScriptContextEnum","","Enum representation of the known valid [ScriptContext]s",null,null],[13,"Legacy","","Legacy scripts",64,null],[13,"Segwitv0","","Segwitv0 scripts",64,null],[11,"is_legacy","","Returns whether the script context is […",64,[[]]],[11,"is_segwit_v0","","Returns whether the script context is […",64,[[]]],[8,"ExtScriptContext","","Trait that adds extra useful methods to [ScriptContext]s",null,null],[10,"as_enum","","Returns the [ScriptContext] as a [ScriptContextEnum]",65,[[],["scriptcontextenum",4]]],[11,"is_legacy","","Returns whether the script context is Legacy",65,[[]]],[11,"is_segwit_v0","","Returns whether the script context is Segwitv0",65,[[]]],[8,"ToDescriptorKey","","Trait for objects that can be turned into a public or …",null,null],[10,"to_descriptor_key","","Turn the key into a [DescriptorKey] within the requested […",66,[[],[["result",4],["descriptorkey",4],["keyerror",4]]]],[8,"DerivableKey","","Trait for keys that can be derived.",null,null],[10,"add_metadata","","Add a extra metadata, consume self and turn it into a […",67,[[["keysource",6],["derivationpath",3],["option",4]],[["result",4],["descriptorkey",4],["keyerror",4]]]],[3,"GeneratedKey","","Output of a [GeneratableKey] key generation",null,null],[11,"into_key","","Consumes self and returns the key",68,[[]]],[8,"GeneratableKey","","Trait for keys that can be generated",null,null],[16,"Entropy","","Type specifying the amount of entropy required e.g. [u8;32…",69,null],[16,"Options","","Extra options required by the generate_with_entropy",69,null],[16,"Error","","Returned error in case of failure",69,null],[10,"generate_with_entropy","","Generate a key given the extra options and the entropy",69,[[],[["result",4],["generatedkey",3]]]],[11,"generate","","Generate a key given the options with a random entropy",69,[[],[["result",4],["generatedkey",3]]]],[8,"GeneratableDefaultOptions","","Trait that allows generating a key with the default …",null,null],[11,"generate_with_entropy_default","","Generate a key with the default options and a given …",70,[[],[["result",4],["generatedkey",3]]]],[11,"generate_default","","Generate a key with the default options and a random …",70,[[],[["result",4],["generatedkey",3]]]],[3,"PrivateKeyGenerateOptions","","Options for generating a [PrivateKey]",null,null],[12,"compressed","","Whether the generated key should be \\\"compressed\\\" or not",71,null],[4,"KeyError","","Errors thrown while working with keys",null,null],[13,"InvalidScriptContext","","The key cannot exist in the given script context",72,null],[13,"InvalidNetwork","","The key is not valid for the given network",72,null],[13,"InvalidChecksum","","The key has an invalid checksum",72,null],[13,"Message","","Custom error message",72,null],[13,"BIP32","","BIP32 error",72,null],[13,"Miniscript","","Miniscript error",72,null],[0,"wallet","bdk","Wallet",null,null],[0,"address_validator","bdk::wallet","Address validation callbacks",null,null],[4,"AddressValidatorError","bdk::wallet::address_validator","Errors that can be returned to fail the validation of an …",null,null],[13,"UserRejected","","User rejected the address",73,null],[13,"ConnectionError","","Network connection error",73,null],[13,"TimeoutError","","Network request timeout error",73,null],[13,"InvalidScript","","Invalid script",73,null],[13,"Message","","A custom error message",73,null],[8,"AddressValidator","","Trait to build address validators",null,null],[10,"validate","","Validate or inspect an address",74,[[["script",3],["hdkeypaths",6],["keychainkind",4]],[["addressvalidatorerror",4],["result",4]]]],[0,"coin_selection","bdk::wallet","Coin selection",null,null],[6,"DefaultCoinSelectionAlgorithm","bdk::wallet::coin_selection","Default coin selection algorithm used by TxBuilder if not …",null,null],[3,"CoinSelectionResult","","Result of a successful coin selection",null,null],[12,"selected","","List of outputs selected for use as inputs",75,null],[12,"selected_amount","","Sum of the selected inputs\' value",75,null],[12,"fee_amount","","Total fee amount in satoshi",75,null],[8,"CoinSelectionAlgorithm","","Trait for generalized coin selection algorithms",null,null],[10,"coin_select","","Perform the coin selection",76,[[["feerate",3],["vec",3]],[["result",4],["error",4],["coinselectionresult",3]]]],[3,"LargestFirstCoinSelection","","Simple and dumb coin selection",null,null],[3,"BranchAndBoundCoinSelection","","Branch and bound coin selection",null,null],[11,"new","","Create new instance with target size for change output",77,[[]]],[0,"export","bdk::wallet","Wallet export",null,null],[3,"WalletExport","bdk::wallet::export","Structure that contains the export of a wallet",null,null],[12,"blockheight","","Earliest block to rescan when looking for the wallet\'s …",78,null],[12,"label","","Arbitrary label for the wallet",78,null],[11,"export_wallet","","Export a wallet",78,[[["wallet",3]],["result",4]]],[11,"descriptor","","Return the external descriptor",78,[[],["string",3]]],[11,"change_descriptor","","Return the internal descriptor, if present",78,[[],[["string",3],["option",4]]]],[0,"signer","bdk::wallet","Generalized signers",null,null],[4,"SignerId","bdk::wallet::signer","Identifier of a signer in the SignersContainers. Used as …",null,null],[13,"PkHash","","Bitcoin HASH160 (RIPEMD160 after SHA256) hash of an ECDSA …",79,null],[13,"Fingerprint","","The fingerprint of a BIP32 extended key",79,null],[4,"SignerError","","Signing error",null,null],[13,"MissingKey","","The private key is missing for the required public key",80,null],[13,"InvalidKey","","The private key in use has the right fingerprint but …",80,null],[13,"UserCanceled","","The user canceled the operation",80,null],[13,"InputIndexOutOfRange","","Input index is out of range",80,null],[13,"MissingNonWitnessUtxo","","The non_witness_utxo field of the transaction is required …",80,null],[13,"InvalidNonWitnessUtxo","","The non_witness_utxo specified is invalid",80,null],[13,"MissingWitnessUtxo","","The witness_utxo field of the transaction is required to …",80,null],[13,"MissingWitnessScript","","The witness_script field of the transaction is requied to …",80,null],[13,"MissingHDKeypath","","The fingerprint and derivation path are missing from the …",80,null],[8,"Signer","","Trait for signers",null,null],[10,"sign","","Sign a PSBT",81,[[["secp256k1",3],["partiallysignedtransaction",3],["option",4]],[["signererror",4],["result",4]]]],[10,"sign_whole_tx","","Return whether or not the signer signs the whole …",81,[[]]],[11,"descriptor_secret_key","","Return the secret key for the signer",81,[[],[["option",4],["descriptorsecretkey",4]]]],[3,"SignerOrdering","","Defines the order in which signers are called",null,null],[12,"0","","",82,null],[3,"SignersContainer","","Container for multiple signers",null,null],[11,"as_key_map","","Create a map of public keys to secret keys",83,[[["secp256k1",3]],["keymap",6]]],[11,"new","","Default constructor",83,[[]]],[11,"add_external","","Adds an external signer to the container for the …",83,[[["signer",8],["arc",3],["signerordering",3],["signerid",4]],[["arc",3],["option",4]]]],[11,"remove","","Removes a signer from the container and returns it",83,[[["signerordering",3],["signerid",4]],[["arc",3],["option",4]]]],[11,"ids","","Returns the list of identifiers of all the signers in the …",83,[[],[["signerid",4],["vec",3]]]],[11,"signers","","Returns the list of signers in the container, sorted by …",83,[[],[["vec",3],["arc",3]]]],[11,"find","","Finds the signer with lowest ordering for a given id in …",83,[[["signerid",4]],[["option",4],["arc",3]]]],[0,"time","bdk::wallet","Cross-platform time",null,null],[5,"get_timestamp","bdk::wallet::time","Return the current timestamp in seconds",null,[[]]],[0,"tx_builder","bdk::wallet","Transaction builder",null,null],[8,"TxBuilderContext","bdk::wallet::tx_builder","Context in which the [TxBuilder] is valid",null,null],[3,"CreateTx","","Wallet::create_tx context",null,null],[3,"BumpFee","","Wallet::bump_fee context",null,null],[3,"TxBuilder","","A transaction builder",null,null],[11,"new","","Create an empty builder",84,[[]]],[11,"fee_rate","","Set a custom fee rate",84,[[["feerate",3]]]],[11,"fee_absolute","","Set an absolute fee",84,[[]]],[11,"policy_path","","Set the policy path to use while creating the transaction …",84,[[["string",3],["btreemap",3],["vec",3],["keychainkind",4]]]],[11,"utxos","","Replace the internal list of utxos that must be spent …",84,[[["vec",3],["outpoint",3]]]],[11,"add_utxo","","Add a utxo to the internal list of utxos that must be …",84,[[["outpoint",3]]]],[11,"manually_selected_only","","Only spend utxos added by add_utxo and utxos.",84,[[]]],[11,"unspendable","","Replace the internal list of unspendable utxos with a new …",84,[[["vec",3],["outpoint",3]]]],[11,"add_unspendable","","Add a utxo to the internal list of unspendable utxos",84,[[["outpoint",3]]]],[11,"sighash","","Sign with a specific sig hash",84,[[["sighashtype",4]]]],[11,"ordering","","Choose the ordering for inputs and outputs of the …",84,[[["txordering",4]]]],[11,"nlocktime","","Use a specific nLockTime while creating the transaction",84,[[]]],[11,"version","","Build a transaction with a specific version",84,[[]]],[11,"do_not_spend_change","","Do not spend change outputs",84,[[]]],[11,"only_spend_change","","Only spend change outputs",84,[[]]],[11,"change_policy","","Set a specific [ChangeSpendPolicy]. See […",84,[[["changespendpolicy",4]]]],[11,"force_non_witness_utxo","","Fill-in the psbt::Input::non_witness_utxo field even if …",84,[[]]],[11,"include_output_redeem_witness_script","","Fill-in the psbt::Output::redeem_script and …",84,[[]]],[11,"add_global_xpubs","","Fill-in the PSBT_GLOBAL_XPUB field with the extended keys …",84,[[]]],[11,"drain_wallet","","Spend all the available inputs. This respects filters …",84,[[]]],[11,"coin_selection","","Choose the coin selection algorithm",84,[[["coinselectionalgorithm",8]],[["coinselectionalgorithm",8],["txbuilder",3]]]],[11,"with_recipients","","Create a builder starting from a list of recipients",84,[[["vec",3]]]],[11,"set_recipients","","Replace the recipients already added with a new list",84,[[["vec",3]]]],[11,"add_recipient","","Add a recipient to the internal list",84,[[["script",3]]]],[11,"set_single_recipient","","Set a single recipient that will get all the selected …",84,[[["script",3]]]],[11,"enable_rbf","","Enable signaling RBF",84,[[]]],[11,"enable_rbf_with_sequence","","Enable signaling RBF with a specific nSequence value",84,[[]]],[11,"maintain_single_recipient","","Bump the fees of a transaction made with …",84,[[]]],[4,"TxOrdering","","Ordering of the transaction\'s inputs and outputs",null,null],[13,"Shuffle","","Randomized (default)",85,null],[13,"Untouched","","Unchanged",85,null],[13,"BIP69Lexicographic","","BIP69 / Lexicographic",85,null],[11,"sort_tx","","Sort transaction inputs and outputs by [TxOrdering] …",85,[[["transaction",3]]]],[4,"ChangeSpendPolicy","","Policy regarding the use of change outputs when creating …",null,null],[13,"ChangeAllowed","","Use both change and non-change outputs (default)",86,null],[13,"OnlyChange","","Only use change outputs (see [TxBuilder::only_spend_change…",86,null],[13,"ChangeForbidden","","Only use non-change outputs (see […",86,null],[8,"IsDust","bdk::wallet","Trait to check if a value is below the dust limit",null,null],[10,"is_dust","","Check whether or not a value is below dust limit",87,[[]]],[6,"OfflineWallet","","Type alias for a [Wallet] that uses [OfflineBlockchain]",null,null],[3,"Wallet","","A Bitcoin wallet",null,null],[11,"new_offline","","Create a new \\\"offline\\\" wallet",88,[[["option",4],["network",4],["towalletdescriptor",8]],[["result",4],["error",4]]]],[11,"get_new_address","","Return a newly generated address using the external …",88,[[],[["address",3],["result",4],["error",4]]]],[11,"is_mine","","Return whether or not a script is part of this wallet …",88,[[["script",3]],[["result",4],["error",4]]]],[11,"list_unspent","","Return the list of unspent outputs of this wallet",88,[[],[["result",4],["vec",3],["error",4]]]],[11,"list_transactions","","Return the list of transactions made and received by the …",88,[[],[["error",4],["result",4],["vec",3]]]],[11,"get_balance","","Return the balance, meaning the sum of this wallet\'s …",88,[[],[["error",4],["result",4]]]],[11,"add_signer","","Add an external signer",88,[[["keychainkind",4],["signer",8],["arc",3],["signerordering",3],["signerid",4]]]],[11,"add_address_validator","","Add an address validator",88,[[["arc",3],["addressvalidator",8]]]],[11,"create_tx","","Create a new transaction following the options specified …",88,[[["coinselectionalgorithm",8],["txbuilder",3],["createtx",3]],[["result",4],["error",4]]]],[11,"bump_fee","","Bump the fee of a transaction following the options …",88,[[["txid",3],["coinselectionalgorithm",8],["txbuilder",3],["bumpfee",3]],[["result",4],["error",4]]]],[11,"sign","","Sign a transaction with all the wallet\'s signers, in the …",88,[[["option",4],["psbt",3]],[["result",4],["error",4]]]],[11,"policies","","Return the spending policies for the wallet\'s descriptor",88,[[["keychainkind",4]],[["error",4],["result",4],["option",4]]]],[11,"public_descriptor","","Return the \\\"public\\\" version of the wallet\'s descriptor, …",88,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"finalize_psbt","","Try to finalize a PSBT",88,[[["option",4],["psbt",3]],[["result",4],["error",4]]]],[11,"secp_ctx","","Return the secp256k1 context used for all signing …",88,[[],["secp256k1",3]]],[11,"new","","Create a new \\\"online\\\" wallet",88,[[["option",4],["network",4],["towalletdescriptor",8]],[["result",4],["error",4]]]],[11,"sync","","Sync the internal database with the blockchain",88,[[["option",4],["progress",8]],[["error",4],["result",4]]]],[11,"client","","Return a reference to the internal blockchain client",88,[[],["option",4]]],[11,"network","","Get the Bitcoin network the wallet is using.",88,[[],["network",4]]],[11,"broadcast","","Broadcast a transaction to the network",88,[[["transaction",3]],[["error",4],["result",4],["txid",3]]]],[4,"Error","bdk","Errors that can be thrown by the Wallet",null,null],[13,"InvalidU32Bytes","","Wrong number of bytes found when trying to convert to u32",89,null],[13,"Generic","","Generic error",89,null],[13,"ScriptDoesntHaveAddressForm","","This error is thrown when trying to convert Bare and …",89,null],[13,"SingleRecipientMultipleOutputs","","Found multiple outputs when single_recipient option has …",89,null],[13,"SingleRecipientNoInputs","","single_recipient option is selected but neither …",89,null],[13,"NoRecipients","","Cannot build a tx without recipients",89,null],[13,"NoUtxosSelected","","manually_selected_only option is selected but no utxo has …",89,null],[13,"OutputBelowDustLimit","","Output created is under the dust limit, 546 satoshis",89,null],[13,"InsufficientFunds","","Wallet\'s UTXO set is not enough to cover recipient\'s …",89,null],[13,"BnBTotalTriesExceeded","","Branch and bound coin selection possible attempts with …",89,null],[13,"BnBNoExactMatch","","Branch and bound coin selection tries to avoid needing a …",89,null],[13,"UnknownUTXO","","Happens when trying to spend an UTXO that is not in the …",89,null],[13,"TransactionNotFound","","Thrown when a tx is not found in the internal database",89,null],[13,"TransactionConfirmed","","Happens when trying to bump a transaction that is already …",89,null],[13,"IrreplaceableTransaction","","Trying to replace a tx that has a sequence >= 0xFFFFFFFE",89,null],[13,"FeeRateTooLow","","When bumping a tx the fee rate requested is lower than …",89,null],[12,"required","bdk::Error","Required fee rate (satoshi/vbyte)",90,null],[13,"FeeTooLow","bdk","When bumping a tx the absolute fee requested is lower …",89,null],[12,"required","bdk::Error","Required fee absolute value (satoshi)",91,null],[13,"MissingKeyOrigin","bdk","In order to use the TxBuilder::add_global_xpubs option …",89,null],[13,"Key","","Error while working with keys",89,null],[13,"ChecksumMismatch","","Descriptor checksum mismatch",89,null],[13,"SpendingPolicyRequired","","Spending policy is not compatible with this KeychainKind",89,null],[13,"InvalidPolicyPathError","","Error while extracting and manipulating policies",89,null],[13,"Signer","","Signing error",89,null],[13,"OfflineClient","","Thrown when trying to call a method that requires a …",89,null],[13,"InvalidProgressValue","","Progress value must be between 0.0 (included) and 100.0 …",89,null],[13,"ProgressUpdateError","","Progress update error (maybe the channel has been closed)",89,null],[13,"InvalidOutpoint","","Requested outpoint doesn\'t exist in the tx (vout greater …",89,null],[13,"Descriptor","","Error related to the parsing and usage of descriptors",89,null],[13,"AddressValidator","","Error that can be returned to fail the validation of an …",89,null],[13,"Encode","","Encoding error",89,null],[13,"Miniscript","","Miniscript error",89,null],[13,"BIP32","","BIP32 error",89,null],[13,"Secp256k1","","An ECDSA error",89,null],[13,"JSON","","Error serializing or deserializing JSON data",89,null],[13,"Hex","","Hex decoding error",89,null],[13,"PSBT","","Partially signed bitcoin transaction error",89,null],[13,"Electrum","","Electrum client error",89,null],[13,"Esplora","","Esplora client error",89,null],[13,"CompactFilters","","Compact filters client error)",89,null],[13,"Sled","","Sled database error",89,null],[4,"KeychainKind","","Types of keychains",null,null],[13,"External","","External",92,null],[13,"Internal","","Internal, usually used for change outputs",92,null],[3,"FeeRate","","Fee rate",null,null],[3,"UTXO","","A wallet unspent output",null,null],[12,"outpoint","","Reference to a transaction output",93,null],[12,"txout","","Transaction output",93,null],[12,"keychain","","Type of keychain",93,null],[3,"TransactionDetails","","A wallet transaction",null,null],[12,"transaction","","Optional transaction",94,null],[12,"txid","","Transaction id",94,null],[12,"timestamp","","Timestamp",94,null],[12,"received","","Received value (sats)",94,null],[12,"sent","","Sent value (sats)",94,null],[12,"fees","","Fee value (sats)",94,null],[12,"height","","Confirmed in block height, None means unconfirmed",94,null],[14,"descriptor","","Macro to write full descriptors with code",null,null],[14,"fragment","","Macro to write descriptor fragments with code",null,null],[11,"from","","",89,[[]]],[11,"into","","",89,[[]]],[11,"to_string","","",89,[[],["string",3]]],[11,"borrow","","",89,[[]]],[11,"borrow_mut","","",89,[[]]],[11,"try_from","","",89,[[],["result",4]]],[11,"try_into","","",89,[[],["result",4]]],[11,"type_id","","",89,[[],["typeid",3]]],[11,"vzip","","",89,[[]]],[11,"init","","",89,[[]]],[11,"deref","","",89,[[]]],[11,"deref_mut","","",89,[[]]],[11,"drop","","",89,[[]]],[11,"from","bdk::blockchain::any","",0,[[]]],[11,"into","","",0,[[]]],[11,"borrow","","",0,[[]]],[11,"borrow_mut","","",0,[[]]],[11,"try_from","","",0,[[],["result",4]]],[11,"try_into","","",0,[[],["result",4]]],[11,"type_id","","",0,[[],["typeid",3]]],[11,"vzip","","",0,[[]]],[11,"init","","",0,[[]]],[11,"deref","","",0,[[]]],[11,"deref_mut","","",0,[[]]],[11,"drop","","",0,[[]]],[11,"from","","",1,[[]]],[11,"into","","",1,[[]]],[11,"borrow","","",1,[[]]],[11,"borrow_mut","","",1,[[]]],[11,"try_from","","",1,[[],["result",4]]],[11,"try_into","","",1,[[],["result",4]]],[11,"type_id","","",1,[[],["typeid",3]]],[11,"vzip","","",1,[[]]],[11,"init","","",1,[[]]],[11,"deref","","",1,[[]]],[11,"deref_mut","","",1,[[]]],[11,"drop","","",1,[[]]],[11,"from","bdk::blockchain::electrum","",95,[[]]],[11,"into","","",95,[[]]],[11,"borrow","","",95,[[]]],[11,"borrow_mut","","",95,[[]]],[11,"try_from","","",95,[[],["result",4]]],[11,"try_into","","",95,[[],["result",4]]],[11,"type_id","","",95,[[],["typeid",3]]],[11,"vzip","","",95,[[]]],[11,"init","","",95,[[]]],[11,"deref","","",95,[[]]],[11,"deref_mut","","",95,[[]]],[11,"drop","","",95,[[]]],[11,"from","","",2,[[]]],[11,"into","","",2,[[]]],[11,"borrow","","",2,[[]]],[11,"borrow_mut","","",2,[[]]],[11,"try_from","","",2,[[],["result",4]]],[11,"try_into","","",2,[[],["result",4]]],[11,"type_id","","",2,[[],["typeid",3]]],[11,"vzip","","",2,[[]]],[11,"init","","",2,[[]]],[11,"deref","","",2,[[]]],[11,"deref_mut","","",2,[[]]],[11,"drop","","",2,[[]]],[11,"from","bdk::blockchain::esplora","",3,[[]]],[11,"into","","",3,[[]]],[11,"borrow","","",3,[[]]],[11,"borrow_mut","","",3,[[]]],[11,"try_from","","",3,[[],["result",4]]],[11,"try_into","","",3,[[],["result",4]]],[11,"type_id","","",3,[[],["typeid",3]]],[11,"vzip","","",3,[[]]],[11,"init","","",3,[[]]],[11,"deref","","",3,[[]]],[11,"deref_mut","","",3,[[]]],[11,"drop","","",3,[[]]],[11,"from","","",4,[[]]],[11,"into","","",4,[[]]],[11,"borrow","","",4,[[]]],[11,"borrow_mut","","",4,[[]]],[11,"try_from","","",4,[[],["result",4]]],[11,"try_into","","",4,[[],["result",4]]],[11,"type_id","","",4,[[],["typeid",3]]],[11,"vzip","","",4,[[]]],[11,"init","","",4,[[]]],[11,"deref","","",4,[[]]],[11,"deref_mut","","",4,[[]]],[11,"drop","","",4,[[]]],[11,"from","","",5,[[]]],[11,"into","","",5,[[]]],[11,"to_string","","",5,[[],["string",3]]],[11,"borrow","","",5,[[]]],[11,"borrow_mut","","",5,[[]]],[11,"try_from","","",5,[[],["result",4]]],[11,"try_into","","",5,[[],["result",4]]],[11,"type_id","","",5,[[],["typeid",3]]],[11,"vzip","","",5,[[]]],[11,"init","","",5,[[]]],[11,"deref","","",5,[[]]],[11,"deref_mut","","",5,[[]]],[11,"drop","","",5,[[]]],[11,"from","bdk::blockchain::compact_filters","",96,[[]]],[11,"into","","",96,[[]]],[11,"borrow","","",96,[[]]],[11,"borrow_mut","","",96,[[]]],[11,"try_from","","",96,[[],["result",4]]],[11,"try_into","","",96,[[],["result",4]]],[11,"type_id","","",96,[[],["typeid",3]]],[11,"vzip","","",96,[[]]],[11,"init","","",96,[[]]],[11,"deref","","",96,[[]]],[11,"deref_mut","","",96,[[]]],[11,"drop","","",96,[[]]],[11,"from","","",97,[[]]],[11,"into","","",97,[[]]],[11,"borrow","","",97,[[]]],[11,"borrow_mut","","",97,[[]]],[11,"try_from","","",97,[[],["result",4]]],[11,"try_into","","",97,[[],["result",4]]],[11,"type_id","","",97,[[],["typeid",3]]],[11,"vzip","","",97,[[]]],[11,"init","","",97,[[]]],[11,"deref","","",97,[[]]],[11,"deref_mut","","",97,[[]]],[11,"drop","","",97,[[]]],[11,"from","","",6,[[]]],[11,"into","","",6,[[]]],[11,"borrow","","",6,[[]]],[11,"borrow_mut","","",6,[[]]],[11,"try_from","","",6,[[],["result",4]]],[11,"try_into","","",6,[[],["result",4]]],[11,"type_id","","",6,[[],["typeid",3]]],[11,"vzip","","",6,[[]]],[11,"init","","",6,[[]]],[11,"deref","","",6,[[]]],[11,"deref_mut","","",6,[[]]],[11,"drop","","",6,[[]]],[11,"from","","",7,[[]]],[11,"into","","",7,[[]]],[11,"borrow","","",7,[[]]],[11,"borrow_mut","","",7,[[]]],[11,"try_from","","",7,[[],["result",4]]],[11,"try_into","","",7,[[],["result",4]]],[11,"type_id","","",7,[[],["typeid",3]]],[11,"vzip","","",7,[[]]],[11,"init","","",7,[[]]],[11,"deref","","",7,[[]]],[11,"deref_mut","","",7,[[]]],[11,"drop","","",7,[[]]],[11,"from","","",8,[[]]],[11,"into","","",8,[[]]],[11,"borrow","","",8,[[]]],[11,"borrow_mut","","",8,[[]]],[11,"try_from","","",8,[[],["result",4]]],[11,"try_into","","",8,[[],["result",4]]],[11,"type_id","","",8,[[],["typeid",3]]],[11,"vzip","","",8,[[]]],[11,"init","","",8,[[]]],[11,"deref","","",8,[[]]],[11,"deref_mut","","",8,[[]]],[11,"drop","","",8,[[]]],[11,"from","","",9,[[]]],[11,"into","","",9,[[]]],[11,"to_string","","",9,[[],["string",3]]],[11,"borrow","","",9,[[]]],[11,"borrow_mut","","",9,[[]]],[11,"try_from","","",9,[[],["result",4]]],[11,"try_into","","",9,[[],["result",4]]],[11,"type_id","","",9,[[],["typeid",3]]],[11,"vzip","","",9,[[]]],[11,"init","","",9,[[]]],[11,"deref","","",9,[[]]],[11,"deref_mut","","",9,[[]]],[11,"drop","","",9,[[]]],[11,"from","bdk::blockchain","",10,[[]]],[11,"into","","",10,[[]]],[11,"to_owned","","",10,[[]]],[11,"clone_into","","",10,[[]]],[11,"borrow","","",10,[[]]],[11,"borrow_mut","","",10,[[]]],[11,"try_from","","",10,[[],["result",4]]],[11,"try_into","","",10,[[],["result",4]]],[11,"type_id","","",10,[[],["typeid",3]]],[11,"vzip","","",10,[[]]],[11,"equivalent","","",10,[[]]],[11,"init","","",10,[[]]],[11,"deref","","",10,[[]]],[11,"deref_mut","","",10,[[]]],[11,"drop","","",10,[[]]],[11,"from","","",98,[[]]],[11,"into","","",98,[[]]],[11,"borrow","","",98,[[]]],[11,"borrow_mut","","",98,[[]]],[11,"try_from","","",98,[[],["result",4]]],[11,"try_into","","",98,[[],["result",4]]],[11,"type_id","","",98,[[],["typeid",3]]],[11,"vzip","","",98,[[]]],[11,"init","","",98,[[]]],[11,"deref","","",98,[[]]],[11,"deref_mut","","",98,[[]]],[11,"drop","","",98,[[]]],[11,"from","","",99,[[]]],[11,"into","","",99,[[]]],[11,"to_owned","","",99,[[]]],[11,"clone_into","","",99,[[]]],[11,"borrow","","",99,[[]]],[11,"borrow_mut","","",99,[[]]],[11,"try_from","","",99,[[],["result",4]]],[11,"try_into","","",99,[[],["result",4]]],[11,"type_id","","",99,[[],["typeid",3]]],[11,"vzip","","",99,[[]]],[11,"init","","",99,[[]]],[11,"deref","","",99,[[]]],[11,"deref_mut","","",99,[[]]],[11,"drop","","",99,[[]]],[11,"from","","",100,[[]]],[11,"into","","",100,[[]]],[11,"to_owned","","",100,[[]]],[11,"clone_into","","",100,[[]]],[11,"borrow","","",100,[[]]],[11,"borrow_mut","","",100,[[]]],[11,"try_from","","",100,[[],["result",4]]],[11,"try_into","","",100,[[],["result",4]]],[11,"type_id","","",100,[[],["typeid",3]]],[11,"vzip","","",100,[[]]],[11,"init","","",100,[[]]],[11,"deref","","",100,[[]]],[11,"deref_mut","","",100,[[]]],[11,"drop","","",100,[[]]],[11,"from","bdk::database::any","",14,[[]]],[11,"into","","",14,[[]]],[11,"borrow","","",14,[[]]],[11,"borrow_mut","","",14,[[]]],[11,"try_from","","",14,[[],["result",4]]],[11,"try_into","","",14,[[],["result",4]]],[11,"type_id","","",14,[[],["typeid",3]]],[11,"vzip","","",14,[[]]],[11,"init","","",14,[[]]],[11,"deref","","",14,[[]]],[11,"deref_mut","","",14,[[]]],[11,"drop","","",14,[[]]],[11,"from","","",15,[[]]],[11,"into","","",15,[[]]],[11,"borrow","","",15,[[]]],[11,"borrow_mut","","",15,[[]]],[11,"try_from","","",15,[[],["result",4]]],[11,"try_into","","",15,[[],["result",4]]],[11,"type_id","","",15,[[],["typeid",3]]],[11,"vzip","","",15,[[]]],[11,"init","","",15,[[]]],[11,"deref","","",15,[[]]],[11,"deref_mut","","",15,[[]]],[11,"drop","","",15,[[]]],[11,"from","","",16,[[]]],[11,"into","","",16,[[]]],[11,"borrow","","",16,[[]]],[11,"borrow_mut","","",16,[[]]],[11,"try_from","","",16,[[],["result",4]]],[11,"try_into","","",16,[[],["result",4]]],[11,"type_id","","",16,[[],["typeid",3]]],[11,"vzip","","",16,[[]]],[11,"init","","",16,[[]]],[11,"deref","","",16,[[]]],[11,"deref_mut","","",16,[[]]],[11,"drop","","",16,[[]]],[11,"from","","",17,[[]]],[11,"into","","",17,[[]]],[11,"borrow","","",17,[[]]],[11,"borrow_mut","","",17,[[]]],[11,"try_from","","",17,[[],["result",4]]],[11,"try_into","","",17,[[],["result",4]]],[11,"type_id","","",17,[[],["typeid",3]]],[11,"vzip","","",17,[[]]],[11,"init","","",17,[[]]],[11,"deref","","",17,[[]]],[11,"deref_mut","","",17,[[]]],[11,"drop","","",17,[[]]],[11,"from","bdk::database::memory","",18,[[]]],[11,"into","","",18,[[]]],[11,"borrow","","",18,[[]]],[11,"borrow_mut","","",18,[[]]],[11,"try_from","","",18,[[],["result",4]]],[11,"try_into","","",18,[[],["result",4]]],[11,"type_id","","",18,[[],["typeid",3]]],[11,"vzip","","",18,[[]]],[11,"init","","",18,[[]]],[11,"deref","","",18,[[]]],[11,"deref_mut","","",18,[[]]],[11,"drop","","",18,[[]]],[11,"from","bdk::descriptor","",23,[[]]],[11,"into","","",23,[[]]],[11,"to_owned","","",23,[[]]],[11,"clone_into","","",23,[[]]],[11,"to_string","","",23,[[],["string",3]]],[11,"borrow","","",23,[[]]],[11,"borrow_mut","","",23,[[]]],[11,"try_from","","",23,[[],["result",4]]],[11,"try_into","","",23,[[],["result",4]]],[11,"type_id","","",23,[[],["typeid",3]]],[11,"vzip","","",23,[[]]],[11,"equivalent","","",23,[[]]],[11,"init","","",23,[[]]],[11,"deref","","",23,[[]]],[11,"deref_mut","","",23,[[]]],[11,"drop","","",23,[[]]],[11,"as_enum","","",101,[[],["scriptcontextenum",4]]],[11,"from","","",101,[[]]],[11,"into","","",101,[[]]],[11,"to_owned","","",101,[[]]],[11,"clone_into","","",101,[[]]],[11,"borrow","","",101,[[]]],[11,"borrow_mut","","",101,[[]]],[11,"try_from","","",101,[[],["result",4]]],[11,"try_into","","",101,[[],["result",4]]],[11,"type_id","","",101,[[],["typeid",3]]],[11,"vzip","","",101,[[]]],[11,"equivalent","","",101,[[]]],[11,"init","","",101,[[]]],[11,"deref","","",101,[[]]],[11,"deref_mut","","",101,[[]]],[11,"drop","","",101,[[]]],[11,"from","","",24,[[]]],[11,"into","","",24,[[]]],[11,"to_owned","","",24,[[]]],[11,"clone_into","","",24,[[]]],[11,"to_string","","",24,[[],["string",3]]],[11,"borrow","","",24,[[]]],[11,"borrow_mut","","",24,[[]]],[11,"try_from","","",24,[[],["result",4]]],[11,"try_into","","",24,[[],["result",4]]],[11,"type_id","","",24,[[],["typeid",3]]],[11,"vzip","","",24,[[]]],[11,"equivalent","","",24,[[]]],[11,"init","","",24,[[]]],[11,"deref","","",24,[[]]],[11,"deref_mut","","",24,[[]]],[11,"drop","","",24,[[]]],[11,"as_enum","","",102,[[],["scriptcontextenum",4]]],[11,"from","","",102,[[]]],[11,"into","","",102,[[]]],[11,"to_owned","","",102,[[]]],[11,"clone_into","","",102,[[]]],[11,"borrow","","",102,[[]]],[11,"borrow_mut","","",102,[[]]],[11,"try_from","","",102,[[],["result",4]]],[11,"try_into","","",102,[[],["result",4]]],[11,"type_id","","",102,[[],["typeid",3]]],[11,"vzip","","",102,[[]]],[11,"equivalent","","",102,[[]]],[11,"init","","",102,[[]]],[11,"deref","","",102,[[]]],[11,"deref_mut","","",102,[[]]],[11,"drop","","",102,[[]]],[11,"from","","",27,[[]]],[11,"into","","",27,[[]]],[11,"to_owned","","",27,[[]]],[11,"clone_into","","",27,[[]]],[11,"to_string","","",27,[[],["string",3]]],[11,"borrow","","",27,[[]]],[11,"borrow_mut","","",27,[[]]],[11,"try_from","","",27,[[],["result",4]]],[11,"try_into","","",27,[[],["result",4]]],[11,"type_id","","",27,[[],["typeid",3]]],[11,"vzip","","",27,[[]]],[11,"equivalent","","",27,[[]]],[11,"init","","",27,[[]]],[11,"deref","","",27,[[]]],[11,"deref_mut","","",27,[[]]],[11,"drop","","",27,[[]]],[11,"from","bdk::descriptor::error","",29,[[]]],[11,"into","","",29,[[]]],[11,"to_string","","",29,[[],["string",3]]],[11,"borrow","","",29,[[]]],[11,"borrow_mut","","",29,[[]]],[11,"try_from","","",29,[[],["result",4]]],[11,"try_into","","",29,[[],["result",4]]],[11,"type_id","","",29,[[],["typeid",3]]],[11,"vzip","","",29,[[]]],[11,"init","","",29,[[]]],[11,"deref","","",29,[[]]],[11,"deref_mut","","",29,[[]]],[11,"drop","","",29,[[]]],[11,"from","bdk::descriptor::policy","",103,[[]]],[11,"into","","",103,[[]]],[11,"to_owned","","",103,[[]]],[11,"clone_into","","",103,[[]]],[11,"borrow","","",103,[[]]],[11,"borrow_mut","","",103,[[]]],[11,"try_from","","",103,[[],["result",4]]],[11,"try_into","","",103,[[],["result",4]]],[11,"type_id","","",103,[[],["typeid",3]]],[11,"vzip","","",103,[[]]],[11,"init","","",103,[[]]],[11,"deref","","",103,[[]]],[11,"deref_mut","","",103,[[]]],[11,"drop","","",103,[[]]],[11,"from","","",30,[[]]],[11,"into","","",30,[[]]],[11,"to_owned","","",30,[[]]],[11,"clone_into","","",30,[[]]],[11,"borrow","","",30,[[]]],[11,"borrow_mut","","",30,[[]]],[11,"try_from","","",30,[[],["result",4]]],[11,"try_into","","",30,[[],["result",4]]],[11,"type_id","","",30,[[],["typeid",3]]],[11,"vzip","","",30,[[]]],[11,"init","","",30,[[]]],[11,"deref","","",30,[[]]],[11,"deref_mut","","",30,[[]]],[11,"drop","","",30,[[]]],[11,"from","","",39,[[]]],[11,"into","","",39,[[]]],[11,"to_owned","","",39,[[]]],[11,"clone_into","","",39,[[]]],[11,"borrow","","",39,[[]]],[11,"borrow_mut","","",39,[[]]],[11,"try_from","","",39,[[],["result",4]]],[11,"try_into","","",39,[[],["result",4]]],[11,"type_id","","",39,[[],["typeid",3]]],[11,"vzip","","",39,[[]]],[11,"init","","",39,[[]]],[11,"deref","","",39,[[]]],[11,"deref_mut","","",39,[[]]],[11,"drop","","",39,[[]]],[11,"from","","",43,[[]]],[11,"into","","",43,[[]]],[11,"to_owned","","",43,[[]]],[11,"clone_into","","",43,[[]]],[11,"borrow","","",43,[[]]],[11,"borrow_mut","","",43,[[]]],[11,"try_from","","",43,[[],["result",4]]],[11,"try_into","","",43,[[],["result",4]]],[11,"type_id","","",43,[[],["typeid",3]]],[11,"vzip","","",43,[[]]],[11,"init","","",43,[[]]],[11,"deref","","",43,[[]]],[11,"deref_mut","","",43,[[]]],[11,"drop","","",43,[[]]],[11,"from","","",44,[[]]],[11,"into","","",44,[[]]],[11,"to_owned","","",44,[[]]],[11,"clone_into","","",44,[[]]],[11,"borrow","","",44,[[]]],[11,"borrow_mut","","",44,[[]]],[11,"try_from","","",44,[[],["result",4]]],[11,"try_into","","",44,[[],["result",4]]],[11,"type_id","","",44,[[],["typeid",3]]],[11,"vzip","","",44,[[]]],[11,"equivalent","","",44,[[]]],[11,"init","","",44,[[]]],[11,"deref","","",44,[[]]],[11,"deref_mut","","",44,[[]]],[11,"drop","","",44,[[]]],[11,"from","","",45,[[]]],[11,"into","","",45,[[]]],[11,"to_string","","",45,[[],["string",3]]],[11,"borrow","","",45,[[]]],[11,"borrow_mut","","",45,[[]]],[11,"try_from","","",45,[[],["result",4]]],[11,"try_into","","",45,[[],["result",4]]],[11,"type_id","","",45,[[],["typeid",3]]],[11,"vzip","","",45,[[]]],[11,"init","","",45,[[]]],[11,"deref","","",45,[[]]],[11,"deref_mut","","",45,[[]]],[11,"drop","","",45,[[]]],[11,"to_wallet_descriptor","bdk::descriptor::template","",47,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",47,[[]]],[11,"into","","",47,[[]]],[11,"borrow","","",47,[[]]],[11,"borrow_mut","","",47,[[]]],[11,"try_from","","",47,[[],["result",4]]],[11,"try_into","","",47,[[],["result",4]]],[11,"type_id","","",47,[[],["typeid",3]]],[11,"vzip","","",47,[[]]],[11,"init","","",47,[[]]],[11,"deref","","",47,[[]]],[11,"deref_mut","","",47,[[]]],[11,"drop","","",47,[[]]],[11,"to_wallet_descriptor","","",48,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",48,[[]]],[11,"into","","",48,[[]]],[11,"borrow","","",48,[[]]],[11,"borrow_mut","","",48,[[]]],[11,"try_from","","",48,[[],["result",4]]],[11,"try_into","","",48,[[],["result",4]]],[11,"type_id","","",48,[[],["typeid",3]]],[11,"vzip","","",48,[[]]],[11,"init","","",48,[[]]],[11,"deref","","",48,[[]]],[11,"deref_mut","","",48,[[]]],[11,"drop","","",48,[[]]],[11,"to_wallet_descriptor","","",49,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",49,[[]]],[11,"into","","",49,[[]]],[11,"borrow","","",49,[[]]],[11,"borrow_mut","","",49,[[]]],[11,"try_from","","",49,[[],["result",4]]],[11,"try_into","","",49,[[],["result",4]]],[11,"type_id","","",49,[[],["typeid",3]]],[11,"vzip","","",49,[[]]],[11,"init","","",49,[[]]],[11,"deref","","",49,[[]]],[11,"deref_mut","","",49,[[]]],[11,"drop","","",49,[[]]],[11,"to_wallet_descriptor","","",50,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",50,[[]]],[11,"into","","",50,[[]]],[11,"borrow","","",50,[[]]],[11,"borrow_mut","","",50,[[]]],[11,"try_from","","",50,[[],["result",4]]],[11,"try_into","","",50,[[],["result",4]]],[11,"type_id","","",50,[[],["typeid",3]]],[11,"vzip","","",50,[[]]],[11,"init","","",50,[[]]],[11,"deref","","",50,[[]]],[11,"deref_mut","","",50,[[]]],[11,"drop","","",50,[[]]],[11,"to_wallet_descriptor","","",51,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",51,[[]]],[11,"into","","",51,[[]]],[11,"borrow","","",51,[[]]],[11,"borrow_mut","","",51,[[]]],[11,"try_from","","",51,[[],["result",4]]],[11,"try_into","","",51,[[],["result",4]]],[11,"type_id","","",51,[[],["typeid",3]]],[11,"vzip","","",51,[[]]],[11,"init","","",51,[[]]],[11,"deref","","",51,[[]]],[11,"deref_mut","","",51,[[]]],[11,"drop","","",51,[[]]],[11,"to_wallet_descriptor","","",52,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",52,[[]]],[11,"into","","",52,[[]]],[11,"borrow","","",52,[[]]],[11,"borrow_mut","","",52,[[]]],[11,"try_from","","",52,[[],["result",4]]],[11,"try_into","","",52,[[],["result",4]]],[11,"type_id","","",52,[[],["typeid",3]]],[11,"vzip","","",52,[[]]],[11,"init","","",52,[[]]],[11,"deref","","",52,[[]]],[11,"deref_mut","","",52,[[]]],[11,"drop","","",52,[[]]],[11,"to_wallet_descriptor","","",53,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",53,[[]]],[11,"into","","",53,[[]]],[11,"borrow","","",53,[[]]],[11,"borrow_mut","","",53,[[]]],[11,"try_from","","",53,[[],["result",4]]],[11,"try_into","","",53,[[],["result",4]]],[11,"type_id","","",53,[[],["typeid",3]]],[11,"vzip","","",53,[[]]],[11,"init","","",53,[[]]],[11,"deref","","",53,[[]]],[11,"deref_mut","","",53,[[]]],[11,"drop","","",53,[[]]],[11,"to_wallet_descriptor","","",54,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",54,[[]]],[11,"into","","",54,[[]]],[11,"borrow","","",54,[[]]],[11,"borrow_mut","","",54,[[]]],[11,"try_from","","",54,[[],["result",4]]],[11,"try_into","","",54,[[],["result",4]]],[11,"type_id","","",54,[[],["typeid",3]]],[11,"vzip","","",54,[[]]],[11,"init","","",54,[[]]],[11,"deref","","",54,[[]]],[11,"deref_mut","","",54,[[]]],[11,"drop","","",54,[[]]],[11,"to_wallet_descriptor","","",55,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",55,[[]]],[11,"into","","",55,[[]]],[11,"borrow","","",55,[[]]],[11,"borrow_mut","","",55,[[]]],[11,"try_from","","",55,[[],["result",4]]],[11,"try_into","","",55,[[],["result",4]]],[11,"type_id","","",55,[[],["typeid",3]]],[11,"vzip","","",55,[[]]],[11,"init","","",55,[[]]],[11,"deref","","",55,[[]]],[11,"deref_mut","","",55,[[]]],[11,"drop","","",55,[[]]],[11,"from","bdk::keys","",58,[[]]],[11,"into","","",58,[[]]],[11,"to_owned","","",58,[[]]],[11,"clone_into","","",58,[[]]],[11,"to_string","","",58,[[],["string",3]]],[11,"borrow","","",58,[[]]],[11,"borrow_mut","","",58,[[]]],[11,"try_from","","",58,[[],["result",4]]],[11,"try_into","","",58,[[],["result",4]]],[11,"type_id","","",58,[[],["typeid",3]]],[11,"vzip","","",58,[[]]],[11,"equivalent","","",58,[[]]],[11,"init","","",58,[[]]],[11,"deref","","",58,[[]]],[11,"deref_mut","","",58,[[]]],[11,"drop","","",58,[[]]],[11,"from","","",59,[[]]],[11,"into","","",59,[[]]],[11,"to_string","","",59,[[],["string",3]]],[11,"borrow","","",59,[[]]],[11,"borrow_mut","","",59,[[]]],[11,"try_from","","",59,[[],["result",4]]],[11,"try_into","","",59,[[],["result",4]]],[11,"type_id","","",59,[[],["typeid",3]]],[11,"vzip","","",59,[[]]],[11,"init","","",59,[[]]],[11,"deref","","",59,[[]]],[11,"deref_mut","","",59,[[]]],[11,"drop","","",59,[[]]],[11,"from","","",60,[[]]],[11,"into","","",60,[[]]],[11,"borrow","","",60,[[]]],[11,"borrow_mut","","",60,[[]]],[11,"try_from","","",60,[[],["result",4]]],[11,"try_into","","",60,[[],["result",4]]],[11,"type_id","","",60,[[],["typeid",3]]],[11,"vzip","","",60,[[]]],[11,"init","","",60,[[]]],[11,"deref","","",60,[[]]],[11,"deref_mut","","",60,[[]]],[11,"drop","","",60,[[]]],[11,"from","","",61,[[]]],[11,"into","","",61,[[]]],[11,"to_owned","","",61,[[]]],[11,"clone_into","","",61,[[]]],[11,"borrow","","",61,[[]]],[11,"borrow_mut","","",61,[[]]],[11,"try_from","","",61,[[],["result",4]]],[11,"try_into","","",61,[[],["result",4]]],[11,"type_id","","",61,[[],["typeid",3]]],[11,"vzip","","",61,[[]]],[11,"equivalent","","",61,[[]]],[11,"init","","",61,[[]]],[11,"deref","","",61,[[]]],[11,"deref_mut","","",61,[[]]],[11,"drop","","",61,[[]]],[11,"from","","",62,[[]]],[11,"into","","",62,[[]]],[11,"to_owned","","",62,[[]]],[11,"clone_into","","",62,[[]]],[11,"to_string","","",62,[[],["string",3]]],[11,"borrow","","",62,[[]]],[11,"borrow_mut","","",62,[[]]],[11,"try_from","","",62,[[],["result",4]]],[11,"try_into","","",62,[[],["result",4]]],[11,"type_id","","",62,[[],["typeid",3]]],[11,"vzip","","",62,[[]]],[11,"equivalent","","",62,[[]]],[11,"init","","",62,[[]]],[11,"deref","","",62,[[]]],[11,"deref_mut","","",62,[[]]],[11,"drop","","",62,[[]]],[11,"from","","",63,[[]]],[11,"into","","",63,[[]]],[11,"borrow","","",63,[[]]],[11,"borrow_mut","","",63,[[]]],[11,"try_from","","",63,[[],["result",4]]],[11,"try_into","","",63,[[],["result",4]]],[11,"type_id","","",63,[[],["typeid",3]]],[11,"vzip","","",63,[[]]],[11,"init","","",63,[[]]],[11,"deref","","",63,[[]]],[11,"deref_mut","","",63,[[]]],[11,"drop","","",63,[[]]],[11,"from","","",64,[[]]],[11,"into","","",64,[[]]],[11,"to_owned","","",64,[[]]],[11,"clone_into","","",64,[[]]],[11,"borrow","","",64,[[]]],[11,"borrow_mut","","",64,[[]]],[11,"try_from","","",64,[[],["result",4]]],[11,"try_into","","",64,[[],["result",4]]],[11,"type_id","","",64,[[],["typeid",3]]],[11,"vzip","","",64,[[]]],[11,"equivalent","","",64,[[]]],[11,"init","","",64,[[]]],[11,"deref","","",64,[[]]],[11,"deref_mut","","",64,[[]]],[11,"drop","","",64,[[]]],[11,"from","","",68,[[]]],[11,"into","","",68,[[]]],[11,"borrow","","",68,[[]]],[11,"borrow_mut","","",68,[[]]],[11,"try_from","","",68,[[],["result",4]]],[11,"try_into","","",68,[[],["result",4]]],[11,"type_id","","",68,[[],["typeid",3]]],[11,"vzip","","",68,[[]]],[11,"init","","",68,[[]]],[11,"deref","","",68,[[]]],[11,"deref_mut","","",68,[[]]],[11,"drop","","",68,[[]]],[11,"from","","",71,[[]]],[11,"into","","",71,[[]]],[11,"to_owned","","",71,[[]]],[11,"clone_into","","",71,[[]]],[11,"borrow","","",71,[[]]],[11,"borrow_mut","","",71,[[]]],[11,"try_from","","",71,[[],["result",4]]],[11,"try_into","","",71,[[],["result",4]]],[11,"type_id","","",71,[[],["typeid",3]]],[11,"vzip","","",71,[[]]],[11,"init","","",71,[[]]],[11,"deref","","",71,[[]]],[11,"deref_mut","","",71,[[]]],[11,"drop","","",71,[[]]],[11,"from","","",72,[[]]],[11,"into","","",72,[[]]],[11,"to_string","","",72,[[],["string",3]]],[11,"borrow","","",72,[[]]],[11,"borrow_mut","","",72,[[]]],[11,"try_from","","",72,[[],["result",4]]],[11,"try_into","","",72,[[],["result",4]]],[11,"type_id","","",72,[[],["typeid",3]]],[11,"vzip","","",72,[[]]],[11,"init","","",72,[[]]],[11,"deref","","",72,[[]]],[11,"deref_mut","","",72,[[]]],[11,"drop","","",72,[[]]],[11,"from","bdk","",92,[[]]],[11,"into","","",92,[[]]],[11,"to_owned","","",92,[[]]],[11,"clone_into","","",92,[[]]],[11,"borrow","","",92,[[]]],[11,"borrow_mut","","",92,[[]]],[11,"try_from","","",92,[[],["result",4]]],[11,"try_into","","",92,[[],["result",4]]],[11,"type_id","","",92,[[],["typeid",3]]],[11,"write_base32","","",92,[[],["result",4]]],[11,"base32_len","","",92,[[]]],[11,"check_base32","","",92,[[],[["result",4],["vec",3]]]],[11,"vzip","","",92,[[]]],[11,"equivalent","","",92,[[]]],[11,"init","","",92,[[]]],[11,"deref","","",92,[[]]],[11,"deref_mut","","",92,[[]]],[11,"drop","","",92,[[]]],[11,"from","","",104,[[]]],[11,"into","","",104,[[]]],[11,"to_owned","","",104,[[]]],[11,"clone_into","","",104,[[]]],[11,"borrow","","",104,[[]]],[11,"borrow_mut","","",104,[[]]],[11,"try_from","","",104,[[],["result",4]]],[11,"try_into","","",104,[[],["result",4]]],[11,"type_id","","",104,[[],["typeid",3]]],[11,"vzip","","",104,[[]]],[11,"init","","",104,[[]]],[11,"deref","","",104,[[]]],[11,"deref_mut","","",104,[[]]],[11,"drop","","",104,[[]]],[11,"from","","",93,[[]]],[11,"into","","",93,[[]]],[11,"to_owned","","",93,[[]]],[11,"clone_into","","",93,[[]]],[11,"borrow","","",93,[[]]],[11,"borrow_mut","","",93,[[]]],[11,"try_from","","",93,[[],["result",4]]],[11,"try_into","","",93,[[],["result",4]]],[11,"type_id","","",93,[[],["typeid",3]]],[11,"vzip","","",93,[[]]],[11,"equivalent","","",93,[[]]],[11,"init","","",93,[[]]],[11,"deref","","",93,[[]]],[11,"deref_mut","","",93,[[]]],[11,"drop","","",93,[[]]],[11,"from","","",94,[[]]],[11,"into","","",94,[[]]],[11,"to_owned","","",94,[[]]],[11,"clone_into","","",94,[[]]],[11,"borrow","","",94,[[]]],[11,"borrow_mut","","",94,[[]]],[11,"try_from","","",94,[[],["result",4]]],[11,"try_into","","",94,[[],["result",4]]],[11,"type_id","","",94,[[],["typeid",3]]],[11,"vzip","","",94,[[]]],[11,"equivalent","","",94,[[]]],[11,"init","","",94,[[]]],[11,"deref","","",94,[[]]],[11,"deref_mut","","",94,[[]]],[11,"drop","","",94,[[]]],[11,"from","bdk::wallet::address_validator","",73,[[]]],[11,"into","","",73,[[]]],[11,"to_owned","","",73,[[]]],[11,"clone_into","","",73,[[]]],[11,"to_string","","",73,[[],["string",3]]],[11,"borrow","","",73,[[]]],[11,"borrow_mut","","",73,[[]]],[11,"try_from","","",73,[[],["result",4]]],[11,"try_into","","",73,[[],["result",4]]],[11,"type_id","","",73,[[],["typeid",3]]],[11,"vzip","","",73,[[]]],[11,"equivalent","","",73,[[]]],[11,"init","","",73,[[]]],[11,"deref","","",73,[[]]],[11,"deref_mut","","",73,[[]]],[11,"drop","","",73,[[]]],[11,"from","bdk::wallet::coin_selection","",75,[[]]],[11,"into","","",75,[[]]],[11,"borrow","","",75,[[]]],[11,"borrow_mut","","",75,[[]]],[11,"try_from","","",75,[[],["result",4]]],[11,"try_into","","",75,[[],["result",4]]],[11,"type_id","","",75,[[],["typeid",3]]],[11,"vzip","","",75,[[]]],[11,"init","","",75,[[]]],[11,"deref","","",75,[[]]],[11,"deref_mut","","",75,[[]]],[11,"drop","","",75,[[]]],[11,"from","","",105,[[]]],[11,"into","","",105,[[]]],[11,"borrow","","",105,[[]]],[11,"borrow_mut","","",105,[[]]],[11,"try_from","","",105,[[],["result",4]]],[11,"try_into","","",105,[[],["result",4]]],[11,"type_id","","",105,[[],["typeid",3]]],[11,"vzip","","",105,[[]]],[11,"init","","",105,[[]]],[11,"deref","","",105,[[]]],[11,"deref_mut","","",105,[[]]],[11,"drop","","",105,[[]]],[11,"from","","",77,[[]]],[11,"into","","",77,[[]]],[11,"borrow","","",77,[[]]],[11,"borrow_mut","","",77,[[]]],[11,"try_from","","",77,[[],["result",4]]],[11,"try_into","","",77,[[],["result",4]]],[11,"type_id","","",77,[[],["typeid",3]]],[11,"vzip","","",77,[[]]],[11,"init","","",77,[[]]],[11,"deref","","",77,[[]]],[11,"deref_mut","","",77,[[]]],[11,"drop","","",77,[[]]],[11,"from","bdk::wallet::export","",78,[[]]],[11,"into","","",78,[[]]],[11,"borrow","","",78,[[]]],[11,"borrow_mut","","",78,[[]]],[11,"try_from","","",78,[[],["result",4]]],[11,"try_into","","",78,[[],["result",4]]],[11,"type_id","","",78,[[],["typeid",3]]],[11,"vzip","","",78,[[]]],[11,"init","","",78,[[]]],[11,"deref","","",78,[[]]],[11,"deref_mut","","",78,[[]]],[11,"drop","","",78,[[]]],[11,"from","bdk::wallet::signer","",79,[[]]],[11,"into","","",79,[[]]],[11,"to_owned","","",79,[[]]],[11,"clone_into","","",79,[[]]],[11,"borrow","","",79,[[]]],[11,"borrow_mut","","",79,[[]]],[11,"try_from","","",79,[[],["result",4]]],[11,"try_into","","",79,[[],["result",4]]],[11,"type_id","","",79,[[],["typeid",3]]],[11,"vzip","","",79,[[]]],[11,"equivalent","","",79,[[]]],[11,"init","","",79,[[]]],[11,"deref","","",79,[[]]],[11,"deref_mut","","",79,[[]]],[11,"drop","","",79,[[]]],[11,"from","","",80,[[]]],[11,"into","","",80,[[]]],[11,"to_owned","","",80,[[]]],[11,"clone_into","","",80,[[]]],[11,"to_string","","",80,[[],["string",3]]],[11,"borrow","","",80,[[]]],[11,"borrow_mut","","",80,[[]]],[11,"try_from","","",80,[[],["result",4]]],[11,"try_into","","",80,[[],["result",4]]],[11,"type_id","","",80,[[],["typeid",3]]],[11,"vzip","","",80,[[]]],[11,"equivalent","","",80,[[]]],[11,"init","","",80,[[]]],[11,"deref","","",80,[[]]],[11,"deref_mut","","",80,[[]]],[11,"drop","","",80,[[]]],[11,"from","","",82,[[]]],[11,"into","","",82,[[]]],[11,"to_owned","","",82,[[]]],[11,"clone_into","","",82,[[]]],[11,"borrow","","",82,[[]]],[11,"borrow_mut","","",82,[[]]],[11,"try_from","","",82,[[],["result",4]]],[11,"try_into","","",82,[[],["result",4]]],[11,"type_id","","",82,[[],["typeid",3]]],[11,"vzip","","",82,[[]]],[11,"equivalent","","",82,[[]]],[11,"init","","",82,[[]]],[11,"deref","","",82,[[]]],[11,"deref_mut","","",82,[[]]],[11,"drop","","",82,[[]]],[11,"from","","",83,[[]]],[11,"into","","",83,[[]]],[11,"to_owned","","",83,[[]]],[11,"clone_into","","",83,[[]]],[11,"borrow","","",83,[[]]],[11,"borrow_mut","","",83,[[]]],[11,"try_from","","",83,[[],["result",4]]],[11,"try_into","","",83,[[],["result",4]]],[11,"type_id","","",83,[[],["typeid",3]]],[11,"vzip","","",83,[[]]],[11,"init","","",83,[[]]],[11,"deref","","",83,[[]]],[11,"deref_mut","","",83,[[]]],[11,"drop","","",83,[[]]],[11,"from","bdk::wallet::tx_builder","",106,[[]]],[11,"into","","",106,[[]]],[11,"to_owned","","",106,[[]]],[11,"clone_into","","",106,[[]]],[11,"borrow","","",106,[[]]],[11,"borrow_mut","","",106,[[]]],[11,"try_from","","",106,[[],["result",4]]],[11,"try_into","","",106,[[],["result",4]]],[11,"type_id","","",106,[[],["typeid",3]]],[11,"vzip","","",106,[[]]],[11,"init","","",106,[[]]],[11,"deref","","",106,[[]]],[11,"deref_mut","","",106,[[]]],[11,"drop","","",106,[[]]],[11,"from","","",107,[[]]],[11,"into","","",107,[[]]],[11,"to_owned","","",107,[[]]],[11,"clone_into","","",107,[[]]],[11,"borrow","","",107,[[]]],[11,"borrow_mut","","",107,[[]]],[11,"try_from","","",107,[[],["result",4]]],[11,"try_into","","",107,[[],["result",4]]],[11,"type_id","","",107,[[],["typeid",3]]],[11,"vzip","","",107,[[]]],[11,"init","","",107,[[]]],[11,"deref","","",107,[[]]],[11,"deref_mut","","",107,[[]]],[11,"drop","","",107,[[]]],[11,"from","","",84,[[]]],[11,"into","","",84,[[]]],[11,"borrow","","",84,[[]]],[11,"borrow_mut","","",84,[[]]],[11,"try_from","","",84,[[],["result",4]]],[11,"try_into","","",84,[[],["result",4]]],[11,"type_id","","",84,[[],["typeid",3]]],[11,"vzip","","",84,[[]]],[11,"init","","",84,[[]]],[11,"deref","","",84,[[]]],[11,"deref_mut","","",84,[[]]],[11,"drop","","",84,[[]]],[11,"from","","",85,[[]]],[11,"into","","",85,[[]]],[11,"to_owned","","",85,[[]]],[11,"clone_into","","",85,[[]]],[11,"borrow","","",85,[[]]],[11,"borrow_mut","","",85,[[]]],[11,"try_from","","",85,[[],["result",4]]],[11,"try_into","","",85,[[],["result",4]]],[11,"type_id","","",85,[[],["typeid",3]]],[11,"vzip","","",85,[[]]],[11,"equivalent","","",85,[[]]],[11,"init","","",85,[[]]],[11,"deref","","",85,[[]]],[11,"deref_mut","","",85,[[]]],[11,"drop","","",85,[[]]],[11,"from","","",86,[[]]],[11,"into","","",86,[[]]],[11,"to_owned","","",86,[[]]],[11,"clone_into","","",86,[[]]],[11,"borrow","","",86,[[]]],[11,"borrow_mut","","",86,[[]]],[11,"try_from","","",86,[[],["result",4]]],[11,"try_into","","",86,[[],["result",4]]],[11,"type_id","","",86,[[],["typeid",3]]],[11,"vzip","","",86,[[]]],[11,"equivalent","","",86,[[]]],[11,"init","","",86,[[]]],[11,"deref","","",86,[[]]],[11,"deref_mut","","",86,[[]]],[11,"drop","","",86,[[]]],[11,"from","bdk::wallet","",88,[[]]],[11,"into","","",88,[[]]],[11,"borrow","","",88,[[]]],[11,"borrow_mut","","",88,[[]]],[11,"try_from","","",88,[[],["result",4]]],[11,"try_into","","",88,[[],["result",4]]],[11,"type_id","","",88,[[],["typeid",3]]],[11,"vzip","","",88,[[]]],[11,"init","","",88,[[]]],[11,"deref","","",88,[[]]],[11,"deref_mut","","",88,[[]]],[11,"drop","","",88,[[]]],[11,"from_str","bdk::descriptor","",23,[[],[["result",4],["descriptor",4],["error",4]]]],[11,"from_str","bdk::keys","",59,[[],[["result",4],["descriptorsecretkey",4]]]],[11,"from_str","","",58,[[],[["descriptorpublickey",4],["result",4]]]],[11,"from_str","bdk::descriptor","Parse a Miniscript from string and perform sanity checks …",24,[[],[["miniscript",3],["result",4],["error",4]]]],[11,"hash","bdk::keys","",58,[[]]],[11,"hash","","",61,[[]]],[11,"hash","bdk::descriptor","",27,[[]]],[11,"hash","","",24,[[]]],[11,"eq","","",27,[[["terminal",4]]]],[11,"ne","","",27,[[["terminal",4]]]],[11,"eq","bdk::keys","",58,[[["descriptorpublickey",4]]]],[11,"ne","","",58,[[["descriptorpublickey",4]]]],[11,"eq","bdk::descriptor","",101,[[["legacy",4]]]],[11,"eq","","",24,[[["miniscript",3]]]],[11,"eq","","",23,[[["descriptor",4]]]],[11,"ne","","",23,[[["descriptor",4]]]],[11,"eq","bdk::keys","",61,[[["descriptorsinglepub",3]]]],[11,"ne","","",61,[[["descriptorsinglepub",3]]]],[11,"eq","bdk::descriptor","",102,[[["segwitv0",4]]]],[11,"eq","bdk::keys","",62,[[["sortedmultivec",3]]]],[11,"ne","","",62,[[["sortedmultivec",3]]]],[11,"cmp","bdk::descriptor","",101,[[["legacy",4]],["ordering",4]]],[11,"cmp","bdk::keys","",61,[[["descriptorsinglepub",3]],["ordering",4]]],[11,"cmp","","",62,[[["sortedmultivec",3]],["ordering",4]]],[11,"cmp","bdk::descriptor","",24,[[["miniscript",3]],["ordering",4]]],[11,"cmp","","",102,[[["segwitv0",4]],["ordering",4]]],[11,"cmp","","",23,[[["descriptor",4]],["ordering",4]]],[11,"cmp","bdk::keys","",58,[[["descriptorpublickey",4]],["ordering",4]]],[11,"cmp","bdk::descriptor","",27,[[["terminal",4]],["ordering",4]]],[11,"check_terminal_non_malleable","","",101,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_witness","","",101,[[],[["scriptcontexterror",4],["result",4]]]],[11,"check_global_consensus_validity","","",101,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_consensus_validity","","",101,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_policy_validity","","",101,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"max_satisfaction_size","","",101,[[["miniscript",3]],["option",4]]],[11,"check_terminal_non_malleable","","",102,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_witness","","",102,[[],[["scriptcontexterror",4],["result",4]]]],[11,"check_global_consensus_validity","","",102,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_consensus_validity","","",102,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_global_policy_validity","","",102,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_policy_validity","","",102,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"max_satisfaction_size","","",102,[[["miniscript",3]],["option",4]]],[11,"clone","","",102,[[],["segwitv0",4]]],[11,"clone","","",24,[[],["miniscript",3]]],[11,"clone","bdk::keys","",62,[[],["sortedmultivec",3]]],[11,"clone","bdk::descriptor","",27,[[],["terminal",4]]],[11,"clone","bdk::keys","",61,[[],["descriptorsinglepub",3]]],[11,"clone","bdk::descriptor","",23,[[],["descriptor",4]]],[11,"clone","","",101,[[],["legacy",4]]],[11,"clone","bdk::keys","",58,[[],["descriptorpublickey",4]]],[11,"fmt","bdk::descriptor","",27,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::keys","",60,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::descriptor","",102,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::keys","",58,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","","",62,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::descriptor","",23,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::keys","",59,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::descriptor","",24,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","","",101,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::keys","",61,[[["formatter",3]],[["error",3],["result",4]]]],[11,"to_pubkeyhash","","",58,[[],["descriptorpublickey",4]]],[11,"partial_cmp","","",58,[[["descriptorpublickey",4]],[["option",4],["ordering",4]]]],[11,"lt","","",58,[[["descriptorpublickey",4]]]],[11,"le","","",58,[[["descriptorpublickey",4]]]],[11,"gt","","",58,[[["descriptorpublickey",4]]]],[11,"ge","","",58,[[["descriptorpublickey",4]]]],[11,"partial_cmp","","",62,[[["sortedmultivec",3]],[["option",4],["ordering",4]]]],[11,"lt","","",62,[[["sortedmultivec",3]]]],[11,"le","","",62,[[["sortedmultivec",3]]]],[11,"gt","","",62,[[["sortedmultivec",3]]]],[11,"ge","","",62,[[["sortedmultivec",3]]]],[11,"partial_cmp","bdk::descriptor","",102,[[["segwitv0",4]],[["option",4],["ordering",4]]]],[11,"partial_cmp","","",24,[[["miniscript",3]],[["option",4],["ordering",4]]]],[11,"partial_cmp","bdk::keys","",61,[[["descriptorsinglepub",3]],[["option",4],["ordering",4]]]],[11,"lt","","",61,[[["descriptorsinglepub",3]]]],[11,"le","","",61,[[["descriptorsinglepub",3]]]],[11,"gt","","",61,[[["descriptorsinglepub",3]]]],[11,"ge","","",61,[[["descriptorsinglepub",3]]]],[11,"partial_cmp","bdk::descriptor","",101,[[["legacy",4]],[["option",4],["ordering",4]]]],[11,"partial_cmp","","",23,[[["descriptor",4]],[["option",4],["ordering",4]]]],[11,"lt","","",23,[[["descriptor",4]]]],[11,"le","","",23,[[["descriptor",4]]]],[11,"gt","","",23,[[["descriptor",4]]]],[11,"ge","","",23,[[["descriptor",4]]]],[11,"partial_cmp","","",27,[[["terminal",4]],[["option",4],["ordering",4]]]],[11,"lt","","",27,[[["terminal",4]]]],[11,"le","","",27,[[["terminal",4]]]],[11,"gt","","",27,[[["terminal",4]]]],[11,"ge","","",27,[[["terminal",4]]]],[11,"lift","bdk::keys","",62,[[],[["result",4],["policy",4],["error",4]]]],[11,"lift","bdk::descriptor","",24,[[],[["result",4],["policy",4],["error",4]]]],[11,"lift","","",23,[[],[["result",4],["policy",4],["error",4]]]],[11,"lift","","",27,[[],[["result",4],["policy",4],["error",4]]]],[11,"to_public_key","bdk::keys","",58,[[["descriptorpublickeyctx",3]],["publickey",3]]],[11,"hash_to_hash160","","",58,[[["descriptorpublickeyctx",3]],["hash",3]]],[11,"fmt","bdk::descriptor","",24,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","","",23,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::keys","",62,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::descriptor","",27,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::keys","",59,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","","",58,[[["formatter",3]],[["error",3],["result",4]]]],[11,"from_tree","bdk::descriptor","",27,[[["tree",3]],[["result",4],["terminal",4],["error",4]]]],[11,"from_tree","","Parse an expression tree into a Miniscript. As a general …",24,[[["tree",3]],[["miniscript",3],["result",4],["error",4]]]],[11,"from_tree","","Parse an expression tree into a descriptor",23,[[["tree",3]],[["result",4],["descriptor",4],["error",4]]]],[11,"from_config","bdk::blockchain::any","",0,[[],[["result",4],["error",4]]]],[11,"from_config","bdk::blockchain::electrum","",95,[[],[["result",4],["error",4]]]],[11,"from_config","bdk::blockchain::esplora","",3,[[],[["result",4],["error",4]]]],[11,"from_config","bdk::blockchain::compact_filters","",6,[[],[["result",4],["error",4]]]],[11,"update","bdk::blockchain","",99,[[["string",3],["option",4]],[["error",4],["result",4]]]],[11,"update","","",100,[[["string",3],["option",4]],[["error",4],["result",4]]]],[11,"set_script_pubkey","bdk::database::any","",14,[[["script",3],["keychainkind",4]],[["error",4],["result",4]]]],[11,"set_utxo","","",14,[[["utxo",3]],[["error",4],["result",4]]]],[11,"set_raw_tx","","",14,[[["transaction",3]],[["error",4],["result",4]]]],[11,"set_tx","","",14,[[["transactiondetails",3]],[["error",4],["result",4]]]],[11,"set_last_index","","",14,[[["keychainkind",4]],[["error",4],["result",4]]]],[11,"del_script_pubkey_from_path","","",14,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"del_path_from_script_pubkey","","",14,[[["script",3]],[["error",4],["result",4],["option",4]]]],[11,"del_utxo","","",14,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[11,"del_raw_tx","","",14,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"del_tx","","",14,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"del_last_index","","",14,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"set_script_pubkey","","",15,[[["script",3],["keychainkind",4]],[["error",4],["result",4]]]],[11,"set_utxo","","",15,[[["utxo",3]],[["error",4],["result",4]]]],[11,"set_raw_tx","","",15,[[["transaction",3]],[["error",4],["result",4]]]],[11,"set_tx","","",15,[[["transactiondetails",3]],[["error",4],["result",4]]]],[11,"set_last_index","","",15,[[["keychainkind",4]],[["error",4],["result",4]]]],[11,"del_script_pubkey_from_path","","",15,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"del_path_from_script_pubkey","","",15,[[["script",3]],[["error",4],["result",4],["option",4]]]],[11,"del_utxo","","",15,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[11,"del_raw_tx","","",15,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"del_tx","","",15,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"del_last_index","","",15,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"set_script_pubkey","bdk::database::memory","",18,[[["script",3],["keychainkind",4]],[["error",4],["result",4]]]],[11,"set_utxo","","",18,[[["utxo",3]],[["error",4],["result",4]]]],[11,"set_raw_tx","","",18,[[["transaction",3]],[["error",4],["result",4]]]],[11,"set_tx","","",18,[[["transactiondetails",3]],[["error",4],["result",4]]]],[11,"set_last_index","","",18,[[["keychainkind",4]],[["error",4],["result",4]]]],[11,"del_script_pubkey_from_path","","",18,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"del_path_from_script_pubkey","","",18,[[["script",3]],[["error",4],["result",4],["option",4]]]],[11,"del_utxo","","",18,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[11,"del_raw_tx","","",18,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"del_tx","","",18,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"del_last_index","","",18,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"check_descriptor_checksum","bdk::database::any","",14,[[["asref",8],["keychainkind",4]],[["error",4],["result",4]]]],[11,"iter_script_pubkeys","","",14,[[["option",4],["keychainkind",4]],[["vec",3],["result",4],["error",4]]]],[11,"iter_utxos","","",14,[[],[["result",4],["vec",3],["error",4]]]],[11,"iter_raw_txs","","",14,[[],[["vec",3],["result",4],["error",4]]]],[11,"iter_txs","","",14,[[],[["error",4],["result",4],["vec",3]]]],[11,"get_script_pubkey_from_path","","",14,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"get_path_from_script_pubkey","","",14,[[["script",3]],[["error",4],["result",4],["option",4]]]],[11,"get_utxo","","",14,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[11,"get_raw_tx","","",14,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"get_tx","","",14,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"get_last_index","","",14,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"increment_last_index","","",14,[[["keychainkind",4]],[["result",4],["error",4]]]],[11,"check_descriptor_checksum","bdk::database::memory","",18,[[["asref",8],["keychainkind",4]],[["error",4],["result",4]]]],[11,"iter_script_pubkeys","","",18,[[["option",4],["keychainkind",4]],[["vec",3],["result",4],["error",4]]]],[11,"iter_utxos","","",18,[[],[["result",4],["vec",3],["error",4]]]],[11,"iter_raw_txs","","",18,[[],[["vec",3],["result",4],["error",4]]]],[11,"iter_txs","","",18,[[],[["error",4],["result",4],["vec",3]]]],[11,"get_script_pubkey_from_path","","",18,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"get_path_from_script_pubkey","","",18,[[["script",3]],[["error",4],["result",4],["option",4]]]],[11,"get_utxo","","",18,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[11,"get_raw_tx","","",18,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"get_tx","","",18,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"get_last_index","","",18,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"increment_last_index","","",18,[[["keychainkind",4]],[["result",4],["error",4]]]],[11,"begin_batch","bdk::database::any","",14,[[]]],[11,"commit_batch","","",14,[[],[["error",4],["result",4]]]],[11,"begin_batch","bdk::database::memory","",18,[[]]],[11,"commit_batch","","",18,[[],[["error",4],["result",4]]]],[11,"from_config","bdk::database::any","",14,[[],[["result",4],["error",4]]]],[11,"from_config","bdk::database::memory","",18,[[],[["result",4],["error",4]]]],[11,"build","bdk::descriptor::template","",47,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"build","","",48,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"build","","",49,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"build","","",50,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"build","","",51,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"build","","",52,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"build","","",53,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"build","","",54,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"build","","",55,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"to_wallet_descriptor","bdk","",108,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"to_wallet_descriptor","","",109,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"extract_policy","bdk::descriptor","",24,[[["signerscontainer",3],["secp256k1",3]],[["result",4],["error",4],["option",4]]]],[11,"extract_policy","","",23,[[["signerscontainer",3],["secp256k1",3]],[["result",4],["error",4],["option",4]]]],[11,"to_descriptor_key","bdk::keys","",68,[[],[["result",4],["descriptorkey",4],["keyerror",4]]]],[11,"to_descriptor_key","","",63,[[],[["result",4],["descriptorkey",4],["keyerror",4]]]],[11,"to_descriptor_key","","",58,[[],[["result",4],["descriptorkey",4],["keyerror",4]]]],[11,"to_descriptor_key","","",59,[[],[["result",4],["descriptorkey",4],["keyerror",4]]]],[11,"add_metadata","bdk","",110,[[["keysource",6],["derivationpath",3],["option",4]],[["result",4],["descriptorkey",4],["keyerror",4]]]],[11,"add_metadata","bdk::keys","",68,[[["keysource",6],["derivationpath",3],["option",4]],[["result",4],["descriptorkey",4],["keyerror",4]]]],[11,"coin_select","bdk::wallet::coin_selection","",105,[[["feerate",3],["vec",3]],[["result",4],["error",4],["coinselectionresult",3]]]],[11,"coin_select","","",77,[[["feerate",3],["vec",3]],[["result",4],["error",4],["coinselectionresult",3]]]],[11,"get_capabilities","bdk::blockchain::any","",0,[[],[["hashset",3],["capability",4]]]],[11,"setup","","",0,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"sync","","",0,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"get_tx","","",0,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"broadcast","","",0,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",0,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",0,[[],[["feerate",3],["error",4],["result",4]]]],[11,"get_capabilities","bdk::blockchain::electrum","",95,[[],[["hashset",3],["capability",4]]]],[11,"setup","","",95,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"get_tx","","",95,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"broadcast","","",95,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",95,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",95,[[],[["feerate",3],["error",4],["result",4]]]],[11,"get_capabilities","bdk::blockchain::esplora","",3,[[],[["hashset",3],["capability",4]]]],[11,"setup","","",3,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"get_tx","","",3,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"broadcast","","",3,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",3,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",3,[[],[["feerate",3],["error",4],["result",4]]]],[11,"get_capabilities","bdk::blockchain::compact_filters","",6,[[],[["hashset",3],["capability",4]]]],[11,"setup","","",6,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"get_tx","","",6,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"broadcast","","",6,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",6,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",6,[[],[["feerate",3],["error",4],["result",4]]]],[11,"as_ref","bdk","",92,[[]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["addressvalidatorerror",4]]]],[11,"from","","",89,[[["policyerror",4]]]],[11,"from","","",89,[[["signererror",4]]]],[11,"from","","",89,[[["keyerror",4]],["error",4]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["error",3]]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["esploraerror",4]]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["compactfilterserror",4]]]],[11,"from","bdk::blockchain::any","",0,[[["electrumblockchain",3]]]],[11,"from","","",0,[[["esplorablockchain",3]]]],[11,"from","","",0,[[["compactfiltersblockchain",3]]]],[11,"from","","",1,[[["electrumblockchainconfig",3]]]],[11,"from","","",1,[[["esplorablockchainconfig",3]]]],[11,"from","","",1,[[["compactfiltersblockchainconfig",3]]]],[11,"from","bdk::blockchain::electrum","",95,[[["client",3]]]],[11,"from","bdk::blockchain::esplora","",5,[[["error",3]]]],[11,"from","","",5,[[["parseinterror",3]]]],[11,"from","","",5,[[["error",4]]]],[11,"from","","",5,[[["error",4]]]],[11,"from","bdk::blockchain::compact_filters","",9,[[["error",3]]]],[11,"from","","",9,[[["error",3]]]],[11,"from","","",9,[[["error",4]]]],[11,"from","","",9,[[["systemtimeerror",3]]]],[11,"from","","",9,[[["error",4]]]],[11,"from","bdk::database::any","",14,[[["memorydatabase",3]]]],[11,"from","","",14,[[["tree",3]]]],[11,"from","","",15,[[]]],[11,"from","","",15,[[]]],[11,"from","","",17,[[]]],[11,"from","","",17,[[["sleddbconfiguration",3]]]],[11,"from","bdk::descriptor::error","",29,[[["keyerror",4]],["error",4]]],[11,"from","","",29,[[["error",4]]]],[11,"from","","",29,[[["error",4]]]],[11,"from","","",29,[[["error",4]]]],[11,"from","","",29,[[["error",4]]]],[11,"from","","",29,[[["error",4]]]],[11,"from","","",29,[[["policyerror",4]]]],[11,"from","bdk::descriptor::policy","",39,[[]]],[11,"from","","",43,[[["satisfiableitem",4]]]],[11,"from","bdk::keys","",72,[[["error",4]]]],[11,"from","","",72,[[["error",4]]]],[11,"from","bdk::wallet::signer","",79,[[["hash",3]],["signerid",4]]],[11,"from","","",79,[[["fingerprint",3]],["signerid",4]]],[11,"from","","",83,[[["keymap",6]],["signerscontainer",3]]],[11,"clone","bdk::blockchain","",10,[[],["capability",4]]],[11,"clone","","",99,[[],["noopprogress",3]]],[11,"clone","","",100,[[],["logprogress",3]]],[11,"clone","bdk::descriptor::policy","",103,[[],["pkorf",3]]],[11,"clone","","",30,[[],["satisfiableitem",4]]],[11,"clone","","",39,[[],["satisfaction",4]]],[11,"clone","","",43,[[],["policy",3]]],[11,"clone","","",44,[[],["condition",3]]],[11,"clone","bdk::keys","",64,[[],["scriptcontextenum",4]]],[11,"clone","","",71,[[],["privatekeygenerateoptions",3]]],[11,"clone","bdk","",92,[[],["keychainkind",4]]],[11,"clone","","",104,[[],["feerate",3]]],[11,"clone","","",93,[[],["utxo",3]]],[11,"clone","","",94,[[],["transactiondetails",3]]],[11,"clone","bdk::wallet::address_validator","",73,[[],["addressvalidatorerror",4]]],[11,"clone","bdk::wallet::signer","",79,[[],["signerid",4]]],[11,"clone","","",80,[[],["signererror",4]]],[11,"clone","","",82,[[],["signerordering",3]]],[11,"clone","","",83,[[],["signerscontainer",3]]],[11,"clone","bdk::wallet::tx_builder","",106,[[],["createtx",3]]],[11,"clone","","",107,[[],["bumpfee",3]]],[11,"clone","","",85,[[],["txordering",4]]],[11,"clone","","",86,[[],["changespendpolicy",4]]],[11,"default","bdk::blockchain::compact_filters","",96,[[],["mempool",3]]],[11,"default","bdk::database::memory","",18,[[],["memorydatabase",3]]],[11,"default","bdk::descriptor::policy","",103,[[],["pkorf",3]]],[11,"default","","",44,[[],["condition",3]]],[11,"default","bdk::keys","",71,[[]]],[11,"default","bdk","",104,[[]]],[11,"default","","",94,[[],["transactiondetails",3]]],[11,"default","bdk::wallet::coin_selection","",105,[[],["largestfirstcoinselection",3]]],[11,"default","","",77,[[]]],[11,"default","bdk::wallet::signer","",82,[[]]],[11,"default","","",83,[[],["signerscontainer",3]]],[11,"default","bdk::wallet::tx_builder","",106,[[],["createtx",3]]],[11,"default","","",107,[[],["bumpfee",3]]],[11,"default","","",84,[[]]],[11,"default","","",85,[[]]],[11,"default","","",86,[[]]],[11,"cmp","bdk::descriptor::policy","",44,[[["condition",3]],["ordering",4]]],[11,"cmp","bdk::wallet::signer","",79,[[["signerid",4]],["ordering",4]]],[11,"cmp","","",82,[[["signerordering",3]],["ordering",4]]],[11,"cmp","bdk::wallet::tx_builder","",85,[[["txordering",4]],["ordering",4]]],[11,"cmp","","",86,[[["changespendpolicy",4]],["ordering",4]]],[11,"eq","bdk::blockchain","",10,[[["capability",4]]]],[11,"eq","bdk::descriptor::policy","",44,[[["condition",3]]]],[11,"ne","","",44,[[["condition",3]]]],[11,"eq","bdk::keys","",64,[[["scriptcontextenum",4]]]],[11,"eq","bdk","",92,[[["keychainkind",4]]]],[11,"eq","","",104,[[["feerate",3]]]],[11,"ne","","",104,[[["feerate",3]]]],[11,"eq","","",93,[[["utxo",3]]]],[11,"ne","","",93,[[["utxo",3]]]],[11,"eq","","",94,[[["transactiondetails",3]]]],[11,"ne","","",94,[[["transactiondetails",3]]]],[11,"eq","bdk::wallet::address_validator","",73,[[["addressvalidatorerror",4]]]],[11,"ne","","",73,[[["addressvalidatorerror",4]]]],[11,"eq","bdk::wallet::signer","",79,[[["signerid",4]]]],[11,"ne","","",79,[[["signerid",4]]]],[11,"eq","","",80,[[["signererror",4]]]],[11,"eq","","",82,[[["signerordering",3]]]],[11,"ne","","",82,[[["signerordering",3]]]],[11,"eq","bdk::wallet::tx_builder","",85,[[["txordering",4]]]],[11,"eq","","",86,[[["changespendpolicy",4]]]],[11,"partial_cmp","bdk::descriptor::policy","",44,[[["condition",3]],[["ordering",4],["option",4]]]],[11,"lt","","",44,[[["condition",3]]]],[11,"le","","",44,[[["condition",3]]]],[11,"gt","","",44,[[["condition",3]]]],[11,"ge","","",44,[[["condition",3]]]],[11,"partial_cmp","bdk","",104,[[["feerate",3]],[["ordering",4],["option",4]]]],[11,"lt","","",104,[[["feerate",3]]]],[11,"le","","",104,[[["feerate",3]]]],[11,"gt","","",104,[[["feerate",3]]]],[11,"ge","","",104,[[["feerate",3]]]],[11,"partial_cmp","bdk::wallet::signer","",79,[[["signerid",4]],[["ordering",4],["option",4]]]],[11,"lt","","",79,[[["signerid",4]]]],[11,"le","","",79,[[["signerid",4]]]],[11,"gt","","",79,[[["signerid",4]]]],[11,"ge","","",79,[[["signerid",4]]]],[11,"partial_cmp","","",82,[[["signerordering",3]],[["ordering",4],["option",4]]]],[11,"lt","","",82,[[["signerordering",3]]]],[11,"le","","",82,[[["signerordering",3]]]],[11,"gt","","",82,[[["signerordering",3]]]],[11,"ge","","",82,[[["signerordering",3]]]],[11,"partial_cmp","bdk::wallet::tx_builder","",85,[[["txordering",4]],[["ordering",4],["option",4]]]],[11,"partial_cmp","","",86,[[["changespendpolicy",4]],[["ordering",4],["option",4]]]],[11,"to_string","bdk::wallet::export","",78,[[],["string",3]]],[11,"deref","bdk::keys","",68,[[]]],[11,"fmt","bdk","",89,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::any","",1,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::electrum","",2,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::esplora","",3,[[["formatter",3]],["result",6]]],[11,"fmt","","",4,[[["formatter",3]],["result",6]]],[11,"fmt","","",5,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::compact_filters","",96,[[["formatter",3]],["result",6]]],[11,"fmt","","",97,[[["formatter",3]],["result",6]]],[11,"fmt","","",6,[[["formatter",3]],["result",6]]],[11,"fmt","","",7,[[["formatter",3]],["result",6]]],[11,"fmt","","",8,[[["formatter",3]],["result",6]]],[11,"fmt","","",9,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain","",10,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::database::any","",14,[[["formatter",3]],["result",6]]],[11,"fmt","","",16,[[["formatter",3]],["result",6]]],[11,"fmt","","",17,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::database::memory","",18,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::error","",29,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::policy","",103,[[["formatter",3]],["result",6]]],[11,"fmt","","",30,[[["formatter",3]],["result",6]]],[11,"fmt","","",39,[[["formatter",3]],["result",6]]],[11,"fmt","","",43,[[["formatter",3]],["result",6]]],[11,"fmt","","",44,[[["formatter",3]],["result",6]]],[11,"fmt","","",45,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::keys","",63,[[["formatter",3]],["result",6]]],[11,"fmt","","",64,[[["formatter",3]],["result",6]]],[11,"fmt","","",71,[[["formatter",3]],["result",6]]],[11,"fmt","","",72,[[["formatter",3]],["result",6]]],[11,"fmt","bdk","",92,[[["formatter",3]],["result",6]]],[11,"fmt","","",104,[[["formatter",3]],["result",6]]],[11,"fmt","","",93,[[["formatter",3]],["result",6]]],[11,"fmt","","",94,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::address_validator","",73,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::coin_selection","",75,[[["formatter",3]],["result",6]]],[11,"fmt","","",105,[[["formatter",3]],["result",6]]],[11,"fmt","","",77,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::export","",78,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::signer","",79,[[["formatter",3]],["result",6]]],[11,"fmt","","",80,[[["formatter",3]],["result",6]]],[11,"fmt","","",82,[[["formatter",3]],["result",6]]],[11,"fmt","","",83,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::tx_builder","",106,[[["formatter",3]],["result",6]]],[11,"fmt","","",107,[[["formatter",3]],["result",6]]],[11,"fmt","","",84,[[["formatter",3]],["result",6]]],[11,"fmt","","",85,[[["formatter",3]],["result",6]]],[11,"fmt","","",86,[[["formatter",3]],["result",6]]],[11,"fmt","bdk","",89,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::esplora","",5,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::compact_filters","",9,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::error","",29,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::policy","",45,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::keys","",72,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::address_validator","",73,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::signer","",80,[[["formatter",3]],["result",6]]],[11,"hash","bdk::blockchain","",10,[[]]],[11,"hash","bdk::descriptor::policy","",44,[[]]],[11,"hash","bdk","",92,[[]]],[11,"hash","bdk::wallet::signer","",79,[[]]],[11,"hash","bdk::wallet::tx_builder","",85,[[]]],[11,"hash","","",86,[[]]],[11,"from_str","bdk::wallet::export","",78,[[],["result",4]]],[11,"serialize","bdk::blockchain::any","",1,[[],["result",4]]],[11,"serialize","bdk::blockchain::electrum","",2,[[],["result",4]]],[11,"serialize","bdk::blockchain::esplora","",4,[[],["result",4]]],[11,"serialize","bdk::blockchain::compact_filters","",7,[[],["result",4]]],[11,"serialize","","",8,[[],["result",4]]],[11,"serialize","bdk::database::any","",16,[[],["result",4]]],[11,"serialize","","",17,[[],["result",4]]],[11,"serialize","bdk::descriptor::policy","",103,[[],["result",4]]],[11,"serialize","","",30,[[],["result",4]]],[11,"serialize","","",39,[[],["result",4]]],[11,"serialize","","",43,[[],["result",4]]],[11,"serialize","","",44,[[],["result",4]]],[11,"serialize","bdk","",92,[[],["result",4]]],[11,"serialize","","",93,[[],["result",4]]],[11,"serialize","","",94,[[],["result",4]]],[11,"serialize","bdk::wallet::export","",78,[[],["result",4]]],[11,"deserialize","bdk::blockchain::any","",1,[[],["result",4]]],[11,"deserialize","bdk::blockchain::electrum","",2,[[],["result",4]]],[11,"deserialize","bdk::blockchain::esplora","",4,[[],["result",4]]],[11,"deserialize","bdk::blockchain::compact_filters","",7,[[],["result",4]]],[11,"deserialize","","",8,[[],["result",4]]],[11,"deserialize","bdk::database::any","",16,[[],["result",4]]],[11,"deserialize","","",17,[[],["result",4]]],[11,"deserialize","bdk","",92,[[],["result",4]]],[11,"deserialize","","",93,[[],["result",4]]],[11,"deserialize","","",94,[[],["result",4]]],[11,"deserialize","bdk::wallet::export","",78,[[],["result",4]]],[11,"add_tx","bdk::blockchain::compact_filters","Add a transaction to the mempool",96,[[["transaction",3]]]],[11,"get_tx","","Look-up a transaction in the mempool given an [Inventory] …",96,[[["inventory",4]],[["option",4],["transaction",3]]]],[11,"has_tx","","Return whether or not the mempool contains a transaction …",96,[[["txid",3]]]],[11,"iter_txs","","Return the list of transactions contained in the mempool",96,[[],[["vec",3],["transaction",3]]]],[11,"connect","","Connect to a peer over a plaintext TCP connection",97,[[["tosocketaddrs",8],["network",4],["arc",3],["mempool",3]],[["compactfilterserror",4],["result",4]]]],[11,"connect_proxy","","Connect to a peer through a SOCKS5 proxy, optionally by …",97,[[["tosocketaddrs",8],["totargetaddr",8],["option",4],["network",4],["arc",3],["mempool",3]],[["compactfilterserror",4],["result",4]]]],[11,"get_version","","Return the [VersionMessage] sent by the peer",97,[[],["versionmessage",3]]],[11,"get_network","","Return the Bitcoin [Network] in use",97,[[],["network",4]]],[11,"get_mempool","","Return the mempool used by this peer",97,[[],[["arc",3],["mempool",3]]]],[11,"is_connected","","Return whether or not the peer is still connected",97,[[]]],[11,"send","","Send a raw Bitcoin message to the peer",97,[[["networkmessage",4]],[["result",4],["compactfilterserror",4]]]],[11,"recv","","Waits for a specific incoming Bitcoin message, optionally …",97,[[["duration",3],["option",4]],[["option",4],["compactfilterserror",4],["result",4]]]],[11,"translate_pk","bdk::descriptor","Convert a descriptor using abstract keys to one using …",23,[[],[["descriptor",4],["result",4]]]],[11,"sanity_check","","Whether the descriptor is safe Checks whether all the …",23,[[],[["error",4],["result",4]]]],[11,"address","","Computes the Bitcoin address of the descriptor, if one …",23,[[["network",4]],[["address",3],["option",4]]]],[11,"script_pubkey","","Computes the scriptpubkey of the descriptor to_pk_ctx …",23,[[],["script",3]]],[11,"unsigned_script_sig","","Computes the scriptSig that will be in place for an …",23,[[],["script",3]]],[11,"witness_script","","Computes the \\\"witness script\\\" of the descriptor, i.e. the …",23,[[],["script",3]]],[11,"get_satisfication","","Returns satisfying witness and scriptSig to spend an …",23,[[],[["error",4],["result",4]]]],[11,"satisfy","","Attempts to produce a satisfying witness and scriptSig to …",23,[[["txin",3]],[["error",4],["result",4]]]],[11,"max_satisfaction_weight","","Computes an upper bound on the weight of a satisfying …",23,[[],["option",4]]],[11,"script_code","","Get the scriptCode of a transaction output.",23,[[],["script",3]]],[11,"derive","","Derives all wildcard keys in the descriptor using the …",23,[[["childnumber",4]],[["descriptorpublickey",4],["descriptor",4]]]],[11,"parse_descriptor","","Parse a descriptor that may contain secret keys",23,[[],[["error",4],["result",4]]]],[11,"to_string_with_secret","","Serialize a descriptor to string with its secret keys",23,[[["hashmap",3]],["string",3]]],[11,"requires_sig","","Whether all spend paths of miniscript require a signature",24,[[]]],[11,"is_non_malleable","","Whether the miniscript is malleable",24,[[]]],[11,"within_resource_limits","","Whether the miniscript can exceed the resource …",24,[[]]],[11,"has_mixed_timelocks","","Whether the miniscript contains a combination of timelocks",24,[[]]],[11,"has_repeated_keys","","Whether the miniscript has repeated Pk or Pkh",24,[[]]],[11,"sanity_check","","Check whether the underlying Miniscript is safe under the …",24,[[],[["result",4],["analysiserror",4]]]],[11,"iter","","Creates a new [Iter] iterator that will iterate over all […",24,[[],["iter",3]]],[11,"iter_pk","","Creates a new [PkIter] iterator that will iterate over …",24,[[],["pkiter",3]]],[11,"iter_pkh","","Creates a new [PkhIter] iterator that will iterate over …",24,[[],["pkhiter",3]]],[11,"iter_pk_pkh","","Creates a new [PkPkhIter] iterator that will iterate over …",24,[[],["pkpkhiter",3]]],[11,"branches","","Enumerates all child nodes of the current AST node (self) …",24,[[],[["miniscript",3],["global",3],["vec",3]]]],[11,"get_nth_child","","Returns child node with given index, if any",24,[[],[["miniscript",3],["option",4]]]],[11,"get_leaf_pk","","Returns Vec with cloned version of all public keys from …",24,[[],[["global",3],["vec",3]]]],[11,"get_leaf_pkh","","Returns Vec with hashes of all public keys from the …",24,[[],[["global",3],["vec",3]]]],[11,"get_leaf_pk_pkh","","Returns Vec of [PkPkh] entries, representing either …",24,[[],[["global",3],["vec",3],["pkpkh",4]]]],[11,"get_nth_pk","","Returns Option::Some with cloned n\'th public key from the …",24,[[],["option",4]]],[11,"get_nth_pkh","","Returns Option::Some with hash of n\'th public key from …",24,[[],["option",4]]],[11,"get_nth_pk_pkh","","Returns Option::Some with hash of n\'th public key or hash …",24,[[],[["option",4],["pkpkh",4]]]],[11,"from_ast","","Add type information(Type and Extdata) to Miniscript …",24,[[["terminal",4]],[["miniscript",3],["result",4],["error",4]]]],[11,"into_inner","","Extracts the AstElem representing the root of the …",24,[[],["terminal",4]]],[11,"as_inner","","Get a reference to the inner AstElem representing the …",24,[[],["terminal",4]]],[11,"parse_insane","","Attempt to parse an insane(scripts don\'t clear sanity …",24,[[["script",3]],[["result",4],["miniscript",3],["error",4]]]],[11,"parse","","Attempt to parse a Script into Miniscript representation. …",24,[[["script",3]],[["result",4],["miniscript",3],["error",4]]]],[11,"encode","","Encode as a Bitcoin script",24,[[],["script",3]]],[11,"script_size","","Size, in bytes of the script-pubkey. If this Miniscript …",24,[[]]],[11,"max_satisfaction_witness_elements","","Maximum number of witness elements used to satisfy the …",24,[[],["option",4]]],[11,"max_satisfaction_size","","Maximum size, in bytes, of a satisfying witness. For …",24,[[],["option",4]]],[11,"translate_pk","","This will panic if translatefpk returns an uncompressed …",24,[[],[["miniscript",3],["result",4]]]],[11,"from_str_insane","","Attempt to parse an insane(scripts don\'t clear sanity …",24,[[],[["miniscript",3],["result",4],["error",4]]]],[11,"satisfy","","Attempt to produce non-malleable satisfying witness for …",24,[[],[["vec",3],["result",4],["error",4]]]],[11,"satisfy_malleable","","Attempt to produce a malleable satisfying witness for the …",24,[[],[["vec",3],["result",4],["error",4]]]],[11,"lift_check","","Lifting corresponds conversion of miniscript into Policy […",24,[[],[["lifterror",4],["result",4]]]],[11,"translate_pk","","Convert an AST element with one public key type to one of …",27,[[],[["terminal",4],["result",4]]]],[11,"encode","","Encode the element as a fragment of Bitcoin Script. The …",27,[[["builder",3]],["builder",3]]],[11,"script_size","","Size, in bytes of the script-pubkey. If this Miniscript …",27,[[]]],[11,"derive","bdk::keys","Derives the specified child key if self is a wildcard …",58,[[["childnumber",4]],["descriptorpublickey",4]]],[11,"as_public","","Return the public version of this key, by applying either …",59,[[["secp256k1",3]],[["result",4],["descriptorpublickey",4],["descriptorkeyparseerror",3]]]],[11,"new","","Create a new instance of SortedMultiVec given a list of …",62,[[["global",3],["vec",3]],[["error",4],["sortedmultivec",3],["result",4]]]],[11,"translate_pk","","This will panic if translatefpk returns an uncompressed …",62,[[],[["result",4],["sortedmultivec",3]]]],[11,"sorted_node","","Create Terminal::Multi containing sorted pubkeys",62,[[],["terminal",4]]],[11,"encode","","Encode as a Bitcoin script",62,[[],["script",3]]],[11,"satisfy","","Attempt to produce a satisfying witness for the witness …",62,[[],[["vec",3],["result",4],["error",4]]]],[11,"script_size","","Size, in bytes of the script-pubkey. If this Miniscript …",62,[[]]],[11,"max_satisfaction_witness_elements","","Maximum number of witness elements used to satisfy the …",62,[[]]],[11,"max_satisfaction_size","","Maximum size, in bytes, of a satisfying witness. For …",62,[[]]],[11,"as_byte","bdk","Return [KeychainKind] as a byte",92,[[]]],[11,"from_btc_per_kvb","","Create a new instance of [FeeRate] given a float fee rate …",104,[[]]],[11,"from_sat_per_vb","","Create a new instance of [FeeRate] given a float fee rate …",104,[[]]],[11,"default_min_relay_fee","","Create a new [FeeRate] with the default min relay fee …",104,[[]]],[11,"as_sat_vb","","Return the value as satoshi/vbyte",104,[[]]]],"p":[[4,"AnyBlockchain"],[4,"AnyBlockchainConfig"],[3,"ElectrumBlockchainConfig"],[3,"EsploraBlockchain"],[3,"EsploraBlockchainConfig"],[4,"EsploraError"],[3,"CompactFiltersBlockchain"],[3,"BitcoinPeerConfig"],[3,"CompactFiltersBlockchainConfig"],[4,"CompactFiltersError"],[4,"Capability"],[8,"Blockchain"],[8,"ConfigurableBlockchain"],[8,"Progress"],[4,"AnyDatabase"],[4,"AnyBatch"],[3,"SledDbConfiguration"],[4,"AnyDatabaseConfig"],[3,"MemoryDatabase"],[8,"BatchOperations"],[8,"Database"],[8,"BatchDatabase"],[8,"ConfigurableDatabase"],[4,"Descriptor"],[3,"Miniscript"],[8,"MiniscriptKey"],[8,"ScriptContext"],[4,"Terminal"],[8,"ToPublicKey"],[4,"Error"],[4,"SatisfiableItem"],[13,"SHA256Preimage"],[13,"HASH256Preimage"],[13,"RIPEMD160Preimage"],[13,"HASH160Preimage"],[13,"AbsoluteTimelock"],[13,"RelativeTimelock"],[13,"Multisig"],[13,"Thresh"],[4,"Satisfaction"],[13,"Partial"],[13,"PartialComplete"],[13,"Complete"],[3,"Policy"],[3,"Condition"],[4,"PolicyError"],[8,"DescriptorTemplate"],[3,"P2PKH"],[3,"P2WPKH_P2SH"],[3,"P2WPKH"],[3,"BIP44"],[3,"BIP44Public"],[3,"BIP49"],[3,"BIP49Public"],[3,"BIP84"],[3,"BIP84Public"],[8,"ToWalletDescriptor"],[8,"ExtractPolicy"],[4,"DescriptorPublicKey"],[4,"DescriptorSecretKey"],[3,"DescriptorSinglePriv"],[3,"DescriptorSinglePub"],[3,"SortedMultiVec"],[4,"DescriptorKey"],[4,"ScriptContextEnum"],[8,"ExtScriptContext"],[8,"ToDescriptorKey"],[8,"DerivableKey"],[3,"GeneratedKey"],[8,"GeneratableKey"],[8,"GeneratableDefaultOptions"],[3,"PrivateKeyGenerateOptions"],[4,"KeyError"],[4,"AddressValidatorError"],[8,"AddressValidator"],[3,"CoinSelectionResult"],[8,"CoinSelectionAlgorithm"],[3,"BranchAndBoundCoinSelection"],[3,"WalletExport"],[4,"SignerId"],[4,"SignerError"],[8,"Signer"],[3,"SignerOrdering"],[3,"SignersContainer"],[3,"TxBuilder"],[4,"TxOrdering"],[4,"ChangeSpendPolicy"],[8,"IsDust"],[3,"Wallet"],[4,"Error"],[13,"FeeRateTooLow"],[13,"FeeTooLow"],[4,"KeychainKind"],[3,"UTXO"],[3,"TransactionDetails"],[3,"ElectrumBlockchain"],[3,"Mempool"],[3,"Peer"],[3,"OfflineBlockchain"],[3,"NoopProgress"],[3,"LogProgress"],[4,"Legacy"],[4,"Segwitv0"],[3,"PKOrF"],[3,"FeeRate"],[3,"LargestFirstCoinSelection"],[3,"CreateTx"],[3,"BumpFee"],[6,"ExtendedDescriptor"],[6,"DescriptorTemplateOut"],[6,"MnemonicWithPassphrase"]]}\ +}'); +addSearchOptions(searchIndex);initSearch(searchIndex); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.css b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.css new file mode 100644 index 0000000000..670986588e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.css @@ -0,0 +1 @@ +.setting-line{padding:5px;position:relative;}.setting-line>div{display:inline-block;vertical-align:top;font-size:17px;padding-top:2px;}.setting-line>.title{font-size:19px;width:100%;max-width:none;border-bottom:1px solid;}.toggle{position:relative;display:inline-block;width:45px;height:27px;margin-right:20px;}.toggle input{opacity:0;position:absolute;}.select-wrapper{float:right;position:relative;height:27px;min-width:25%;}.select-wrapper select{appearance:none;-moz-appearance:none;-webkit-appearance:none;background:none;border:2px solid #ccc;padding-right:28px;width:100%;}.select-wrapper img{pointer-events:none;position:absolute;right:0;bottom:0;background:#ccc;height:100%;width:28px;padding:0px 4px;}.select-wrapper select option{color:initial;}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.3s;transition:.3s;}.slider:before{position:absolute;content:"";height:19px;width:19px;left:4px;bottom:4px;background-color:white;-webkit-transition:.3s;transition:.3s;}input:checked+.slider{background-color:#2196F3;}input:focus+.slider{box-shadow:0 0 0 2px #0a84ff,0 0 0 6px rgba(10,132,255,0.3);}input:checked+.slider:before{-webkit-transform:translateX(19px);-ms-transform:translateX(19px);transform:translateX(19px);}.setting-line>.sub-settings{padding-left:42px;width:100%;display:block;} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.html new file mode 100644 index 0000000000..ad50d10b1c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.html @@ -0,0 +1,6 @@ +Rustdoc settings + +

Rustdoc settings

Theme preferences
Use system theme
Preferred dark theme
Preferred light theme
+
Auto-hide item declarations
Auto-hide structs declaration
Auto-hide enums declaration
Auto-hide unions declaration
Auto-hide traits declaration
Auto-hide macros declaration
+
Auto-hide item attributes.
Auto-hide item methods' documentation
Auto-hide trait implementation documentation
Auto-hide implementors of a trait
Directly go to item in search if there is only one result
Show line numbers on code examples
Disable keyboard shortcuts
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.js new file mode 100644 index 0000000000..b4d6fdcd78 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.js @@ -0,0 +1 @@ +(function(){function changeSetting(settingName,value){updateLocalStorage("rustdoc-"+settingName,value);switch(settingName){case"preferred-dark-theme":case"preferred-light-theme":case"use-system-theme":updateSystemTheme();break}}function handleKey(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey){return}switch(getVirtualKey(ev)){case"Enter":case"Return":case"Space":ev.target.checked=!ev.target.checked;ev.preventDefault();break}}function setEvents(){onEachLazy(document.getElementsByClassName("slider"),function(elem){var toggle=elem.previousElementSibling;var settingId=toggle.id;var settingValue=getSettingValue(settingId);if(settingValue!==null){toggle.checked=settingValue==="true"}toggle.onchange=function(){changeSetting(this.id,this.checked)};toggle.onkeyup=handleKey;toggle.onkeyrelease=handleKey});onEachLazy(document.getElementsByClassName("select-wrapper"),function(elem){var select=elem.getElementsByTagName("select")[0];var settingId=select.id;var settingValue=getSettingValue(settingId);if(settingValue!==null){select.value=settingValue}select.onchange=function(){changeSetting(this.id,this.value)}})}window.addEventListener("DOMContentLoaded",setEvents)})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/source-files.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/source-files.js new file mode 100644 index 0000000000..1d8e89293a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/source-files.js @@ -0,0 +1,3 @@ +var N = null;var sourcesIndex = {}; +sourcesIndex["bdk"] = {"name":"","dirs":[{"name":"blockchain","dirs":[{"name":"compact_filters","files":["mod.rs","peer.rs","store.rs","sync.rs"]}],"files":["any.rs","electrum.rs","esplora.rs","mod.rs","utils.rs"]},{"name":"database","files":["any.rs","keyvalue.rs","memory.rs","mod.rs"]},{"name":"descriptor","files":["checksum.rs","dsl.rs","error.rs","mod.rs","policy.rs","template.rs"]},{"name":"keys","files":["bip39.rs","mod.rs"]},{"name":"psbt","files":["mod.rs"]},{"name":"wallet","files":["address_validator.rs","coin_selection.rs","export.rs","mod.rs","signer.rs","time.rs","tx_builder.rs","utils.rs"]}],"files":["error.rs","lib.rs","types.rs"]}; +createSourceSidebar(); diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/source-script.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/source-script.js new file mode 100644 index 0000000000..de663ca5a9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/source-script.js @@ -0,0 +1 @@ +function getCurrentFilePath(){var parts=window.location.pathname.split("/");var rootPathParts=window.rootPath.split("/");for(var i=0;i"){sidebar.style.left="";this.style.left="";child.innerText="<";updateLocalStorage("rustdoc-source-sidebar-show","true")}else{sidebar.style.left="-300px";this.style.left="0";child.innerText=">";updateLocalStorage("rustdoc-source-sidebar-show","false")}}function createSidebarToggle(){var sidebarToggle=document.createElement("div");sidebarToggle.id="sidebar-toggle";sidebarToggle.onclick=toggleSidebar;var inner1=document.createElement("div");inner1.style.position="relative";var inner2=document.createElement("div");inner2.style.paddingTop="3px";if(getCurrentValue("rustdoc-source-sidebar-show")==="true"){inner2.innerText="<"}else{inner2.innerText=">";sidebarToggle.style.left="0"}inner1.appendChild(inner2);sidebarToggle.appendChild(inner1);return sidebarToggle}function createSourceSidebar(){if(window.rootPath.endsWith("/")===false){window.rootPath+="/"}var main=document.getElementById("main");var sidebarToggle=createSidebarToggle();main.insertBefore(sidebarToggle,main.firstChild);var sidebar=document.createElement("div");sidebar.id="source-sidebar";if(getCurrentValue("rustdoc-source-sidebar-show")!=="true"){sidebar.style.left="-300px"}var currentFile=getCurrentFilePath();var hasFoundFile=false;var title=document.createElement("div");title.className="title";title.innerText="Files";sidebar.appendChild(title);Object.keys(sourcesIndex).forEach(function(key){sourcesIndex[key].name=key;hasFoundFile=createDirEntry(sourcesIndex[key],sidebar,"",currentFile,hasFoundFile)});main.insertBefore(sidebar,main.firstChild);var selected_elem=sidebar.getElementsByClassName("selected")[0];if(typeof selected_elem!=="undefined"){selected_elem.focus()}} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/any.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/any.rs.html new file mode 100644 index 0000000000..44fe66832a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/any.rs.html @@ -0,0 +1,470 @@ +any.rs - source + +
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Runtime-checked blockchain types
+//!
+//! This module provides the implementation of [`AnyBlockchain`] which allows switching the
+//! inner [`Blockchain`] type at runtime.
+//!
+//! ## Example
+//!
+//! In this example both `wallet_electrum` and `wallet_esplora` have the same type of
+//! `Wallet<AnyBlockchain, MemoryDatabase>`. This means that they could both, for instance, be
+//! assigned to a struct member.
+//!
+//! ```no_run
+//! # use bitcoin::Network;
+//! # use bdk::blockchain::*;
+//! # use bdk::database::MemoryDatabase;
+//! # use bdk::Wallet;
+//! # #[cfg(feature = "electrum")]
+//! # {
+//! let electrum_blockchain = ElectrumBlockchain::from(electrum_client::Client::new("...")?);
+//! let wallet_electrum: Wallet<AnyBlockchain, _> = Wallet::new(
+//!     "...",
+//!     None,
+//!     Network::Testnet,
+//!     MemoryDatabase::default(),
+//!     electrum_blockchain.into(),
+//! )?;
+//! # }
+//!
+//! # #[cfg(feature = "esplora")]
+//! # {
+//! let esplora_blockchain = EsploraBlockchain::new("...", None);
+//! let wallet_esplora: Wallet<AnyBlockchain, _> = Wallet::new(
+//!     "...",
+//!     None,
+//!     Network::Testnet,
+//!     MemoryDatabase::default(),
+//!     esplora_blockchain.into(),
+//! )?;
+//! # }
+//!
+//! # Ok::<(), bdk::Error>(())
+//! ```
+//!
+//! When paired with the use of [`ConfigurableBlockchain`], it allows creating wallets with any
+//! blockchain type supported using a single line of code:
+//!
+//! ```no_run
+//! # use bitcoin::Network;
+//! # use bdk::blockchain::*;
+//! # use bdk::database::MemoryDatabase;
+//! # use bdk::Wallet;
+//! let config = serde_json::from_str("...")?;
+//! let blockchain = AnyBlockchain::from_config(&config)?;
+//! let wallet = Wallet::new(
+//!     "...",
+//!     None,
+//!     Network::Testnet,
+//!     MemoryDatabase::default(),
+//!     blockchain,
+//! )?;
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use super::*;
+
+macro_rules! impl_from {
+    ( $from:ty, $to:ty, $variant:ident, $( $cfg:tt )* ) => {
+        $( $cfg )*
+        impl From<$from> for $to {
+            fn from(inner: $from) -> Self {
+                <$to>::$variant(inner)
+            }
+        }
+    };
+}
+
+macro_rules! impl_inner_method {
+    ( $self:expr, $name:ident $(, $args:expr)* ) => {
+        match $self {
+            #[cfg(feature = "electrum")]
+            AnyBlockchain::Electrum(inner) => inner.$name( $($args, )* ),
+            #[cfg(feature = "esplora")]
+            AnyBlockchain::Esplora(inner) => inner.$name( $($args, )* ),
+            #[cfg(feature = "compact_filters")]
+            AnyBlockchain::CompactFilters(inner) => inner.$name( $($args, )* ),
+        }
+    }
+}
+
+/// Type that can contain any of the [`Blockchain`] types defined by the library
+///
+/// It allows switching backend at runtime
+///
+/// See [this module](crate::blockchain::any)'s documentation for a usage example.
+pub enum AnyBlockchain {
+    #[cfg(feature = "electrum")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
+    /// Electrum client
+    Electrum(electrum::ElectrumBlockchain),
+    #[cfg(feature = "esplora")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
+    /// Esplora client
+    Esplora(esplora::EsploraBlockchain),
+    #[cfg(feature = "compact_filters")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
+    /// Compact filters client
+    CompactFilters(compact_filters::CompactFiltersBlockchain),
+}
+
+#[maybe_async]
+impl Blockchain for AnyBlockchain {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        maybe_await!(impl_inner_method!(self, get_capabilities))
+    }
+
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(impl_inner_method!(
+            self,
+            setup,
+            stop_gap,
+            database,
+            progress_update
+        ))
+    }
+    fn sync<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(impl_inner_method!(
+            self,
+            sync,
+            stop_gap,
+            database,
+            progress_update
+        ))
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        maybe_await!(impl_inner_method!(self, get_tx, txid))
+    }
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        maybe_await!(impl_inner_method!(self, broadcast, tx))
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        maybe_await!(impl_inner_method!(self, get_height))
+    }
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
+        maybe_await!(impl_inner_method!(self, estimate_fee, target))
+    }
+}
+
+impl_from!(electrum::ElectrumBlockchain, AnyBlockchain, Electrum, #[cfg(feature = "electrum")]);
+impl_from!(esplora::EsploraBlockchain, AnyBlockchain, Esplora, #[cfg(feature = "esplora")]);
+impl_from!(compact_filters::CompactFiltersBlockchain, AnyBlockchain, CompactFilters, #[cfg(feature = "compact_filters")]);
+
+/// Type that can contain any of the blockchain configurations defined by the library
+///
+/// This allows storing a single configuration that can be loaded into an [`AnyBlockchain`]
+/// instance. Wallets that plan to offer users the ability to switch blockchain backend at runtime
+/// will find this particularly useful.
+#[derive(Debug, serde::Serialize, serde::Deserialize)]
+pub enum AnyBlockchainConfig {
+    #[cfg(feature = "electrum")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
+    /// Electrum client
+    Electrum(electrum::ElectrumBlockchainConfig),
+    #[cfg(feature = "esplora")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
+    /// Esplora client
+    Esplora(esplora::EsploraBlockchainConfig),
+    #[cfg(feature = "compact_filters")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
+    /// Compact filters client
+    CompactFilters(compact_filters::CompactFiltersBlockchainConfig),
+}
+
+impl ConfigurableBlockchain for AnyBlockchain {
+    type Config = AnyBlockchainConfig;
+
+    fn from_config(config: &Self::Config) -> Result<Self, Error> {
+        Ok(match config {
+            #[cfg(feature = "electrum")]
+            AnyBlockchainConfig::Electrum(inner) => {
+                AnyBlockchain::Electrum(electrum::ElectrumBlockchain::from_config(inner)?)
+            }
+            #[cfg(feature = "esplora")]
+            AnyBlockchainConfig::Esplora(inner) => {
+                AnyBlockchain::Esplora(esplora::EsploraBlockchain::from_config(inner)?)
+            }
+            #[cfg(feature = "compact_filters")]
+            AnyBlockchainConfig::CompactFilters(inner) => AnyBlockchain::CompactFilters(
+                compact_filters::CompactFiltersBlockchain::from_config(inner)?,
+            ),
+        })
+    }
+}
+
+impl_from!(electrum::ElectrumBlockchainConfig, AnyBlockchainConfig, Electrum, #[cfg(feature = "electrum")]);
+impl_from!(esplora::EsploraBlockchainConfig, AnyBlockchainConfig, Esplora, #[cfg(feature = "esplora")]);
+impl_from!(compact_filters::CompactFiltersBlockchainConfig, AnyBlockchainConfig, CompactFilters, #[cfg(feature = "compact_filters")]);
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/mod.rs.html new file mode 100644 index 0000000000..f9b808e361 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/mod.rs.html @@ -0,0 +1,1166 @@ +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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Compact Filters
+//!
+//! This module contains a multithreaded implementation of an [`Blockchain`] backend that
+//! uses BIP157 (aka "Neutrino") to populate the wallet's [database](crate::database::Database)
+//! by downloading compact filters from the P2P network.
+//!
+//! Since there are currently very few peers "in the wild" that advertise the required service
+//! flag, this implementation requires that one or more known peers are provided by the user.
+//! No dns or other kinds of peer discovery are done internally.
+//!
+//! Moreover, this module doesn't currently support detecting and resolving conflicts between
+//! messages received by different peers. Thus, it's recommended to use this module by only
+//! connecting to a single peer at a time, optionally by opening multiple connections if it's
+//! desirable to use multiple threads at once to sync in parallel.
+//!
+//! This is an **EXPERIMENTAL** feature, API and other major changes are expected.
+//!
+//! ## Example
+//!
+//! ```no_run
+//! # use std::sync::Arc;
+//! # use bitcoin::*;
+//! # use bdk::*;
+//! # use bdk::blockchain::compact_filters::*;
+//! let num_threads = 4;
+//!
+//! let mempool = Arc::new(Mempool::default());
+//! let peers = (0..num_threads)
+//!     .map(|_| {
+//!         Peer::connect(
+//!             "btcd-mainnet.lightning.computer:8333",
+//!             Arc::clone(&mempool),
+//!             Network::Bitcoin,
+//!         )
+//!     })
+//!     .collect::<Result<_, _>>()?;
+//! let blockchain = CompactFiltersBlockchain::new(peers, "./wallet-filters", Some(500_000))?;
+//! # Ok::<(), CompactFiltersError>(())
+//! ```
+
+use std::collections::HashSet;
+use std::fmt;
+use std::path::Path;
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::{Arc, Mutex};
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use bitcoin::network::message_blockdata::Inventory;
+use bitcoin::{Network, OutPoint, Transaction, Txid};
+
+use rocksdb::{Options, SliceTransform, DB};
+
+mod peer;
+mod store;
+mod sync;
+
+use super::{Blockchain, Capability, ConfigurableBlockchain, Progress};
+use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
+use crate::error::Error;
+use crate::types::{KeychainKind, TransactionDetails, UTXO};
+use crate::FeeRate;
+
+use peer::*;
+use store::*;
+use sync::*;
+
+pub use peer::{Mempool, Peer};
+
+const SYNC_HEADERS_COST: f32 = 1.0;
+const SYNC_FILTERS_COST: f32 = 11.6 * 1_000.0;
+const PROCESS_BLOCKS_COST: f32 = 20_000.0;
+
+/// Structure implementing the required blockchain traits
+///
+/// ## Example
+/// See the [`blockchain::compact_filters`](crate::blockchain::compact_filters) module for a usage example.
+#[derive(Debug)]
+pub struct CompactFiltersBlockchain {
+    peers: Vec<Arc<Peer>>,
+    headers: Arc<ChainStore<Full>>,
+    skip_blocks: Option<usize>,
+}
+
+impl CompactFiltersBlockchain {
+    /// Construct a new instance given a list of peers, a path to store headers and block
+    /// filters downloaded during the sync and optionally a number of blocks to ignore starting
+    /// from the genesis while scanning for the wallet's outputs.
+    ///
+    /// For each [`Peer`] specified a new thread will be spawned to download and verify the filters
+    /// in parallel. It's currently recommended to only connect to a single peer to avoid
+    /// inconsistencies in the data returned, optionally with multiple connections in parallel to
+    /// speed-up the sync process.
+    pub fn new<P: AsRef<Path>>(
+        peers: Vec<Peer>,
+        storage_dir: P,
+        skip_blocks: Option<usize>,
+    ) -> Result<Self, CompactFiltersError> {
+        if peers.is_empty() {
+            return Err(CompactFiltersError::NoPeers);
+        }
+
+        let mut opts = Options::default();
+        opts.create_if_missing(true);
+        opts.set_prefix_extractor(SliceTransform::create_fixed_prefix(16));
+
+        let network = peers[0].get_network();
+
+        let cfs = DB::list_cf(&opts, &storage_dir).unwrap_or(vec!["default".to_string()]);
+        let db = DB::open_cf(&opts, &storage_dir, &cfs)?;
+        let headers = Arc::new(ChainStore::new(db, network)?);
+
+        // try to recover partial snapshots
+        for cf_name in &cfs {
+            if !cf_name.starts_with("_headers:") {
+                continue;
+            }
+
+            info!("Trying to recover: {:?}", cf_name);
+            headers.recover_snapshot(cf_name)?;
+        }
+
+        Ok(CompactFiltersBlockchain {
+            peers: peers.into_iter().map(Arc::new).collect(),
+            headers,
+            skip_blocks,
+        })
+    }
+
+    /// Process a transaction by looking for inputs that spend from a UTXO in the database or
+    /// outputs that send funds to a know script_pubkey.
+    fn process_tx<D: BatchDatabase>(
+        &self,
+        database: &mut D,
+        tx: &Transaction,
+        height: Option<u32>,
+        timestamp: u64,
+        internal_max_deriv: &mut Option<u32>,
+        external_max_deriv: &mut Option<u32>,
+    ) -> Result<(), Error> {
+        let mut updates = database.begin_batch();
+
+        let mut incoming: u64 = 0;
+        let mut outgoing: u64 = 0;
+
+        let mut inputs_sum: u64 = 0;
+        let mut outputs_sum: u64 = 0;
+
+        // look for our own inputs
+        for (i, input) in tx.input.iter().enumerate() {
+            if let Some(previous_output) = database.get_previous_output(&input.previous_output)? {
+                inputs_sum += previous_output.value;
+
+                if database.is_mine(&previous_output.script_pubkey)? {
+                    outgoing += previous_output.value;
+
+                    debug!("{} input #{} is mine, removing from utxo", tx.txid(), i);
+                    updates.del_utxo(&input.previous_output)?;
+                }
+            }
+        }
+
+        for (i, output) in tx.output.iter().enumerate() {
+            // to compute the fees later
+            outputs_sum += output.value;
+
+            // this output is ours, we have a path to derive it
+            if let Some((keychain, child)) =
+                database.get_path_from_script_pubkey(&output.script_pubkey)?
+            {
+                debug!("{} output #{} is mine, adding utxo", tx.txid(), i);
+                updates.set_utxo(&UTXO {
+                    outpoint: OutPoint::new(tx.txid(), i as u32),
+                    txout: output.clone(),
+                    keychain,
+                })?;
+                incoming += output.value;
+
+                if keychain == KeychainKind::Internal
+                    && (internal_max_deriv.is_none() || child > internal_max_deriv.unwrap_or(0))
+                {
+                    *internal_max_deriv = Some(child);
+                } else if keychain == KeychainKind::External
+                    && (external_max_deriv.is_none() || child > external_max_deriv.unwrap_or(0))
+                {
+                    *external_max_deriv = Some(child);
+                }
+            }
+        }
+
+        if incoming > 0 || outgoing > 0 {
+            let tx = TransactionDetails {
+                txid: tx.txid(),
+                transaction: Some(tx.clone()),
+                received: incoming,
+                sent: outgoing,
+                height,
+                timestamp,
+                fees: inputs_sum.checked_sub(outputs_sum).unwrap_or(0),
+            };
+
+            info!("Saving tx {}", tx.txid);
+            updates.set_tx(&tx)?;
+        }
+
+        database.commit_batch(updates)?;
+
+        Ok(())
+    }
+}
+
+impl Blockchain for CompactFiltersBlockchain {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        vec![Capability::FullHistory].into_iter().collect()
+    }
+
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        _stop_gap: Option<usize>, // TODO: move to electrum and esplora only
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        let first_peer = &self.peers[0];
+
+        let skip_blocks = self.skip_blocks.unwrap_or(0);
+
+        let cf_sync = Arc::new(CFSync::new(Arc::clone(&self.headers), skip_blocks, 0x00)?);
+
+        let initial_height = self.headers.get_height()?;
+        let total_bundles = (first_peer.get_version().start_height as usize)
+            .checked_sub(skip_blocks)
+            .map(|x| x / 1000)
+            .unwrap_or(0)
+            + 1;
+        let expected_bundles_to_sync = total_bundles
+            .checked_sub(cf_sync.pruned_bundles()?)
+            .unwrap_or(0);
+
+        let headers_cost = (first_peer.get_version().start_height as usize)
+            .checked_sub(initial_height)
+            .unwrap_or(0) as f32
+            * SYNC_HEADERS_COST;
+        let filters_cost = expected_bundles_to_sync as f32 * SYNC_FILTERS_COST;
+
+        let total_cost = headers_cost + filters_cost + PROCESS_BLOCKS_COST;
+
+        if let Some(snapshot) = sync::sync_headers(
+            Arc::clone(&first_peer),
+            Arc::clone(&self.headers),
+            |new_height| {
+                let local_headers_cost =
+                    new_height.checked_sub(initial_height).unwrap_or(0) as f32 * SYNC_HEADERS_COST;
+                progress_update.update(
+                    local_headers_cost / total_cost * 100.0,
+                    Some(format!("Synced headers to {}", new_height)),
+                )
+            },
+        )? {
+            if snapshot.work()? > self.headers.work()? {
+                info!("Applying snapshot with work: {}", snapshot.work()?);
+                self.headers.apply_snapshot(snapshot)?;
+            }
+        }
+
+        let synced_height = self.headers.get_height()?;
+        let buried_height = synced_height
+            .checked_sub(sync::BURIED_CONFIRMATIONS)
+            .unwrap_or(0);
+        info!("Synced headers to height: {}", synced_height);
+
+        cf_sync.prepare_sync(Arc::clone(&first_peer))?;
+
+        let all_scripts = Arc::new(
+            database
+                .iter_script_pubkeys(None)?
+                .into_iter()
+                .map(|s| s.to_bytes())
+                .collect::<Vec<_>>(),
+        );
+
+        let last_synced_block = Arc::new(Mutex::new(synced_height));
+        let synced_bundles = Arc::new(AtomicUsize::new(0));
+        let progress_update = Arc::new(Mutex::new(progress_update));
+
+        let mut threads = Vec::with_capacity(self.peers.len());
+        for peer in &self.peers {
+            let cf_sync = Arc::clone(&cf_sync);
+            let peer = Arc::clone(&peer);
+            let headers = Arc::clone(&self.headers);
+            let all_scripts = Arc::clone(&all_scripts);
+            let last_synced_block = Arc::clone(&last_synced_block);
+            let progress_update = Arc::clone(&progress_update);
+            let synced_bundles = Arc::clone(&synced_bundles);
+
+            let thread = std::thread::spawn(move || {
+                cf_sync.capture_thread_for_sync(
+                    peer,
+                    |block_hash, filter| {
+                        if !filter
+                            .match_any(block_hash, &mut all_scripts.iter().map(AsRef::as_ref))?
+                        {
+                            return Ok(false);
+                        }
+
+                        let block_height = headers.get_height_for(block_hash)?.unwrap_or(0);
+                        let saved_correct_block = match headers.get_full_block(block_height)? {
+                            Some(block) if &block.block_hash() == block_hash => true,
+                            _ => false,
+                        };
+
+                        if saved_correct_block {
+                            Ok(false)
+                        } else {
+                            let mut last_synced_block = last_synced_block.lock().unwrap();
+
+                            // If we download a block older than `last_synced_block`, we update it so that
+                            // we know to delete and re-process all txs starting from that height
+                            if block_height < *last_synced_block {
+                                *last_synced_block = block_height;
+                            }
+
+                            Ok(true)
+                        }
+                    },
+                    |index| {
+                        let synced_bundles = synced_bundles.fetch_add(1, Ordering::SeqCst);
+                        let local_filters_cost = synced_bundles as f32 * SYNC_FILTERS_COST;
+                        progress_update.lock().unwrap().update(
+                            (headers_cost + local_filters_cost) / total_cost * 100.0,
+                            Some(format!(
+                                "Synced filters {} - {}",
+                                index * 1000 + 1,
+                                (index + 1) * 1000
+                            )),
+                        )
+                    },
+                )
+            });
+
+            threads.push(thread);
+        }
+
+        for t in threads {
+            t.join().unwrap()?;
+        }
+
+        progress_update.lock().unwrap().update(
+            (headers_cost + filters_cost) / total_cost * 100.0,
+            Some("Processing downloaded blocks and mempool".into()),
+        )?;
+
+        // delete all txs newer than last_synced_block
+        let last_synced_block = *last_synced_block.lock().unwrap();
+        log::debug!(
+            "Dropping transactions newer than `last_synced_block` = {}",
+            last_synced_block
+        );
+        let mut updates = database.begin_batch();
+        for details in database.iter_txs(false)? {
+            match details.height {
+                Some(height) if (height as usize) < last_synced_block => continue,
+                _ => updates.del_tx(&details.txid, false)?,
+            };
+        }
+        database.commit_batch(updates)?;
+
+        first_peer.ask_for_mempool()?;
+
+        let mut internal_max_deriv = None;
+        let mut external_max_deriv = None;
+
+        for (height, block) in self.headers.iter_full_blocks()? {
+            for tx in &block.txdata {
+                self.process_tx(
+                    database,
+                    tx,
+                    Some(height as u32),
+                    0,
+                    &mut internal_max_deriv,
+                    &mut external_max_deriv,
+                )?;
+            }
+        }
+        for tx in first_peer.get_mempool().iter_txs().iter() {
+            self.process_tx(
+                database,
+                tx,
+                None,
+                0,
+                &mut internal_max_deriv,
+                &mut external_max_deriv,
+            )?;
+        }
+
+        let current_ext = database
+            .get_last_index(KeychainKind::External)?
+            .unwrap_or(0);
+        let first_ext_new = external_max_deriv.map(|x| x + 1).unwrap_or(0);
+        if first_ext_new > current_ext {
+            info!("Setting external index to {}", first_ext_new);
+            database.set_last_index(KeychainKind::External, first_ext_new)?;
+        }
+
+        let current_int = database
+            .get_last_index(KeychainKind::Internal)?
+            .unwrap_or(0);
+        let first_int_new = internal_max_deriv.map(|x| x + 1).unwrap_or(0);
+        if first_int_new > current_int {
+            info!("Setting internal index to {}", first_int_new);
+            database.set_last_index(KeychainKind::Internal, first_int_new)?;
+        }
+
+        info!("Dropping blocks until {}", buried_height);
+        self.headers.delete_blocks_until(buried_height)?;
+
+        progress_update
+            .lock()
+            .unwrap()
+            .update(100.0, Some("Done".into()))?;
+
+        Ok(())
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        Ok(self.peers[0]
+            .get_mempool()
+            .get_tx(&Inventory::Transaction(*txid)))
+    }
+
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        self.peers[0].broadcast_tx(tx.clone())?;
+
+        Ok(())
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        Ok(self.headers.get_height()? as u32)
+    }
+
+    fn estimate_fee(&self, _target: usize) -> Result<FeeRate, Error> {
+        // TODO
+        Ok(FeeRate::default())
+    }
+}
+
+/// Data to connect to a Bitcoin P2P peer
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct BitcoinPeerConfig {
+    /// Peer address such as 127.0.0.1:18333
+    pub address: String,
+    /// Optional socks5 proxy
+    pub socks5: Option<String>,
+    /// Optional socks5 proxy credentials
+    pub socks5_credentials: Option<(String, String)>,
+}
+
+/// Configuration for a [`CompactFiltersBlockchain`]
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct CompactFiltersBlockchainConfig {
+    /// List of peers to try to connect to for asking headers and filters
+    pub peers: Vec<BitcoinPeerConfig>,
+    /// Network used
+    pub network: Network,
+    /// Storage dir to save partially downloaded headers and full blocks
+    pub storage_dir: String,
+    /// Optionally skip initial `skip_blocks` blocks (default: 0)
+    pub skip_blocks: Option<usize>,
+}
+
+impl ConfigurableBlockchain for CompactFiltersBlockchain {
+    type Config = CompactFiltersBlockchainConfig;
+
+    fn from_config(config: &Self::Config) -> Result<Self, Error> {
+        let mempool = Arc::new(Mempool::default());
+        let peers = config
+            .peers
+            .iter()
+            .map(|peer_conf| match &peer_conf.socks5 {
+                None => Peer::connect(&peer_conf.address, Arc::clone(&mempool), config.network),
+                Some(proxy) => Peer::connect_proxy(
+                    peer_conf.address.as_str(),
+                    proxy,
+                    peer_conf
+                        .socks5_credentials
+                        .as_ref()
+                        .map(|(a, b)| (a.as_str(), b.as_str())),
+                    Arc::clone(&mempool),
+                    config.network,
+                ),
+            })
+            .collect::<Result<_, _>>()?;
+
+        Ok(CompactFiltersBlockchain::new(
+            peers,
+            &config.storage_dir,
+            config.skip_blocks,
+        )?)
+    }
+}
+
+/// An error that can occur during sync with a [`CompactFiltersBlockchain`]
+#[derive(Debug)]
+pub enum CompactFiltersError {
+    /// A peer sent an invalid or unexpected response
+    InvalidResponse,
+    /// The headers returned are invalid
+    InvalidHeaders,
+    /// The compact filter headers returned are invalid
+    InvalidFilterHeader,
+    /// The compact filter returned is invalid
+    InvalidFilter,
+    /// The peer is missing a block in the valid chain
+    MissingBlock,
+    /// The data stored in the block filters storage are corrupted
+    DataCorruption,
+
+    /// A peer is not connected
+    NotConnected,
+    /// A peer took too long to reply to one of our messages
+    Timeout,
+
+    /// No peers have been specified
+    NoPeers,
+
+    /// Internal database error
+    DB(rocksdb::Error),
+    /// Internal I/O error
+    IO(std::io::Error),
+    /// Invalid BIP158 filter
+    BIP158(bitcoin::util::bip158::Error),
+    /// Internal system time error
+    Time(std::time::SystemTimeError),
+
+    /// Wrapper for [`crate::error::Error`]
+    Global(Box<crate::error::Error>),
+}
+
+impl fmt::Display for CompactFiltersError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for CompactFiltersError {}
+
+impl_error!(rocksdb::Error, DB, CompactFiltersError);
+impl_error!(std::io::Error, IO, CompactFiltersError);
+impl_error!(bitcoin::util::bip158::Error, BIP158, CompactFiltersError);
+impl_error!(std::time::SystemTimeError, Time, CompactFiltersError);
+
+impl From<crate::error::Error> for CompactFiltersError {
+    fn from(err: crate::error::Error) -> Self {
+        CompactFiltersError::Global(Box::new(err))
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/peer.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/peer.rs.html new file mode 100644 index 0000000000..16eba3f0d0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/peer.rs.html @@ -0,0 +1,1106 @@ +peer.rs - source + +
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::collections::HashMap;
+use std::net::{TcpStream, ToSocketAddrs};
+use std::sync::{Arc, Condvar, Mutex, RwLock};
+use std::thread;
+use std::time::{Duration, SystemTime, UNIX_EPOCH};
+
+use socks::{Socks5Stream, ToTargetAddr};
+
+use rand::{thread_rng, Rng};
+
+use bitcoin::consensus::Encodable;
+use bitcoin::hash_types::BlockHash;
+use bitcoin::hashes::Hash;
+use bitcoin::network::constants::ServiceFlags;
+use bitcoin::network::message::{NetworkMessage, RawNetworkMessage};
+use bitcoin::network::message_blockdata::*;
+use bitcoin::network::message_filter::*;
+use bitcoin::network::message_network::VersionMessage;
+use bitcoin::network::stream_reader::StreamReader;
+use bitcoin::network::Address;
+use bitcoin::{Block, Network, Transaction, Txid};
+
+use super::CompactFiltersError;
+
+type ResponsesMap = HashMap<&'static str, Arc<(Mutex<Vec<NetworkMessage>>, Condvar)>>;
+
+pub(crate) const TIMEOUT_SECS: u64 = 30;
+
+/// Container for unconfirmed, but valid Bitcoin transactions
+///
+/// It is normally shared between [`Peer`]s with the use of [`Arc`], so that transactions are not
+/// duplicated in memory.
+#[derive(Debug, Default)]
+pub struct Mempool {
+    txs: RwLock<HashMap<Txid, Transaction>>,
+}
+
+impl Mempool {
+    /// Add a transaction to the mempool
+    ///
+    /// Note that this doesn't propagate the transaction to other
+    /// peers. To do that, [`broadcast`](crate::blockchain::Blockchain::broadcast) should be used.
+    pub fn add_tx(&self, tx: Transaction) {
+        self.txs.write().unwrap().insert(tx.txid(), tx);
+    }
+
+    /// Look-up a transaction in the mempool given an [`Inventory`] request
+    pub fn get_tx(&self, inventory: &Inventory) -> Option<Transaction> {
+        let txid = match inventory {
+            Inventory::Error | Inventory::Block(_) | Inventory::WitnessBlock(_) => return None,
+            Inventory::Transaction(txid) => *txid,
+            Inventory::WitnessTransaction(wtxid) => Txid::from_inner(wtxid.into_inner()),
+        };
+        self.txs.read().unwrap().get(&txid).cloned()
+    }
+
+    /// Return whether or not the mempool contains a transaction with a given txid
+    pub fn has_tx(&self, txid: &Txid) -> bool {
+        self.txs.read().unwrap().contains_key(txid)
+    }
+
+    /// Return the list of transactions contained in the mempool
+    pub fn iter_txs(&self) -> Vec<Transaction> {
+        self.txs.read().unwrap().values().cloned().collect()
+    }
+}
+
+/// A Bitcoin peer
+#[derive(Debug)]
+pub struct Peer {
+    writer: Arc<Mutex<TcpStream>>,
+    responses: Arc<RwLock<ResponsesMap>>,
+
+    reader_thread: thread::JoinHandle<()>,
+    connected: Arc<RwLock<bool>>,
+
+    mempool: Arc<Mempool>,
+
+    version: VersionMessage,
+    network: Network,
+}
+
+impl Peer {
+    /// Connect to a peer over a plaintext TCP connection
+    ///
+    /// This function internally spawns a new thread that will monitor incoming messages from the
+    /// peer, and optionally reply to some of them transparently, like [pings](bitcoin::network::message::NetworkMessage::Ping)
+    pub fn connect<A: ToSocketAddrs>(
+        address: A,
+        mempool: Arc<Mempool>,
+        network: Network,
+    ) -> Result<Self, CompactFiltersError> {
+        let stream = TcpStream::connect(address)?;
+
+        Peer::from_stream(stream, mempool, network)
+    }
+
+    /// Connect to a peer through a SOCKS5 proxy, optionally by using some credentials, specified
+    /// as a tuple of `(username, password)`
+    ///
+    /// This function internally spawns a new thread that will monitor incoming messages from the
+    /// peer, and optionally reply to some of them transparently, like [pings](NetworkMessage::Ping)
+    pub fn connect_proxy<T: ToTargetAddr, P: ToSocketAddrs>(
+        target: T,
+        proxy: P,
+        credentials: Option<(&str, &str)>,
+        mempool: Arc<Mempool>,
+        network: Network,
+    ) -> Result<Self, CompactFiltersError> {
+        let socks_stream = if let Some((username, password)) = credentials {
+            Socks5Stream::connect_with_password(proxy, target, username, password)?
+        } else {
+            Socks5Stream::connect(proxy, target)?
+        };
+
+        Peer::from_stream(socks_stream.into_inner(), mempool, network)
+    }
+
+    /// Create a [`Peer`] from an already connected TcpStream
+    fn from_stream(
+        stream: TcpStream,
+        mempool: Arc<Mempool>,
+        network: Network,
+    ) -> Result<Self, CompactFiltersError> {
+        let writer = Arc::new(Mutex::new(stream.try_clone()?));
+        let responses: Arc<RwLock<ResponsesMap>> = Arc::new(RwLock::new(HashMap::new()));
+        let connected = Arc::new(RwLock::new(true));
+
+        let mut locked_writer = writer.lock().unwrap();
+
+        let reader_thread_responses = Arc::clone(&responses);
+        let reader_thread_writer = Arc::clone(&writer);
+        let reader_thread_mempool = Arc::clone(&mempool);
+        let reader_thread_connected = Arc::clone(&connected);
+        let reader_thread = thread::spawn(move || {
+            Self::reader_thread(
+                network,
+                stream,
+                reader_thread_responses,
+                reader_thread_writer,
+                reader_thread_mempool,
+                reader_thread_connected,
+            )
+        });
+
+        let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() as i64;
+        let nonce = thread_rng().gen();
+        let receiver = Address::new(&locked_writer.peer_addr()?, ServiceFlags::NONE);
+        let sender = Address {
+            services: ServiceFlags::NONE,
+            address: [0u16; 8],
+            port: 0,
+        };
+
+        Self::_send(
+            &mut locked_writer,
+            network.magic(),
+            NetworkMessage::Version(VersionMessage::new(
+                ServiceFlags::WITNESS,
+                timestamp,
+                receiver,
+                sender,
+                nonce,
+                "MagicalBitcoinWallet".into(),
+                0,
+            )),
+        )?;
+        let version = if let NetworkMessage::Version(version) =
+            Self::_recv(&responses, "version", None)?.unwrap()
+        {
+            version
+        } else {
+            return Err(CompactFiltersError::InvalidResponse);
+        };
+
+        if let NetworkMessage::Verack = Self::_recv(&responses, "verack", None)?.unwrap() {
+            Self::_send(&mut locked_writer, network.magic(), NetworkMessage::Verack)?;
+        } else {
+            return Err(CompactFiltersError::InvalidResponse);
+        }
+
+        std::mem::drop(locked_writer);
+
+        Ok(Peer {
+            writer,
+            reader_thread,
+            responses,
+            connected,
+            mempool,
+            network,
+            version,
+        })
+    }
+
+    /// Send a Bitcoin network message
+    fn _send(
+        writer: &mut TcpStream,
+        magic: u32,
+        payload: NetworkMessage,
+    ) -> Result<(), CompactFiltersError> {
+        log::trace!("==> {:?}", payload);
+
+        let raw_message = RawNetworkMessage { magic, payload };
+
+        raw_message
+            .consensus_encode(writer)
+            .map_err(|_| CompactFiltersError::DataCorruption)?;
+
+        Ok(())
+    }
+
+    /// Wait for a specific incoming Bitcoin message, optionally with a timeout
+    fn _recv(
+        responses: &Arc<RwLock<ResponsesMap>>,
+        wait_for: &'static str,
+        timeout: Option<Duration>,
+    ) -> Result<Option<NetworkMessage>, CompactFiltersError> {
+        let message_resp = {
+            let mut lock = responses.write().unwrap();
+            let message_resp = lock.entry(wait_for).or_default();
+            Arc::clone(&message_resp)
+        };
+
+        let (lock, cvar) = &*message_resp;
+
+        let mut messages = lock.lock().unwrap();
+        while messages.is_empty() {
+            match timeout {
+                None => messages = cvar.wait(messages).unwrap(),
+                Some(t) => {
+                    let result = cvar.wait_timeout(messages, t).unwrap();
+                    if result.1.timed_out() {
+                        return Ok(None);
+                    }
+
+                    messages = result.0;
+                }
+            }
+        }
+
+        Ok(messages.pop())
+    }
+
+    /// Return the [`VersionMessage`] sent by the peer
+    pub fn get_version(&self) -> &VersionMessage {
+        &self.version
+    }
+
+    /// Return the Bitcoin [`Network`] in use
+    pub fn get_network(&self) -> Network {
+        self.network
+    }
+
+    /// Return the mempool used by this peer
+    pub fn get_mempool(&self) -> Arc<Mempool> {
+        Arc::clone(&self.mempool)
+    }
+
+    /// Return whether or not the peer is still connected
+    pub fn is_connected(&self) -> bool {
+        *self.connected.read().unwrap()
+    }
+
+    /// Internal function called once the `reader_thread` is spawned
+    fn reader_thread(
+        network: Network,
+        connection: TcpStream,
+        reader_thread_responses: Arc<RwLock<ResponsesMap>>,
+        reader_thread_writer: Arc<Mutex<TcpStream>>,
+        reader_thread_mempool: Arc<Mempool>,
+        reader_thread_connected: Arc<RwLock<bool>>,
+    ) {
+        macro_rules! check_disconnect {
+            ($call:expr) => {
+                match $call {
+                    Ok(good) => good,
+                    Err(e) => {
+                        log::debug!("Error {:?}", e);
+                        *reader_thread_connected.write().unwrap() = false;
+
+                        break;
+                    }
+                }
+            };
+        }
+
+        let mut reader = StreamReader::new(connection, None);
+        loop {
+            let raw_message: RawNetworkMessage = check_disconnect!(reader.read_next());
+
+            let in_message = if raw_message.magic != network.magic() {
+                continue;
+            } else {
+                raw_message.payload
+            };
+
+            log::trace!("<== {:?}", in_message);
+
+            match in_message {
+                NetworkMessage::Ping(nonce) => {
+                    check_disconnect!(Self::_send(
+                        &mut reader_thread_writer.lock().unwrap(),
+                        network.magic(),
+                        NetworkMessage::Pong(nonce),
+                    ));
+
+                    continue;
+                }
+                NetworkMessage::Alert(_) => continue,
+                NetworkMessage::GetData(ref inv) => {
+                    let (found, not_found): (Vec<_>, Vec<_>) = inv
+                        .into_iter()
+                        .map(|item| (*item, reader_thread_mempool.get_tx(item)))
+                        .partition(|(_, d)| d.is_some());
+                    for (_, found_tx) in found {
+                        check_disconnect!(Self::_send(
+                            &mut reader_thread_writer.lock().unwrap(),
+                            network.magic(),
+                            NetworkMessage::Tx(found_tx.unwrap()),
+                        ));
+                    }
+
+                    if !not_found.is_empty() {
+                        check_disconnect!(Self::_send(
+                            &mut reader_thread_writer.lock().unwrap(),
+                            network.magic(),
+                            NetworkMessage::NotFound(
+                                not_found.into_iter().map(|(i, _)| i).collect(),
+                            ),
+                        ));
+                    }
+                }
+                _ => {}
+            }
+
+            let message_resp = {
+                let mut lock = reader_thread_responses.write().unwrap();
+                let message_resp = lock.entry(in_message.cmd()).or_default();
+                Arc::clone(&message_resp)
+            };
+
+            let (lock, cvar) = &*message_resp;
+            let mut messages = lock.lock().unwrap();
+            messages.push(in_message);
+            cvar.notify_all();
+        }
+    }
+
+    /// Send a raw Bitcoin message to the peer
+    pub fn send(&self, payload: NetworkMessage) -> Result<(), CompactFiltersError> {
+        let mut writer = self.writer.lock().unwrap();
+        Self::_send(&mut writer, self.network.magic(), payload)
+    }
+
+    /// Waits for a specific incoming Bitcoin message, optionally with a timeout
+    pub fn recv(
+        &self,
+        wait_for: &'static str,
+        timeout: Option<Duration>,
+    ) -> Result<Option<NetworkMessage>, CompactFiltersError> {
+        Self::_recv(&self.responses, wait_for, timeout)
+    }
+}
+
+pub trait CompactFiltersPeer {
+    fn get_cf_checkpt(
+        &self,
+        filter_type: u8,
+        stop_hash: BlockHash,
+    ) -> Result<CFCheckpt, CompactFiltersError>;
+    fn get_cf_headers(
+        &self,
+        filter_type: u8,
+        start_height: u32,
+        stop_hash: BlockHash,
+    ) -> Result<CFHeaders, CompactFiltersError>;
+    fn get_cf_filters(
+        &self,
+        filter_type: u8,
+        start_height: u32,
+        stop_hash: BlockHash,
+    ) -> Result<(), CompactFiltersError>;
+    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError>;
+}
+
+impl CompactFiltersPeer for Peer {
+    fn get_cf_checkpt(
+        &self,
+        filter_type: u8,
+        stop_hash: BlockHash,
+    ) -> Result<CFCheckpt, CompactFiltersError> {
+        self.send(NetworkMessage::GetCFCheckpt(GetCFCheckpt {
+            filter_type,
+            stop_hash,
+        }))?;
+
+        let response = self
+            .recv("cfcheckpt", Some(Duration::from_secs(TIMEOUT_SECS)))?
+            .ok_or(CompactFiltersError::Timeout)?;
+        let response = match response {
+            NetworkMessage::CFCheckpt(response) => response,
+            _ => return Err(CompactFiltersError::InvalidResponse),
+        };
+
+        if response.filter_type != filter_type {
+            return Err(CompactFiltersError::InvalidResponse);
+        }
+
+        Ok(response)
+    }
+
+    fn get_cf_headers(
+        &self,
+        filter_type: u8,
+        start_height: u32,
+        stop_hash: BlockHash,
+    ) -> Result<CFHeaders, CompactFiltersError> {
+        self.send(NetworkMessage::GetCFHeaders(GetCFHeaders {
+            filter_type,
+            start_height,
+            stop_hash,
+        }))?;
+
+        let response = self
+            .recv("cfheaders", Some(Duration::from_secs(TIMEOUT_SECS)))?
+            .ok_or(CompactFiltersError::Timeout)?;
+        let response = match response {
+            NetworkMessage::CFHeaders(response) => response,
+            _ => return Err(CompactFiltersError::InvalidResponse),
+        };
+
+        if response.filter_type != filter_type {
+            return Err(CompactFiltersError::InvalidResponse);
+        }
+
+        Ok(response)
+    }
+
+    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError> {
+        let response = self
+            .recv("cfilter", Some(Duration::from_secs(TIMEOUT_SECS)))?
+            .ok_or(CompactFiltersError::Timeout)?;
+        let response = match response {
+            NetworkMessage::CFilter(response) => response,
+            _ => return Err(CompactFiltersError::InvalidResponse),
+        };
+
+        Ok(response)
+    }
+
+    fn get_cf_filters(
+        &self,
+        filter_type: u8,
+        start_height: u32,
+        stop_hash: BlockHash,
+    ) -> Result<(), CompactFiltersError> {
+        self.send(NetworkMessage::GetCFilters(GetCFilters {
+            filter_type,
+            start_height,
+            stop_hash,
+        }))?;
+
+        Ok(())
+    }
+}
+
+pub trait InvPeer {
+    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError>;
+    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError>;
+    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError>;
+}
+
+impl InvPeer for Peer {
+    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError> {
+        self.send(NetworkMessage::GetData(vec![Inventory::WitnessBlock(
+            block_hash,
+        )]))?;
+
+        match self.recv("block", Some(Duration::from_secs(TIMEOUT_SECS)))? {
+            None => Ok(None),
+            Some(NetworkMessage::Block(response)) => Ok(Some(response)),
+            _ => Err(CompactFiltersError::InvalidResponse),
+        }
+    }
+
+    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError> {
+        self.send(NetworkMessage::MemPool)?;
+        let inv = match self.recv("inv", Some(Duration::from_secs(5)))? {
+            None => return Ok(()), // empty mempool
+            Some(NetworkMessage::Inv(inv)) => inv,
+            _ => return Err(CompactFiltersError::InvalidResponse),
+        };
+
+        let getdata = inv
+            .iter()
+            .cloned()
+            .filter(|item| match item {
+                Inventory::Transaction(txid) if !self.mempool.has_tx(txid) => true,
+                _ => false,
+            })
+            .collect::<Vec<_>>();
+        let num_txs = getdata.len();
+        self.send(NetworkMessage::GetData(getdata))?;
+
+        for _ in 0..num_txs {
+            let tx = self
+                .recv("tx", Some(Duration::from_secs(TIMEOUT_SECS)))?
+                .ok_or(CompactFiltersError::Timeout)?;
+            let tx = match tx {
+                NetworkMessage::Tx(tx) => tx,
+                _ => return Err(CompactFiltersError::InvalidResponse),
+            };
+
+            self.mempool.add_tx(tx);
+        }
+
+        Ok(())
+    }
+
+    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError> {
+        self.mempool.add_tx(tx.clone());
+        self.send(NetworkMessage::Tx(tx))?;
+
+        Ok(())
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/store.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/store.rs.html new file mode 100644 index 0000000000..35d649a23b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/store.rs.html @@ -0,0 +1,1814 @@ +store.rs - source + +
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::convert::TryInto;
+use std::fmt;
+use std::io::{Read, Write};
+use std::marker::PhantomData;
+use std::ops::Deref;
+use std::sync::Arc;
+use std::sync::RwLock;
+
+use rand::distributions::Alphanumeric;
+use rand::{thread_rng, Rng};
+
+use rocksdb::{Direction, IteratorMode, ReadOptions, WriteBatch, DB};
+
+use bitcoin::consensus::{deserialize, encode::VarInt, serialize, Decodable, Encodable};
+use bitcoin::hash_types::FilterHash;
+use bitcoin::hashes::hex::FromHex;
+use bitcoin::hashes::{sha256d, Hash};
+use bitcoin::util::bip158::BlockFilter;
+use bitcoin::util::uint::Uint256;
+use bitcoin::Block;
+use bitcoin::BlockHash;
+use bitcoin::BlockHeader;
+use bitcoin::Network;
+
+use super::CompactFiltersError;
+
+lazy_static! {
+    static ref MAINNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A29AB5F49FFFF001D1DAC2B7C0101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
+    static ref TESTNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4ADAE5494DFFFF001D1AA4AE180101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
+    static ref REGTEST_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4ADAE5494DFFFF7F20020000000101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
+}
+
+pub trait StoreType: Default + fmt::Debug {}
+
+#[derive(Default, Debug)]
+pub struct Full;
+impl StoreType for Full {}
+#[derive(Default, Debug)]
+pub struct Snapshot;
+impl StoreType for Snapshot {}
+
+pub enum StoreEntry {
+    BlockHeader(Option<usize>),
+    Block(Option<usize>),
+    BlockHeaderIndex(Option<BlockHash>),
+    CFilterTable((u8, Option<usize>)),
+}
+
+impl StoreEntry {
+    pub fn get_prefix(&self) -> Vec<u8> {
+        match self {
+            StoreEntry::BlockHeader(_) => b"z",
+            StoreEntry::Block(_) => b"x",
+            StoreEntry::BlockHeaderIndex(_) => b"i",
+            StoreEntry::CFilterTable(_) => b"t",
+        }
+        .to_vec()
+    }
+
+    pub fn get_key(&self) -> Vec<u8> {
+        let mut prefix = self.get_prefix();
+        match self {
+            StoreEntry::BlockHeader(Some(height)) => {
+                prefix.extend_from_slice(&height.to_be_bytes())
+            }
+            StoreEntry::Block(Some(height)) => prefix.extend_from_slice(&height.to_be_bytes()),
+            StoreEntry::BlockHeaderIndex(Some(hash)) => {
+                prefix.extend_from_slice(&hash.into_inner())
+            }
+            StoreEntry::CFilterTable((filter_type, bundle_index)) => {
+                prefix.push(*filter_type);
+                if let Some(bundle_index) = bundle_index {
+                    prefix.extend_from_slice(&bundle_index.to_be_bytes());
+                }
+            }
+            _ => {}
+        }
+
+        prefix
+    }
+}
+
+pub trait SerializeDb: Sized {
+    fn serialize(&self) -> Vec<u8>;
+    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError>;
+}
+
+impl<T> SerializeDb for T
+where
+    T: Encodable + Decodable,
+{
+    fn serialize(&self) -> Vec<u8> {
+        serialize(self)
+    }
+
+    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError> {
+        Ok(deserialize(data).map_err(|_| CompactFiltersError::DataCorruption)?)
+    }
+}
+
+impl Encodable for FilterHeader {
+    fn consensus_encode<W: Write>(
+        &self,
+        mut e: W,
+    ) -> Result<usize, bitcoin::consensus::encode::Error> {
+        let mut written = self.prev_header_hash.consensus_encode(&mut e)?;
+        written += self.filter_hash.consensus_encode(&mut e)?;
+        Ok(written)
+    }
+}
+
+impl Decodable for FilterHeader {
+    fn consensus_decode<D: Read>(mut d: D) -> Result<Self, bitcoin::consensus::encode::Error> {
+        let prev_header_hash = FilterHeaderHash::consensus_decode(&mut d)?;
+        let filter_hash = FilterHash::consensus_decode(&mut d)?;
+
+        Ok(FilterHeader {
+            prev_header_hash,
+            filter_hash,
+        })
+    }
+}
+
+impl Encodable for BundleStatus {
+    fn consensus_encode<W: Write>(
+        &self,
+        mut e: W,
+    ) -> Result<usize, bitcoin::consensus::encode::Error> {
+        let mut written = 0;
+
+        match self {
+            BundleStatus::Init => {
+                written += 0x00u8.consensus_encode(&mut e)?;
+            }
+            BundleStatus::CFHeaders { cf_headers } => {
+                written += 0x01u8.consensus_encode(&mut e)?;
+                written += VarInt(cf_headers.len() as u64).consensus_encode(&mut e)?;
+                for header in cf_headers {
+                    written += header.consensus_encode(&mut e)?;
+                }
+            }
+            BundleStatus::CFilters { cf_filters } => {
+                written += 0x02u8.consensus_encode(&mut e)?;
+                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
+                for filter in cf_filters {
+                    written += filter.consensus_encode(&mut e)?;
+                }
+            }
+            BundleStatus::Processed { cf_filters } => {
+                written += 0x03u8.consensus_encode(&mut e)?;
+                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
+                for filter in cf_filters {
+                    written += filter.consensus_encode(&mut e)?;
+                }
+            }
+            BundleStatus::Pruned => {
+                written += 0x04u8.consensus_encode(&mut e)?;
+            }
+            BundleStatus::Tip { cf_filters } => {
+                written += 0x05u8.consensus_encode(&mut e)?;
+                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
+                for filter in cf_filters {
+                    written += filter.consensus_encode(&mut e)?;
+                }
+            }
+        }
+
+        Ok(written)
+    }
+}
+
+impl Decodable for BundleStatus {
+    fn consensus_decode<D: Read>(mut d: D) -> Result<Self, bitcoin::consensus::encode::Error> {
+        let byte_type = u8::consensus_decode(&mut d)?;
+        match byte_type {
+            0x00 => Ok(BundleStatus::Init),
+            0x01 => {
+                let num = VarInt::consensus_decode(&mut d)?;
+                let num = num.0 as usize;
+
+                let mut cf_headers = Vec::with_capacity(num);
+                for _ in 0..num {
+                    cf_headers.push(FilterHeader::consensus_decode(&mut d)?);
+                }
+
+                Ok(BundleStatus::CFHeaders { cf_headers })
+            }
+            0x02 => {
+                let num = VarInt::consensus_decode(&mut d)?;
+                let num = num.0 as usize;
+
+                let mut cf_filters = Vec::with_capacity(num);
+                for _ in 0..num {
+                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
+                }
+
+                Ok(BundleStatus::CFilters { cf_filters })
+            }
+            0x03 => {
+                let num = VarInt::consensus_decode(&mut d)?;
+                let num = num.0 as usize;
+
+                let mut cf_filters = Vec::with_capacity(num);
+                for _ in 0..num {
+                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
+                }
+
+                Ok(BundleStatus::Processed { cf_filters })
+            }
+            0x04 => Ok(BundleStatus::Pruned),
+            0x05 => {
+                let num = VarInt::consensus_decode(&mut d)?;
+                let num = num.0 as usize;
+
+                let mut cf_filters = Vec::with_capacity(num);
+                for _ in 0..num {
+                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
+                }
+
+                Ok(BundleStatus::Tip { cf_filters })
+            }
+            _ => Err(bitcoin::consensus::encode::Error::ParseFailed(
+                "Invalid byte type",
+            )),
+        }
+    }
+}
+
+pub struct ChainStore<T: StoreType> {
+    store: Arc<RwLock<DB>>,
+    cf_name: String,
+    min_height: usize,
+    network: Network,
+    phantom: PhantomData<T>,
+}
+
+impl ChainStore<Full> {
+    pub fn new(store: DB, network: Network) -> Result<Self, CompactFiltersError> {
+        let genesis = match network {
+            Network::Bitcoin => MAINNET_GENESIS.deref(),
+            Network::Testnet => TESTNET_GENESIS.deref(),
+            Network::Regtest => REGTEST_GENESIS.deref(),
+        };
+
+        let cf_name = "default".to_string();
+        let cf_handle = store.cf_handle(&cf_name).unwrap();
+
+        let genesis_key = StoreEntry::BlockHeader(Some(0)).get_key();
+
+        if store.get_pinned_cf(cf_handle, &genesis_key)?.is_none() {
+            let mut batch = WriteBatch::default();
+            batch.put_cf(
+                cf_handle,
+                genesis_key,
+                (genesis.header, genesis.header.work()).serialize(),
+            );
+            batch.put_cf(
+                cf_handle,
+                StoreEntry::BlockHeaderIndex(Some(genesis.block_hash())).get_key(),
+                &0usize.to_be_bytes(),
+            );
+            store.write(batch)?;
+        }
+
+        Ok(ChainStore {
+            store: Arc::new(RwLock::new(store)),
+            cf_name,
+            min_height: 0,
+            network,
+            phantom: PhantomData,
+        })
+    }
+
+    pub fn get_locators(&self) -> Result<Vec<(BlockHash, usize)>, CompactFiltersError> {
+        let mut step = 1;
+        let mut index = self.get_height()?;
+        let mut answer = Vec::new();
+
+        let store_read = self.store.read().unwrap();
+        let cf_handle = store_read.cf_handle(&self.cf_name).unwrap();
+
+        loop {
+            if answer.len() > 10 {
+                step *= 2;
+            }
+
+            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(
+                &store_read
+                    .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(index)).get_key())?
+                    .unwrap(),
+            )?;
+            answer.push((header.block_hash(), index));
+
+            if let Some(new_index) = index.checked_sub(step) {
+                index = new_index;
+            } else {
+                break;
+            }
+        }
+
+        Ok(answer)
+    }
+
+    pub fn start_snapshot(&self, from: usize) -> Result<ChainStore<Snapshot>, CompactFiltersError> {
+        let new_cf_name: String = thread_rng().sample_iter(&Alphanumeric).take(16).collect();
+        let new_cf_name = format!("_headers:{}", new_cf_name);
+
+        let mut write_store = self.store.write().unwrap();
+
+        write_store.create_cf(&new_cf_name, &Default::default())?;
+
+        let cf_handle = write_store.cf_handle(&self.cf_name).unwrap();
+        let new_cf_handle = write_store.cf_handle(&new_cf_name).unwrap();
+
+        let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(
+            &write_store
+                .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
+                .ok_or(CompactFiltersError::DataCorruption)?,
+        )?;
+
+        let mut batch = WriteBatch::default();
+        batch.put_cf(
+            new_cf_handle,
+            StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
+            &from.to_be_bytes(),
+        );
+        batch.put_cf(
+            new_cf_handle,
+            StoreEntry::BlockHeader(Some(from)).get_key(),
+            (header, work).serialize(),
+        );
+        write_store.write(batch)?;
+
+        let store = Arc::clone(&self.store);
+        Ok(ChainStore {
+            store,
+            cf_name: new_cf_name,
+            min_height: from,
+            network: self.network,
+            phantom: PhantomData,
+        })
+    }
+
+    pub fn recover_snapshot(&self, cf_name: &str) -> Result<(), CompactFiltersError> {
+        let mut write_store = self.store.write().unwrap();
+        let snapshot_cf_handle = write_store.cf_handle(cf_name).unwrap();
+
+        let prefix = StoreEntry::BlockHeader(None).get_key();
+        let mut iterator = write_store.prefix_iterator_cf(snapshot_cf_handle, prefix);
+
+        let min_height = match iterator
+            .next()
+            .and_then(|(k, _)| k[1..].try_into().ok())
+            .map(|bytes| usize::from_be_bytes(bytes))
+        {
+            None => {
+                std::mem::drop(iterator);
+                write_store.drop_cf(cf_name).ok();
+
+                return Ok(());
+            }
+            Some(x) => x,
+        };
+        std::mem::drop(iterator);
+        std::mem::drop(write_store);
+
+        let snapshot = ChainStore {
+            store: Arc::clone(&self.store),
+            cf_name: cf_name.into(),
+            min_height,
+            network: self.network,
+            phantom: PhantomData,
+        };
+        if snapshot.work()? > self.work()? {
+            self.apply_snapshot(snapshot)?;
+        }
+
+        Ok(())
+    }
+
+    pub fn apply_snapshot(
+        &self,
+        snaphost: ChainStore<Snapshot>,
+    ) -> Result<(), CompactFiltersError> {
+        let mut batch = WriteBatch::default();
+
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+        let snapshot_cf_handle = read_store.cf_handle(&snaphost.cf_name).unwrap();
+
+        let from_key = StoreEntry::BlockHeader(Some(snaphost.min_height)).get_key();
+        let to_key = StoreEntry::BlockHeader(Some(usize::MAX)).get_key();
+
+        let mut opts = ReadOptions::default();
+        opts.set_iterate_upper_bound(to_key.clone());
+
+        log::debug!("Removing items");
+        batch.delete_range_cf(cf_handle, &from_key, &to_key);
+        for (_, v) in read_store.iterator_cf_opt(
+            cf_handle,
+            opts,
+            IteratorMode::From(&from_key, Direction::Forward),
+        ) {
+            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
+
+            batch.delete_cf(
+                cf_handle,
+                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
+            );
+        }
+
+        // Delete full blocks overriden by snapshot
+        let from_key = StoreEntry::Block(Some(snaphost.min_height)).get_key();
+        let to_key = StoreEntry::Block(Some(usize::MAX)).get_key();
+        batch.delete_range(&from_key, &to_key);
+
+        log::debug!("Copying over new items");
+        for (k, v) in read_store.iterator_cf(snapshot_cf_handle, IteratorMode::Start) {
+            batch.put_cf(cf_handle, k, v);
+        }
+
+        read_store.write(batch)?;
+
+        std::mem::drop(snapshot_cf_handle);
+        std::mem::drop(cf_handle);
+        std::mem::drop(read_store);
+
+        self.store.write().unwrap().drop_cf(&snaphost.cf_name)?;
+
+        Ok(())
+    }
+
+    pub fn get_height_for(
+        &self,
+        block_hash: &BlockHash,
+    ) -> Result<Option<usize>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let key = StoreEntry::BlockHeaderIndex(Some(block_hash.clone())).get_key();
+        let data = read_store.get_pinned_cf(cf_handle, key)?;
+        Ok(data
+            .map(|data| {
+                Ok::<_, CompactFiltersError>(usize::from_be_bytes(
+                    data.as_ref()
+                        .try_into()
+                        .map_err(|_| CompactFiltersError::DataCorruption)?,
+                ))
+            })
+            .transpose()?)
+    }
+
+    pub fn get_block_hash(&self, height: usize) -> Result<Option<BlockHash>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let key = StoreEntry::BlockHeader(Some(height)).get_key();
+        let data = read_store.get_pinned_cf(cf_handle, key)?;
+        Ok(data
+            .map(|data| {
+                let (header, _): (BlockHeader, Uint256) =
+                    deserialize(&data).map_err(|_| CompactFiltersError::DataCorruption)?;
+                Ok::<_, CompactFiltersError>(header.block_hash())
+            })
+            .transpose()?)
+    }
+
+    pub fn save_full_block(&self, block: &Block, height: usize) -> Result<(), CompactFiltersError> {
+        let key = StoreEntry::Block(Some(height)).get_key();
+        self.store.read().unwrap().put(key, block.serialize())?;
+
+        Ok(())
+    }
+
+    pub fn get_full_block(&self, height: usize) -> Result<Option<Block>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+
+        let key = StoreEntry::Block(Some(height)).get_key();
+        let opt_block = read_store.get_pinned(key)?;
+
+        Ok(opt_block
+            .map(|data| deserialize(&data))
+            .transpose()
+            .map_err(|_| CompactFiltersError::DataCorruption)?)
+    }
+
+    pub fn delete_blocks_until(&self, height: usize) -> Result<(), CompactFiltersError> {
+        let from_key = StoreEntry::Block(Some(0)).get_key();
+        let to_key = StoreEntry::Block(Some(height)).get_key();
+
+        let mut batch = WriteBatch::default();
+        batch.delete_range(&from_key, &to_key);
+
+        self.store.read().unwrap().write(batch)?;
+
+        Ok(())
+    }
+
+    pub fn iter_full_blocks(&self) -> Result<Vec<(usize, Block)>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+
+        let prefix = StoreEntry::Block(None).get_key();
+
+        let iterator = read_store.prefix_iterator(&prefix);
+        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
+        // have the right prefix
+        iterator
+            .filter(|(k, _)| k.starts_with(&prefix))
+            .map(|(k, v)| {
+                let height: usize = usize::from_be_bytes(
+                    k[1..]
+                        .try_into()
+                        .map_err(|_| CompactFiltersError::DataCorruption)?,
+                );
+                let block = SerializeDb::deserialize(&v)?;
+
+                Ok((height, block))
+            })
+            .collect::<Result<_, _>>()
+    }
+}
+
+impl<T: StoreType> ChainStore<T> {
+    pub fn work(&self) -> Result<Uint256, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let prefix = StoreEntry::BlockHeader(None).get_key();
+        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
+
+        Ok(iterator
+            .last()
+            .map(|(_, v)| -> Result<_, CompactFiltersError> {
+                let (_, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
+
+                Ok(work)
+            })
+            .transpose()?
+            .unwrap_or_default())
+    }
+
+    pub fn get_height(&self) -> Result<usize, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let prefix = StoreEntry::BlockHeader(None).get_key();
+        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
+
+        Ok(iterator
+            .last()
+            .map(|(k, _)| -> Result<_, CompactFiltersError> {
+                let height = usize::from_be_bytes(
+                    k[1..]
+                        .try_into()
+                        .map_err(|_| CompactFiltersError::DataCorruption)?,
+                );
+
+                Ok(height)
+            })
+            .transpose()?
+            .unwrap_or_default())
+    }
+
+    pub fn get_tip_hash(&self) -> Result<Option<BlockHash>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let prefix = StoreEntry::BlockHeader(None).get_key();
+        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
+
+        Ok(iterator
+            .last()
+            .map(|(_, v)| -> Result<_, CompactFiltersError> {
+                let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
+
+                Ok(header.block_hash())
+            })
+            .transpose()?)
+    }
+
+    pub fn apply(
+        &mut self,
+        from: usize,
+        headers: Vec<BlockHeader>,
+    ) -> Result<BlockHash, CompactFiltersError> {
+        let mut batch = WriteBatch::default();
+
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let (mut last_hash, mut accumulated_work) = read_store
+            .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
+            .map(|result| {
+                let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&result)?;
+                Ok::<_, CompactFiltersError>((header.block_hash(), work))
+            })
+            .transpose()?
+            .ok_or(CompactFiltersError::DataCorruption)?;
+
+        for (index, header) in headers.into_iter().enumerate() {
+            if header.prev_blockhash != last_hash {
+                return Err(CompactFiltersError::InvalidHeaders);
+            }
+
+            last_hash = header.block_hash();
+            accumulated_work = accumulated_work + header.work();
+
+            let height = from + index + 1;
+            batch.put_cf(
+                cf_handle,
+                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
+                &(height).to_be_bytes(),
+            );
+            batch.put_cf(
+                cf_handle,
+                StoreEntry::BlockHeader(Some(height)).get_key(),
+                (header, accumulated_work).serialize(),
+            );
+        }
+
+        std::mem::drop(cf_handle);
+        std::mem::drop(read_store);
+
+        self.store.write().unwrap().write(batch)?;
+        Ok(last_hash)
+    }
+}
+
+impl<T: StoreType> fmt::Debug for ChainStore<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct(&format!("ChainStore<{:?}>", T::default()))
+            .field("cf_name", &self.cf_name)
+            .field("min_height", &self.min_height)
+            .field("network", &self.network)
+            .field("headers_height", &self.get_height())
+            .field("tip_hash", &self.get_tip_hash())
+            .finish()
+    }
+}
+
+pub type FilterHeaderHash = FilterHash;
+
+#[derive(Debug, Clone)]
+pub struct FilterHeader {
+    prev_header_hash: FilterHeaderHash,
+    filter_hash: FilterHash,
+}
+
+impl FilterHeader {
+    fn header_hash(&self) -> FilterHeaderHash {
+        let mut hash_data = self.filter_hash.into_inner().to_vec();
+        hash_data.extend_from_slice(&self.prev_header_hash);
+        sha256d::Hash::hash(&hash_data).into()
+    }
+}
+
+pub enum BundleStatus {
+    Init,
+    CFHeaders { cf_headers: Vec<FilterHeader> },
+    CFilters { cf_filters: Vec<Vec<u8>> },
+    Processed { cf_filters: Vec<Vec<u8>> },
+    Tip { cf_filters: Vec<Vec<u8>> },
+    Pruned,
+}
+
+pub struct CFStore {
+    store: Arc<RwLock<DB>>,
+    filter_type: u8,
+}
+
+type BundleEntry = (BundleStatus, FilterHeaderHash);
+
+impl CFStore {
+    pub fn new(
+        headers_store: &ChainStore<Full>,
+        filter_type: u8,
+    ) -> Result<Self, CompactFiltersError> {
+        let cf_store = CFStore {
+            store: Arc::clone(&headers_store.store),
+            filter_type,
+        };
+
+        let genesis = match headers_store.network {
+            Network::Bitcoin => MAINNET_GENESIS.deref(),
+            Network::Testnet => TESTNET_GENESIS.deref(),
+            Network::Regtest => REGTEST_GENESIS.deref(),
+        };
+
+        let filter = BlockFilter::new_script_filter(genesis, |utxo| {
+            Err(bitcoin::util::bip158::Error::UtxoMissing(*utxo))
+        })?;
+        let first_key = StoreEntry::CFilterTable((filter_type, Some(0))).get_key();
+
+        // Add the genesis' filter
+        {
+            let read_store = cf_store.store.read().unwrap();
+            if read_store.get_pinned(&first_key)?.is_none() {
+                read_store.put(
+                    &first_key,
+                    (BundleStatus::Init, filter.filter_id(&FilterHash::default())).serialize(),
+                )?;
+            }
+        }
+
+        Ok(cf_store)
+    }
+
+    pub fn get_filter_type(&self) -> u8 {
+        self.filter_type
+    }
+
+    pub fn get_bundles(&self) -> Result<Vec<BundleEntry>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+
+        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
+        let iterator = read_store.prefix_iterator(&prefix);
+
+        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
+        // have the right prefix
+        iterator
+            .filter(|(k, _)| k.starts_with(&prefix))
+            .map(|(_, data)| BundleEntry::deserialize(&data))
+            .collect::<Result<_, _>>()
+    }
+
+    pub fn get_checkpoints(&self) -> Result<Vec<FilterHash>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+
+        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
+        let iterator = read_store.prefix_iterator(&prefix);
+
+        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
+        // have the right prefix
+        Ok(iterator
+            .filter(|(k, _)| k.starts_with(&prefix))
+            .skip(1)
+            .map(|(_, data)| Ok::<_, CompactFiltersError>(BundleEntry::deserialize(&data)?.1))
+            .collect::<Result<_, _>>()?)
+    }
+
+    pub fn replace_checkpoints(
+        &self,
+        checkpoints: Vec<FilterHash>,
+    ) -> Result<(), CompactFiltersError> {
+        let current_checkpoints = self.get_checkpoints()?;
+
+        let mut equal_bundles = 0;
+        for (index, (our, their)) in current_checkpoints
+            .iter()
+            .zip(checkpoints.iter())
+            .enumerate()
+        {
+            equal_bundles = index;
+
+            if our != their {
+                break;
+            }
+        }
+
+        let read_store = self.store.read().unwrap();
+        let mut batch = WriteBatch::default();
+
+        for (index, filter_hash) in checkpoints.iter().enumerate().skip(equal_bundles) {
+            let key = StoreEntry::CFilterTable((self.filter_type, Some(index + 1))).get_key(); // +1 to skip the genesis' filter
+
+            if let Some((BundleStatus::Tip { .. }, _)) = read_store
+                .get_pinned(&key)?
+                .map(|data| BundleEntry::deserialize(&data))
+                .transpose()?
+            {
+                println!("Keeping bundle #{} as Tip", index);
+            } else {
+                batch.put(&key, (BundleStatus::Init, *filter_hash).serialize());
+            }
+        }
+
+        read_store.write(batch)?;
+
+        Ok(())
+    }
+
+    pub fn advance_to_cf_headers(
+        &self,
+        bundle: usize,
+        checkpoint_hash: FilterHeaderHash,
+        filter_headers: Vec<FilterHash>,
+    ) -> Result<BundleStatus, CompactFiltersError> {
+        let mut last_hash = checkpoint_hash;
+        let cf_headers = filter_headers
+            .into_iter()
+            .map(|filter_hash| {
+                let filter_header = FilterHeader {
+                    prev_header_hash: last_hash,
+                    filter_hash,
+                };
+                last_hash = filter_header.header_hash();
+
+                filter_header
+            })
+            .collect();
+
+        let read_store = self.store.read().unwrap();
+
+        let next_key = StoreEntry::CFilterTable((self.filter_type, Some(bundle + 1))).get_key(); // +1 to skip the genesis' filter
+        if let Some((_, next_checkpoint)) = read_store
+            .get_pinned(&next_key)?
+            .map(|data| BundleEntry::deserialize(&data))
+            .transpose()?
+        {
+            // check connection with the next bundle if present
+            if last_hash != next_checkpoint {
+                return Err(CompactFiltersError::InvalidFilterHeader);
+            }
+        }
+
+        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
+        let value = (BundleStatus::CFHeaders { cf_headers }, checkpoint_hash);
+
+        read_store.put(key, value.serialize())?;
+
+        Ok(value.0)
+    }
+
+    pub fn advance_to_cf_filters(
+        &self,
+        bundle: usize,
+        checkpoint_hash: FilterHeaderHash,
+        headers: Vec<FilterHeader>,
+        filters: Vec<(usize, Vec<u8>)>,
+    ) -> Result<BundleStatus, CompactFiltersError> {
+        let cf_filters = filters
+            .into_iter()
+            .zip(headers.iter())
+            .map(|((_, filter_content), header)| {
+                if header.filter_hash != sha256d::Hash::hash(&filter_content).into() {
+                    return Err(CompactFiltersError::InvalidFilter);
+                }
+
+                Ok::<_, CompactFiltersError>(filter_content)
+            })
+            .collect::<Result<_, _>>()?;
+
+        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
+        let value = (BundleStatus::CFilters { cf_filters }, checkpoint_hash);
+
+        let read_store = self.store.read().unwrap();
+        read_store.put(key, value.serialize())?;
+
+        Ok(value.0)
+    }
+
+    pub fn prune_filters(
+        &self,
+        bundle: usize,
+        checkpoint_hash: FilterHeaderHash,
+    ) -> Result<BundleStatus, CompactFiltersError> {
+        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
+        let value = (BundleStatus::Pruned, checkpoint_hash);
+
+        let read_store = self.store.read().unwrap();
+        read_store.put(key, value.serialize())?;
+
+        Ok(value.0)
+    }
+
+    pub fn mark_as_tip(
+        &self,
+        bundle: usize,
+        cf_filters: Vec<Vec<u8>>,
+        checkpoint_hash: FilterHeaderHash,
+    ) -> Result<BundleStatus, CompactFiltersError> {
+        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
+        let value = (BundleStatus::Tip { cf_filters }, checkpoint_hash);
+
+        let read_store = self.store.read().unwrap();
+        read_store.put(key, value.serialize())?;
+
+        Ok(value.0)
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/sync.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/sync.rs.html new file mode 100644 index 0000000000..3ac0bf5529 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/sync.rs.html @@ -0,0 +1,632 @@ +sync.rs - source + +
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::collections::{BTreeMap, HashMap, VecDeque};
+use std::sync::{Arc, Mutex};
+use std::time::Duration;
+
+use bitcoin::hash_types::{BlockHash, FilterHash};
+use bitcoin::network::message::NetworkMessage;
+use bitcoin::network::message_blockdata::GetHeadersMessage;
+use bitcoin::util::bip158::BlockFilter;
+
+use super::peer::*;
+use super::store::*;
+use super::CompactFiltersError;
+use crate::error::Error;
+
+pub(crate) const BURIED_CONFIRMATIONS: usize = 100;
+
+pub struct CFSync {
+    headers_store: Arc<ChainStore<Full>>,
+    cf_store: Arc<CFStore>,
+    skip_blocks: usize,
+    bundles: Mutex<VecDeque<(BundleStatus, FilterHash, usize)>>,
+}
+
+impl CFSync {
+    pub fn new(
+        headers_store: Arc<ChainStore<Full>>,
+        skip_blocks: usize,
+        filter_type: u8,
+    ) -> Result<Self, CompactFiltersError> {
+        let cf_store = Arc::new(CFStore::new(&headers_store, filter_type)?);
+
+        Ok(CFSync {
+            headers_store,
+            cf_store,
+            skip_blocks,
+            bundles: Mutex::new(VecDeque::new()),
+        })
+    }
+
+    pub fn pruned_bundles(&self) -> Result<usize, CompactFiltersError> {
+        Ok(self
+            .cf_store
+            .get_bundles()?
+            .into_iter()
+            .skip(self.skip_blocks / 1000)
+            .fold(0, |acc, (status, _)| match status {
+                BundleStatus::Pruned => acc + 1,
+                _ => acc,
+            }))
+    }
+
+    pub fn prepare_sync(&self, peer: Arc<Peer>) -> Result<(), CompactFiltersError> {
+        let mut bundles_lock = self.bundles.lock().unwrap();
+
+        let resp = peer.get_cf_checkpt(
+            self.cf_store.get_filter_type(),
+            self.headers_store.get_tip_hash()?.unwrap(),
+        )?;
+        self.cf_store.replace_checkpoints(resp.filter_headers)?;
+
+        bundles_lock.clear();
+        for (index, (status, checkpoint)) in self.cf_store.get_bundles()?.into_iter().enumerate() {
+            bundles_lock.push_back((status, checkpoint, index));
+        }
+
+        Ok(())
+    }
+
+    pub fn capture_thread_for_sync<F, Q>(
+        &self,
+        peer: Arc<Peer>,
+        process: F,
+        completed_bundle: Q,
+    ) -> Result<(), CompactFiltersError>
+    where
+        F: Fn(&BlockHash, &BlockFilter) -> Result<bool, CompactFiltersError>,
+        Q: Fn(usize) -> Result<(), Error>,
+    {
+        let current_height = self.headers_store.get_height()?; // TODO: we should update it in case headers_store is also updated
+
+        loop {
+            let (mut status, checkpoint, index) = match self.bundles.lock().unwrap().pop_front() {
+                None => break,
+                Some(x) => x,
+            };
+
+            log::debug!(
+                "Processing bundle #{} - height {} to {}",
+                index,
+                index * 1000 + 1,
+                (index + 1) * 1000
+            );
+
+            let process_received_filters =
+                |expected_filters| -> Result<BTreeMap<usize, Vec<u8>>, CompactFiltersError> {
+                    let mut filters_map = BTreeMap::new();
+                    for _ in 0..expected_filters {
+                        let filter = peer.pop_cf_filter_resp()?;
+                        if filter.filter_type != self.cf_store.get_filter_type() {
+                            return Err(CompactFiltersError::InvalidResponse);
+                        }
+
+                        match self.headers_store.get_height_for(&filter.block_hash)? {
+                            Some(height) => filters_map.insert(height, filter.filter),
+                            None => return Err(CompactFiltersError::InvalidFilter),
+                        };
+                    }
+
+                    Ok(filters_map)
+                };
+
+            let start_height = index * 1000 + 1;
+            let mut already_processed = 0;
+
+            if start_height < self.skip_blocks {
+                status = self.cf_store.prune_filters(index, checkpoint)?;
+            }
+
+            let stop_height = std::cmp::min(current_height, start_height + 999);
+            let stop_hash = self.headers_store.get_block_hash(stop_height)?.unwrap();
+
+            if let BundleStatus::Init = status {
+                log::trace!("status: Init");
+
+                let resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
+
+                assert!(resp.previous_filter == checkpoint);
+                status =
+                    self.cf_store
+                        .advance_to_cf_headers(index, checkpoint, resp.filter_hashes)?;
+            }
+            if let BundleStatus::Tip { cf_filters } = status {
+                log::trace!("status: Tip (beginning) ");
+
+                already_processed = cf_filters.len();
+                let headers_resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
+
+                let cf_headers = match self.cf_store.advance_to_cf_headers(
+                    index,
+                    checkpoint,
+                    headers_resp.filter_hashes,
+                )? {
+                    BundleStatus::CFHeaders { cf_headers } => cf_headers,
+                    _ => return Err(CompactFiltersError::InvalidResponse),
+                };
+
+                peer.get_cf_filters(
+                    self.cf_store.get_filter_type(),
+                    (start_height + cf_filters.len()) as u32,
+                    stop_hash,
+                )?;
+                let expected_filters = stop_height - start_height + 1 - cf_filters.len();
+                let filters_map = process_received_filters(expected_filters)?;
+                let filters = cf_filters
+                    .into_iter()
+                    .enumerate()
+                    .chain(filters_map.into_iter())
+                    .collect();
+                status = self
+                    .cf_store
+                    .advance_to_cf_filters(index, checkpoint, cf_headers, filters)?;
+            }
+            if let BundleStatus::CFHeaders { cf_headers } = status {
+                log::trace!("status: CFHeaders");
+
+                peer.get_cf_filters(
+                    self.cf_store.get_filter_type(),
+                    start_height as u32,
+                    stop_hash,
+                )?;
+                let expected_filters = stop_height - start_height + 1;
+                let filters_map = process_received_filters(expected_filters)?;
+                status = self.cf_store.advance_to_cf_filters(
+                    index,
+                    checkpoint,
+                    cf_headers,
+                    filters_map.into_iter().collect(),
+                )?;
+            }
+            if let BundleStatus::CFilters { cf_filters } = status {
+                log::trace!("status: CFilters");
+
+                let last_sync_buried_height = (start_height + already_processed)
+                    .checked_sub(BURIED_CONFIRMATIONS)
+                    .unwrap_or(0);
+
+                for (filter_index, filter) in cf_filters.iter().enumerate() {
+                    let height = filter_index + start_height;
+
+                    // do not download blocks that were already "buried" since the last sync
+                    if height < last_sync_buried_height {
+                        continue;
+                    }
+
+                    let block_hash = self.headers_store.get_block_hash(height)?.unwrap();
+
+                    // TODO: also download random blocks?
+                    if process(&block_hash, &BlockFilter::new(&filter))? {
+                        log::debug!("Downloading block {}", block_hash);
+
+                        let block = peer
+                            .get_block(block_hash)?
+                            .ok_or(CompactFiltersError::MissingBlock)?;
+                        self.headers_store.save_full_block(&block, height)?;
+                    }
+                }
+
+                status = BundleStatus::Processed { cf_filters };
+            }
+            if let BundleStatus::Processed { cf_filters } = status {
+                log::trace!("status: Processed");
+
+                if current_height - stop_height > 1000 {
+                    status = self.cf_store.prune_filters(index, checkpoint)?;
+                } else {
+                    status = self.cf_store.mark_as_tip(index, cf_filters, checkpoint)?;
+                }
+
+                completed_bundle(index)?;
+            }
+            if let BundleStatus::Pruned = status {
+                log::trace!("status: Pruned");
+            }
+            if let BundleStatus::Tip { .. } = status {
+                log::trace!("status: Tip");
+            }
+        }
+
+        Ok(())
+    }
+}
+
+pub fn sync_headers<F>(
+    peer: Arc<Peer>,
+    store: Arc<ChainStore<Full>>,
+    sync_fn: F,
+) -> Result<Option<ChainStore<Snapshot>>, CompactFiltersError>
+where
+    F: Fn(usize) -> Result<(), Error>,
+{
+    let locators = store.get_locators()?;
+    let locators_vec = locators.iter().map(|(hash, _)| hash).cloned().collect();
+    let locators_map: HashMap<_, _> = locators.into_iter().collect();
+
+    peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
+        locators_vec,
+        Default::default(),
+    )))?;
+    let (mut snapshot, mut last_hash) = if let NetworkMessage::Headers(headers) = peer
+        .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
+        .ok_or(CompactFiltersError::Timeout)?
+    {
+        if headers.is_empty() {
+            return Ok(None);
+        }
+
+        match locators_map.get(&headers[0].prev_blockhash) {
+            None => return Err(CompactFiltersError::InvalidHeaders),
+            Some(from) => (
+                store.start_snapshot(*from)?,
+                headers[0].prev_blockhash.clone(),
+            ),
+        }
+    } else {
+        return Err(CompactFiltersError::InvalidResponse);
+    };
+
+    let mut sync_height = store.get_height()?;
+    while sync_height < peer.get_version().start_height as usize {
+        peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
+            vec![last_hash],
+            Default::default(),
+        )))?;
+        if let NetworkMessage::Headers(headers) = peer
+            .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
+            .ok_or(CompactFiltersError::Timeout)?
+        {
+            let batch_len = headers.len();
+            last_hash = snapshot.apply(sync_height, headers)?;
+
+            sync_height += batch_len;
+            sync_fn(sync_height)?;
+        } else {
+            return Err(CompactFiltersError::InvalidResponse);
+        }
+    }
+
+    Ok(Some(snapshot))
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/electrum.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/electrum.rs.html new file mode 100644 index 0000000000..e40065bc4e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/electrum.rs.html @@ -0,0 +1,386 @@ +electrum.rs - source + +
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Electrum
+//!
+//! This module defines a [`Blockchain`] struct that wraps an [`electrum_client::Client`]
+//! and implements the logic required to populate the wallet's [database](crate::database::Database) by
+//! querying the inner client.
+//!
+//! ## Example
+//!
+//! ```no_run
+//! # use bdk::blockchain::electrum::ElectrumBlockchain;
+//! let client = electrum_client::Client::new("ssl://electrum.blockstream.info:50002")?;
+//! let blockchain = ElectrumBlockchain::from(client);
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use std::collections::HashSet;
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use bitcoin::{BlockHeader, Script, Transaction, Txid};
+
+use electrum_client::{Client, ConfigBuilder, ElectrumApi, Socks5Config};
+
+use self::utils::{ELSGetHistoryRes, ElectrumLikeSync};
+use super::*;
+use crate::database::BatchDatabase;
+use crate::error::Error;
+use crate::FeeRate;
+
+/// Wrapper over an Electrum Client that implements the required blockchain traits
+///
+/// ## Example
+/// See the [`blockchain::electrum`](crate::blockchain::electrum) module for a usage example.
+pub struct ElectrumBlockchain(Client);
+
+#[cfg(test)]
+#[cfg(feature = "test-electrum")]
+#[bdk_blockchain_tests(crate)]
+fn local_electrs() -> ElectrumBlockchain {
+    ElectrumBlockchain::from(Client::new(&testutils::get_electrum_url()).unwrap())
+}
+
+impl std::convert::From<Client> for ElectrumBlockchain {
+    fn from(client: Client) -> Self {
+        ElectrumBlockchain(client)
+    }
+}
+
+impl Blockchain for ElectrumBlockchain {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        vec![
+            Capability::FullHistory,
+            Capability::GetAnyTx,
+            Capability::AccurateFees,
+        ]
+        .into_iter()
+        .collect()
+    }
+
+    fn setup<D: BatchDatabase, P: Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        self.0
+            .electrum_like_setup(stop_gap, database, progress_update)
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        Ok(self.0.transaction_get(txid).map(Option::Some)?)
+    }
+
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        Ok(self.0.transaction_broadcast(tx).map(|_| ())?)
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        // TODO: unsubscribe when added to the client, or is there a better call to use here?
+
+        Ok(self
+            .0
+            .block_headers_subscribe()
+            .map(|data| data.height as u32)?)
+    }
+
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
+        Ok(FeeRate::from_btc_per_kvb(
+            self.0.estimate_fee(target)? as f32
+        ))
+    }
+}
+
+impl ElectrumLikeSync for Client {
+    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script> + Clone>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error> {
+        self.batch_script_get_history(scripts)
+            .map(|v| {
+                v.into_iter()
+                    .map(|v| {
+                        v.into_iter()
+                            .map(
+                                |electrum_client::GetHistoryRes {
+                                     height, tx_hash, ..
+                                 }| ELSGetHistoryRes {
+                                    height,
+                                    tx_hash,
+                                },
+                            )
+                            .collect()
+                    })
+                    .collect()
+            })
+            .map_err(Error::Electrum)
+    }
+
+    fn els_batch_transaction_get<'s, I: IntoIterator<Item = &'s Txid> + Clone>(
+        &self,
+        txids: I,
+    ) -> Result<Vec<Transaction>, Error> {
+        self.batch_transaction_get(txids).map_err(Error::Electrum)
+    }
+
+    fn els_batch_block_header<I: IntoIterator<Item = u32> + Clone>(
+        &self,
+        heights: I,
+    ) -> Result<Vec<BlockHeader>, Error> {
+        self.batch_block_header(heights).map_err(Error::Electrum)
+    }
+}
+
+/// Configuration for an [`ElectrumBlockchain`]
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct ElectrumBlockchainConfig {
+    /// URL of the Electrum server (such as ElectrumX, Esplora, BWT) may start with `ssl://` or `tcp://` and include a port
+    ///
+    /// eg. `ssl://electrum.blockstream.info:60002`
+    pub url: String,
+    /// URL of the socks5 proxy server or a Tor service
+    pub socks5: Option<String>,
+    /// Request retry count
+    pub retry: u8,
+    /// Request timeout (seconds)
+    pub timeout: u8,
+}
+
+impl ConfigurableBlockchain for ElectrumBlockchain {
+    type Config = ElectrumBlockchainConfig;
+
+    fn from_config(config: &Self::Config) -> Result<Self, Error> {
+        let socks5 = config.socks5.as_ref().map(Socks5Config::new);
+        let electrum_config = ConfigBuilder::new()
+            .retry(config.retry)
+            .socks5(socks5)?
+            .timeout(config.timeout)?
+            .build();
+
+        Ok(ElectrumBlockchain(Client::from_config(
+            config.url.as_str(),
+            electrum_config,
+        )?))
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/esplora.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/esplora.rs.html new file mode 100644 index 0000000000..df6abccb0d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/esplora.rs.html @@ -0,0 +1,864 @@ +esplora.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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Esplora
+//!
+//! This module defines a [`Blockchain`] struct that can query an Esplora backend
+//! populate the wallet's [database](crate::database::Database) by
+//!
+//! ## Example
+//!
+//! ```no_run
+//! # use bdk::blockchain::esplora::EsploraBlockchain;
+//! let blockchain = EsploraBlockchain::new("https://blockstream.info/testnet/api", None);
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use std::collections::{HashMap, HashSet};
+use std::fmt;
+
+use futures::stream::{self, FuturesOrdered, StreamExt, TryStreamExt};
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use serde::Deserialize;
+
+use reqwest::{Client, StatusCode};
+
+use bitcoin::consensus::{self, deserialize, serialize};
+use bitcoin::hashes::hex::{FromHex, ToHex};
+use bitcoin::hashes::{sha256, Hash};
+use bitcoin::{BlockHash, BlockHeader, Script, Transaction, Txid};
+
+use self::utils::{ELSGetHistoryRes, ElectrumLikeSync};
+use super::*;
+use crate::database::BatchDatabase;
+use crate::error::Error;
+use crate::wallet::utils::ChunksIterator;
+use crate::FeeRate;
+
+const DEFAULT_CONCURRENT_REQUESTS: u8 = 4;
+
+#[derive(Debug)]
+struct UrlClient {
+    url: String,
+    // We use the async client instead of the blocking one because it automatically uses `fetch`
+    // when the target platform is wasm32.
+    client: Client,
+    concurrency: u8,
+}
+
+/// Structure that implements the logic to sync with Esplora
+///
+/// ## Example
+/// See the [`blockchain::esplora`](crate::blockchain::esplora) module for a usage example.
+#[derive(Debug)]
+pub struct EsploraBlockchain(UrlClient);
+
+impl std::convert::From<UrlClient> for EsploraBlockchain {
+    fn from(url_client: UrlClient) -> Self {
+        EsploraBlockchain(url_client)
+    }
+}
+
+impl EsploraBlockchain {
+    /// Create a new instance of the client from a base URL
+    pub fn new(base_url: &str, concurrency: Option<u8>) -> Self {
+        EsploraBlockchain(UrlClient {
+            url: base_url.to_string(),
+            client: Client::new(),
+            concurrency: concurrency.unwrap_or(DEFAULT_CONCURRENT_REQUESTS),
+        })
+    }
+}
+
+#[maybe_async]
+impl Blockchain for EsploraBlockchain {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        vec![
+            Capability::FullHistory,
+            Capability::GetAnyTx,
+            Capability::AccurateFees,
+        ]
+        .into_iter()
+        .collect()
+    }
+
+    fn setup<D: BatchDatabase, P: Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(self
+            .0
+            .electrum_like_setup(stop_gap, database, progress_update))
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        Ok(await_or_block!(self.0._get_tx(txid))?)
+    }
+
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        Ok(await_or_block!(self.0._broadcast(tx))?)
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        Ok(await_or_block!(self.0._get_height())?)
+    }
+
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
+        let estimates = await_or_block!(self.0._get_fee_estimates())?;
+
+        let fee_val = estimates
+            .into_iter()
+            .map(|(k, v)| Ok::<_, std::num::ParseIntError>((k.parse::<usize>()?, v)))
+            .collect::<Result<Vec<_>, _>>()
+            .map_err(|e| Error::Generic(e.to_string()))?
+            .into_iter()
+            .take_while(|(k, _)| k <= &target)
+            .map(|(_, v)| v)
+            .last()
+            .unwrap_or(1.0);
+
+        Ok(FeeRate::from_sat_per_vb(fee_val as f32))
+    }
+}
+
+impl UrlClient {
+    fn script_to_scripthash(script: &Script) -> String {
+        sha256::Hash::hash(script.as_bytes()).into_inner().to_hex()
+    }
+
+    async fn _get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, EsploraError> {
+        let resp = self
+            .client
+            .get(&format!("{}/tx/{}/raw", self.url, txid))
+            .send()
+            .await?;
+
+        if let StatusCode::NOT_FOUND = resp.status() {
+            return Ok(None);
+        }
+
+        Ok(Some(deserialize(&resp.error_for_status()?.bytes().await?)?))
+    }
+
+    async fn _get_tx_no_opt(&self, txid: &Txid) -> Result<Transaction, EsploraError> {
+        match self._get_tx(txid).await {
+            Ok(Some(tx)) => Ok(tx),
+            Ok(None) => Err(EsploraError::TransactionNotFound(*txid)),
+            Err(e) => Err(e),
+        }
+    }
+
+    async fn _get_header(&self, block_height: u32) -> Result<BlockHeader, EsploraError> {
+        let resp = self
+            .client
+            .get(&format!("{}/block-height/{}", self.url, block_height))
+            .send()
+            .await?;
+
+        if let StatusCode::NOT_FOUND = resp.status() {
+            return Err(EsploraError::HeaderHeightNotFound(block_height));
+        }
+        let bytes = resp.bytes().await?;
+        let hash = std::str::from_utf8(&bytes)
+            .map_err(|_| EsploraError::HeaderHeightNotFound(block_height))?;
+
+        let resp = self
+            .client
+            .get(&format!("{}/block/{}/header", self.url, hash))
+            .send()
+            .await?;
+
+        let header = deserialize(&Vec::from_hex(&resp.text().await?)?)?;
+
+        Ok(header)
+    }
+
+    async fn _broadcast(&self, transaction: &Transaction) -> Result<(), EsploraError> {
+        self.client
+            .post(&format!("{}/tx", self.url))
+            .body(serialize(transaction).to_hex())
+            .send()
+            .await?
+            .error_for_status()?;
+
+        Ok(())
+    }
+
+    async fn _get_height(&self) -> Result<u32, EsploraError> {
+        let req = self
+            .client
+            .get(&format!("{}/blocks/tip/height", self.url))
+            .send()
+            .await?;
+
+        Ok(req.error_for_status()?.text().await?.parse()?)
+    }
+
+    async fn _script_get_history(
+        &self,
+        script: &Script,
+    ) -> Result<Vec<ELSGetHistoryRes>, EsploraError> {
+        let mut result = Vec::new();
+        let scripthash = Self::script_to_scripthash(script);
+
+        // Add the unconfirmed transactions first
+        result.extend(
+            self.client
+                .get(&format!(
+                    "{}/scripthash/{}/txs/mempool",
+                    self.url, scripthash
+                ))
+                .send()
+                .await?
+                .error_for_status()?
+                .json::<Vec<EsploraGetHistory>>()
+                .await?
+                .into_iter()
+                .map(|x| ELSGetHistoryRes {
+                    tx_hash: x.txid,
+                    height: x.status.block_height.unwrap_or(0) as i32,
+                }),
+        );
+
+        debug!(
+            "Found {} mempool txs for {} - {:?}",
+            result.len(),
+            scripthash,
+            script
+        );
+
+        // Then go through all the pages of confirmed transactions
+        let mut last_txid = String::new();
+        loop {
+            let response = self
+                .client
+                .get(&format!(
+                    "{}/scripthash/{}/txs/chain/{}",
+                    self.url, scripthash, last_txid
+                ))
+                .send()
+                .await?
+                .error_for_status()?
+                .json::<Vec<EsploraGetHistory>>()
+                .await?;
+            let len = response.len();
+            if let Some(elem) = response.last() {
+                last_txid = elem.txid.to_hex();
+            }
+
+            debug!("... adding {} confirmed transactions", len);
+
+            result.extend(response.into_iter().map(|x| ELSGetHistoryRes {
+                tx_hash: x.txid,
+                height: x.status.block_height.unwrap_or(0) as i32,
+            }));
+
+            if len < 25 {
+                break;
+            }
+        }
+
+        Ok(result)
+    }
+
+    async fn _get_fee_estimates(&self) -> Result<HashMap<String, f64>, EsploraError> {
+        Ok(self
+            .client
+            .get(&format!("{}/fee-estimates", self.url,))
+            .send()
+            .await?
+            .error_for_status()?
+            .json::<HashMap<String, f64>>()
+            .await?)
+    }
+}
+
+#[maybe_async]
+impl ElectrumLikeSync for UrlClient {
+    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error> {
+        let future = async {
+            let mut results = vec![];
+            for chunk in ChunksIterator::new(scripts.into_iter(), self.concurrency as usize) {
+                let mut futs = FuturesOrdered::new();
+                for script in chunk {
+                    futs.push(self._script_get_history(&script));
+                }
+                let partial_results: Vec<Vec<ELSGetHistoryRes>> = futs.try_collect().await?;
+                results.extend(partial_results);
+            }
+            Ok(stream::iter(results).collect().await)
+        };
+
+        await_or_block!(future)
+    }
+
+    fn els_batch_transaction_get<'s, I: IntoIterator<Item = &'s Txid>>(
+        &self,
+        txids: I,
+    ) -> Result<Vec<Transaction>, Error> {
+        let future = async {
+            let mut results = vec![];
+            for chunk in ChunksIterator::new(txids.into_iter(), self.concurrency as usize) {
+                let mut futs = FuturesOrdered::new();
+                for txid in chunk {
+                    futs.push(self._get_tx_no_opt(&txid));
+                }
+                let partial_results: Vec<Transaction> = futs.try_collect().await?;
+                results.extend(partial_results);
+            }
+            Ok(stream::iter(results).collect().await)
+        };
+
+        await_or_block!(future)
+    }
+
+    fn els_batch_block_header<I: IntoIterator<Item = u32>>(
+        &self,
+        heights: I,
+    ) -> Result<Vec<BlockHeader>, Error> {
+        let future = async {
+            let mut results = vec![];
+            for chunk in ChunksIterator::new(heights.into_iter(), self.concurrency as usize) {
+                let mut futs = FuturesOrdered::new();
+                for height in chunk {
+                    futs.push(self._get_header(height));
+                }
+                let partial_results: Vec<BlockHeader> = futs.try_collect().await?;
+                results.extend(partial_results);
+            }
+            Ok(stream::iter(results).collect().await)
+        };
+
+        await_or_block!(future)
+    }
+}
+
+#[derive(Deserialize)]
+struct EsploraGetHistoryStatus {
+    block_height: Option<usize>,
+}
+
+#[derive(Deserialize)]
+struct EsploraGetHistory {
+    txid: Txid,
+    status: EsploraGetHistoryStatus,
+}
+
+/// Configuration for an [`EsploraBlockchain`]
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub struct EsploraBlockchainConfig {
+    /// Base URL of the esplora service
+    ///
+    /// eg. `https://blockstream.info/api/`
+    pub base_url: String,
+    /// Number of parallel requests sent to the esplora service (default: 4)
+    pub concurrency: Option<u8>,
+}
+
+impl ConfigurableBlockchain for EsploraBlockchain {
+    type Config = EsploraBlockchainConfig;
+
+    fn from_config(config: &Self::Config) -> Result<Self, Error> {
+        Ok(EsploraBlockchain::new(
+            config.base_url.as_str(),
+            config.concurrency,
+        ))
+    }
+}
+
+/// Errors that can happen during a sync with [`EsploraBlockchain`]
+#[derive(Debug)]
+pub enum EsploraError {
+    /// Error with the HTTP call
+    Reqwest(reqwest::Error),
+    /// Invalid number returned
+    Parsing(std::num::ParseIntError),
+    /// Invalid Bitcoin data returned
+    BitcoinEncoding(bitcoin::consensus::encode::Error),
+    /// Invalid Hex data returned
+    Hex(bitcoin::hashes::hex::Error),
+
+    /// Transaction not found
+    TransactionNotFound(Txid),
+    /// Header height not found
+    HeaderHeightNotFound(u32),
+    /// Header hash not found
+    HeaderHashNotFound(BlockHash),
+}
+
+impl fmt::Display for EsploraError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for EsploraError {}
+
+impl_error!(reqwest::Error, Reqwest, EsploraError);
+impl_error!(std::num::ParseIntError, Parsing, EsploraError);
+impl_error!(consensus::encode::Error, BitcoinEncoding, EsploraError);
+impl_error!(bitcoin::hashes::hex::Error, Hex, EsploraError);
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/mod.rs.html new file mode 100644 index 0000000000..75931fe4bf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/mod.rs.html @@ -0,0 +1,554 @@ +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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Blockchain backends
+//!
+//! This module provides the implementation of a few commonly-used backends like
+//! [Electrum](crate::blockchain::electrum), [Esplora](crate::blockchain::esplora) and
+//! [Compact Filters/Neutrino](crate::blockchain::compact_filters), along with a generalized trait
+//! [`Blockchain`] that can be implemented to build customized backends.
+
+use std::collections::HashSet;
+use std::ops::Deref;
+use std::sync::mpsc::{channel, Receiver, Sender};
+use std::sync::Arc;
+
+use bitcoin::{Transaction, Txid};
+
+use crate::database::BatchDatabase;
+use crate::error::Error;
+use crate::FeeRate;
+
+#[cfg(any(feature = "electrum", feature = "esplora"))]
+pub(crate) mod utils;
+
+#[cfg(any(feature = "electrum", feature = "esplora", feature = "compact_filters"))]
+pub mod any;
+#[cfg(any(feature = "electrum", feature = "esplora", feature = "compact_filters"))]
+pub use any::{AnyBlockchain, AnyBlockchainConfig};
+
+#[cfg(feature = "electrum")]
+#[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
+pub mod electrum;
+#[cfg(feature = "electrum")]
+pub use self::electrum::ElectrumBlockchain;
+#[cfg(feature = "electrum")]
+pub use self::electrum::ElectrumBlockchainConfig;
+
+#[cfg(feature = "esplora")]
+#[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
+pub mod esplora;
+#[cfg(feature = "esplora")]
+pub use self::esplora::EsploraBlockchain;
+
+#[cfg(feature = "compact_filters")]
+#[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
+pub mod compact_filters;
+#[cfg(feature = "compact_filters")]
+pub use self::compact_filters::CompactFiltersBlockchain;
+
+/// Capabilities that can be supported by a [`Blockchain`] backend
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum Capability {
+    /// Can recover the full history of a wallet and not only the set of currently spendable UTXOs
+    FullHistory,
+    /// Can fetch any historical transaction given its txid
+    GetAnyTx,
+    /// Can compute accurate fees for the transactions found during sync
+    AccurateFees,
+}
+
+/// Marker trait for a blockchain backend
+///
+/// This is a marker trait for blockchain types. It is automatically implemented for types that
+/// implement [`Blockchain`], so as a user of the library you won't have to implement this
+/// manually.
+///
+/// Users of the library will probably never have to implement this trait manually, but they
+/// could still need to import it to define types and structs with generics;
+/// Implementing only the marker trait is pointless, since [`OfflineBlockchain`]
+/// already does that, and whenever [`Blockchain`] is implemented, the marker trait is also
+/// automatically implemented by the library.
+pub trait BlockchainMarker {}
+
+/// The [`BlockchainMarker`] marker trait is automatically implemented for [`Blockchain`] types
+impl<T: Blockchain> BlockchainMarker for T {}
+
+/// Type that only implements [`BlockchainMarker`] and is always "offline"
+pub struct OfflineBlockchain;
+impl BlockchainMarker for OfflineBlockchain {}
+
+/// Trait that defines the actions that must be supported by a blockchain backend
+#[maybe_async]
+pub trait Blockchain: BlockchainMarker {
+    /// Return the set of [`Capability`] supported by this backend
+    fn get_capabilities(&self) -> HashSet<Capability>;
+
+    /// Setup the backend and populate the internal database for the first time
+    ///
+    /// This method is the equivalent of [`Blockchain::sync`], but it's guaranteed to only be
+    /// called once, at the first [`Wallet::sync`](crate::wallet::Wallet::sync).
+    ///
+    /// The rationale behind the distinction between `sync` and `setup` is that some custom backends
+    /// might need to perform specific actions only the first time they are synced.
+    ///
+    /// For types that do not have that distinction, only this method can be implemented, since
+    /// [`Blockchain::sync`] defaults to calling this internally if not overridden.
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error>;
+    /// Populate the internal database with transactions and UTXOs
+    ///
+    /// If not overridden, it defaults to calling [`Blockchain::setup`] internally.
+    ///
+    /// This method should implement the logic required to iterate over the list of the wallet's
+    /// script_pubkeys using [`Database::iter_script_pubkeys`] and look for relevant transactions
+    /// in the blockchain to populate the database with [`BatchOperations::set_tx`] and
+    /// [`BatchOperations::set_utxo`].
+    ///
+    /// This method should also take care of removing UTXOs that are seen as spent in the
+    /// blockchain, using [`BatchOperations::del_utxo`].
+    ///
+    /// The `progress_update` object can be used to give the caller updates about the progress by using
+    /// [`Progress::update`].
+    ///
+    /// [`Database::iter_script_pubkeys`]: crate::database::Database::iter_script_pubkeys
+    /// [`BatchOperations::set_tx`]: crate::database::BatchOperations::set_tx
+    /// [`BatchOperations::set_utxo`]: crate::database::BatchOperations::set_utxo
+    /// [`BatchOperations::del_utxo`]: crate::database::BatchOperations::del_utxo
+    fn sync<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(self.setup(stop_gap, database, progress_update))
+    }
+
+    /// Fetch a transaction from the blockchain given its txid
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
+    /// Broadcast a transaction
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error>;
+
+    /// Return the current height
+    fn get_height(&self) -> Result<u32, Error>;
+    /// Estimate the fee rate required to confirm a transaction in a given `target` of blocks
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>;
+}
+
+/// Trait for [`Blockchain`] types that can be created given a configuration
+pub trait ConfigurableBlockchain: Blockchain + Sized {
+    /// Type that contains the configuration
+    type Config: std::fmt::Debug;
+
+    /// Create a new instance given a configuration
+    fn from_config(config: &Self::Config) -> Result<Self, Error>;
+}
+
+/// Data sent with a progress update over a [`channel`]
+pub type ProgressData = (f32, Option<String>);
+
+/// Trait for types that can receive and process progress updates during [`Blockchain::sync`] and
+/// [`Blockchain::setup`]
+pub trait Progress: Send {
+    /// Send a new progress update
+    ///
+    /// The `progress` value should be in the range 0.0 - 100.0, and the `message` value is an
+    /// optional text message that can be displayed to the user.
+    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error>;
+}
+
+/// Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]
+pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>) {
+    channel()
+}
+
+impl Progress for Sender<ProgressData> {
+    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
+        if progress < 0.0 || progress > 100.0 {
+            return Err(Error::InvalidProgressValue(progress));
+        }
+
+        self.send((progress, message))
+            .map_err(|_| Error::ProgressUpdateError)
+    }
+}
+
+/// Type that implements [`Progress`] and drops every update received
+#[derive(Clone)]
+pub struct NoopProgress;
+
+/// Create a new instance of [`NoopProgress`]
+pub fn noop_progress() -> NoopProgress {
+    NoopProgress
+}
+
+impl Progress for NoopProgress {
+    fn update(&self, _progress: f32, _message: Option<String>) -> Result<(), Error> {
+        Ok(())
+    }
+}
+
+/// Type that implements [`Progress`] and logs at level `INFO` every update received
+#[derive(Clone)]
+pub struct LogProgress;
+
+/// Create a nwe instance of [`LogProgress`]
+pub fn log_progress() -> LogProgress {
+    LogProgress
+}
+
+impl Progress for LogProgress {
+    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
+        log::info!(
+            "Sync {:.3}%: `{}`",
+            progress,
+            message.unwrap_or_else(|| "".into())
+        );
+
+        Ok(())
+    }
+}
+
+#[maybe_async]
+impl<T: Blockchain> Blockchain for Arc<T> {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        maybe_await!(self.deref().get_capabilities())
+    }
+
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(self.deref().setup(stop_gap, database, progress_update))
+    }
+
+    fn sync<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(self.deref().sync(stop_gap, database, progress_update))
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        maybe_await!(self.deref().get_tx(txid))
+    }
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        maybe_await!(self.deref().broadcast(tx))
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        maybe_await!(self.deref().get_height())
+    }
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
+        maybe_await!(self.deref().estimate_fee(target))
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/utils.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/utils.rs.html new file mode 100644 index 0000000000..8cbfbf4840 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/utils.rs.html @@ -0,0 +1,800 @@ +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
+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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::collections::{HashMap, HashSet};
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+use rand::seq::SliceRandom;
+use rand::thread_rng;
+
+use bitcoin::{BlockHeader, OutPoint, Script, Transaction, Txid};
+
+use super::*;
+use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
+use crate::error::Error;
+use crate::types::{KeychainKind, TransactionDetails, UTXO};
+use crate::wallet::time::Instant;
+use crate::wallet::utils::ChunksIterator;
+
+#[derive(Debug)]
+pub struct ELSGetHistoryRes {
+    pub height: i32,
+    pub tx_hash: Txid,
+}
+
+/// Implements the synchronization logic for an Electrum-like client.
+#[maybe_async]
+pub trait ElectrumLikeSync {
+    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script> + Clone>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error>;
+
+    fn els_batch_transaction_get<'s, I: IntoIterator<Item = &'s Txid> + Clone>(
+        &self,
+        txids: I,
+    ) -> Result<Vec<Transaction>, Error>;
+
+    fn els_batch_block_header<I: IntoIterator<Item = u32> + Clone>(
+        &self,
+        heights: I,
+    ) -> Result<Vec<BlockHeader>, Error>;
+
+    // Provided methods down here...
+
+    fn electrum_like_setup<D: BatchDatabase, P: Progress>(
+        &self,
+        stop_gap: Option<usize>,
+        db: &mut D,
+        _progress_update: P,
+    ) -> Result<(), Error> {
+        // TODO: progress
+        let start = Instant::new();
+        debug!("start setup");
+
+        let stop_gap = stop_gap.unwrap_or(20);
+        let chunk_size = stop_gap;
+
+        let mut history_txs_id = HashSet::new();
+        let mut txid_height = HashMap::new();
+        let mut max_indexes = HashMap::new();
+
+        let mut wallet_chains = vec![KeychainKind::Internal, KeychainKind::External];
+        // shuffling improve privacy, the server doesn't know my first request is from my internal or external addresses
+        wallet_chains.shuffle(&mut thread_rng());
+        // download history of our internal and external script_pubkeys
+        for keychain in wallet_chains.iter() {
+            let script_iter = db.iter_script_pubkeys(Some(*keychain))?.into_iter();
+
+            for (i, chunk) in ChunksIterator::new(script_iter, stop_gap).enumerate() {
+                // TODO if i == last, should create another chunk of addresses in db
+                let call_result: Vec<Vec<ELSGetHistoryRes>> =
+                    maybe_await!(self.els_batch_script_get_history(chunk.iter()))?;
+                let max_index = call_result
+                    .iter()
+                    .enumerate()
+                    .filter_map(|(i, v)| v.first().map(|_| i as u32))
+                    .max();
+                if let Some(max) = max_index {
+                    max_indexes.insert(keychain, max + (i * chunk_size) as u32);
+                }
+                let flattened: Vec<ELSGetHistoryRes> = call_result.into_iter().flatten().collect();
+                debug!("#{} of {:?} results:{}", i, keychain, flattened.len());
+                if flattened.is_empty() {
+                    // Didn't find anything in the last `stop_gap` script_pubkeys, breaking
+                    break;
+                }
+
+                for el in flattened {
+                    // el.height = -1 means unconfirmed with unconfirmed parents
+                    // el.height =  0 means unconfirmed with confirmed parents
+                    // but we treat those tx the same
+                    if el.height <= 0 {
+                        txid_height.insert(el.tx_hash, None);
+                    } else {
+                        txid_height.insert(el.tx_hash, Some(el.height as u32));
+                    }
+                    history_txs_id.insert(el.tx_hash);
+                }
+            }
+        }
+
+        // saving max indexes
+        info!("max indexes are: {:?}", max_indexes);
+        for keychain in wallet_chains.iter() {
+            if let Some(index) = max_indexes.get(keychain) {
+                db.set_last_index(*keychain, *index)?;
+            }
+        }
+
+        // get db status
+        let txs_details_in_db: HashMap<Txid, TransactionDetails> = db
+            .iter_txs(false)?
+            .into_iter()
+            .map(|tx| (tx.txid, tx))
+            .collect();
+        let txs_raw_in_db: HashMap<Txid, Transaction> = db
+            .iter_raw_txs()?
+            .into_iter()
+            .map(|tx| (tx.txid(), tx))
+            .collect();
+        let utxos_deps = utxos_deps(db, &txs_raw_in_db)?;
+
+        // download new txs and headers
+        let new_txs = maybe_await!(self.download_and_save_needed_raw_txs(
+            &history_txs_id,
+            &txs_raw_in_db,
+            chunk_size,
+            db
+        ))?;
+        let new_timestamps = maybe_await!(self.download_needed_headers(
+            &txid_height,
+            &txs_details_in_db,
+            chunk_size
+        ))?;
+
+        let mut batch = db.begin_batch();
+
+        // save any tx details not in db but in history_txs_id or with different height/timestamp
+        for txid in history_txs_id.iter() {
+            let height = txid_height.get(txid).cloned().flatten();
+            let timestamp = *new_timestamps.get(txid).unwrap_or(&0u64);
+            if let Some(tx_details) = txs_details_in_db.get(txid) {
+                // check if height matches, otherwise updates it
+                if tx_details.height != height {
+                    let mut new_tx_details = tx_details.clone();
+                    new_tx_details.height = height;
+                    new_tx_details.timestamp = timestamp;
+                    batch.set_tx(&new_tx_details)?;
+                }
+            } else {
+                save_transaction_details_and_utxos(
+                    &txid,
+                    db,
+                    timestamp,
+                    height,
+                    &mut batch,
+                    &utxos_deps,
+                )?;
+            }
+        }
+
+        // remove any tx details in db but not in history_txs_id
+        for txid in txs_details_in_db.keys() {
+            if !history_txs_id.contains(txid) {
+                batch.del_tx(&txid, false)?;
+            }
+        }
+
+        // remove any spent utxo
+        for new_tx in new_txs.iter() {
+            for input in new_tx.input.iter() {
+                batch.del_utxo(&input.previous_output)?;
+            }
+        }
+
+        db.commit_batch(batch)?;
+        info!("finish setup, elapsed {:?}ms", start.elapsed().as_millis());
+
+        Ok(())
+    }
+
+    /// download txs identified by `history_txs_id` and theirs previous outputs if not already present in db
+    fn download_and_save_needed_raw_txs<D: BatchDatabase>(
+        &self,
+        history_txs_id: &HashSet<Txid>,
+        txs_raw_in_db: &HashMap<Txid, Transaction>,
+        chunk_size: usize,
+        db: &mut D,
+    ) -> Result<Vec<Transaction>, Error> {
+        let mut txs_downloaded = vec![];
+        let txids_raw_in_db: HashSet<Txid> = txs_raw_in_db.keys().cloned().collect();
+        let txids_to_download: Vec<&Txid> = history_txs_id.difference(&txids_raw_in_db).collect();
+        if !txids_to_download.is_empty() {
+            info!("got {} txs to download", txids_to_download.len());
+            txs_downloaded.extend(maybe_await!(self.download_and_save_in_chunks(
+                txids_to_download,
+                chunk_size,
+                db,
+            ))?);
+            let mut prev_txids = HashSet::new();
+            let mut txids_downloaded = HashSet::new();
+            for tx in txs_downloaded.iter() {
+                txids_downloaded.insert(tx.txid());
+                // add every previous input tx, but skip coinbase
+                for input in tx.input.iter().filter(|i| !i.previous_output.is_null()) {
+                    prev_txids.insert(input.previous_output.txid);
+                }
+            }
+            let already_present: HashSet<Txid> =
+                txids_downloaded.union(&txids_raw_in_db).cloned().collect();
+            let prev_txs_to_download: Vec<&Txid> =
+                prev_txids.difference(&already_present).collect();
+            info!("{} previous txs to download", prev_txs_to_download.len());
+            txs_downloaded.extend(maybe_await!(self.download_and_save_in_chunks(
+                prev_txs_to_download,
+                chunk_size,
+                db,
+            ))?);
+        }
+
+        Ok(txs_downloaded)
+    }
+
+    /// download headers at heights in `txid_height` if tx details not already present, returns a map Txid -> timestamp
+    fn download_needed_headers(
+        &self,
+        txid_height: &HashMap<Txid, Option<u32>>,
+        txs_details_in_db: &HashMap<Txid, TransactionDetails>,
+        chunk_size: usize,
+    ) -> Result<HashMap<Txid, u64>, Error> {
+        let mut txid_timestamp = HashMap::new();
+        let needed_txid_height: HashMap<&Txid, u32> = txid_height
+            .iter()
+            .filter(|(t, _)| txs_details_in_db.get(*t).is_none())
+            .filter_map(|(t, o)| o.map(|h| (t, h)))
+            .collect();
+        let needed_heights: HashSet<u32> = needed_txid_height.values().cloned().collect();
+        if !needed_heights.is_empty() {
+            info!("{} headers to download for timestamp", needed_heights.len());
+            let mut height_timestamp: HashMap<u32, u64> = HashMap::new();
+            for chunk in ChunksIterator::new(needed_heights.into_iter(), chunk_size) {
+                let call_result: Vec<BlockHeader> =
+                    maybe_await!(self.els_batch_block_header(chunk.clone()))?;
+                height_timestamp.extend(
+                    chunk
+                        .into_iter()
+                        .zip(call_result.iter().map(|h| h.time as u64)),
+                );
+            }
+            for (txid, height) in needed_txid_height {
+                let timestamp = height_timestamp
+                    .get(&height)
+                    .ok_or_else(|| Error::Generic("timestamp missing".to_string()))?;
+                txid_timestamp.insert(*txid, *timestamp);
+            }
+        }
+
+        Ok(txid_timestamp)
+    }
+
+    fn download_and_save_in_chunks<D: BatchDatabase>(
+        &self,
+        to_download: Vec<&Txid>,
+        chunk_size: usize,
+        db: &mut D,
+    ) -> Result<Vec<Transaction>, Error> {
+        let mut txs_downloaded = vec![];
+        for chunk in ChunksIterator::new(to_download.into_iter(), chunk_size) {
+            let call_result: Vec<Transaction> =
+                maybe_await!(self.els_batch_transaction_get(chunk))?;
+            let mut batch = db.begin_batch();
+            for new_tx in call_result.iter() {
+                batch.set_raw_tx(new_tx)?;
+            }
+            db.commit_batch(batch)?;
+            txs_downloaded.extend(call_result);
+        }
+
+        Ok(txs_downloaded)
+    }
+}
+
+fn save_transaction_details_and_utxos<D: BatchDatabase>(
+    txid: &Txid,
+    db: &mut D,
+    timestamp: u64,
+    height: Option<u32>,
+    updates: &mut dyn BatchOperations,
+    utxo_deps: &HashMap<OutPoint, OutPoint>,
+) -> Result<(), Error> {
+    let tx = db.get_raw_tx(txid)?.ok_or(Error::TransactionNotFound)?;
+
+    let mut incoming: u64 = 0;
+    let mut outgoing: u64 = 0;
+
+    let mut inputs_sum: u64 = 0;
+    let mut outputs_sum: u64 = 0;
+
+    // look for our own inputs
+    for input in tx.input.iter() {
+        // skip coinbase inputs
+        if input.previous_output.is_null() {
+            continue;
+        }
+
+        // We already downloaded all previous output txs in the previous step
+        if let Some(previous_output) = db.get_previous_output(&input.previous_output)? {
+            inputs_sum += previous_output.value;
+
+            if db.is_mine(&previous_output.script_pubkey)? {
+                outgoing += previous_output.value;
+            }
+        } else {
+            // The input is not ours, but we still need to count it for the fees
+            let tx = db
+                .get_raw_tx(&input.previous_output.txid)?
+                .ok_or(Error::TransactionNotFound)?;
+            inputs_sum += tx.output[input.previous_output.vout as usize].value;
+        }
+
+        // removes conflicting UTXO if any (generated from same inputs, like for example RBF)
+        if let Some(outpoint) = utxo_deps.get(&input.previous_output) {
+            updates.del_utxo(&outpoint)?;
+        }
+    }
+
+    for (i, output) in tx.output.iter().enumerate() {
+        // to compute the fees later
+        outputs_sum += output.value;
+
+        // this output is ours, we have a path to derive it
+        if let Some((keychain, _child)) = db.get_path_from_script_pubkey(&output.script_pubkey)? {
+            debug!("{} output #{} is mine, adding utxo", txid, i);
+            updates.set_utxo(&UTXO {
+                outpoint: OutPoint::new(tx.txid(), i as u32),
+                txout: output.clone(),
+                keychain,
+            })?;
+
+            incoming += output.value;
+        }
+    }
+
+    let tx_details = TransactionDetails {
+        txid: tx.txid(),
+        transaction: Some(tx),
+        received: incoming,
+        sent: outgoing,
+        height,
+        timestamp,
+        fees: inputs_sum.saturating_sub(outputs_sum), /* if the tx is a coinbase, fees would be negative */
+    };
+    updates.set_tx(&tx_details)?;
+
+    Ok(())
+}
+
+/// returns utxo dependency as the inputs needed for the utxo to exist
+/// `tx_raw_in_db` must contains utxo's generating txs or errors witt [crate::Error::TransactionNotFound]
+fn utxos_deps<D: BatchDatabase>(
+    db: &mut D,
+    tx_raw_in_db: &HashMap<Txid, Transaction>,
+) -> Result<HashMap<OutPoint, OutPoint>, Error> {
+    let utxos = db.iter_utxos()?;
+    let mut utxos_deps = HashMap::new();
+    for utxo in utxos {
+        let from_tx = tx_raw_in_db
+            .get(&utxo.outpoint.txid)
+            .ok_or(Error::TransactionNotFound)?;
+        for input in from_tx.input.iter() {
+            utxos_deps.insert(input.previous_output, utxo.outpoint);
+        }
+    }
+    Ok(utxos_deps)
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/any.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/any.rs.html new file mode 100644 index 0000000000..55b9fbcc5f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/any.rs.html @@ -0,0 +1,782 @@ +any.rs - source + +
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Runtime-checked database types
+//!
+//! This module provides the implementation of [`AnyDatabase`] which allows switching the
+//! inner [`Database`] type at runtime.
+//!
+//! ## Example
+//!
+//! In this example, `wallet_memory` and `wallet_sled` have the same type of `Wallet<OfflineBlockchain, AnyDatabase>`.
+//!
+//! ```no_run
+//! # use bitcoin::Network;
+//! # use bdk::database::{AnyDatabase, MemoryDatabase};
+//! # use bdk::{Wallet, OfflineWallet};
+//! let memory = MemoryDatabase::default().into();
+//! let wallet_memory: OfflineWallet<AnyDatabase> =
+//!     Wallet::new_offline("...", None, Network::Testnet, memory)?;
+//!
+//! # #[cfg(feature = "key-value-db")]
+//! # {
+//! let sled = sled::open("my-database")?.open_tree("default_tree")?.into();
+//! let wallet_sled: OfflineWallet<AnyDatabase> =
+//!     Wallet::new_offline("...", None, Network::Testnet, sled)?;
+//! # }
+//! # Ok::<(), bdk::Error>(())
+//! ```
+//!
+//! When paired with the use of [`ConfigurableDatabase`], it allows creating wallets with any
+//! database supported using a single line of code:
+//!
+//! ```no_run
+//! # use bitcoin::Network;
+//! # use bdk::database::*;
+//! # use bdk::{Wallet, OfflineWallet};
+//! let config = serde_json::from_str("...")?;
+//! let database = AnyDatabase::from_config(&config)?;
+//! let wallet: OfflineWallet<_> = Wallet::new_offline("...", None, Network::Testnet, database)?;
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use super::*;
+
+macro_rules! impl_from {
+    ( $from:ty, $to:ty, $variant:ident, $( $cfg:tt )* ) => {
+        $( $cfg )*
+        impl From<$from> for $to {
+            fn from(inner: $from) -> Self {
+                <$to>::$variant(inner)
+            }
+        }
+    };
+}
+
+macro_rules! impl_inner_method {
+    ( $enum_name:ident, $self:expr, $name:ident $(, $args:expr)* ) => {
+        match $self {
+            $enum_name::Memory(inner) => inner.$name( $($args, )* ),
+            #[cfg(feature = "key-value-db")]
+            $enum_name::Sled(inner) => inner.$name( $($args, )* ),
+        }
+    }
+}
+
+/// Type that can contain any of the [`Database`] types defined by the library
+///
+/// It allows switching database type at runtime.
+///
+/// See [this module](crate::database::any)'s documentation for a usage example.
+#[derive(Debug)]
+pub enum AnyDatabase {
+    /// In-memory ephemeral database
+    Memory(memory::MemoryDatabase),
+    #[cfg(feature = "key-value-db")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
+    /// Simple key-value embedded database based on [`sled`]
+    Sled(sled::Tree),
+}
+
+impl_from!(memory::MemoryDatabase, AnyDatabase, Memory,);
+impl_from!(sled::Tree, AnyDatabase, Sled, #[cfg(feature = "key-value-db")]);
+
+/// Type that contains any of the [`BatchDatabase::Batch`] types defined by the library
+pub enum AnyBatch {
+    /// In-memory ephemeral database
+    Memory(<memory::MemoryDatabase as BatchDatabase>::Batch),
+    #[cfg(feature = "key-value-db")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
+    /// Simple key-value embedded database based on [`sled`]
+    Sled(<sled::Tree as BatchDatabase>::Batch),
+}
+
+impl_from!(
+    <memory::MemoryDatabase as BatchDatabase>::Batch,
+    AnyBatch,
+    Memory,
+);
+impl_from!(<sled::Tree as BatchDatabase>::Batch, AnyBatch, Sled, #[cfg(feature = "key-value-db")]);
+
+impl BatchOperations for AnyDatabase {
+    fn set_script_pubkey(
+        &mut self,
+        script: &Script,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<(), Error> {
+        impl_inner_method!(
+            AnyDatabase,
+            self,
+            set_script_pubkey,
+            script,
+            keychain,
+            child
+        )
+    }
+    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
+        impl_inner_method!(AnyDatabase, self, set_utxo, utxo)
+    }
+    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
+        impl_inner_method!(AnyDatabase, self, set_raw_tx, transaction)
+    }
+    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
+        impl_inner_method!(AnyDatabase, self, set_tx, transaction)
+    }
+    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
+        impl_inner_method!(AnyDatabase, self, set_last_index, keychain, value)
+    }
+
+    fn del_script_pubkey_from_path(
+        &mut self,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<Option<Script>, Error> {
+        impl_inner_method!(
+            AnyDatabase,
+            self,
+            del_script_pubkey_from_path,
+            keychain,
+            child
+        )
+    }
+    fn del_path_from_script_pubkey(
+        &mut self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error> {
+        impl_inner_method!(AnyDatabase, self, del_path_from_script_pubkey, script)
+    }
+    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
+        impl_inner_method!(AnyDatabase, self, del_utxo, outpoint)
+    }
+    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        impl_inner_method!(AnyDatabase, self, del_raw_tx, txid)
+    }
+    fn del_tx(
+        &mut self,
+        txid: &Txid,
+        include_raw: bool,
+    ) -> Result<Option<TransactionDetails>, Error> {
+        impl_inner_method!(AnyDatabase, self, del_tx, txid, include_raw)
+    }
+    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
+        impl_inner_method!(AnyDatabase, self, del_last_index, keychain)
+    }
+}
+
+impl Database for AnyDatabase {
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
+        &mut self,
+        keychain: KeychainKind,
+        bytes: B,
+    ) -> Result<(), Error> {
+        impl_inner_method!(
+            AnyDatabase,
+            self,
+            check_descriptor_checksum,
+            keychain,
+            bytes
+        )
+    }
+
+    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
+        impl_inner_method!(AnyDatabase, self, iter_script_pubkeys, keychain)
+    }
+    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error> {
+        impl_inner_method!(AnyDatabase, self, iter_utxos)
+    }
+    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
+        impl_inner_method!(AnyDatabase, self, iter_raw_txs)
+    }
+    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
+        impl_inner_method!(AnyDatabase, self, iter_txs, include_raw)
+    }
+
+    fn get_script_pubkey_from_path(
+        &self,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<Option<Script>, Error> {
+        impl_inner_method!(
+            AnyDatabase,
+            self,
+            get_script_pubkey_from_path,
+            keychain,
+            child
+        )
+    }
+    fn get_path_from_script_pubkey(
+        &self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error> {
+        impl_inner_method!(AnyDatabase, self, get_path_from_script_pubkey, script)
+    }
+    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
+        impl_inner_method!(AnyDatabase, self, get_utxo, outpoint)
+    }
+    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        impl_inner_method!(AnyDatabase, self, get_raw_tx, txid)
+    }
+    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
+        impl_inner_method!(AnyDatabase, self, get_tx, txid, include_raw)
+    }
+    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
+        impl_inner_method!(AnyDatabase, self, get_last_index, keychain)
+    }
+
+    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
+        impl_inner_method!(AnyDatabase, self, increment_last_index, keychain)
+    }
+}
+
+impl BatchOperations for AnyBatch {
+    fn set_script_pubkey(
+        &mut self,
+        script: &Script,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<(), Error> {
+        impl_inner_method!(AnyBatch, self, set_script_pubkey, script, keychain, child)
+    }
+    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
+        impl_inner_method!(AnyBatch, self, set_utxo, utxo)
+    }
+    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
+        impl_inner_method!(AnyBatch, self, set_raw_tx, transaction)
+    }
+    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
+        impl_inner_method!(AnyBatch, self, set_tx, transaction)
+    }
+    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
+        impl_inner_method!(AnyBatch, self, set_last_index, keychain, value)
+    }
+
+    fn del_script_pubkey_from_path(
+        &mut self,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<Option<Script>, Error> {
+        impl_inner_method!(AnyBatch, self, del_script_pubkey_from_path, keychain, child)
+    }
+    fn del_path_from_script_pubkey(
+        &mut self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error> {
+        impl_inner_method!(AnyBatch, self, del_path_from_script_pubkey, script)
+    }
+    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
+        impl_inner_method!(AnyBatch, self, del_utxo, outpoint)
+    }
+    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        impl_inner_method!(AnyBatch, self, del_raw_tx, txid)
+    }
+    fn del_tx(
+        &mut self,
+        txid: &Txid,
+        include_raw: bool,
+    ) -> Result<Option<TransactionDetails>, Error> {
+        impl_inner_method!(AnyBatch, self, del_tx, txid, include_raw)
+    }
+    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
+        impl_inner_method!(AnyBatch, self, del_last_index, keychain)
+    }
+}
+
+impl BatchDatabase for AnyDatabase {
+    type Batch = AnyBatch;
+
+    fn begin_batch(&self) -> Self::Batch {
+        match self {
+            AnyDatabase::Memory(inner) => inner.begin_batch().into(),
+            #[cfg(feature = "key-value-db")]
+            AnyDatabase::Sled(inner) => inner.begin_batch().into(),
+        }
+    }
+    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
+        // TODO: refactor once `move_ref_pattern` is stable
+        #[allow(irrefutable_let_patterns)]
+        match self {
+            AnyDatabase::Memory(db) => {
+                if let AnyBatch::Memory(batch) = batch {
+                    db.commit_batch(batch)
+                } else {
+                    unimplemented!()
+                }
+            }
+            #[cfg(feature = "key-value-db")]
+            AnyDatabase::Sled(db) => {
+                if let AnyBatch::Sled(batch) = batch {
+                    db.commit_batch(batch)
+                } else {
+                    unimplemented!()
+                }
+            }
+        }
+    }
+}
+
+/// Configuration type for a [`sled::Tree`] database
+#[cfg(feature = "key-value-db")]
+#[derive(Debug, serde::Serialize, serde::Deserialize)]
+pub struct SledDbConfiguration {
+    /// Main directory of the db
+    pub path: String,
+    /// Name of the database tree, a separated namespace for the data
+    pub tree_name: String,
+}
+
+#[cfg(feature = "key-value-db")]
+impl ConfigurableDatabase for sled::Tree {
+    type Config = SledDbConfiguration;
+
+    fn from_config(config: &Self::Config) -> Result<Self, Error> {
+        Ok(sled::open(&config.path)?.open_tree(&config.tree_name)?)
+    }
+}
+
+/// Type that can contain any of the database configurations defined by the library
+///
+/// This allows storing a single configuration that can be loaded into an [`AnyDatabase`]
+/// instance. Wallets that plan to offer users the ability to switch blockchain backend at runtime
+/// will find this particularly useful.
+#[derive(Debug, serde::Serialize, serde::Deserialize)]
+pub enum AnyDatabaseConfig {
+    /// Memory database has no config
+    Memory(()),
+    #[cfg(feature = "key-value-db")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
+    /// Simple key-value embedded database based on [`sled`]
+    Sled(SledDbConfiguration),
+}
+
+impl ConfigurableDatabase for AnyDatabase {
+    type Config = AnyDatabaseConfig;
+
+    fn from_config(config: &Self::Config) -> Result<Self, Error> {
+        Ok(match config {
+            AnyDatabaseConfig::Memory(inner) => {
+                AnyDatabase::Memory(memory::MemoryDatabase::from_config(inner)?)
+            }
+            #[cfg(feature = "key-value-db")]
+            AnyDatabaseConfig::Sled(inner) => AnyDatabase::Sled(sled::Tree::from_config(inner)?),
+        })
+    }
+}
+
+impl_from!((), AnyDatabaseConfig, Memory,);
+impl_from!(SledDbConfiguration, AnyDatabaseConfig, Sled, #[cfg(feature = "key-value-db")]);
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/keyvalue.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/keyvalue.rs.html new file mode 100644 index 0000000000..200aeebca1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/keyvalue.rs.html @@ -0,0 +1,968 @@ +keyvalue.rs - source + +
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::convert::TryInto;
+
+use sled::{Batch, Tree};
+
+use bitcoin::consensus::encode::{deserialize, serialize};
+use bitcoin::hash_types::Txid;
+use bitcoin::{OutPoint, Script, Transaction};
+
+use crate::database::memory::MapKey;
+use crate::database::{BatchDatabase, BatchOperations, Database};
+use crate::error::Error;
+use crate::types::*;
+
+macro_rules! impl_batch_operations {
+    ( { $($after_insert:tt)* }, $process_delete:ident ) => {
+        fn set_script_pubkey(&mut self, script: &Script, keychain: KeychainKind, path: u32) -> Result<(), Error> {
+            let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
+            self.insert(key, serialize(script))$($after_insert)*;
+
+            let key = MapKey::Script(Some(script)).as_map_key();
+            let value = json!({
+                "t": keychain,
+                "p": path,
+            });
+            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
+
+            Ok(())
+        }
+
+        fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
+            let key = MapKey::UTXO(Some(&utxo.outpoint)).as_map_key();
+            let value = json!({
+                "t": utxo.txout,
+                "i": utxo.keychain,
+            });
+            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
+
+            Ok(())
+        }
+
+        fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
+            let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
+            let value = serialize(transaction);
+            self.insert(key, value)$($after_insert)*;
+
+            Ok(())
+        }
+
+        fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
+            let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
+
+            // remove the raw tx from the serialized version
+            let mut value = serde_json::to_value(transaction)?;
+            value["transaction"] = serde_json::Value::Null;
+            let value = serde_json::to_vec(&value)?;
+
+            self.insert(key, value)$($after_insert)*;
+
+            // insert the raw_tx if present
+            if let Some(ref tx) = transaction.transaction {
+                self.set_raw_tx(tx)?;
+            }
+
+            Ok(())
+        }
+
+        fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
+            let key = MapKey::LastIndex(keychain).as_map_key();
+            self.insert(key, &value.to_be_bytes())$($after_insert)*;
+
+            Ok(())
+        }
+
+        fn del_script_pubkey_from_path(&mut self, keychain: KeychainKind, path: u32) -> Result<Option<Script>, Error> {
+            let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
+        }
+
+        fn del_path_from_script_pubkey(&mut self, script: &Script) -> Result<Option<(KeychainKind, u32)>, Error> {
+            let key = MapKey::Script(Some(script)).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            match res {
+                None => Ok(None),
+                Some(b) => {
+                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
+                    let st = serde_json::from_value(val["t"].take())?;
+                    let path = serde_json::from_value(val["p"].take())?;
+
+                    Ok(Some((st, path)))
+                }
+            }
+        }
+
+        fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
+            let key = MapKey::UTXO(Some(outpoint)).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            match res {
+                None => Ok(None),
+                Some(b) => {
+                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
+                    let txout = serde_json::from_value(val["t"].take())?;
+                    let keychain = serde_json::from_value(val["i"].take())?;
+
+                    Ok(Some(UTXO { outpoint: outpoint.clone(), txout, keychain }))
+                }
+            }
+        }
+
+        fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+            let key = MapKey::RawTx(Some(txid)).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
+        }
+
+        fn del_tx(&mut self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
+            let raw_tx = if include_raw {
+                self.del_raw_tx(txid)?
+            } else {
+                None
+            };
+
+            let key = MapKey::Transaction(Some(txid)).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            match res {
+                None => Ok(None),
+                Some(b) => {
+                    let mut val: TransactionDetails = serde_json::from_slice(&b)?;
+                    val.transaction = raw_tx;
+
+                    Ok(Some(val))
+                }
+            }
+        }
+
+        fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
+            let key = MapKey::LastIndex(keychain).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            match res {
+                None => Ok(None),
+                Some(b) => {
+                    let array: [u8; 4] = b.as_ref().try_into().map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
+                    let val = u32::from_be_bytes(array);
+                    Ok(Some(val))
+                }
+            }
+        }
+    }
+}
+
+macro_rules! process_delete_tree {
+    ($res:expr) => {
+        $res?
+    };
+}
+impl BatchOperations for Tree {
+    impl_batch_operations!({?}, process_delete_tree);
+}
+
+macro_rules! process_delete_batch {
+    ($res:expr) => {
+        None as Option<sled::IVec>
+    };
+}
+#[allow(unused_variables)]
+impl BatchOperations for Batch {
+    impl_batch_operations!({}, process_delete_batch);
+}
+
+impl Database for Tree {
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
+        &mut self,
+        keychain: KeychainKind,
+        bytes: B,
+    ) -> Result<(), Error> {
+        let key = MapKey::DescriptorChecksum(keychain).as_map_key();
+
+        let prev = self.get(&key)?.map(|x| x.to_vec());
+        if let Some(val) = prev {
+            if val == bytes.as_ref() {
+                Ok(())
+            } else {
+                Err(Error::ChecksumMismatch)
+            }
+        } else {
+            self.insert(&key, bytes.as_ref())?;
+            Ok(())
+        }
+    }
+
+    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
+        let key = MapKey::Path((keychain, None)).as_map_key();
+        self.scan_prefix(key)
+            .map(|x| -> Result<_, Error> {
+                let (_, v) = x?;
+                Ok(deserialize(&v)?)
+            })
+            .collect()
+    }
+
+    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error> {
+        let key = MapKey::UTXO(None).as_map_key();
+        self.scan_prefix(key)
+            .map(|x| -> Result<_, Error> {
+                let (k, v) = x?;
+                let outpoint = deserialize(&k[1..])?;
+
+                let mut val: serde_json::Value = serde_json::from_slice(&v)?;
+                let txout = serde_json::from_value(val["t"].take())?;
+                let keychain = serde_json::from_value(val["i"].take())?;
+
+                Ok(UTXO {
+                    outpoint,
+                    txout,
+                    keychain,
+                })
+            })
+            .collect()
+    }
+
+    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
+        let key = MapKey::RawTx(None).as_map_key();
+        self.scan_prefix(key)
+            .map(|x| -> Result<_, Error> {
+                let (_, v) = x?;
+                Ok(deserialize(&v)?)
+            })
+            .collect()
+    }
+
+    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
+        let key = MapKey::Transaction(None).as_map_key();
+        self.scan_prefix(key)
+            .map(|x| -> Result<_, Error> {
+                let (k, v) = x?;
+                let mut txdetails: TransactionDetails = serde_json::from_slice(&v)?;
+                if include_raw {
+                    let txid = deserialize(&k[1..])?;
+                    txdetails.transaction = self.get_raw_tx(&txid)?;
+                }
+
+                Ok(txdetails)
+            })
+            .collect()
+    }
+
+    fn get_script_pubkey_from_path(
+        &self,
+        keychain: KeychainKind,
+        path: u32,
+    ) -> Result<Option<Script>, Error> {
+        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
+        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
+    }
+
+    fn get_path_from_script_pubkey(
+        &self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error> {
+        let key = MapKey::Script(Some(script)).as_map_key();
+        self.get(key)?
+            .map(|b| -> Result<_, Error> {
+                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
+                let st = serde_json::from_value(val["t"].take())?;
+                let path = serde_json::from_value(val["p"].take())?;
+
+                Ok((st, path))
+            })
+            .transpose()
+    }
+
+    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
+        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
+        self.get(key)?
+            .map(|b| -> Result<_, Error> {
+                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
+                let txout = serde_json::from_value(val["t"].take())?;
+                let keychain = serde_json::from_value(val["i"].take())?;
+
+                Ok(UTXO {
+                    outpoint: *outpoint,
+                    txout,
+                    keychain,
+                })
+            })
+            .transpose()
+    }
+
+    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        let key = MapKey::RawTx(Some(txid)).as_map_key();
+        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
+    }
+
+    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
+        let key = MapKey::Transaction(Some(txid)).as_map_key();
+        self.get(key)?
+            .map(|b| -> Result<_, Error> {
+                let mut txdetails: TransactionDetails = serde_json::from_slice(&b)?;
+                if include_raw {
+                    txdetails.transaction = self.get_raw_tx(&txid)?;
+                }
+
+                Ok(txdetails)
+            })
+            .transpose()
+    }
+
+    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
+        let key = MapKey::LastIndex(keychain).as_map_key();
+        self.get(key)?
+            .map(|b| -> Result<_, Error> {
+                let array: [u8; 4] = b
+                    .as_ref()
+                    .try_into()
+                    .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
+                let val = u32::from_be_bytes(array);
+                Ok(val)
+            })
+            .transpose()
+    }
+
+    // inserts 0 if not present
+    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
+        let key = MapKey::LastIndex(keychain).as_map_key();
+        self.update_and_fetch(key, |prev| {
+            let new = match prev {
+                Some(b) => {
+                    let array: [u8; 4] = b.try_into().unwrap_or([0; 4]);
+                    let val = u32::from_be_bytes(array);
+
+                    val + 1
+                }
+                None => 0,
+            };
+
+            Some(new.to_be_bytes().to_vec())
+        })?
+        .map_or(Ok(0), |b| -> Result<_, Error> {
+            let array: [u8; 4] = b
+                .as_ref()
+                .try_into()
+                .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
+            let val = u32::from_be_bytes(array);
+            Ok(val)
+        })
+    }
+}
+
+impl BatchDatabase for Tree {
+    type Batch = sled::Batch;
+
+    fn begin_batch(&self) -> Self::Batch {
+        sled::Batch::default()
+    }
+
+    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
+        Ok(self.apply_batch(batch)?)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::sync::{Arc, Condvar, Mutex, Once};
+    use std::time::{SystemTime, UNIX_EPOCH};
+
+    use sled::{Db, Tree};
+
+    static mut COUNT: usize = 0;
+
+    lazy_static! {
+        static ref DB: Arc<(Mutex<Option<Db>>, Condvar)> =
+            Arc::new((Mutex::new(None), Condvar::new()));
+        static ref INIT: Once = Once::new();
+    }
+
+    fn get_tree() -> Tree {
+        unsafe {
+            let cloned = DB.clone();
+            let (mutex, cvar) = &*cloned;
+
+            INIT.call_once(|| {
+                let mut db = mutex.lock().unwrap();
+
+                let time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
+                let mut dir = std::env::temp_dir();
+                dir.push(format!("mbw_{}", time.as_nanos()));
+
+                *db = Some(sled::open(dir).unwrap());
+                cvar.notify_all();
+            });
+
+            let mut db = mutex.lock().unwrap();
+            while !db.is_some() {
+                db = cvar.wait(db).unwrap();
+            }
+
+            COUNT += 1;
+
+            db.as_ref()
+                .unwrap()
+                .open_tree(format!("tree_{}", COUNT))
+                .unwrap()
+        }
+    }
+
+    #[test]
+    fn test_script_pubkey() {
+        crate::database::test::test_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_batch_script_pubkey() {
+        crate::database::test::test_batch_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_iter_script_pubkey() {
+        crate::database::test::test_iter_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_del_script_pubkey() {
+        crate::database::test::test_del_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_utxo() {
+        crate::database::test::test_utxo(get_tree());
+    }
+
+    #[test]
+    fn test_raw_tx() {
+        crate::database::test::test_raw_tx(get_tree());
+    }
+
+    #[test]
+    fn test_tx() {
+        crate::database::test::test_tx(get_tree());
+    }
+
+    #[test]
+    fn test_last_index() {
+        crate::database::test::test_last_index(get_tree());
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/memory.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/memory.rs.html new file mode 100644 index 0000000000..350db935c6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/memory.rs.html @@ -0,0 +1,1138 @@ +memory.rs - source + +
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! In-memory ephemeral database
+//!
+//! This module defines an in-memory database type called [`MemoryDatabase`] that is based on a
+//! [`BTreeMap`].
+
+use std::collections::BTreeMap;
+use std::ops::Bound::{Excluded, Included};
+
+use bitcoin::consensus::encode::{deserialize, serialize};
+use bitcoin::hash_types::Txid;
+use bitcoin::{OutPoint, Script, Transaction};
+
+use crate::database::{BatchDatabase, BatchOperations, ConfigurableDatabase, Database};
+use crate::error::Error;
+use crate::types::*;
+
+// path -> script       p{i,e}<path> -> script
+// script -> path       s<script> -> {i,e}<path>
+// outpoint             u<outpoint> -> txout
+// rawtx                r<txid> -> tx
+// transactions         t<txid> -> tx details
+// deriv indexes        c{i,e} -> u32
+// descriptor checksum  d{i,e} -> vec<u8>
+
+pub(crate) enum MapKey<'a> {
+    Path((Option<KeychainKind>, Option<u32>)),
+    Script(Option<&'a Script>),
+    UTXO(Option<&'a OutPoint>),
+    RawTx(Option<&'a Txid>),
+    Transaction(Option<&'a Txid>),
+    LastIndex(KeychainKind),
+    DescriptorChecksum(KeychainKind),
+}
+
+impl MapKey<'_> {
+    fn as_prefix(&self) -> Vec<u8> {
+        match self {
+            MapKey::Path((st, _)) => {
+                let mut v = b"p".to_vec();
+                if let Some(st) = st {
+                    v.push(st.as_byte());
+                }
+                v
+            }
+            MapKey::Script(_) => b"s".to_vec(),
+            MapKey::UTXO(_) => b"u".to_vec(),
+            MapKey::RawTx(_) => b"r".to_vec(),
+            MapKey::Transaction(_) => b"t".to_vec(),
+            MapKey::LastIndex(st) => [b"c", st.as_ref()].concat(),
+            MapKey::DescriptorChecksum(st) => [b"d", st.as_ref()].concat(),
+        }
+    }
+
+    fn serialize_content(&self) -> Vec<u8> {
+        match self {
+            MapKey::Path((_, Some(child))) => child.to_be_bytes().to_vec(),
+            MapKey::Script(Some(s)) => serialize(*s),
+            MapKey::UTXO(Some(s)) => serialize(*s),
+            MapKey::RawTx(Some(s)) => serialize(*s),
+            MapKey::Transaction(Some(s)) => serialize(*s),
+            _ => vec![],
+        }
+    }
+
+    pub fn as_map_key(&self) -> Vec<u8> {
+        let mut v = self.as_prefix();
+        v.extend_from_slice(&self.serialize_content());
+
+        v
+    }
+}
+
+fn after(key: &[u8]) -> Vec<u8> {
+    let mut key = key.to_owned();
+    let mut idx = key.len();
+    while idx > 0 {
+        if key[idx - 1] == 0xFF {
+            idx -= 1;
+            continue;
+        } else {
+            key[idx - 1] += 1;
+            break;
+        }
+    }
+
+    key
+}
+
+/// In-memory ephemeral database
+///
+/// This database can be used as a temporary storage for wallets that are not kept permanently on
+/// a device, or on platforms that don't provide a filesystem, like `wasm32`.
+///
+/// Once it's dropped its content will be lost.
+///
+/// If you are looking for a permanent storage solution, you can try with the default key-value
+/// database called [`sled`]. See the [`database`] module documentation for more defailts.
+///
+/// [`database`]: crate::database
+#[derive(Debug, Default)]
+pub struct MemoryDatabase {
+    map: BTreeMap<Vec<u8>, Box<dyn std::any::Any>>,
+    deleted_keys: Vec<Vec<u8>>,
+}
+
+impl MemoryDatabase {
+    /// Create a new empty database
+    pub fn new() -> Self {
+        MemoryDatabase {
+            map: BTreeMap::new(),
+            deleted_keys: Vec::new(),
+        }
+    }
+}
+
+impl BatchOperations for MemoryDatabase {
+    fn set_script_pubkey(
+        &mut self,
+        script: &Script,
+        keychain: KeychainKind,
+        path: u32,
+    ) -> Result<(), Error> {
+        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
+        self.map.insert(key, Box::new(script.clone()));
+
+        let key = MapKey::Script(Some(script)).as_map_key();
+        let value = json!({
+            "t": keychain,
+            "p": path,
+        });
+        self.map.insert(key, Box::new(value));
+
+        Ok(())
+    }
+
+    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
+        let key = MapKey::UTXO(Some(&utxo.outpoint)).as_map_key();
+        self.map
+            .insert(key, Box::new((utxo.txout.clone(), utxo.keychain)));
+
+        Ok(())
+    }
+    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
+        let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
+        self.map.insert(key, Box::new(transaction.clone()));
+
+        Ok(())
+    }
+    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
+        let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
+
+        // insert the raw_tx if present
+        if let Some(ref tx) = transaction.transaction {
+            self.set_raw_tx(tx)?;
+        }
+
+        // remove the raw tx from the serialized version
+        let mut transaction = transaction.clone();
+        transaction.transaction = None;
+
+        self.map.insert(key, Box::new(transaction));
+
+        Ok(())
+    }
+    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
+        let key = MapKey::LastIndex(keychain).as_map_key();
+        self.map.insert(key, Box::new(value));
+
+        Ok(())
+    }
+
+    fn del_script_pubkey_from_path(
+        &mut self,
+        keychain: KeychainKind,
+        path: u32,
+    ) -> Result<Option<Script>, Error> {
+        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
+    }
+    fn del_path_from_script_pubkey(
+        &mut self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error> {
+        let key = MapKey::Script(Some(script)).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        match res {
+            None => Ok(None),
+            Some(b) => {
+                let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
+                let st = serde_json::from_value(val["t"].take())?;
+                let path = serde_json::from_value(val["p"].take())?;
+
+                Ok(Some((st, path)))
+            }
+        }
+    }
+    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
+        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        match res {
+            None => Ok(None),
+            Some(b) => {
+                let (txout, keychain) = b.downcast_ref().cloned().unwrap();
+                Ok(Some(UTXO {
+                    outpoint: *outpoint,
+                    txout,
+                    keychain,
+                }))
+            }
+        }
+    }
+    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        let key = MapKey::RawTx(Some(txid)).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
+    }
+    fn del_tx(
+        &mut self,
+        txid: &Txid,
+        include_raw: bool,
+    ) -> Result<Option<TransactionDetails>, Error> {
+        let raw_tx = if include_raw {
+            self.del_raw_tx(txid)?
+        } else {
+            None
+        };
+
+        let key = MapKey::Transaction(Some(txid)).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        match res {
+            None => Ok(None),
+            Some(b) => {
+                let mut val: TransactionDetails = b.downcast_ref().cloned().unwrap();
+                val.transaction = raw_tx;
+
+                Ok(Some(val))
+            }
+        }
+    }
+    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
+        let key = MapKey::LastIndex(keychain).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        match res {
+            None => Ok(None),
+            Some(b) => Ok(Some(*b.downcast_ref().unwrap())),
+        }
+    }
+}
+
+impl Database for MemoryDatabase {
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
+        &mut self,
+        keychain: KeychainKind,
+        bytes: B,
+    ) -> Result<(), Error> {
+        let key = MapKey::DescriptorChecksum(keychain).as_map_key();
+
+        let prev = self
+            .map
+            .get(&key)
+            .map(|x| x.downcast_ref::<Vec<u8>>().unwrap());
+        if let Some(val) = prev {
+            if val == &bytes.as_ref().to_vec() {
+                Ok(())
+            } else {
+                Err(Error::ChecksumMismatch)
+            }
+        } else {
+            self.map.insert(key, Box::new(bytes.as_ref().to_vec()));
+            Ok(())
+        }
+    }
+
+    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
+        let key = MapKey::Path((keychain, None)).as_map_key();
+        self.map
+            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
+            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
+            .collect()
+    }
+
+    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error> {
+        let key = MapKey::UTXO(None).as_map_key();
+        self.map
+            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
+            .map(|(k, v)| {
+                let outpoint = deserialize(&k[1..]).unwrap();
+                let (txout, keychain) = v.downcast_ref().cloned().unwrap();
+                Ok(UTXO {
+                    outpoint,
+                    txout,
+                    keychain,
+                })
+            })
+            .collect()
+    }
+
+    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
+        let key = MapKey::RawTx(None).as_map_key();
+        self.map
+            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
+            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
+            .collect()
+    }
+
+    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
+        let key = MapKey::Transaction(None).as_map_key();
+        self.map
+            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
+            .map(|(k, v)| {
+                let mut txdetails: TransactionDetails = v.downcast_ref().cloned().unwrap();
+                if include_raw {
+                    let txid = deserialize(&k[1..])?;
+                    txdetails.transaction = self.get_raw_tx(&txid)?;
+                }
+
+                Ok(txdetails)
+            })
+            .collect()
+    }
+
+    fn get_script_pubkey_from_path(
+        &self,
+        keychain: KeychainKind,
+        path: u32,
+    ) -> Result<Option<Script>, Error> {
+        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
+        Ok(self
+            .map
+            .get(&key)
+            .map(|b| b.downcast_ref().cloned().unwrap()))
+    }
+
+    fn get_path_from_script_pubkey(
+        &self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error> {
+        let key = MapKey::Script(Some(script)).as_map_key();
+        Ok(self.map.get(&key).map(|b| {
+            let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
+            let st = serde_json::from_value(val["t"].take()).unwrap();
+            let path = serde_json::from_value(val["p"].take()).unwrap();
+
+            (st, path)
+        }))
+    }
+
+    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
+        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
+        Ok(self.map.get(&key).map(|b| {
+            let (txout, keychain) = b.downcast_ref().cloned().unwrap();
+            UTXO {
+                outpoint: *outpoint,
+                txout,
+                keychain,
+            }
+        }))
+    }
+
+    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        let key = MapKey::RawTx(Some(txid)).as_map_key();
+        Ok(self
+            .map
+            .get(&key)
+            .map(|b| b.downcast_ref().cloned().unwrap()))
+    }
+
+    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
+        let key = MapKey::Transaction(Some(txid)).as_map_key();
+        Ok(self.map.get(&key).map(|b| {
+            let mut txdetails: TransactionDetails = b.downcast_ref().cloned().unwrap();
+            if include_raw {
+                txdetails.transaction = self.get_raw_tx(&txid).unwrap();
+            }
+
+            txdetails
+        }))
+    }
+
+    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
+        let key = MapKey::LastIndex(keychain).as_map_key();
+        Ok(self.map.get(&key).map(|b| *b.downcast_ref().unwrap()))
+    }
+
+    // inserts 0 if not present
+    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
+        let key = MapKey::LastIndex(keychain).as_map_key();
+        let value = self
+            .map
+            .entry(key)
+            .and_modify(|x| *x.downcast_mut::<u32>().unwrap() += 1)
+            .or_insert_with(|| Box::<u32>::new(0))
+            .downcast_mut()
+            .unwrap();
+
+        Ok(*value)
+    }
+}
+
+impl BatchDatabase for MemoryDatabase {
+    type Batch = Self;
+
+    fn begin_batch(&self) -> Self::Batch {
+        MemoryDatabase::new()
+    }
+
+    fn commit_batch(&mut self, mut batch: Self::Batch) -> Result<(), Error> {
+        for key in batch.deleted_keys {
+            self.map.remove(&key);
+        }
+        self.map.append(&mut batch.map);
+        Ok(())
+    }
+}
+
+impl ConfigurableDatabase for MemoryDatabase {
+    type Config = ();
+
+    fn from_config(_config: &Self::Config) -> Result<Self, Error> {
+        Ok(MemoryDatabase::default())
+    }
+}
+
+#[cfg(test)]
+impl MemoryDatabase {
+    // Artificially insert a tx in the database, as if we had found it with a `sync`
+    pub fn received_tx(
+        &mut self,
+        tx_meta: testutils::TestIncomingTx,
+        current_height: Option<u32>,
+    ) -> bitcoin::Txid {
+        use std::str::FromStr;
+
+        let tx = Transaction {
+            version: 1,
+            lock_time: 0,
+            input: vec![],
+            output: tx_meta
+                .output
+                .iter()
+                .map(|out_meta| bitcoin::TxOut {
+                    value: out_meta.value,
+                    script_pubkey: bitcoin::Address::from_str(&out_meta.to_address)
+                        .unwrap()
+                        .script_pubkey(),
+                })
+                .collect(),
+        };
+
+        let txid = tx.txid();
+        let height = tx_meta
+            .min_confirmations
+            .map(|conf| current_height.unwrap().checked_sub(conf as u32).unwrap());
+
+        let tx_details = TransactionDetails {
+            transaction: Some(tx.clone()),
+            txid,
+            timestamp: 0,
+            height,
+            received: 0,
+            sent: 0,
+            fees: 0,
+        };
+
+        self.set_tx(&tx_details).unwrap();
+        for (vout, out) in tx.output.iter().enumerate() {
+            self.set_utxo(&UTXO {
+                txout: out.clone(),
+                outpoint: OutPoint {
+                    txid,
+                    vout: vout as u32,
+                },
+                keychain: KeychainKind::External,
+            })
+            .unwrap();
+        }
+
+        txid
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::MemoryDatabase;
+
+    fn get_tree() -> MemoryDatabase {
+        MemoryDatabase::new()
+    }
+
+    #[test]
+    fn test_script_pubkey() {
+        crate::database::test::test_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_batch_script_pubkey() {
+        crate::database::test::test_batch_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_iter_script_pubkey() {
+        crate::database::test::test_iter_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_del_script_pubkey() {
+        crate::database::test::test_del_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_utxo() {
+        crate::database::test::test_utxo(get_tree());
+    }
+
+    #[test]
+    fn test_raw_tx() {
+        crate::database::test::test_raw_tx(get_tree());
+    }
+
+    #[test]
+    fn test_tx() {
+        crate::database::test::test_tx(get_tree());
+    }
+
+    #[test]
+    fn test_last_index() {
+        crate::database::test::test_last_index(get_tree());
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/mod.rs.html new file mode 100644 index 0000000000..864f1cb872 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/mod.rs.html @@ -0,0 +1,772 @@ +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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Database types
+//!
+//! This module provides the implementation of some defaults database types, along with traits that
+//! can be implemented externally to let [`Wallet`]s use customized databases.
+//!
+//! It's important to note that the databases defined here only contains "blockchain-related" data.
+//! They can be seen more as a cache than a critical piece of storage that contains secrets and
+//! keys.
+//!
+//! The currently recommended database is [`sled`], which is a pretty simple key-value embedded
+//! database written in Rust. If the `key-value-db` feature is enabled (which by default is),
+//! this library automatically implements all the required traits for [`sled::Tree`].
+//!
+//! [`Wallet`]: crate::wallet::Wallet
+
+use bitcoin::hash_types::Txid;
+use bitcoin::{OutPoint, Script, Transaction, TxOut};
+
+use crate::error::Error;
+use crate::types::*;
+
+pub mod any;
+pub use any::{AnyDatabase, AnyDatabaseConfig};
+
+#[cfg(feature = "key-value-db")]
+pub(crate) mod keyvalue;
+
+pub mod memory;
+pub use memory::MemoryDatabase;
+
+/// Trait for operations that can be batched
+///
+/// This trait defines the list of operations that must be implemented on the [`Database`] type and
+/// the [`BatchDatabase::Batch`] type.
+pub trait BatchOperations {
+    /// Store a script_pubkey along with its keychain and child number.
+    fn set_script_pubkey(
+        &mut self,
+        script: &Script,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<(), Error>;
+    /// Store a [`UTXO`]
+    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>;
+    /// Store a raw transaction
+    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>;
+    /// Store the metadata of a transaction
+    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>;
+    /// Store the last derivation index for a given keychain.
+    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error>;
+
+    /// Delete a script_pubkey given the keychain and its child number.
+    fn del_script_pubkey_from_path(
+        &mut self,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<Option<Script>, Error>;
+    /// Delete the data related to a specific script_pubkey, meaning the keychain and the child
+    /// number.
+    fn del_path_from_script_pubkey(
+        &mut self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error>;
+    /// Delete a [`UTXO`] given its [`OutPoint`]
+    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>;
+    /// Delete a raw transaction given its [`Txid`]
+    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>;
+    /// Delete the metadata of a transaction and optionally the raw transaction itself
+    fn del_tx(
+        &mut self,
+        txid: &Txid,
+        include_raw: bool,
+    ) -> Result<Option<TransactionDetails>, Error>;
+    /// Delete the last derivation index for a keychain.
+    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error>;
+}
+
+/// Trait for reading data from a database
+///
+/// This traits defines the operations that can be used to read data out of a database
+pub trait Database: BatchOperations {
+    /// Read and checks the descriptor checksum for a given keychain.
+    ///
+    /// Should return [`Error::ChecksumMismatch`](crate::error::Error::ChecksumMismatch) if the
+    /// checksum doesn't match. If there's no checksum in the database, simply store it for the
+    /// next time.
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
+        &mut self,
+        keychain: KeychainKind,
+        bytes: B,
+    ) -> Result<(), Error>;
+
+    /// Return the list of script_pubkeys
+    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error>;
+    /// Return the list of [`UTXO`]s
+    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error>;
+    /// Return the list of raw transactions
+    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>;
+    /// Return the list of transactions metadata
+    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error>;
+
+    /// Fetch a script_pubkey given the child number of a keychain.
+    fn get_script_pubkey_from_path(
+        &self,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<Option<Script>, Error>;
+    /// Fetch the keychain and child number of a given script_pubkey
+    fn get_path_from_script_pubkey(
+        &self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error>;
+    /// Fetch a [`UTXO`] given its [`OutPoint`]
+    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>;
+    /// Fetch a raw transaction given its [`Txid`]
+    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
+    /// Fetch the transaction metadata and optionally also the raw transaction
+    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error>;
+    /// Return the last defivation index for a keychain.
+    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error>;
+
+    /// Increment the last derivation index for a keychain and return it
+    ///
+    /// It should insert and return `0` if not present in the database
+    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error>;
+}
+
+/// Trait for a database that supports batch operations
+///
+/// This trait defines the methods to start and apply a batch of operations.
+pub trait BatchDatabase: Database {
+    /// Container for the operations
+    type Batch: BatchOperations;
+
+    /// Create a new batch container
+    fn begin_batch(&self) -> Self::Batch;
+    /// Consume and apply a batch of operations
+    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>;
+}
+
+/// Trait for [`Database`] types that can be created given a configuration
+pub trait ConfigurableDatabase: Database + Sized {
+    /// Type that contains the configuration
+    type Config: std::fmt::Debug;
+
+    /// Create a new instance given a configuration
+    fn from_config(config: &Self::Config) -> Result<Self, Error>;
+}
+
+pub(crate) trait DatabaseUtils: Database {
+    fn is_mine(&self, script: &Script) -> Result<bool, Error> {
+        self.get_path_from_script_pubkey(script)
+            .map(|o| o.is_some())
+    }
+
+    fn get_raw_tx_or<F>(&self, txid: &Txid, f: F) -> Result<Option<Transaction>, Error>
+    where
+        F: FnOnce() -> Result<Option<Transaction>, Error>,
+    {
+        self.get_tx(txid, true)?
+            .map(|t| t.transaction)
+            .flatten()
+            .map_or_else(f, |t| Ok(Some(t)))
+    }
+
+    fn get_previous_output(&self, outpoint: &OutPoint) -> Result<Option<TxOut>, Error> {
+        self.get_raw_tx(&outpoint.txid)?
+            .map(|previous_tx| {
+                if outpoint.vout as usize >= previous_tx.output.len() {
+                    Err(Error::InvalidOutpoint(*outpoint))
+                } else {
+                    Ok(previous_tx.output[outpoint.vout as usize].clone())
+                }
+            })
+            .transpose()
+    }
+}
+
+impl<T: Database> DatabaseUtils for T {}
+
+#[cfg(test)]
+pub mod test {
+    use std::str::FromStr;
+
+    use bitcoin::consensus::encode::deserialize;
+    use bitcoin::hashes::hex::*;
+    use bitcoin::*;
+
+    use super::*;
+
+    pub fn test_script_pubkey<D: Database>(mut tree: D) {
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let path = 42;
+        let keychain = KeychainKind::External;
+
+        tree.set_script_pubkey(&script, keychain, path).unwrap();
+
+        assert_eq!(
+            tree.get_script_pubkey_from_path(keychain, path).unwrap(),
+            Some(script.clone())
+        );
+        assert_eq!(
+            tree.get_path_from_script_pubkey(&script).unwrap(),
+            Some((keychain, path.clone()))
+        );
+    }
+
+    pub fn test_batch_script_pubkey<D: BatchDatabase>(mut tree: D) {
+        let mut batch = tree.begin_batch();
+
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let path = 42;
+        let keychain = KeychainKind::External;
+
+        batch.set_script_pubkey(&script, keychain, path).unwrap();
+
+        assert_eq!(
+            tree.get_script_pubkey_from_path(keychain, path).unwrap(),
+            None
+        );
+        assert_eq!(tree.get_path_from_script_pubkey(&script).unwrap(), None);
+
+        tree.commit_batch(batch).unwrap();
+
+        assert_eq!(
+            tree.get_script_pubkey_from_path(keychain, path).unwrap(),
+            Some(script.clone())
+        );
+        assert_eq!(
+            tree.get_path_from_script_pubkey(&script).unwrap(),
+            Some((keychain, path.clone()))
+        );
+    }
+
+    pub fn test_iter_script_pubkey<D: Database>(mut tree: D) {
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let path = 42;
+        let keychain = KeychainKind::External;
+
+        tree.set_script_pubkey(&script, keychain, path).unwrap();
+
+        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 1);
+    }
+
+    pub fn test_del_script_pubkey<D: Database>(mut tree: D) {
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let path = 42;
+        let keychain = KeychainKind::External;
+
+        tree.set_script_pubkey(&script, keychain, path).unwrap();
+        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 1);
+
+        tree.del_script_pubkey_from_path(keychain, path).unwrap();
+        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 0);
+    }
+
+    pub fn test_utxo<D: Database>(mut tree: D) {
+        let outpoint = OutPoint::from_str(
+            "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0",
+        )
+        .unwrap();
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let txout = TxOut {
+            value: 133742,
+            script_pubkey: script,
+        };
+        let utxo = UTXO {
+            txout,
+            outpoint,
+            keychain: KeychainKind::External,
+        };
+
+        tree.set_utxo(&utxo).unwrap();
+
+        assert_eq!(tree.get_utxo(&outpoint).unwrap(), Some(utxo));
+    }
+
+    pub fn test_raw_tx<D: Database>(mut tree: D) {
+        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
+        let tx: Transaction = deserialize(&hex_tx).unwrap();
+
+        tree.set_raw_tx(&tx).unwrap();
+
+        let txid = tx.txid();
+
+        assert_eq!(tree.get_raw_tx(&txid).unwrap(), Some(tx));
+    }
+
+    pub fn test_tx<D: Database>(mut tree: D) {
+        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
+        let tx: Transaction = deserialize(&hex_tx).unwrap();
+        let txid = tx.txid();
+        let mut tx_details = TransactionDetails {
+            transaction: Some(tx),
+            txid,
+            timestamp: 123456,
+            received: 1337,
+            sent: 420420,
+            fees: 140,
+            height: Some(1000),
+        };
+
+        tree.set_tx(&tx_details).unwrap();
+
+        // get with raw tx too
+        assert_eq!(
+            tree.get_tx(&tx_details.txid, true).unwrap(),
+            Some(tx_details.clone())
+        );
+        // get only raw_tx
+        assert_eq!(
+            tree.get_raw_tx(&tx_details.txid).unwrap(),
+            tx_details.transaction
+        );
+
+        // now get without raw_tx
+        tx_details.transaction = None;
+        assert_eq!(
+            tree.get_tx(&tx_details.txid, false).unwrap(),
+            Some(tx_details)
+        );
+    }
+
+    pub fn test_last_index<D: Database>(mut tree: D) {
+        tree.set_last_index(KeychainKind::External, 1337).unwrap();
+
+        assert_eq!(
+            tree.get_last_index(KeychainKind::External).unwrap(),
+            Some(1337)
+        );
+        assert_eq!(tree.get_last_index(KeychainKind::Internal).unwrap(), None);
+
+        let res = tree.increment_last_index(KeychainKind::External).unwrap();
+        assert_eq!(res, 1338);
+        let res = tree.increment_last_index(KeychainKind::Internal).unwrap();
+        assert_eq!(res, 0);
+
+        assert_eq!(
+            tree.get_last_index(KeychainKind::External).unwrap(),
+            Some(1338)
+        );
+        assert_eq!(
+            tree.get_last_index(KeychainKind::Internal).unwrap(),
+            Some(0)
+        );
+    }
+
+    // TODO: more tests...
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/checksum.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/checksum.rs.html new file mode 100644 index 0000000000..d1a56388f4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/checksum.rs.html @@ -0,0 +1,258 @@ +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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Descriptor checksum
+//!
+//! This module contains a re-implementation of the function used by Bitcoin Core to calculate the
+//! checksum of a descriptor
+
+use std::iter::FromIterator;
+
+use crate::descriptor::Error;
+
+const INPUT_CHARSET: &str =  "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
+const CHECKSUM_CHARSET: &str = "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 of a descriptor
+pub fn get_checksum(desc: &str) -> Result<String, Error> {
+    let mut c = 1;
+    let mut cls = 0;
+    let mut clscount = 0;
+    for ch in desc.chars() {
+        let pos = INPUT_CHARSET
+            .find(ch)
+            .ok_or(Error::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 chars = Vec::with_capacity(8);
+    for j in 0..8 {
+        chars.push(
+            CHECKSUM_CHARSET
+                .chars()
+                .nth(((c >> (5 * (7 - j))) & 31) as usize)
+                .unwrap(),
+        );
+    }
+
+    Ok(String::from_iter(chars))
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use crate::descriptor::get_checksum;
+
+    // test get_checksum() function; it should return the same value as Bitcoin Core
+    #[test]
+    fn test_get_checksum() {
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)";
+        assert_eq!(get_checksum(desc).unwrap(), "tqz0nc62");
+
+        let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)";
+        assert_eq!(get_checksum(desc).unwrap(), "lasegmfs");
+    }
+
+    #[test]
+    fn test_get_checksum_invalid_character() {
+        let sparkle_heart = vec![240, 159, 146, 150];
+        let sparkle_heart = std::str::from_utf8(&sparkle_heart)
+            .unwrap()
+            .chars()
+            .next()
+            .unwrap();
+        let invalid_desc = format!("wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcL{}fjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)", sparkle_heart);
+
+        assert!(matches!(
+            get_checksum(&invalid_desc).err(),
+            Some(Error::InvalidDescriptorCharacter(invalid_char)) if invalid_char == sparkle_heart
+        ));
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/dsl.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/dsl.rs.html new file mode 100644 index 0000000000..418ef8e3ab --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/dsl.rs.html @@ -0,0 +1,1630 @@ +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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Descriptors DSL
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_top_level_sh {
+    // disallow `sortedmulti` in `bare()`
+    ( Bare, Bare, sortedmulti $( $inner:tt )* ) => {
+        compile_error!("`bare()` descriptors can't contain any `sortedmulti` operands");
+    };
+    ( Bare, Bare, sortedmulti_vec $( $inner:tt )* ) => {
+        compile_error!("`bare()` descriptors can't contain any `sortedmulti_vec` operands");
+    };
+
+    ( $descriptor_variant:ident, $sortedmulti_variant:ident, sortedmulti $( $inner:tt )* ) => {
+        $crate::impl_sortedmulti!(sortedmulti $( $inner )*)
+            .and_then(|(inner, key_map, valid_networks)| Ok(($crate::miniscript::Descriptor::$sortedmulti_variant(inner), key_map, valid_networks)))
+    };
+    ( $descriptor_variant:ident, $sortedmulti_variant:ident, sortedmulti_vec $( $inner:tt )* ) => {
+        $crate::impl_sortedmulti!(sortedmulti_vec $( $inner )*)
+            .and_then(|(inner, key_map, valid_networks)| Ok(($crate::miniscript::Descriptor::$sortedmulti_variant(inner), key_map, valid_networks)))
+    };
+
+    ( $descriptor_variant:ident, $sortedmulti_variant:ident, $( $minisc:tt )* ) => {
+        $crate::fragment!($( $minisc )*)
+            .map(|(minisc, keymap, networks)|($crate::miniscript::Descriptor::<$crate::miniscript::descriptor::DescriptorPublicKey>::$descriptor_variant(minisc), keymap, networks))
+    };
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_top_level_pk {
+    ( $descriptor_variant:ident, $ctx:ty, $key:expr ) => {{
+        #[allow(unused_imports)]
+        use $crate::keys::{DescriptorKey, ToDescriptorKey};
+        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
+
+        $key.to_descriptor_key()
+            .and_then(|key: DescriptorKey<$ctx>| key.extract(&secp))
+            .map(|(pk, key_map, valid_networks)| {
+                (
+                    $crate::miniscript::Descriptor::<
+                        $crate::miniscript::descriptor::DescriptorPublicKey,
+                    >::$descriptor_variant(pk),
+                    key_map,
+                    valid_networks,
+                )
+            })
+    }};
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_modifier {
+    ( $terminal_variant:ident, $( $inner:tt )* ) => {
+        $crate::fragment!($( $inner )*)
+            .map_err(|e| -> $crate::Error { e.into() })
+            .and_then(|(minisc, keymap, networks)| Ok(($crate::miniscript::Miniscript::from_ast($crate::miniscript::miniscript::decode::Terminal::$terminal_variant(std::sync::Arc::new(minisc)))?, keymap, networks)))
+    };
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_leaf_opcode {
+    ( $terminal_variant:ident ) => {
+        $crate::miniscript::Miniscript::from_ast(
+            $crate::miniscript::miniscript::decode::Terminal::$terminal_variant,
+        )
+        .map_err($crate::Error::Miniscript)
+        .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 ) => {
+        $crate::miniscript::Miniscript::from_ast(
+            $crate::miniscript::miniscript::decode::Terminal::$terminal_variant($value),
+        )
+        .map_err($crate::Error::Miniscript)
+        .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 ) => {
+        $crate::miniscript::Miniscript::from_ast(
+            $crate::miniscript::miniscript::decode::Terminal::$terminal_variant($one, $two),
+        )
+        .map_err($crate::Error::Miniscript)
+        .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, ( $( $a:tt )* ), ( $( $b:tt )* ) ) => {
+        $crate::fragment!($( $a )*)
+            .and_then(|a| Ok((a, $crate::fragment!($( $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());
+
+                Ok(($crate::miniscript::Miniscript::from_ast($crate::miniscript::miniscript::decode::Terminal::$terminal_variant(
+                    std::sync::Arc::new(a_minisc),
+                    std::sync::Arc::new(b_minisc),
+                ))?, a_keymap, $crate::keys::merge_networks(&a_networks, &b_networks)))
+            })
+    };
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_node_opcode_three {
+    ( $terminal_variant:ident, ( $( $a:tt )* ), ( $( $b:tt )* ), ( $( $c:tt )* ) ) => {
+        $crate::fragment!($( $a )*)
+            .and_then(|a| Ok((a, $crate::fragment!($( $b )*)?, $crate::fragment!($( $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);
+
+                Ok(($crate::miniscript::Miniscript::from_ast($crate::miniscript::miniscript::decode::Terminal::$terminal_variant(
+                    std::sync::Arc::new(a_minisc),
+                    std::sync::Arc::new(b_minisc),
+                    std::sync::Arc::new(c_minisc),
+                ))?, a_keymap, networks))
+            })
+    };
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! impl_sortedmulti {
+    ( sortedmulti_vec $thresh:expr, $keys:expr ) => ({
+        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
+        $crate::keys::make_sortedmulti_inner($thresh, $keys, &secp)
+    });
+    ( sortedmulti $thresh:expr $(, $key:expr )+ ) => ({
+        use $crate::keys::ToDescriptorKey;
+        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
+
+        let mut keys = vec![];
+        $(
+            keys.push($key.to_descriptor_key());
+        )*
+
+        keys.into_iter().collect::<Result<Vec<_>, _>>()
+            .and_then(|keys| $crate::keys::make_sortedmulti_inner($thresh, keys, &secp))
+    });
+
+}
+
+/// Macro to write full descriptors with code
+///
+/// This macro expands to a `Result` of
+/// [`DescriptorTemplateOut`](super::template::DescriptorTemplateOut) and [`Error`](crate::Error)
+///
+/// ## Example
+///
+/// Signature plus timelock, equivalent to: `sh(wsh(and_v(v:pk(...), older(...))))`
+///
+/// ```
+/// # use std::str::FromStr;
+/// let my_key = bitcoin::PublicKey::from_str("02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c")?;
+/// let my_timelock = 50;
+/// let (my_descriptor, my_keys_map, networks) = bdk::descriptor!(sh ( wsh ( and_v (+v pk my_key), ( older my_timelock ))))?;
+/// # 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(...),sdv: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+d+v older my_timelock)
+///     )
+/// }?;
+///
+/// let b_items = vec![
+///     bdk::fragment!(pk my_key_1)?,
+///     bdk::fragment!(+s pk my_key_2)?,
+///     bdk::fragment!(+s+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>>(())
+/// ```
+#[macro_export]
+macro_rules! descriptor {
+    ( bare ( $( $minisc:tt )* ) ) => ({
+        $crate::impl_top_level_sh!(Bare, Bare, $( $minisc )*)
+    });
+    ( sh ( wsh ( $( $minisc:tt )* ) ) ) => ({
+        $crate::descriptor!(shwsh ($( $minisc )*))
+    });
+    ( shwsh ( $( $minisc:tt )* ) ) => ({
+        $crate::impl_top_level_sh!(ShWsh, ShWshSortedMulti, $( $minisc )*)
+    });
+    ( pk $key:expr ) => ({
+        $crate::impl_top_level_pk!(Pk, $crate::miniscript::Legacy, $key)
+    });
+    ( pkh $key:expr ) => ({
+        $crate::impl_top_level_pk!(Pkh,$crate::miniscript::Legacy, $key)
+    });
+    ( wpkh $key:expr ) => ({
+        $crate::impl_top_level_pk!(Wpkh, $crate::miniscript::Segwitv0, $key)
+    });
+    ( sh ( wpkh ( $key:expr ) ) ) => ({
+        $crate::descriptor!(shwpkh ( $key ))
+    });
+    ( shwpkh ( $key:expr ) ) => ({
+        $crate::impl_top_level_pk!(ShWpkh, $crate::miniscript::Segwitv0, $key)
+    });
+    ( sh ( $( $minisc:tt )* ) ) => ({
+        $crate::impl_top_level_sh!(Sh, ShSortedMulti, $( $minisc )*)
+    });
+    ( wsh ( $( $minisc:tt )* ) ) => ({
+        $crate::impl_top_level_sh!(Wsh, WshSortedMulti, $( $minisc )*)
+    });
+}
+
+/// Macro to write descriptor fragments with code
+///
+/// This macro will be expanded to an object of type `Result<(Miniscript<DescriptorPublicKey, _>, KeyMap, ValidNetworks), Error>`. It allows writing
+/// fragments of larger descriptors that can be pieced together using `fragment!(thresh_vec ...)`.
+#[macro_export]
+macro_rules! fragment {
+    // Modifiers
+    ( +a $( $inner:tt )* ) => ({
+        $crate::impl_modifier!(Alt, $( $inner )*)
+    });
+    ( +s $( $inner:tt )* ) => ({
+        $crate::impl_modifier!(Swap, $( $inner )*)
+    });
+    ( +c $( $inner:tt )* ) => ({
+        $crate::impl_modifier!(Check, $( $inner )*)
+    });
+    ( +d $( $inner:tt )* ) => ({
+        $crate::impl_modifier!(DupIf, $( $inner )*)
+    });
+    ( +v $( $inner:tt )* ) => ({
+        $crate::impl_modifier!(Verify, $( $inner )*)
+    });
+    ( +j $( $inner:tt )* ) => ({
+        $crate::impl_modifier!(NonZero, $( $inner )*)
+    });
+    ( +n $( $inner:tt )* ) => ({
+        $crate::impl_modifier!(ZeroNotEqual, $( $inner )*)
+    });
+    ( +t $( $inner:tt )* ) => ({
+        $crate::fragment!(and_v ( $( $inner )* ), ( true ) )
+    });
+    ( +l $( $inner:tt )* ) => ({
+        $crate::fragment!(or_i ( false ), ( $( $inner )* ) )
+    });
+    ( +u $( $inner:tt )* ) => ({
+        $crate::fragment!(or_i ( $( $inner )* ), ( false ) )
+    });
+
+    // 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_hash:expr ) => ({
+        $crate::impl_leaf_opcode_value!(PkH, $key_hash)
+    });
+    ( after $value:expr ) => ({
+        $crate::impl_leaf_opcode_value!(After, $value)
+    });
+    ( older $value:expr ) => ({
+        $crate::impl_leaf_opcode_value!(Older, $value)
+    });
+    ( 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 ( $( $a:tt )* ), ( $( $b:tt )* ) ) => ({
+        $crate::impl_node_opcode_two!(AndV, ( $( $a )* ), ( $( $b )* ))
+    });
+    ( and_b ( $( $a:tt )* ), ( $( $b:tt )* ) ) => ({
+        $crate::impl_node_opcode_two!(AndB, ( $( $a )* ), ( $( $b )* ))
+    });
+    ( and_or ( $( $a:tt )* ), ( $( $b:tt )* ), ( $( $c:tt )* ) ) => ({
+        $crate::impl_node_opcode_three!(AndOr, ( $( $a )* ), ( $( $b )* ), ( $( $c )* ))
+    });
+    ( or_b ( $( $a:tt )* ), ( $( $b:tt )* ) ) => ({
+        $crate::impl_node_opcode_two!(OrB, ( $( $a )* ), ( $( $b )* ))
+    });
+    ( or_d ( $( $a:tt )* ), ( $( $b:tt )* ) ) => ({
+        $crate::impl_node_opcode_two!(OrD, ( $( $a )* ), ( $( $b )* ))
+    });
+    ( or_c ( $( $a:tt )* ), ( $( $b:tt )* ) ) => ({
+        $crate::impl_node_opcode_two!(OrC, ( $( $a )* ), ( $( $b )* ))
+    });
+    ( or_i ( $( $a:tt )* ), ( $( $b:tt )* ) ) => ({
+        $crate::impl_node_opcode_two!(OrI, ( $( $a )* ), ( $( $b )* ))
+    });
+    ( thresh_vec $thresh:expr, $items:expr ) => ({
+        use $crate::miniscript::descriptor::KeyMap;
+
+        let (items, key_maps_networks): (Vec<_>, Vec<_>) = $items.into_iter().map(|(a, b, c)| (a, (b, c))).unzip();
+        let items = items.into_iter().map(std::sync::Arc::new).collect();
+
+        let (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 $(, ( $( $item:tt )* ) )+ ) => ({
+        let mut items = vec![];
+        $(
+            items.push($crate::fragment!($( $item )*));
+        )*
+
+        items.into_iter().collect::<Result<Vec<_>, _>>()
+            .and_then(|items| $crate::fragment!(thresh_vec $thresh, items))
+    });
+    ( multi_vec $thresh:expr, $keys:expr ) => ({
+        $crate::keys::make_multi($thresh, $keys)
+    });
+    ( multi $thresh:expr $(, $key:expr )+ ) => ({
+        use $crate::keys::ToDescriptorKey;
+        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
+
+        let mut keys = vec![];
+        $(
+            keys.push($key.to_descriptor_key());
+        )*
+
+        keys.into_iter().collect::<Result<Vec<_>, _>>()
+            .and_then(|keys| $crate::keys::make_multi($thresh, keys, &secp))
+    });
+
+    // `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 bitcoin::hashes::hex::ToHex;
+    use bitcoin::secp256k1::Secp256k1;
+    use miniscript::descriptor::{DescriptorPublicKey, DescriptorPublicKeyCtx, KeyMap};
+    use miniscript::{Descriptor, Legacy, Segwitv0};
+
+    use std::str::FromStr;
+
+    use crate::descriptor::DescriptorMeta;
+    use crate::keys::{DescriptorKey, KeyError, ToDescriptorKey, ValidNetworks};
+    use bitcoin::network::constants::Network::{Bitcoin, Regtest, Testnet};
+    use bitcoin::util::bip32;
+    use bitcoin::util::bip32::ChildNumber;
+
+    // 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), KeyError>,
+        is_witness: bool,
+        is_fixed: bool,
+        expected: &[&str],
+    ) {
+        let secp = Secp256k1::new();
+        let deriv_ctx = DescriptorPublicKeyCtx::new(&secp, ChildNumber::Normal { index: 0 });
+
+        let (desc, _key_map, _networks) = desc.unwrap();
+        assert_eq!(desc.is_witness(), is_witness);
+        assert_eq!(desc.is_fixed(), is_fixed);
+        for i in 0..expected.len() {
+            let index = i as u32;
+            let child_desc = if desc.is_fixed() {
+                desc.clone()
+            } else {
+                desc.derive(ChildNumber::from_normal_idx(index).unwrap())
+            };
+            let address = child_desc.address(Regtest, deriv_ctx);
+            if let Some(address) = address {
+                assert_eq!(address.to_string(), *expected.get(i).unwrap());
+            } else {
+                let script = child_desc.script_pubkey(deriv_ctx);
+                assert_eq!(script.to_hex().as_str(), *expected.get(i).unwrap());
+            }
+        }
+    }
+
+    // - at least one of each "type" of operator; ie. one modifier, one leaf_opcode, one leaf_opcode_value, etc.
+    // - mixing up key types that implement ToDescriptorKey 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_bip32_legacy_descriptors() {
+        let xprv = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+
+        let path = bip32::DerivationPath::from_str("m/0").unwrap();
+        let desc_key = (xprv, path.clone()).to_descriptor_key().unwrap();
+        check(
+            descriptor!(pk(desc_key)),
+            false,
+            false,
+            &[
+                "2102363ad03c10024e1b597a5b01b9982807fb638e00b06f3b2d4a89707de3b93c37ac",
+                "2102063a21fd780df370ed2fc8c4b86aa5ea642630609c203009df631feb7b480dd2ac",
+                "2102ba2685ad1fa5891cb100f1656b2ce3801822ccb9bac0336734a6f8c1b93ebbc0ac",
+            ],
+        );
+
+        let desc_key = (xprv, path.clone()).to_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).to_descriptor_key().unwrap();
+        let desc_key2 = (xprv, path2).to_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::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+
+        let path = bip32::DerivationPath::from_str("m/0").unwrap();
+        let desc_key = (xprv, path.clone()).to_descriptor_key().unwrap();
+        check(
+            descriptor!(wpkh(desc_key)),
+            true,
+            false,
+            &[
+                "bcrt1qnhm8w9fhc8cxzgqsmqdf9fyjccyvc0gltnymu0",
+                "bcrt1qhylfd55rn75w9fj06zspctad5w4hz33rf0ttad",
+                "bcrt1qq5sq3a6k9av9d8cne0k9wcldy4nqey5yt6889r",
+            ],
+        );
+
+        let desc_key = (xprv, path.clone()).to_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()).to_descriptor_key().unwrap();
+        let desc_key2 = (xprv, path2.clone()).to_descriptor_key().unwrap();
+        check(
+            descriptor!(wsh(multi 1,desc_key1,desc_key2)),
+            true,
+            false,
+            &[
+                "bcrt1qfxv8mxmlv5sz8q2mnuyaqdfe9jr4vvmx0csjhn092p6f4qfygfkq2hng49",
+                "bcrt1qerj85g243e6jlcdxpmn9spk0gefcwvu7nw7ee059d5ydzpdhkm2qwfkf5k",
+                "bcrt1qxkl2qss3k58q9ktc8e89pwr4gnptfpw4hju4xstxcjc0hkcae3jstluty7",
+            ],
+        );
+
+        let desc_key1 = (xprv, path).to_descriptor_key().unwrap();
+        let desc_key2 = (xprv, path2).to_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::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        let path_1 = bip32::DerivationPath::from_str("m/0").unwrap();
+
+        let key_2 = bip32::ExtendedPrivKey::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::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        let path = bip32::DerivationPath::from_str("m/0").unwrap();
+        let desc_key = (xprv, path.clone()).to_descriptor_key().unwrap();
+
+        let (_desc, _key_map, valid_networks) = descriptor!(pkh(desc_key)).unwrap();
+        assert_eq!(valid_networks, [Testnet, Regtest].iter().cloned().collect());
+
+        let xprv = bip32::ExtendedPrivKey::from_str("xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi").unwrap();
+        let path = bip32::DerivationPath::from_str("m/10/20/30/40").unwrap();
+        let desc_key = (xprv, path.clone()).to_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::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        let path1 = bip32::DerivationPath::from_str("m/0").unwrap();
+        let desc_key1 = (xprv1, path1.clone()).to_descriptor_key().unwrap();
+
+        let xprv2 = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF").unwrap();
+        let path2 = bip32::DerivationPath::from_str("m/2147483647'/0").unwrap();
+        let desc_key2 = (xprv2, path2.clone()).to_descriptor_key().unwrap();
+
+        let xprv3 = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf").unwrap();
+        let path3 = bip32::DerivationPath::from_str("m/10/20/30/40").unwrap();
+        let desc_key3 = (xprv3, path3.clone()).to_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.clone()).to_descriptor_key().unwrap();
+        let desc_key2: DescriptorKey<Segwitv0> =
+            (xprv2, path2.clone()).to_descriptor_key().unwrap();
+        let desc_key3: DescriptorKey<Segwitv0> =
+            (xprv3, path3.clone()).to_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 ToDescriptorKey<Segwitv0> to a pkh() descriptor should throw a compilation error
+    #[test]
+    fn test_script_context_validation() {
+        // this compiles
+        let xprv = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        let path = bip32::DerivationPath::from_str("m/0").unwrap();
+        let desc_key: DescriptorKey<Legacy> = (xprv, path.clone()).to_descriptor_key().unwrap();
+
+        let (desc, _key_map, _valid_networks) = descriptor!(pkh(desc_key)).unwrap();
+        assert_eq!(desc.to_string(), "pkh(tpubD6NzVbkrYhZ4WR7a4vY1VT3khMJMeAxVsfq9TBJyJWrNk247zCJtV7AWf6UJP7rAVsn8NNKdJi3gFyKPTmWZS9iukb91xbn2HbFSMQm2igY/0/*)");
+
+        // as expected this does not compile due to invalid context
+        //let desc_key:DescriptorKey<Segwitv0> = (xprv, path.clone()).to_descriptor_key().unwrap();
+        //let (desc, _key_map, _valid_networks) = descriptor!(pkh(desc_key)).unwrap();
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/error.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/error.rs.html new file mode 100644 index 0000000000..2472440c46 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/error.rs.html @@ -0,0 +1,176 @@ +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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Descriptor errors
+
+/// Errors related to the parsing and usage of descriptors
+#[derive(Debug)]
+pub enum Error {
+    //InternalError,
+    //InvalidPrefix(Vec<u8>),
+    //HardenedDerivationOnXpub,
+    //MalformedInput,
+    /// Invalid HD Key path, such as having a wildcard but a length != 1
+    InvalidHDKeyPath,
+
+    //KeyParsingError(String),
+    /// Error thrown while working with [`keys`](crate::keys)
+    Key(crate::keys::KeyError),
+    /// Error while extracting and manipulating policies
+    Policy(crate::descriptor::policy::PolicyError),
+
+    //InputIndexDoesntExist,
+    //MissingPublicKey,
+    //MissingDetails,
+    /// Invalid character found in the descriptor checksum
+    InvalidDescriptorCharacter(char),
+
+    //CantDeriveWithMiniscript,
+    /// BIP32 error
+    BIP32(bitcoin::util::bip32::Error),
+    /// Error during base58 decoding
+    Base58(bitcoin::util::base58::Error),
+    /// Key-related error
+    PK(bitcoin::util::key::Error),
+    /// Miniscript error
+    Miniscript(miniscript::Error),
+    /// Hex decoding error
+    Hex(bitcoin::hashes::hex::Error),
+}
+
+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 std::fmt::Display for Error {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for Error {}
+
+impl_error!(bitcoin::util::bip32::Error, BIP32);
+impl_error!(bitcoin::util::base58::Error, Base58);
+impl_error!(bitcoin::util::key::Error, PK);
+impl_error!(miniscript::Error, Miniscript);
+impl_error!(bitcoin::hashes::hex::Error, Hex);
+impl_error!(crate::descriptor::policy::PolicyError, Policy);
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/mod.rs.html new file mode 100644 index 0000000000..22803d1c76 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/mod.rs.html @@ -0,0 +1,1560 @@ +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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Descriptors
+//!
+//! This module contains generic utilities to work with descriptors, plus some re-exported types
+//! from [`miniscript`].
+
+use std::collections::{BTreeMap, HashMap};
+use std::fmt;
+
+use bitcoin::secp256k1::Secp256k1;
+use bitcoin::util::bip32::{ChildNumber, DerivationPath, ExtendedPubKey, Fingerprint, KeySource};
+use bitcoin::util::psbt;
+use bitcoin::{Network, PublicKey, Script, TxOut};
+
+use miniscript::descriptor::{DescriptorPublicKey, DescriptorXKey, InnerXKey};
+pub use miniscript::{
+    descriptor::KeyMap, Descriptor, Legacy, Miniscript, MiniscriptKey, ScriptContext, Segwitv0,
+    Terminal, ToPublicKey,
+};
+
+pub mod checksum;
+mod dsl;
+pub mod error;
+pub mod policy;
+pub mod template;
+
+pub use self::checksum::get_checksum;
+use self::error::Error;
+pub use self::policy::Policy;
+use self::template::DescriptorTemplateOut;
+use crate::keys::{KeyError, ToDescriptorKey};
+use crate::wallet::signer::SignersContainer;
+use crate::wallet::utils::{descriptor_to_pk_ctx, SecpCtx};
+
+/// Alias for a [`Descriptor`] that can contain extended keys using [`DescriptorPublicKey`]
+pub type ExtendedDescriptor = Descriptor<DescriptorPublicKey>;
+
+/// Alias for the type of maps that represent derivation paths in a [`psbt::Input`] or
+/// [`psbt::Output`]
+///
+/// [`psbt::Input`]: bitcoin::util::psbt::Input
+/// [`psbt::Output`]: bitcoin::util::psbt::Output
+pub type HDKeyPaths = BTreeMap<PublicKey, KeySource>;
+
+/// Trait for types which can be converted into an [`ExtendedDescriptor`] and a [`KeyMap`] usable by a wallet in a specific [`Network`]
+pub trait ToWalletDescriptor {
+    /// Convert to wallet descriptor
+    fn to_wallet_descriptor(
+        self,
+        network: Network,
+    ) -> Result<(ExtendedDescriptor, KeyMap), KeyError>;
+}
+
+impl ToWalletDescriptor for &str {
+    fn to_wallet_descriptor(
+        self,
+        network: Network,
+    ) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
+        let descriptor = if self.contains('#') {
+            let parts: Vec<&str> = self.splitn(2, '#').collect();
+            if !get_checksum(parts[0])
+                .ok()
+                .map(|computed| computed == parts[1])
+                .unwrap_or(false)
+            {
+                return Err(KeyError::InvalidChecksum);
+            }
+
+            parts[0]
+        } else {
+            self
+        };
+
+        ExtendedDescriptor::parse_descriptor(descriptor)?.to_wallet_descriptor(network)
+    }
+}
+
+impl ToWalletDescriptor for &String {
+    fn to_wallet_descriptor(
+        self,
+        network: Network,
+    ) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
+        self.as_str().to_wallet_descriptor(network)
+    }
+}
+
+impl ToWalletDescriptor for ExtendedDescriptor {
+    fn to_wallet_descriptor(
+        self,
+        network: Network,
+    ) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
+        (self, KeyMap::default()).to_wallet_descriptor(network)
+    }
+}
+
+impl ToWalletDescriptor for (ExtendedDescriptor, KeyMap) {
+    fn to_wallet_descriptor(
+        self,
+        network: Network,
+    ) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
+        use crate::keys::DescriptorKey;
+
+        let secp = Secp256k1::new();
+
+        let check_key = |pk: &DescriptorPublicKey| {
+            let (pk, _, networks) = if self.0.is_witness() {
+                let desciptor_key: DescriptorKey<miniscript::Segwitv0> =
+                    pk.clone().to_descriptor_key()?;
+                desciptor_key.extract(&secp)?
+            } else {
+                let desciptor_key: DescriptorKey<miniscript::Legacy> =
+                    pk.clone().to_descriptor_key()?;
+                desciptor_key.extract(&secp)?
+            };
+
+            if networks.contains(&network) {
+                Ok(pk)
+            } else {
+                Err(KeyError::InvalidNetwork)
+            }
+        };
+
+        // check the network for the keys
+        let translated = self.0.translate_pk(check_key, check_key)?;
+
+        Ok((translated, self.1))
+    }
+}
+
+impl ToWalletDescriptor for DescriptorTemplateOut {
+    fn to_wallet_descriptor(
+        self,
+        network: Network,
+    ) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
+        let valid_networks = &self.2;
+
+        let fix_key = |pk: &DescriptorPublicKey| {
+            if valid_networks.contains(&network) {
+                // 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 = network;
+
+                        DescriptorPublicKey::XPub(xpub)
+                    }
+                    other => other.clone(),
+                };
+
+                Ok(pk)
+            } else {
+                Err(KeyError::InvalidNetwork)
+            }
+        };
+
+        // fixup the network for keys that need it
+        let translated = self.0.translate_pk(fix_key, fix_key)?;
+
+        Ok((translated, self.1))
+    }
+}
+
+/// 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,
+        secp: &SecpCtx,
+    ) -> Result<Option<Policy>, Error>;
+}
+
+pub(crate) trait XKeyUtils {
+    fn full_path(&self, append: &[ChildNumber]) -> DerivationPath;
+    fn root_fingerprint(&self, secp: &SecpCtx) -> Fingerprint;
+}
+
+impl<K: InnerXKey> XKeyUtils for DescriptorXKey<K> {
+    fn full_path(&self, append: &[ChildNumber]) -> DerivationPath {
+        let full_path = match self.origin {
+            Some((_, ref path)) => path
+                .into_iter()
+                .chain(self.derivation_path.into_iter())
+                .cloned()
+                .collect(),
+            None => self.derivation_path.clone(),
+        };
+
+        if self.is_wildcard {
+            full_path
+                .into_iter()
+                .chain(append.iter())
+                .cloned()
+                .collect()
+        } else {
+            full_path
+        }
+    }
+
+    fn root_fingerprint(&self, secp: &SecpCtx) -> Fingerprint {
+        match self.origin {
+            Some((fingerprint, _)) => fingerprint,
+            None => self.xkey.xkey_fingerprint(secp),
+        }
+    }
+}
+
+pub(crate) trait DescriptorMeta: Sized {
+    fn is_witness(&self) -> bool;
+    fn get_hd_keypaths(&self, index: u32, secp: &SecpCtx) -> Result<HDKeyPaths, Error>;
+    fn get_extended_keys(&self) -> Result<Vec<DescriptorXKey<ExtendedPubKey>>, Error>;
+    fn is_fixed(&self) -> bool;
+    fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths, secp: &SecpCtx) -> Option<Self>;
+    fn derive_from_psbt_input(
+        &self,
+        psbt_input: &psbt::Input,
+        utxo: Option<TxOut>,
+        secp: &SecpCtx,
+    ) -> Option<Self>;
+}
+
+pub(crate) trait DescriptorScripts {
+    fn psbt_redeem_script(&self, secp: &SecpCtx) -> Option<Script>;
+    fn psbt_witness_script(&self, secp: &SecpCtx) -> Option<Script>;
+}
+
+impl DescriptorScripts for Descriptor<DescriptorPublicKey> {
+    fn psbt_redeem_script(&self, secp: &SecpCtx) -> Option<Script> {
+        let deriv_ctx = descriptor_to_pk_ctx(secp);
+
+        match self {
+            Descriptor::ShWpkh(_) => Some(self.witness_script(deriv_ctx)),
+            Descriptor::ShWsh(ref script) => Some(script.encode(deriv_ctx).to_v0_p2wsh()),
+            Descriptor::Sh(ref script) => Some(script.encode(deriv_ctx)),
+            Descriptor::Bare(ref script) => Some(script.encode(deriv_ctx)),
+            Descriptor::ShSortedMulti(ref keys) => Some(keys.encode(deriv_ctx)),
+            _ => None,
+        }
+    }
+
+    fn psbt_witness_script(&self, secp: &SecpCtx) -> Option<Script> {
+        let deriv_ctx = descriptor_to_pk_ctx(secp);
+
+        match self {
+            Descriptor::Wsh(ref script) => Some(script.encode(deriv_ctx)),
+            Descriptor::ShWsh(ref script) => Some(script.encode(deriv_ctx)),
+            Descriptor::WshSortedMulti(ref keys) | Descriptor::ShWshSortedMulti(ref keys) => {
+                Some(keys.encode(deriv_ctx))
+            }
+            _ => None,
+        }
+    }
+}
+
+impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
+    fn is_witness(&self) -> bool {
+        match self {
+            Descriptor::Bare(_)
+            | Descriptor::Pk(_)
+            | Descriptor::Pkh(_)
+            | Descriptor::Sh(_)
+            | Descriptor::ShSortedMulti(_) => false,
+            Descriptor::Wpkh(_)
+            | Descriptor::ShWpkh(_)
+            | Descriptor::Wsh(_)
+            | Descriptor::ShWsh(_)
+            | Descriptor::ShWshSortedMulti(_)
+            | Descriptor::WshSortedMulti(_) => true,
+        }
+    }
+
+    fn get_hd_keypaths(&self, index: u32, secp: &SecpCtx) -> Result<HDKeyPaths, Error> {
+        let translate_key = |key: &DescriptorPublicKey,
+                             index: u32,
+                             paths: &mut HDKeyPaths|
+         -> Result<DummyKey, Error> {
+            match key {
+                DescriptorPublicKey::SinglePub(_) => {}
+                DescriptorPublicKey::XPub(xpub) => {
+                    let derive_path = if xpub.is_wildcard {
+                        xpub.derivation_path
+                            .into_iter()
+                            .chain([ChildNumber::from_normal_idx(index)?].iter())
+                            .cloned()
+                            .collect()
+                    } else {
+                        xpub.derivation_path.clone()
+                    };
+                    let derived_pubkey = xpub
+                        .xkey
+                        .derive_pub(&Secp256k1::verification_only(), &derive_path)?;
+
+                    paths.insert(
+                        derived_pubkey.public_key,
+                        (
+                            xpub.root_fingerprint(secp),
+                            xpub.full_path(&[ChildNumber::from_normal_idx(index)?]),
+                        ),
+                    );
+                }
+            }
+
+            Ok(DummyKey::default())
+        };
+
+        let mut answer_pk = BTreeMap::new();
+        let mut answer_pkh = BTreeMap::new();
+
+        self.translate_pk(
+            |pk| translate_key(pk, index, &mut answer_pk),
+            |pkh| translate_key(pkh, index, &mut answer_pkh),
+        )?;
+
+        answer_pk.append(&mut answer_pkh);
+
+        Ok(answer_pk)
+    }
+
+    fn get_extended_keys(&self) -> Result<Vec<DescriptorXKey<ExtendedPubKey>>, Error> {
+        let get_key = |key: &DescriptorPublicKey,
+                       keys: &mut Vec<DescriptorXKey<ExtendedPubKey>>|
+         -> Result<DummyKey, Error> {
+            if let DescriptorPublicKey::XPub(xpub) = key {
+                keys.push(xpub.clone())
+            }
+
+            Ok(DummyKey::default())
+        };
+
+        let mut answer_pk = Vec::new();
+        let mut answer_pkh = Vec::new();
+
+        self.translate_pk(
+            |pk| get_key(pk, &mut answer_pk),
+            |pkh| get_key(pkh, &mut answer_pkh),
+        )?;
+
+        answer_pk.append(&mut answer_pkh);
+
+        Ok(answer_pk)
+    }
+
+    fn is_fixed(&self) -> bool {
+        fn check_key(key: &DescriptorPublicKey, flag: &mut bool) -> Result<DummyKey, Error> {
+            match key {
+                DescriptorPublicKey::SinglePub(_) => {}
+                DescriptorPublicKey::XPub(xpub) => {
+                    if xpub.is_wildcard {
+                        *flag = true;
+                    }
+                }
+            }
+
+            Ok(DummyKey::default())
+        }
+
+        let mut found_wildcard_pk = false;
+        let mut found_wildcard_pkh = false;
+
+        self.translate_pk(
+            |pk| check_key(pk, &mut found_wildcard_pk),
+            |pkh| check_key(pkh, &mut found_wildcard_pkh),
+        )
+        .unwrap();
+
+        !found_wildcard_pk && !found_wildcard_pkh
+    }
+
+    fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths, secp: &SecpCtx) -> Option<Self> {
+        let try_key = |key: &DescriptorPublicKey,
+                       index: &HashMap<Fingerprint, DerivationPath>,
+                       found_path: &mut Option<ChildNumber>|
+         -> Result<DummyKey, Error> {
+            if found_path.is_some() {
+                // already found a matching path, we are done
+                return Ok(DummyKey::default());
+            }
+
+            if let DescriptorPublicKey::XPub(xpub) = key {
+                // Check if the key matches one entry in our `index`. If it does, `matches()` will
+                // return the "prefix" that matched, so we remove that prefix from the full path
+                // found in `index` 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 derivation_path: Option<Vec<ChildNumber>> = index
+                    .get_key_value(&root_fingerprint)
+                    .and_then(|(fingerprint, path)| {
+                        xpub.matches(&(*fingerprint, path.clone()), secp)
+                    })
+                    .map(|prefix| {
+                        index
+                            .get(&xpub.root_fingerprint(secp))
+                            .unwrap()
+                            .into_iter()
+                            .skip(prefix.into_iter().count())
+                            .cloned()
+                            .collect()
+                    });
+
+                match derivation_path {
+                    Some(path) if xpub.is_wildcard && path.len() == 1 => {
+                        *found_path = Some(path[0])
+                    }
+                    Some(path) if !xpub.is_wildcard && path.is_empty() => {
+                        *found_path = Some(ChildNumber::Normal { index: 0 })
+                    }
+                    Some(_) => return Err(Error::InvalidHDKeyPath),
+                    _ => {}
+                }
+            }
+
+            Ok(DummyKey::default())
+        };
+
+        let index: HashMap<_, _> = hd_keypaths.values().cloned().collect();
+
+        let mut found_path_pk = None;
+        let mut found_path_pkh = None;
+
+        if self
+            .translate_pk(
+                |pk| try_key(pk, &index, &mut found_path_pk),
+                |pkh| try_key(pkh, &index, &mut found_path_pkh),
+            )
+            .is_err()
+        {
+            return None;
+        }
+
+        // if we have found a path for both `found_path_pk` and `found_path_pkh` but they are
+        // different we consider this an error and return None. we only return a path either if
+        // they are equal or if only one of them is Some(_)
+        let merged_path = match (found_path_pk, found_path_pkh) {
+            (Some(a), Some(b)) if a != b => return None,
+            (a, b) => a.or(b),
+        };
+
+        merged_path.map(|path| self.derive(path))
+    }
+
+    fn derive_from_psbt_input(
+        &self,
+        psbt_input: &psbt::Input,
+        utxo: Option<TxOut>,
+        secp: &SecpCtx,
+    ) -> Option<Self> {
+        if let Some(derived) = self.derive_from_hd_keypaths(&psbt_input.hd_keypaths, secp) {
+            return Some(derived);
+        } else if !self.is_fixed() {
+            // If the descriptor is not fixed we can't brute-force the derivation address, so just
+            // exit here
+            return None;
+        }
+
+        let deriv_ctx = descriptor_to_pk_ctx(secp);
+        match self {
+            Descriptor::Pk(_)
+            | Descriptor::Pkh(_)
+            | Descriptor::Wpkh(_)
+            | Descriptor::ShWpkh(_)
+                if utxo.is_some()
+                    && self.script_pubkey(deriv_ctx) == utxo.as_ref().unwrap().script_pubkey =>
+            {
+                Some(self.clone())
+            }
+            Descriptor::Bare(ms)
+                if psbt_input.redeem_script.is_some()
+                    && &ms.encode(deriv_ctx) == psbt_input.redeem_script.as_ref().unwrap() =>
+            {
+                Some(self.clone())
+            }
+            Descriptor::Sh(ms)
+                if psbt_input.redeem_script.is_some()
+                    && &ms.encode(deriv_ctx) == psbt_input.redeem_script.as_ref().unwrap() =>
+            {
+                Some(self.clone())
+            }
+            Descriptor::Wsh(ms) | Descriptor::ShWsh(ms)
+                if psbt_input.witness_script.is_some()
+                    && &ms.encode(deriv_ctx) == psbt_input.witness_script.as_ref().unwrap() =>
+            {
+                Some(self.clone())
+            }
+            Descriptor::ShSortedMulti(keys)
+                if psbt_input.redeem_script.is_some()
+                    && &keys.encode(deriv_ctx) == psbt_input.redeem_script.as_ref().unwrap() =>
+            {
+                Some(self.clone())
+            }
+            Descriptor::WshSortedMulti(keys) | Descriptor::ShWshSortedMulti(keys)
+                if psbt_input.witness_script.is_some()
+                    && &keys.encode(deriv_ctx) == psbt_input.witness_script.as_ref().unwrap() =>
+            {
+                Some(self.clone())
+            }
+            _ => None,
+        }
+    }
+}
+
+#[derive(Debug, Clone, Hash, PartialEq, PartialOrd, Eq, Ord, Default)]
+struct DummyKey();
+
+impl fmt::Display for DummyKey {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "DummyKey")
+    }
+}
+
+impl std::str::FromStr for DummyKey {
+    type Err = ();
+
+    fn from_str(_: &str) -> Result<Self, Self::Err> {
+        Ok(DummyKey::default())
+    }
+}
+
+impl miniscript::MiniscriptKey for DummyKey {
+    type Hash = DummyKey;
+
+    fn to_pubkeyhash(&self) -> DummyKey {
+        DummyKey::default()
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::str::FromStr;
+
+    use bitcoin::consensus::encode::deserialize;
+    use bitcoin::hashes::hex::FromHex;
+    use bitcoin::secp256k1::Secp256k1;
+    use bitcoin::util::{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::PartiallySignedTransaction = 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::PartiallySignedTransaction = 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::PartiallySignedTransaction = 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::PartiallySignedTransaction = 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, ToDescriptorKey};
+
+        let xpub = bip32::ExtendedPubKey::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").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 = (xpub, path).to_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 conver the key that supports "any_network" to the right network (testnet)
+        let (wallet_desc, _) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
+
+        assert_eq!(wallet_desc.to_string(), "wpkh(tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)");
+    }
+
+    // test ToWalletDescriptor trait from &str with and without checksum appended
+    #[test]
+    fn test_descriptor_from_str_with_checksum() {
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#tqz0nc62"
+            .to_wallet_descriptor(Network::Testnet);
+        assert!(desc.is_ok());
+
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
+            .to_wallet_descriptor(Network::Testnet);
+        assert!(desc.is_ok());
+
+        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)#67ju93jw"
+            .to_wallet_descriptor(Network::Testnet);
+        assert!(desc.is_ok());
+
+        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
+            .to_wallet_descriptor(Network::Testnet);
+        assert!(desc.is_ok());
+
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#67ju93jw"
+            .to_wallet_descriptor(Network::Testnet);
+        assert!(matches!(desc.err(), Some(KeyError::InvalidChecksum)));
+
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#67ju93jw"
+            .to_wallet_descriptor(Network::Testnet);
+        assert!(matches!(desc.err(), Some(KeyError::InvalidChecksum)));
+    }
+
+    // test ToWalletDescriptor trait from &str with keys from right and wrong network
+    #[test]
+    fn test_descriptor_from_str_with_keys_network() {
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
+            .to_wallet_descriptor(Network::Testnet);
+        assert!(desc.is_ok());
+
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
+            .to_wallet_descriptor(Network::Regtest);
+        assert!(desc.is_ok());
+
+        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
+            .to_wallet_descriptor(Network::Testnet);
+        assert!(desc.is_ok());
+
+        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
+            .to_wallet_descriptor(Network::Regtest);
+        assert!(desc.is_ok());
+
+        let desc = "sh(wpkh(02864bb4ad00cefa806098a69e192bbda937494e69eb452b87bb3f20f6283baedb))"
+            .to_wallet_descriptor(Network::Testnet);
+        assert!(desc.is_ok());
+
+        let desc = "sh(wpkh(02864bb4ad00cefa806098a69e192bbda937494e69eb452b87bb3f20f6283baedb))"
+            .to_wallet_descriptor(Network::Bitcoin);
+        assert!(desc.is_ok());
+
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
+            .to_wallet_descriptor(Network::Bitcoin);
+        assert!(matches!(desc.err(), Some(KeyError::InvalidNetwork)));
+
+        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
+            .to_wallet_descriptor(Network::Bitcoin);
+        assert!(matches!(desc.err(), Some(KeyError::InvalidNetwork)));
+    }
+
+    // test ToWalletDescriptor trait from the output of the descriptor!() macro
+    #[test]
+    fn test_descriptor_from_str_from_output_of_macro() {
+        let tpub = bip32::ExtendedPubKey::from_str("tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK").unwrap();
+        let path = bip32::DerivationPath::from_str("m/1/2").unwrap();
+        let key = (tpub, path).to_descriptor_key().unwrap();
+
+        // make a descriptor out of it
+        let desc = crate::descriptor!(wpkh(key)).unwrap();
+
+        let (wallet_desc, _) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
+        let wallet_desc_str = wallet_desc.to_string();
+        assert_eq!(wallet_desc_str, "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)");
+
+        let (wallet_desc2, _) = wallet_desc_str
+            .to_wallet_descriptor(Network::Testnet)
+            .unwrap();
+        assert_eq!(wallet_desc, wallet_desc2)
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/policy.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/policy.rs.html new file mode 100644 index 0000000000..ea8a2c70d1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/policy.rs.html @@ -0,0 +1,2462 @@ +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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! 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::bitcoin::secp256k1::Secp256k1;
+//! 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(desc)?;
+//! println!("{:?}", extended_desc);
+//!
+//! let signers = Arc::new(key_map.into());
+//! let policy = extended_desc.extract_policy(&signers, &secp)?;
+//! println!("policy: {}", serde_json::to_string(&policy)?);
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use std::cmp::{max, Ordering};
+use std::collections::{BTreeMap, HashSet, VecDeque};
+use std::fmt;
+
+use serde::ser::SerializeMap;
+use serde::{Serialize, Serializer};
+
+use bitcoin::hashes::*;
+use bitcoin::util::bip32::Fingerprint;
+use bitcoin::PublicKey;
+
+use miniscript::descriptor::{DescriptorPublicKey, SortedMultiVec};
+use miniscript::{Descriptor, Miniscript, MiniscriptKey, ScriptContext, Terminal, ToPublicKey};
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use crate::descriptor::ExtractPolicy;
+use crate::wallet::signer::{SignerId, SignersContainer};
+use crate::wallet::utils::{self, descriptor_to_pk_ctx, SecpCtx};
+
+use super::checksum::get_checksum;
+use super::error::Error;
+use super::XKeyUtils;
+
+/// Raw public key or extended key fingerprint
+#[derive(Debug, Clone, Default, Serialize)]
+pub struct PKOrF {
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pubkey: Option<PublicKey>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pubkey_hash: Option<hash160::Hash>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    fingerprint: Option<Fingerprint>,
+}
+
+impl PKOrF {
+    fn from_key(k: &DescriptorPublicKey, secp: &SecpCtx) -> Self {
+        match k {
+            DescriptorPublicKey::SinglePub(pubkey) => PKOrF {
+                pubkey: Some(pubkey.key),
+                ..Default::default()
+            },
+            DescriptorPublicKey::XPub(xpub) => PKOrF {
+                fingerprint: Some(xpub.root_fingerprint(secp)),
+                ..Default::default()
+            },
+        }
+    }
+
+    fn from_key_hash(k: hash160::Hash) -> Self {
+        PKOrF {
+            pubkey_hash: Some(k),
+            ..Default::default()
+        }
+    }
+}
+
+/// An item that needs to be satisfied
+#[derive(Debug, Clone, Serialize)]
+#[serde(tag = "type", rename_all = "UPPERCASE")]
+pub enum SatisfiableItem {
+    // Leaves
+    /// Signature for a raw public key
+    Signature(PKOrF),
+    /// Signature for an extended key fingerprint
+    SignatureKey(PKOrF),
+    /// SHA256 preimage hash
+    SHA256Preimage {
+        /// The digest value
+        hash: sha256::Hash,
+    },
+    /// Double SHA256 preimage hash
+    HASH256Preimage {
+        /// The digest value
+        hash: sha256d::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 timestamp value
+        value: u32,
+    },
+    /// Relative timelock locktime
+    RelativeTimelock {
+        /// The locktime value
+        value: u32,
+    },
+    /// 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 {
+        get_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, 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
+        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) -> Result<(), PolicyError> {
+        // 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 ([choosen 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 possibile options and check whether or not they are compatible.
+                    .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: &Vec<(Vec<usize>, Vec<Condition>)>| println!("fetch {:?}", x))
+                    // since the previous step can turn one item of the iterator into multiple ones, we call flatten to expand them out
+                    .flatten()
+                    // .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,
+                };
+            }
+        }
+
+        Ok(())
+    }
+}
+
+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, Serialize)]
+pub struct Policy {
+    /// Identifier for this policy node
+    pub id: String,
+
+    /// Type of this policy node
+    #[serde(flatten)]
+    pub item: SatisfiableItem,
+    /// How a much given PSBT already satisfies this polcy node **(currently unused)**
+    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
+#[derive(Hash, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default, Serialize)]
+pub struct Condition {
+    /// Optional CheckSequenceVerify condition
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub csv: Option<u32>,
+    /// Optional timelock condition
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub timelock: Option<u32>,
+}
+
+impl Condition {
+    fn merge_nlocktime(a: u32, b: u32) -> Result<u32, PolicyError> {
+        if (a < utils::BLOCKS_TIMELOCK_THRESHOLD) != (b < utils::BLOCKS_TIMELOCK_THRESHOLD) {
+            Err(PolicyError::MixedTimelockUnits)
+        } else {
+            Ok(max(a, b))
+        }
+    }
+
+    fn merge_nsequence(a: u32, b: u32) -> Result<u32, PolicyError> {
+        let mask = utils::SEQUENCE_LOCKTIME_TYPE_FLAG | utils::SEQUENCE_LOCKTIME_MASK;
+
+        let a = a & mask;
+        let b = b & mask;
+
+        if (a < utils::SEQUENCE_LOCKTIME_TYPE_FLAG) != (b < utils::SEQUENCE_LOCKTIME_TYPE_FLAG) {
+            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)]
+pub enum PolicyError {
+    /// Not enough items are selected to satisfy a [`SatisfiableItem::Thresh`]
+    NotEnoughItemsSelected(String),
+    /// Too many items are selected to satisfy a [`SatisfiableItem::Thresh`]
+    TooManyItemsSelected(String),
+    /// Index out of range for an item to satisfy a [`SatisfiableItem::Thresh`]
+    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 {
+        write!(f, "{:?}", self)
+    }
+}
+
+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,
+        };
+        for (index, item) in items.iter().enumerate() {
+            contribution.add(&item.contribution, index)?;
+        }
+        contribution.finalize()?;
+
+        let mut policy: Policy = SatisfiableItem::Thresh { items, threshold }.into();
+        policy.contribution = contribution;
+
+        Ok(Some(policy))
+    }
+
+    fn make_multisig(
+        keys: &[DescriptorPublicKey],
+        signers: &SignersContainer,
+        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),
+        };
+        for (index, key) in keys.iter().enumerate() {
+            if signers.find(signer_id(key, secp)).is_some() {
+                contribution.add(
+                    &Satisfaction::Complete {
+                        condition: Default::default(),
+                    },
+                    index,
+                )?;
+            }
+        }
+        contribution.finalize()?;
+
+        let mut policy: Policy = SatisfiableItem::Multisig {
+            keys: parsed_keys,
+            threshold,
+        }
+        .into();
+        policy.contribution = contribution;
+
+        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()
+            }
+            _ => vec![],
+        };
+        let selected = match path.get(&self.id) {
+            _ if !default.is_empty() => &default,
+            Some(arr) => arr,
+            _ => &default,
+        };
+
+        match &self.item {
+            SatisfiableItem::Thresh { items, threshold } => {
+                let mapped_req = items
+                    .iter()
+                    .map(|i| i.get_condition(path))
+                    .collect::<Result<Vec<_>, _>>()?;
+
+                // if all the requirements are null we don't care about `selected` because there
+                // are no requirements
+                if mapped_req.iter().all(Condition::is_null) {
+                    return Ok(Condition::default());
+                }
+
+                // 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
+                match selected.len().cmp(threshold) {
+                    Ordering::Less => {
+                        return Err(PolicyError::NotEnoughItemsSelected(self.id.clone()))
+                    }
+                    Ordering::Greater => {
+                        return Err(PolicyError::TooManyItemsSelected(self.id.clone()))
+                    }
+                    Ordering::Equal => (),
+                }
+
+                // check the selected items, see if there are conflicting requirements
+                let mut requirements = Condition::default();
+                for item_index in selected {
+                    requirements = requirements.merge(
+                        mapped_req
+                            .get(*item_index)
+                            .ok_or(PolicyError::IndexOutOfRange(*item_index))?,
+                    )?;
+                }
+
+                Ok(requirements)
+            }
+            _ if !selected.is_empty() => Err(PolicyError::TooManyItemsSelected(self.id.clone())),
+            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 {
+    match key {
+        DescriptorPublicKey::SinglePub(pubkey) => pubkey.key.to_pubkeyhash().into(),
+        DescriptorPublicKey::XPub(xpub) => xpub.root_fingerprint(secp).into(),
+    }
+}
+
+fn signature(key: &DescriptorPublicKey, signers: &SignersContainer, secp: &SecpCtx) -> Policy {
+    let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key(key, secp)).into();
+
+    policy.contribution = if signers.find(signer_id(key, secp)).is_some() {
+        Satisfaction::Complete {
+            condition: Default::default(),
+        }
+    } else {
+        Satisfaction::None
+    };
+
+    policy
+}
+
+fn signature_key(
+    key: &<DescriptorPublicKey as MiniscriptKey>::Hash,
+    signers: &SignersContainer,
+    secp: &SecpCtx,
+) -> Policy {
+    let deriv_ctx = descriptor_to_pk_ctx(secp);
+    let key_hash = key.to_public_key(deriv_ctx).to_pubkeyhash();
+    let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key_hash(key_hash)).into();
+
+    if signers.find(SignerId::PkHash(key_hash)).is_some() {
+        policy.contribution = Satisfaction::Complete {
+            condition: Default::default(),
+        }
+    }
+
+    policy
+}
+
+impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx> {
+    fn extract_policy(
+        &self,
+        signers: &SignersContainer,
+        secp: &SecpCtx,
+    ) -> Result<Option<Policy>, Error> {
+        Ok(match &self.node {
+            // Leaves
+            Terminal::True | Terminal::False => None,
+            Terminal::PkK(pubkey) => Some(signature(pubkey, signers, secp)),
+            Terminal::PkH(pubkey_hash) => Some(signature_key(pubkey_hash, signers, secp)),
+            Terminal::After(value) => {
+                let mut policy: Policy = SatisfiableItem::AbsoluteTimelock { value: *value }.into();
+                policy.contribution = Satisfaction::Complete {
+                    condition: Condition {
+                        timelock: Some(*value),
+                        csv: None,
+                    },
+                };
+
+                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),
+                    },
+                };
+
+                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) => Policy::make_multisig(pks, signers, *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, secp)?,
+            // Complex policies
+            Terminal::AndV(a, b) | Terminal::AndB(a, b) => Policy::make_and(
+                a.extract_policy(signers, secp)?,
+                b.extract_policy(signers, secp)?,
+            )?,
+            Terminal::AndOr(x, y, z) => Policy::make_or(
+                Policy::make_and(
+                    x.extract_policy(signers, secp)?,
+                    y.extract_policy(signers, secp)?,
+                )?,
+                z.extract_policy(signers, secp)?,
+            )?,
+            Terminal::OrB(a, b)
+            | Terminal::OrD(a, b)
+            | Terminal::OrC(a, b)
+            | Terminal::OrI(a, b) => Policy::make_or(
+                a.extract_policy(signers, secp)?,
+                b.extract_policy(signers, secp)?,
+            )?,
+            Terminal::Thresh(k, nodes) => {
+                let mut threshold = *k;
+                let mapped: Vec<_> = nodes
+                    .iter()
+                    .map(|n| n.extract_policy(signers, secp))
+                    .collect::<Result<Vec<_>, _>>()?
+                    .into_iter()
+                    .filter_map(|x| x)
+                    .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)?
+            }
+        })
+    }
+}
+
+impl ExtractPolicy for Descriptor<DescriptorPublicKey> {
+    fn extract_policy(
+        &self,
+        signers: &SignersContainer,
+        secp: &SecpCtx,
+    ) -> Result<Option<Policy>, Error> {
+        fn make_sortedmulti<Ctx: ScriptContext>(
+            keys: &SortedMultiVec<DescriptorPublicKey, Ctx>,
+            signers: &SignersContainer,
+            secp: &SecpCtx,
+        ) -> Result<Option<Policy>, Error> {
+            Ok(Policy::make_multisig(
+                keys.pks.as_ref(),
+                signers,
+                keys.k,
+                true,
+                secp,
+            )?)
+        }
+
+        match self {
+            Descriptor::Pk(pubkey)
+            | Descriptor::Pkh(pubkey)
+            | Descriptor::Wpkh(pubkey)
+            | Descriptor::ShWpkh(pubkey) => Ok(Some(signature(pubkey, signers, secp))),
+            Descriptor::Bare(inner) => Ok(inner.extract_policy(signers, secp)?),
+            Descriptor::Sh(inner) => Ok(inner.extract_policy(signers, secp)?),
+            Descriptor::Wsh(inner) | Descriptor::ShWsh(inner) => {
+                Ok(inner.extract_policy(signers, secp)?)
+            }
+
+            // `sortedmulti()` is handled separately
+            Descriptor::ShSortedMulti(keys) => make_sortedmulti(&keys, signers, secp),
+            Descriptor::ShWshSortedMulti(keys) | Descriptor::WshSortedMulti(keys) => {
+                make_sortedmulti(&keys, signers, secp)
+            }
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+
+    use crate::descriptor;
+    use crate::descriptor::{ExtractPolicy, ToWalletDescriptor};
+
+    use super::*;
+    use crate::descriptor::policy::SatisfiableItem::{Multisig, Signature, Thresh};
+    use crate::keys::{DescriptorKey, ToDescriptorKey};
+    use crate::wallet::signer::SignersContainer;
+    use bitcoin::secp256k1::{All, Secp256k1};
+    use bitcoin::util::bip32;
+    use bitcoin::util::bip32::ChildNumber;
+    use bitcoin::Network;
+    use std::str::FromStr;
+    use std::sync::Arc;
+
+    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::ExtendedPrivKey::from_str(tprv).unwrap();
+        let tpub = bip32::ExtendedPubKey::from_private(&secp, &tprv);
+        let fingerprint = tprv.fingerprint(&secp);
+        let prvkey = (tprv, path.clone()).to_descriptor_key().unwrap();
+        let pubkey = (tpub, path).to_descriptor_key().unwrap();
+
+        (prvkey, pubkey, fingerprint)
+    }
+
+    // test ExtractPolicy trait for simple descriptors; wpkh(), sh(multi())
+
+    #[test]
+    fn test_extract_policy_for_wpkh() {
+        let (prvkey, pubkey, fingerprint) = setup_keys(TPRV0_STR);
+        let desc = descriptor!(wpkh(pubkey)).unwrap();
+        let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
+        let signers_container = Arc::new(SignersContainer::from(keymap));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, &Secp256k1::new())
+            .unwrap()
+            .unwrap();
+
+        assert!(
+            matches!(&policy.item, Signature(pk_or_f) if &pk_or_f.fingerprint.unwrap() == &fingerprint)
+        );
+        assert!(matches!(&policy.contribution, Satisfaction::None));
+
+        let desc = descriptor!(wpkh(prvkey)).unwrap();
+        let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
+        let signers_container = Arc::new(SignersContainer::from(keymap));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, &Secp256k1::new())
+            .unwrap()
+            .unwrap();
+
+        assert!(
+            matches!(&policy.item, Signature(pk_or_f) if &pk_or_f.fingerprint.unwrap() == &fingerprint)
+        );
+        assert!(
+            matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == None)
+        );
+    }
+
+    // 2 pub keys descriptor, required 2 prv keys
+    // #[test]
+    // fn test_extract_policy_for_sh_multi_partial_0of2() {
+    //     let (_prvkey0, pubkey0, fingerprint0) = setup_keys(TPRV0_STR);
+    //     let (_prvkey1, pubkey1, fingerprint1) = setup_keys(TPRV1_STR);
+    //     let desc = descriptor!(sh(multi 2, pubkey0, pubkey1)).unwrap();
+    //     let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
+    //     let signers_container = Arc::new(SignersContainer::from(keymap));
+    //     let policy = wallet_desc
+    //         .extract_policy(signers_container)
+    //         .unwrap()
+    //         .unwrap();
+    //
+    //     assert!(
+    //         matches!(&policy.item, Multisig { keys, threshold } if threshold == &2
+    //         && &keys[0].fingerprint.unwrap() == &fingerprint0
+    //         && &keys[1].fingerprint.unwrap() == &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 == &2
+    //         && m == &2
+    //         && 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 (prvkey0, _pubkey0, fingerprint0) = setup_keys(TPRV0_STR);
+    //     let (_prvkey1, pubkey1, fingerprint1) = setup_keys(TPRV1_STR);
+    //     let desc = descriptor!(sh(multi 2, prvkey0, pubkey1)).unwrap();
+    //     let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
+    //     let signers_container = Arc::new(SignersContainer::from(keymap));
+    //     let policy = wallet_desc
+    //         .extract_policy(signers_container)
+    //         .unwrap()
+    //         .unwrap();
+    //
+    //     assert!(
+    //         matches!(&policy.item, Multisig { keys, threshold } if threshold == &2
+    //         && &keys[0].fingerprint.unwrap() == &fingerprint0
+    //         && &keys[1].fingerprint.unwrap() == &fingerprint1)
+    //     );
+    //
+    //     // TODO should this be "Satisfaction::Partial" since we have only one of two prv keys?
+    //     assert!(
+    //         matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions} if n == &2
+    //          && m == &2
+    //          && items.len() == 2
+    //          && conditions.contains_key(&vec![0,1])
+    //         )
+    //     );
+    // }
+
+    // 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 (_prvkey0, pubkey0, fingerprint0) = setup_keys(TPRV0_STR);
+        let (prvkey1, _pubkey1, fingerprint1) = setup_keys(TPRV1_STR);
+        let desc = descriptor!(sh(multi 1, pubkey0, prvkey1)).unwrap();
+        let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
+        let signers_container = Arc::new(SignersContainer::from(keymap));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, &Secp256k1::new())
+            .unwrap()
+            .unwrap();
+
+        assert!(
+            matches!(&policy.item, Multisig { keys, threshold } if threshold == &1
+            && &keys[0].fingerprint.unwrap() == &fingerprint0
+            && &keys[1].fingerprint.unwrap() == &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 (prvkey0, _pubkey0, fingerprint0) = setup_keys(TPRV0_STR);
+        let (prvkey1, _pubkey1, fingerprint1) = setup_keys(TPRV1_STR);
+        let desc = descriptor!(sh(multi 2, prvkey0, prvkey1)).unwrap();
+        let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
+        let signers_container = Arc::new(SignersContainer::from(keymap));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, &Secp256k1::new())
+            .unwrap()
+            .unwrap();
+
+        assert!(
+            matches!(&policy.item, Multisig { keys, threshold } if threshold == &2
+            && &keys[0].fingerprint.unwrap() == &fingerprint0
+            && &keys[1].fingerprint.unwrap() == &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 (prvkey, pubkey, fingerprint) = setup_keys(TPRV0_STR);
+        let desc = descriptor!(wpkh(pubkey)).unwrap();
+        let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
+        let single_key = wallet_desc.derive(ChildNumber::from_normal_idx(0).unwrap());
+        let signers_container = Arc::new(SignersContainer::from(keymap));
+        let policy = single_key
+            .extract_policy(&signers_container, &Secp256k1::new())
+            .unwrap()
+            .unwrap();
+
+        assert!(
+            matches!(&policy.item, Signature(pk_or_f) if &pk_or_f.fingerprint.unwrap() == &fingerprint)
+        );
+        assert!(matches!(&policy.contribution, Satisfaction::None));
+
+        let desc = descriptor!(wpkh(prvkey)).unwrap();
+        let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
+        let single_key = wallet_desc.derive(ChildNumber::from_normal_idx(0).unwrap());
+        let signers_container = Arc::new(SignersContainer::from(keymap));
+        let policy = single_key
+            .extract_policy(&signers_container, &Secp256k1::new())
+            .unwrap()
+            .unwrap();
+
+        assert!(
+            matches!(&policy.item, Signature(pk_or_f) if &pk_or_f.fingerprint.unwrap() == &fingerprint)
+        );
+        assert!(
+            matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == 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 (_prvkey0, pubkey0, fingerprint0) = setup_keys(TPRV0_STR);
+        let (prvkey1, _pubkey1, fingerprint1) = setup_keys(TPRV1_STR);
+        let desc = descriptor!(sh(multi 1, pubkey0, prvkey1)).unwrap();
+        let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
+        let single_key = wallet_desc.derive(ChildNumber::from_normal_idx(0).unwrap());
+        let signers_container = Arc::new(SignersContainer::from(keymap));
+        let policy = single_key
+            .extract_policy(&signers_container, &Secp256k1::new())
+            .unwrap()
+            .unwrap();
+
+        assert!(
+            matches!(&policy.item, Multisig { keys, threshold } if threshold == &1
+            && &keys[0].fingerprint.unwrap() == &fingerprint0
+            && &keys[1].fingerprint.unwrap() == &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 (prvkey0, _pubkey0, _fingerprint0) = setup_keys(TPRV0_STR);
+        let (_prvkey1, pubkey1, _fingerprint1) = setup_keys(TPRV1_STR);
+        let sequence = 50;
+        let desc = descriptor!(wsh (
+            thresh 2, (pk prvkey0), (+s pk pubkey1), (+s+d+v older sequence)
+        ))
+        .unwrap();
+
+        let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
+        let signers_container = Arc::new(SignersContainer::from(keymap));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, &Secp256k1::new())
+            .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)
+             && conditions.get(&vec![1,2]).unwrap().iter().next().unwrap().csv == Some(sequence)
+            )
+        );
+    }
+
+    // - mixed timelocks should fail
+
+    // #[test]
+    // fn test_extract_policy_for_wsh_mixed_timelocks() {
+    //     let (prvkey0, _pubkey0, _fingerprint0) = setup_keys(TPRV0_STR);
+    //     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.to_wallet_descriptor(Network::Testnet).unwrap();
+    //     let signers_container = Arc::new(SignersContainer::from(keymap));
+    //     let policy = wallet_desc
+    //         .extract_policy(signers_container)
+    //         .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]
+    // fn test_extract_policy_for_multiple_same_timelocks() {
+    //     let (prvkey0, _pubkey0, _fingerprint0) = setup_keys(TPRV0_STR);
+    //     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.to_wallet_descriptor(Network::Testnet).unwrap();
+    //     let signers_container = Arc::new(SignersContainer::from(keymap));
+    //     let policy = wallet_desc
+    //         .extract_policy(signers_container)
+    //         .unwrap()
+    //         .unwrap();
+    //
+    //     println!("desc policy = {:?}", policy); // TODO remove
+    //
+    //     // TODO how should this merge timelocks?
+    //
+    //     let (prvkey1, _pubkey1, _fingerprint1) = setup_keys(TPRV0_STR);
+    //     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.to_wallet_descriptor(Network::Testnet).unwrap();
+    //     let signers_container = Arc::new(SignersContainer::from(keymap));
+    //     let policy = wallet_desc
+    //         .extract_policy(signers_container)
+    //         .unwrap()
+    //         .unwrap();
+    //
+    //     println!("desc policy = {:?}", policy); // TODO remove
+    //
+    //     // TODO how should this merge timelocks?
+    // }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/template.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/template.rs.html new file mode 100644 index 0000000000..751445aba5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/template.rs.html @@ -0,0 +1,1460 @@ +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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! 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::util::bip32;
+use bitcoin::Network;
+
+use miniscript::{Legacy, Segwitv0};
+
+use super::{ExtendedDescriptor, KeyMap, ToWalletDescriptor};
+use crate::keys::{DerivableKey, KeyError, ToDescriptorKey, ValidNetworks};
+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 [`ToWalletDescriptor`] is implemented for any [`DescriptorTemplate`], they can also be
+/// passed directly to the [`Wallet`](crate::Wallet) constructor.
+///
+/// ## Example
+///
+/// ```
+/// use bdk::keys::{KeyError, ToDescriptorKey};
+/// use bdk::miniscript::Legacy;
+/// use bdk::template::{DescriptorTemplate, DescriptorTemplateOut};
+///
+/// struct MyP2PKH<K: ToDescriptorKey<Legacy>>(K);
+///
+/// impl<K: ToDescriptorKey<Legacy>> DescriptorTemplate for MyP2PKH<K> {
+///     fn build(self) -> Result<DescriptorTemplateOut, KeyError> {
+///         Ok(bdk::descriptor!(pkh(self.0))?)
+///     }
+/// }
+/// ```
+pub trait DescriptorTemplate {
+    /// Build the complete descriptor
+    fn build(self) -> Result<DescriptorTemplateOut, KeyError>;
+}
+
+/// Turns a [`DescriptorTemplate`] into a valid wallet descriptor by calling its
+/// [`build`](DescriptorTemplate::build) method
+impl<T: DescriptorTemplate> ToWalletDescriptor for T {
+    fn to_wallet_descriptor(
+        self,
+        network: Network,
+    ) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
+        Ok(self.build()?.to_wallet_descriptor(network)?)
+    }
+}
+
+/// P2PKH template. Expands to a descriptor `pkh(key)`
+///
+/// ## Example
+///
+/// ```
+/// # use bdk::bitcoin::{PrivateKey, Network};
+/// # use bdk::{Wallet, OfflineWallet};
+/// # use bdk::database::MemoryDatabase;
+/// use bdk::template::P2PKH;
+///
+/// let key =
+///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+///     P2PKH(key),
+///     None,
+///     Network::Testnet,
+///     MemoryDatabase::default(),
+/// )?;
+///
+/// assert_eq!(
+///     wallet.get_new_address()?.to_string(),
+///     "mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"
+/// );
+/// # Ok::<_, Box<dyn std::error::Error>>(())
+/// ```
+pub struct P2PKH<K: ToDescriptorKey<Legacy>>(pub K);
+
+impl<K: ToDescriptorKey<Legacy>> DescriptorTemplate for P2PKH<K> {
+    fn build(self) -> Result<DescriptorTemplateOut, KeyError> {
+        Ok(descriptor!(pkh(self.0))?)
+    }
+}
+
+/// P2WPKH-P2SH template. Expands to a descriptor `sh(wpkh(key))`
+///
+/// ## Example
+///
+/// ```
+/// # use bdk::bitcoin::{PrivateKey, Network};
+/// # use bdk::{Wallet, OfflineWallet};
+/// # use bdk::database::MemoryDatabase;
+/// use bdk::template::P2WPKH_P2SH;
+///
+/// let key =
+///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+///     P2WPKH_P2SH(key),
+///     None,
+///     Network::Testnet,
+///     MemoryDatabase::default(),
+/// )?;
+///
+/// assert_eq!(
+///     wallet.get_new_address()?.to_string(),
+///     "2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"
+/// );
+/// # Ok::<_, Box<dyn std::error::Error>>(())
+/// ```
+#[allow(non_camel_case_types)]
+pub struct P2WPKH_P2SH<K: ToDescriptorKey<Segwitv0>>(pub K);
+
+impl<K: ToDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH_P2SH<K> {
+    fn build(self) -> Result<DescriptorTemplateOut, KeyError> {
+        Ok(descriptor!(sh(wpkh(self.0)))?)
+    }
+}
+
+/// P2WPKH template. Expands to a descriptor `wpkh(key)`
+///
+/// ## Example
+///
+/// ```
+/// # use bdk::bitcoin::{PrivateKey, Network};
+/// # use bdk::{Wallet, OfflineWallet};
+/// # use bdk::database::MemoryDatabase;
+/// use bdk::template::P2WPKH;
+///
+/// let key =
+///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+///     P2WPKH(key),
+///     None,
+///     Network::Testnet,
+///     MemoryDatabase::default(),
+/// )?;
+///
+/// assert_eq!(
+///     wallet.get_new_address()?.to_string(),
+///     "tb1q4525hmgw265tl3drrl8jjta7ayffu6jf68ltjd"
+/// );
+/// # Ok::<_, Box<dyn std::error::Error>>(())
+/// ```
+pub struct P2WPKH<K: ToDescriptorKey<Segwitv0>>(pub K);
+
+impl<K: ToDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH<K> {
+    fn build(self) -> Result<DescriptorTemplateOut, KeyError> {
+        Ok(descriptor!(wpkh(self.0))?)
+    }
+}
+
+/// BIP44 template. Expands to `pkh(key/44'/0'/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, OfflineWallet, KeychainKind};
+/// # use bdk::database::MemoryDatabase;
+/// use bdk::template::BIP44;
+///
+/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+///     BIP44(key.clone(), KeychainKind::External),
+///     Some(BIP44(key, KeychainKind::Internal)),
+///     Network::Testnet,
+///     MemoryDatabase::default()
+/// )?;
+///
+/// assert_eq!(wallet.get_new_address()?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
+/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)");
+/// # 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) -> Result<DescriptorTemplateOut, KeyError> {
+        Ok(P2PKH(legacy::make_bipxx_private(44, self.0, self.1)?).build()?)
+    }
+}
+
+/// BIP44 public template. Expands to `pkh(key/{0,1}/*)`
+///
+/// This assumes that the key used has already been derived with `m/44'/0'/0'`.
+///
+/// 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, OfflineWallet, KeychainKind};
+/// # use bdk::database::MemoryDatabase;
+/// use bdk::template::BIP44Public;
+///
+/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
+/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
+/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+///     BIP44Public(key.clone(), fingerprint, KeychainKind::External),
+///     Some(BIP44Public(key, fingerprint, KeychainKind::Internal)),
+///     Network::Testnet,
+///     MemoryDatabase::default()
+/// )?;
+///
+/// assert_eq!(wallet.get_new_address()?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
+/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)");
+/// # 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) -> Result<DescriptorTemplateOut, KeyError> {
+        Ok(P2PKH(legacy::make_bipxx_public(44, self.0, self.1, self.2)?).build()?)
+    }
+}
+
+/// BIP49 template. Expands to `sh(wpkh(key/49'/0'/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, OfflineWallet, KeychainKind};
+/// # use bdk::database::MemoryDatabase;
+/// use bdk::template::BIP49;
+///
+/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+///     BIP49(key.clone(), KeychainKind::External),
+///     Some(BIP49(key, KeychainKind::Internal)),
+///     Network::Testnet,
+///     MemoryDatabase::default()
+/// )?;
+///
+/// assert_eq!(wallet.get_new_address()?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
+/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))");
+/// # 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) -> Result<DescriptorTemplateOut, KeyError> {
+        Ok(P2WPKH_P2SH(segwit_v0::make_bipxx_private(49, self.0, self.1)?).build()?)
+    }
+}
+
+/// 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'`.
+///
+/// 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, OfflineWallet, KeychainKind};
+/// # use bdk::database::MemoryDatabase;
+/// use bdk::template::BIP49Public;
+///
+/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
+/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
+/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+///     BIP49Public(key.clone(), fingerprint, KeychainKind::External),
+///     Some(BIP49Public(key, fingerprint, KeychainKind::Internal)),
+///     Network::Testnet,
+///     MemoryDatabase::default()
+/// )?;
+///
+/// assert_eq!(wallet.get_new_address()?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
+/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))");
+/// # 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) -> Result<DescriptorTemplateOut, KeyError> {
+        Ok(P2WPKH_P2SH(segwit_v0::make_bipxx_public(49, self.0, self.1, self.2)?).build()?)
+    }
+}
+
+/// BIP84 template. Expands to `wpkh(key/84'/0'/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, OfflineWallet, KeychainKind};
+/// # use bdk::database::MemoryDatabase;
+/// use bdk::template::BIP84;
+///
+/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+///     BIP84(key.clone(), KeychainKind::External),
+///     Some(BIP84(key, KeychainKind::Internal)),
+///     Network::Testnet,
+///     MemoryDatabase::default()
+/// )?;
+///
+/// assert_eq!(wallet.get_new_address()?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
+/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)");
+/// # 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) -> Result<DescriptorTemplateOut, KeyError> {
+        Ok(P2WPKH(segwit_v0::make_bipxx_private(84, self.0, self.1)?).build()?)
+    }
+}
+
+/// BIP84 public template. Expands to `wpkh(key/{0,1}/*)`
+///
+/// This assumes that the key used has already been derived with `m/84'/0'/0'`.
+///
+/// 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, OfflineWallet, KeychainKind};
+/// # use bdk::database::MemoryDatabase;
+/// use bdk::template::BIP84Public;
+///
+/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
+/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
+/// let wallet: OfflineWallet<_> = Wallet::new_offline(
+///     BIP84Public(key.clone(), fingerprint, KeychainKind::External),
+///     Some(BIP84Public(key, fingerprint, KeychainKind::Internal)),
+///     Network::Testnet,
+///     MemoryDatabase::default()
+/// )?;
+///
+/// assert_eq!(wallet.get_new_address()?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
+/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)");
+/// # 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) -> Result<DescriptorTemplateOut, KeyError> {
+        Ok(P2WPKH(segwit_v0::make_bipxx_public(84, self.0, self.1, self.2)?).build()?)
+    }
+}
+
+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,
+            ) -> Result<impl ToDescriptorKey<$ctx>, KeyError> {
+                let mut derivation_path = Vec::with_capacity(4);
+                derivation_path.push(bip32::ChildNumber::from_hardened_idx(bip)?);
+                derivation_path.push(bip32::ChildNumber::from_hardened_idx(0)?);
+                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,
+            ) -> Result<impl ToDescriptorKey<$ctx>, KeyError> {
+                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 mut source_path = Vec::with_capacity(3);
+                source_path.push(bip32::ChildNumber::from_hardened_idx(bip)?);
+                source_path.push(bip32::ChildNumber::from_hardened_idx(0)?);
+                source_path.push(bip32::ChildNumber::from_hardened_idx(0)?);
+                let source_path: bip32::DerivationPath = source_path.into();
+
+                Ok((key, (parent_fingerprint, source_path), derivation_path))
+            }
+        }
+    };
+}
+
+expand_make_bipxx!(legacy, Legacy);
+expand_make_bipxx!(segwit_v0, Segwitv0);
+
+#[cfg(test)]
+mod test {
+    // test existing descriptor templates, make sure they are expanded to the right descriptors
+
+    use super::*;
+    use crate::descriptor::DescriptorMeta;
+    use crate::keys::{KeyError, ValidNetworks};
+    use bitcoin::hashes::core::str::FromStr;
+    use bitcoin::network::constants::Network::Regtest;
+    use bitcoin::secp256k1::Secp256k1;
+    use bitcoin::util::bip32::ChildNumber;
+    use miniscript::descriptor::{DescriptorPublicKey, DescriptorPublicKeyCtx, KeyMap};
+    use miniscript::Descriptor;
+
+    // verify template descriptor generates expected address(es)
+    fn check(
+        desc: Result<(Descriptor<DescriptorPublicKey>, KeyMap, ValidNetworks), KeyError>,
+        is_witness: bool,
+        is_fixed: bool,
+        expected: &[&str],
+    ) {
+        let secp = Secp256k1::new();
+        let deriv_ctx =
+            DescriptorPublicKeyCtx::new(&secp, ChildNumber::from_normal_idx(0).unwrap());
+
+        let (desc, _key_map, _networks) = desc.unwrap();
+        assert_eq!(desc.is_witness(), is_witness);
+        assert_eq!(desc.is_fixed(), is_fixed);
+        for i in 0..expected.len() {
+            let index = i as u32;
+            let child_desc = if desc.is_fixed() {
+                desc.clone()
+            } else {
+                desc.derive(ChildNumber::from_normal_idx(index).unwrap())
+            };
+            let address = child_desc.address(Regtest, deriv_ctx).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(),
+            false,
+            true,
+            &["mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"],
+        );
+
+        let pubkey = bitcoin::PublicKey::from_str(
+            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
+        )
+        .unwrap();
+        check(
+            P2PKH(pubkey).build(),
+            false,
+            true,
+            &["muZpTpBYhxmRFuCjLc7C6BBDF32C8XVJUi"],
+        );
+    }
+
+    // P2WPKH-P2SH `sh(wpkh(key))`
+    #[test]
+    fn test_p2wphp2sh_template() {
+        let prvkey =
+            bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
+                .unwrap();
+        check(
+            P2WPKH_P2SH(prvkey).build(),
+            true,
+            true,
+            &["2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"],
+        );
+
+        let pubkey = bitcoin::PublicKey::from_str(
+            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
+        )
+        .unwrap();
+        check(
+            P2WPKH_P2SH(pubkey).build(),
+            true,
+            true,
+            &["2N5LiC3CqzxDamRTPG1kiNv1FpNJQ7x28sb"],
+        );
+    }
+
+    // P2WPKH `wpkh(key)`
+    #[test]
+    fn test_p2wph_template() {
+        let prvkey =
+            bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
+                .unwrap();
+        check(
+            P2WPKH(prvkey).build(),
+            true,
+            true,
+            &["bcrt1q4525hmgw265tl3drrl8jjta7ayffu6jfcwxx9y"],
+        );
+
+        let pubkey = bitcoin::PublicKey::from_str(
+            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
+        )
+        .unwrap();
+        check(
+            P2WPKH(pubkey).build(),
+            true,
+            true,
+            &["bcrt1qngw83fg8dz0k749cg7k3emc7v98wy0c7azaa6h"],
+        );
+    }
+
+    // BIP44 `pkh(key/44'/0'/0'/{0,1}/*)`
+    #[test]
+    fn test_bip44_template() {
+        let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        check(
+            BIP44(prvkey, KeychainKind::External).build(),
+            false,
+            false,
+            &[
+                "n453VtnjDHPyDt2fDstKSu7A3YCJoHZ5g5",
+                "mvfrrumXgTtwFPWDNUecBBgzuMXhYM7KRP",
+                "mzYvhRAuQqbdSKMVVzXNYyqihgNdRadAUQ",
+            ],
+        );
+        check(
+            BIP44(prvkey, KeychainKind::Internal).build(),
+            false,
+            false,
+            &[
+                "muHF98X9KxEzdKrnFAX85KeHv96eXopaip",
+                "n4hpyLJE5ub6B5Bymv4eqFxS5KjrewSmYR",
+                "mgvkdv1ffmsXd2B1sRKQ5dByK3SzpG42rA",
+            ],
+        );
+    }
+
+    // BIP44 public `pkh(key/{0,1}/*)`
+    #[test]
+    fn test_bip44_public_template() {
+        let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU").unwrap();
+        let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
+        check(
+            BIP44Public(pubkey, fingerprint, KeychainKind::External).build(),
+            false,
+            false,
+            &[
+                "miNG7dJTzJqNbFS19svRdTCisC65dsubtR",
+                "n2UqaDbCjWSFJvpC84m3FjUk5UaeibCzYg",
+                "muCPpS6Ue7nkzeJMWDViw7Lkwr92Yc4K8g",
+            ],
+        );
+        check(
+            BIP44Public(pubkey, fingerprint, KeychainKind::Internal).build(),
+            false,
+            false,
+            &[
+                "moDr3vJ8wpt5nNxSK55MPq797nXJb2Ru9H",
+                "ms7A1Yt4uTezT2XkefW12AvLoko8WfNJMG",
+                "mhYiyat2rtEnV77cFfQsW32y1m2ceCGHPo",
+            ],
+        );
+    }
+
+    // BIP49 `sh(wpkh(key/49'/0'/0'/{0,1}/*))`
+    #[test]
+    fn test_bip49_template() {
+        let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        check(
+            BIP49(prvkey, KeychainKind::External).build(),
+            true,
+            false,
+            &[
+                "2N9bCAJXGm168MjVwpkBdNt6ucka3PKVoUV",
+                "2NDckYkqrYyDMtttEav5hB3Bfw9EGAW5HtS",
+                "2NAFTVtksF9T4a97M7nyCjwUBD24QevZ5Z4",
+            ],
+        );
+        check(
+            BIP49(prvkey, KeychainKind::Internal).build(),
+            true,
+            false,
+            &[
+                "2NB3pA8PnzJLGV8YEKNDFpbViZv3Bm1K6CG",
+                "2NBiX2Wzxngb5rPiWpUiJQ2uLVB4HBjFD4p",
+                "2NA8ek4CdQ6aMkveYF6AYuEYNrftB47QGTn",
+            ],
+        );
+    }
+
+    // BIP49 public `sh(wpkh(key/{0,1}/*))`
+    #[test]
+    fn test_bip49_public_template() {
+        let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L").unwrap();
+        let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
+        check(
+            BIP49Public(pubkey, fingerprint, KeychainKind::External).build(),
+            true,
+            false,
+            &[
+                "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt",
+                "2NCTQfJ1sZa3wQ3pPseYRHbaNEpC3AquEfX",
+                "2MveFxAuC8BYPzTybx7FxSzW8HSd8ATT4z7",
+            ],
+        );
+        check(
+            BIP49Public(pubkey, fingerprint, KeychainKind::Internal).build(),
+            true,
+            false,
+            &[
+                "2NF2vttKibwyxigxtx95Zw8K7JhDbo5zPVJ",
+                "2Mtmyd8taksxNVWCJ4wVvaiss7QPZGcAJuH",
+                "2NBs3CTVYPr1HCzjB4YFsnWCPCtNg8uMEfp",
+            ],
+        );
+    }
+
+    // BIP84 `wpkh(key/84'/0'/0'/{0,1}/*)`
+    #[test]
+    fn test_bip84_template() {
+        let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        check(
+            BIP84(prvkey, KeychainKind::External).build(),
+            true,
+            false,
+            &[
+                "bcrt1qkmvk2nadgplmd57ztld8nf8v2yxkzmdvwtjf8s",
+                "bcrt1qx0v6zgfwe50m4kqc58cqzcyem7ay2sfl3gvqhp",
+                "bcrt1q4h7fq9zhxst6e69p3n882nfj649l7w9g3zccfp",
+            ],
+        );
+        check(
+            BIP84(prvkey, KeychainKind::Internal).build(),
+            true,
+            false,
+            &[
+                "bcrt1qtrwtz00wxl69e5xex7amy4xzlxkaefg3gfdkxa",
+                "bcrt1qqqasfhxpkkf7zrxqnkr2sfhn74dgsrc3e3ky45",
+                "bcrt1qpks7n0gq74hsgsz3phn5vuazjjq0f5eqhsgyce",
+            ],
+        );
+    }
+
+    // BIP84 public `wpkh(key/{0,1}/*)`
+    #[test]
+    fn test_bip84_public_template() {
+        let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q").unwrap();
+        let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
+        check(
+            BIP84Public(pubkey, fingerprint, KeychainKind::External).build(),
+            true,
+            false,
+            &[
+                "bcrt1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2prcdvd0h",
+                "bcrt1q3lncdlwq3lgcaaeyruynjnlccr0ve0kakh6ana",
+                "bcrt1qt9800y6xl3922jy3uyl0z33jh5wfpycyhcylr9",
+            ],
+        );
+        check(
+            BIP84Public(pubkey, fingerprint, KeychainKind::Internal).build(),
+            true,
+            false,
+            &[
+                "bcrt1qm6wqukenh7guu792lj2njgw9n78cmwsy8xy3z2",
+                "bcrt1q694twxtjn4nnrvnyvra769j0a23rllj5c6cgwp",
+                "bcrt1qhlac3c5ranv5w5emlnqs7wxhkxt8maelylcarp",
+            ],
+        );
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/error.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/error.rs.html new file mode 100644 index 0000000000..cd048a7951 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/error.rs.html @@ -0,0 +1,414 @@ +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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::fmt;
+
+use crate::{descriptor, wallet, wallet::address_validator};
+use bitcoin::OutPoint;
+
+/// Errors that can be thrown by the [`Wallet`](crate::wallet::Wallet)
+#[derive(Debug)]
+pub enum Error {
+    /// Wrong number of bytes found when trying to convert to u32
+    InvalidU32Bytes(Vec<u8>),
+    /// Generic error
+    Generic(String),
+    /// This error is thrown when trying to convert Bare and Public key script to address
+    ScriptDoesntHaveAddressForm,
+    /// Found multiple outputs when `single_recipient` option has been specified
+    SingleRecipientMultipleOutputs,
+    /// `single_recipient` option is selected but neither `drain_wallet` nor `manually_selected_only` are
+    SingleRecipientNoInputs,
+    /// Cannot build a tx without recipients
+    NoRecipients,
+    /// `manually_selected_only` option is selected but no utxo has been passed
+    NoUtxosSelected,
+    /// Output created is under the dust limit, 546 satoshis
+    OutputBelowDustLimit(usize),
+    /// Wallet's UTXO set is not enough to cover recipient's requested plus fee
+    InsufficientFunds,
+    /// 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,
+    /// 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,
+    /// Happens when trying to spend an UTXO that is not in the internal database
+    UnknownUTXO,
+    /// Thrown when a tx is not found in the internal database
+    TransactionNotFound,
+    /// Happens when trying to bump a transaction that is already confirmed
+    TransactionConfirmed,
+    /// Trying to replace a tx that has a sequence >= `0xFFFFFFFE`
+    IrreplaceableTransaction,
+    /// When bumping a tx the fee rate requested is lower than required
+    FeeRateTooLow {
+        /// Required fee rate (satoshi/vbyte)
+        required: crate::types::FeeRate,
+    },
+    /// When bumping a tx the absolute fee requested is lower than replaced tx absolute fee
+    FeeTooLow {
+        /// Required fee absolute value (satoshi)
+        required: u64,
+    },
+    /// 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),
+    /// Error while working with [`keys`](crate::keys)
+    Key(crate::keys::KeyError),
+    /// Descriptor checksum mismatch
+    ChecksumMismatch,
+    /// Spending policy is not compatible with this [`KeychainKind`](crate::types::KeychainKind)
+    SpendingPolicyRequired(crate::types::KeychainKind),
+    /// Error while extracting and manipulating policies
+    InvalidPolicyPathError(crate::descriptor::policy::PolicyError),
+    /// Signing error
+    Signer(crate::wallet::signer::SignerError),
+
+    // Blockchain interface errors
+    /// Thrown when trying to call a method that requires a network connection, [`Wallet::sync`](crate::Wallet::sync) and [`Wallet::broadcast`](crate::Wallet::broadcast)
+    /// This error is thrown when creating the Client for the first time, while recovery attempts are tried
+    /// during the sync
+    OfflineClient,
+    /// Progress value must be between `0.0` (included) and `100.0` (included)
+    InvalidProgressValue(f32),
+    /// Progress update error (maybe the channel has been closed)
+    ProgressUpdateError,
+    /// Requested outpoint doesn't exist in the tx (vout greater than available outputs)
+    InvalidOutpoint(OutPoint),
+
+    /// Error related to the parsing and usage of descriptors
+    Descriptor(crate::descriptor::error::Error),
+    /// Error that can be returned to fail the validation of an address
+    AddressValidator(crate::wallet::address_validator::AddressValidatorError),
+    /// Encoding error
+    Encode(bitcoin::consensus::encode::Error),
+    /// Miniscript error
+    Miniscript(miniscript::Error),
+    /// BIP32 error
+    BIP32(bitcoin::util::bip32::Error),
+    /// An ECDSA error
+    Secp256k1(bitcoin::secp256k1::Error),
+    /// Error serializing or deserializing JSON data
+    JSON(serde_json::Error),
+    /// Hex decoding error
+    Hex(bitcoin::hashes::hex::Error),
+    /// Partially signed bitcoin transaction error
+    PSBT(bitcoin::util::psbt::Error),
+
+    //KeyMismatch(bitcoin::secp256k1::PublicKey, bitcoin::secp256k1::PublicKey),
+    //MissingInputUTXO(usize),
+    //InvalidAddressNetwork(Address),
+    //DifferentTransactions,
+    //DifferentDescriptorStructure,
+    //Uncapable(crate::blockchain::Capability),
+    //MissingCachedAddresses,
+    #[cfg(feature = "electrum")]
+    /// Electrum client error
+    Electrum(electrum_client::Error),
+    #[cfg(feature = "esplora")]
+    /// Esplora client error
+    Esplora(crate::blockchain::esplora::EsploraError),
+    #[cfg(feature = "compact_filters")]
+    /// Compact filters client error)
+    CompactFilters(crate::blockchain::compact_filters::CompactFiltersError),
+    #[cfg(feature = "key-value-db")]
+    /// Sled database error
+    Sled(sled::Error),
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for Error {}
+
+macro_rules! impl_error {
+    ( $from:ty, $to:ident ) => {
+        impl_error!($from, $to, Error);
+    };
+    ( $from:ty, $to:ident, $impl_for:ty ) => {
+        impl std::convert::From<$from> for $impl_for {
+            fn from(err: $from) -> Self {
+                <$impl_for>::$to(err)
+            }
+        }
+    };
+}
+
+impl_error!(descriptor::error::Error, Descriptor);
+impl_error!(address_validator::AddressValidatorError, AddressValidator);
+impl_error!(descriptor::policy::PolicyError, InvalidPolicyPathError);
+impl_error!(wallet::signer::SignerError, Signer);
+
+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),
+            crate::keys::KeyError::InvalidChecksum => Error::ChecksumMismatch,
+            e => Error::Key(e),
+        }
+    }
+}
+
+impl_error!(bitcoin::consensus::encode::Error, Encode);
+impl_error!(miniscript::Error, Miniscript);
+impl_error!(bitcoin::util::bip32::Error, BIP32);
+impl_error!(bitcoin::secp256k1::Error, Secp256k1);
+impl_error!(serde_json::Error, JSON);
+impl_error!(bitcoin::hashes::hex::Error, Hex);
+impl_error!(bitcoin::util::psbt::Error, PSBT);
+
+#[cfg(feature = "electrum")]
+impl_error!(electrum_client::Error, Electrum);
+#[cfg(feature = "esplora")]
+impl_error!(crate::blockchain::esplora::EsploraError, Esplora);
+#[cfg(feature = "key-value-db")]
+impl_error!(sled::Error, Sled);
+
+#[cfg(feature = "compact_filters")]
+impl From<crate::blockchain::compact_filters::CompactFiltersError> for Error {
+    fn from(other: crate::blockchain::compact_filters::CompactFiltersError) -> Self {
+        match other {
+            crate::blockchain::compact_filters::CompactFiltersError::Global(e) => *e,
+            err @ _ => Error::CompactFilters(err),
+        }
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/keys/bip39.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/keys/bip39.rs.html new file mode 100644 index 0000000000..b7bd41a2f9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/keys/bip39.rs.html @@ -0,0 +1,352 @@ +bip39.rs - source + +
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! BIP-0039
+
+// TODO: maybe write our own implementation of bip39? Seems stupid to have an extra dependency for
+// something that should be fairly simple to re-implement.
+
+use bitcoin::util::bip32;
+use bitcoin::Network;
+
+use miniscript::ScriptContext;
+
+use bip39::{Language, Mnemonic, MnemonicType, Seed};
+
+use super::{any_network, DerivableKey, DescriptorKey, GeneratableKey, GeneratedKey, KeyError};
+
+/// Type for a BIP39 mnemonic with an optional passphrase
+pub type MnemonicWithPassphrase = (Mnemonic, Option<String>);
+
+#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed {
+    fn add_metadata(
+        self,
+        source: Option<bip32::KeySource>,
+        derivation_path: bip32::DerivationPath,
+    ) -> Result<DescriptorKey<Ctx>, KeyError> {
+        let xprv = bip32::ExtendedPrivKey::new_master(Network::Bitcoin, &self.as_bytes())?;
+        let descriptor_key = xprv.add_metadata(source, derivation_path)?;
+
+        // here we must choose one network to build the xpub, but since the bip39 standard doesn't
+        // encode the network, the xpub we create is actually valid everywhere. so we override the
+        // valid networks with `any_network()`.
+        Ok(descriptor_key.override_valid_networks(any_network()))
+    }
+}
+
+#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for MnemonicWithPassphrase {
+    fn add_metadata(
+        self,
+        source: Option<bip32::KeySource>,
+        derivation_path: bip32::DerivationPath,
+    ) -> Result<DescriptorKey<Ctx>, KeyError> {
+        let (mnemonic, passphrase) = self;
+        let seed = Seed::new(&mnemonic, passphrase.as_deref().unwrap_or(""));
+        seed.add_metadata(source, derivation_path)
+    }
+}
+
+#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for Mnemonic {
+    fn add_metadata(
+        self,
+        source: Option<bip32::KeySource>,
+        derivation_path: bip32::DerivationPath,
+    ) -> Result<DescriptorKey<Ctx>, KeyError> {
+        (self, None).add_metadata(source, derivation_path)
+    }
+}
+
+#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
+impl<Ctx: ScriptContext> GeneratableKey<Ctx> for Mnemonic {
+    type Entropy = [u8; 32];
+
+    type Options = (MnemonicType, Language);
+    type Error = Option<bip39::ErrorKind>;
+
+    fn generate_with_entropy(
+        (mnemonic_type, language): Self::Options,
+        entropy: Self::Entropy,
+    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
+        let entropy = &entropy.as_ref()[..(mnemonic_type.entropy_bits() / 8)];
+        let mnemonic = Mnemonic::from_entropy(entropy, language).map_err(|e| e.downcast().ok())?;
+
+        Ok(GeneratedKey::new(mnemonic, any_network()))
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::str::FromStr;
+
+    use bitcoin::util::bip32;
+
+    use bip39::{Language, Mnemonic, MnemonicType};
+
+    use crate::keys::{any_network, GeneratableKey, GeneratedKey};
+
+    #[test]
+    fn test_keys_bip39_mnemonic() {
+        let mnemonic =
+            "aim bunker wash balance finish force paper analyst cabin spoon stable organ";
+        let mnemonic = Mnemonic::from_phrase(mnemonic, Language::English).unwrap();
+        let path = bip32::DerivationPath::from_str("m/44'/0'/0'/0").unwrap();
+
+        let key = (mnemonic, path);
+        let (desc, keys, networks) = crate::descriptor!(wpkh(key)).unwrap();
+        assert_eq!(desc.to_string(), "wpkh([be83839f/44'/0'/0']xpub6DCQ1YcqvZtSwGWMrwHELPehjWV3f2MGZ69yBADTxFEUAoLwb5Mp5GniQK6tTp3AgbngVz9zEFbBJUPVnkG7LFYt8QMTfbrNqs6FNEwAPKA/0/*)");
+        assert_eq!(keys.len(), 1);
+        assert_eq!(networks.len(), 3);
+    }
+
+    #[test]
+    fn test_keys_bip39_mnemonic_passphrase() {
+        let mnemonic =
+            "aim bunker wash balance finish force paper analyst cabin spoon stable organ";
+        let mnemonic = Mnemonic::from_phrase(mnemonic, Language::English).unwrap();
+        let path = bip32::DerivationPath::from_str("m/44'/0'/0'/0").unwrap();
+
+        let key = ((mnemonic, Some("passphrase".into())), path);
+        let (desc, keys, networks) = crate::descriptor!(wpkh(key)).unwrap();
+        assert_eq!(desc.to_string(), "wpkh([8f6cb80c/44'/0'/0']xpub6DWYS8bbihFevy29M4cbw4ZR3P5E12jB8R88gBDWCTCNpYiDHhYWNywrCF9VZQYagzPmsZpxXpytzSoxynyeFr4ZyzheVjnpLKuse4fiwZw/0/*)");
+        assert_eq!(keys.len(), 1);
+        assert_eq!(networks.len(), 3);
+    }
+
+    #[test]
+    fn test_keys_generate_bip39() {
+        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
+            Mnemonic::generate_with_entropy(
+                (MnemonicType::Words12, Language::English),
+                crate::keys::test::TEST_ENTROPY,
+            )
+            .unwrap();
+        assert_eq!(generated_mnemonic.valid_networks, any_network());
+        assert_eq!(
+            generated_mnemonic.to_string(),
+            "primary fetch primary fetch primary fetch primary fetch primary fetch primary fever"
+        );
+
+        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
+            Mnemonic::generate_with_entropy(
+                (MnemonicType::Words24, Language::English),
+                crate::keys::test::TEST_ENTROPY,
+            )
+            .unwrap();
+        assert_eq!(generated_mnemonic.valid_networks, any_network());
+        assert_eq!(generated_mnemonic.to_string(), "primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary foster");
+    }
+
+    #[test]
+    fn test_keys_generate_bip39_random() {
+        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
+            Mnemonic::generate((MnemonicType::Words12, Language::English)).unwrap();
+        assert_eq!(generated_mnemonic.valid_networks, any_network());
+
+        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
+            Mnemonic::generate((MnemonicType::Words24, Language::English)).unwrap();
+        assert_eq!(generated_mnemonic.valid_networks, any_network());
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/keys/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/keys/mod.rs.html new file mode 100644 index 0000000000..a18ef6494a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/keys/mod.rs.html @@ -0,0 +1,1482 @@ +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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Key formats
+
+use std::any::TypeId;
+use std::collections::HashSet;
+use std::marker::PhantomData;
+use std::ops::Deref;
+
+use bitcoin::secp256k1;
+
+use bitcoin::util::bip32;
+use bitcoin::{Network, PrivateKey, PublicKey};
+
+pub use miniscript::descriptor::{
+    DescriptorPublicKey, DescriptorSecretKey, DescriptorSinglePriv, DescriptorSinglePub,
+    SortedMultiVec,
+};
+use miniscript::descriptor::{DescriptorXKey, KeyMap};
+pub use miniscript::ScriptContext;
+use miniscript::{Miniscript, Terminal};
+
+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 and regtest
+pub fn any_network() -> ValidNetworks {
+    vec![Network::Bitcoin, Network::Testnet, Network::Regtest]
+        .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]
+        .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::with_capacity(1);
+
+                let public = secret
+                    .as_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,
+}
+
+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
+    }
+}
+
+/// 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()
+    }
+}
+
+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,
+            _ => 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, KeyError, ScriptContext, ToDescriptorKey};
+///
+/// pub struct MyKeyType {
+///     pubkey: PublicKey,
+/// }
+///
+/// impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for MyKeyType {
+///     fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+///         self.pubkey.to_descriptor_key()
+///     }
+/// }
+/// ```
+///
+/// Key type that is only valid on mainnet:
+///
+/// ```
+/// use bdk::bitcoin::PublicKey;
+///
+/// use bdk::keys::{
+///     mainnet_network, DescriptorKey, DescriptorPublicKey, DescriptorSinglePub, KeyError,
+///     ScriptContext, ToDescriptorKey,
+/// };
+///
+/// pub struct MyKeyType {
+///     pubkey: PublicKey,
+/// }
+///
+/// impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for MyKeyType {
+///     fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+///         Ok(DescriptorKey::from_public(
+///             DescriptorPublicKey::SinglePub(DescriptorSinglePub {
+///                 origin: None,
+///                 key: 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, KeyError, ScriptContext, ToDescriptorKey};
+///
+/// pub struct MyKeyType {
+///     is_legacy: bool,
+///     pubkey: PublicKey,
+/// }
+///
+/// impl<Ctx: ScriptContext + 'static> ToDescriptorKey<Ctx> for MyKeyType {
+///     fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+///         if Ctx::is_legacy() == self.is_legacy {
+///             self.pubkey.to_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 std::str::FromStr;
+///
+/// use bdk::keys::{DescriptorKey, KeyError, ToDescriptorKey};
+///
+/// pub struct MySegwitOnlyKeyType {
+///     pubkey: PublicKey,
+/// }
+///
+/// impl ToDescriptorKey<bdk::miniscript::Segwitv0> for MySegwitOnlyKeyType {
+///     fn to_descriptor_key(self) -> Result<DescriptorKey<bdk::miniscript::Segwitv0>, KeyError> {
+///         self.pubkey.to_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 ToDescriptorKey<Ctx: ScriptContext>: Sized {
+    /// Turn the key into a [`DescriptorKey`] within the requested [`ScriptContext`]
+    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError>;
+}
+
+/// Trait for keys that can be derived.
+///
+/// When extra metadata are provided, a [`DerivableKey`] can be transofrmed into a
+/// [`DescriptorKey`]: the trait [`ToDescriptorKey`] 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 implemented this trait instead of [`ToDescriptorKey`]. The same
+/// rules regarding script context and valid networks apply.
+///
+/// [`DerivationPath`]: (bip32::DerivationPath)
+pub trait DerivableKey<Ctx: ScriptContext> {
+    /// Add a extra metadata, consume `self` and turn it into a [`DescriptorKey`]
+    fn add_metadata(
+        self,
+        origin: Option<bip32::KeySource>,
+        derivation_path: bip32::DerivationPath,
+    ) -> Result<DescriptorKey<Ctx>, KeyError>;
+}
+
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPubKey {
+    fn add_metadata(
+        self,
+        origin: Option<bip32::KeySource>,
+        derivation_path: bip32::DerivationPath,
+    ) -> Result<DescriptorKey<Ctx>, KeyError> {
+        DescriptorPublicKey::XPub(DescriptorXKey {
+            origin,
+            xkey: self,
+            derivation_path,
+            is_wildcard: true,
+        })
+        .to_descriptor_key()
+    }
+}
+
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPrivKey {
+    fn add_metadata(
+        self,
+        origin: Option<bip32::KeySource>,
+        derivation_path: bip32::DerivationPath,
+    ) -> Result<DescriptorKey<Ctx>, KeyError> {
+        DescriptorSecretKey::XPrv(DescriptorXKey {
+            origin,
+            xkey: self,
+            derivation_path,
+            is_wildcard: true,
+        })
+        .to_descriptor_key()
+    }
+}
+
+/// 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
+    }
+}
+
+// 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 add_metadata(
+        self,
+        origin: Option<bip32::KeySource>,
+        derivation_path: bip32::DerivationPath,
+    ) -> Result<DescriptorKey<Ctx>, KeyError> {
+        let descriptor_key = self.key.add_metadata(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> ToDescriptorKey<Ctx> for GeneratedKey<K, Ctx>
+where
+    Ctx: ScriptContext,
+    K: ToDescriptorKey<Ctx>,
+{
+    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        let desc_key = self.key.to_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 [`ToDescriptorKey`] 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
+/// [`ToDescriptorKey`]: the generated keys can be directly used in descriptors if `Self` is also
+/// [`ToDescriptorKey`].
+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: std::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::ExtendedPrivKey {
+    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::ExtendedPrivKey::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 key = secp256k1::SecretKey::from_slice(&entropy)?;
+        let private_key = PrivateKey {
+            compressed: options.compressed,
+            network: Network::Bitcoin,
+            key,
+        };
+
+        Ok(GeneratedKey::new(private_key, any_network()))
+    }
+}
+
+impl<Ctx: ScriptContext, T: DerivableKey<Ctx>> ToDescriptorKey<Ctx> for (T, bip32::DerivationPath) {
+    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        self.0.add_metadata(None, self.1)
+    }
+}
+
+impl<Ctx: ScriptContext, T: DerivableKey<Ctx>> ToDescriptorKey<Ctx>
+    for (T, bip32::KeySource, bip32::DerivationPath)
+{
+    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        self.0.add_metadata(Some(self.1), self.2)
+    }
+}
+
+fn expand_multi_keys<Pk: ToDescriptorKey<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| Ok::<_, KeyError>(key.to_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.into_iter());
+            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: ToDescriptorKey<Ctx>, Ctx: ScriptContext>(
+    descriptor_key: Pk,
+    secp: &SecpCtx,
+) -> Result<(Miniscript<DescriptorPublicKey, Ctx>, KeyMap, ValidNetworks), KeyError> {
+    let (key, key_map, valid_networks) = descriptor_key.to_descriptor_key()?.extract(secp)?;
+
+    Ok((
+        Miniscript::from_ast(Terminal::PkK(key))?,
+        key_map,
+        valid_networks,
+    ))
+}
+
+// Used internally by `bdk::fragment!` to build `multi()` fragments
+#[doc(hidden)]
+pub fn make_multi<Pk: ToDescriptorKey<Ctx>, Ctx: ScriptContext>(
+    thresh: usize,
+    pks: Vec<Pk>,
+    secp: &SecpCtx,
+) -> Result<(Miniscript<DescriptorPublicKey, Ctx>, KeyMap, ValidNetworks), KeyError> {
+    let (pks, key_map, valid_networks) = expand_multi_keys(pks, secp)?;
+
+    Ok((
+        Miniscript::from_ast(Terminal::Multi(thresh, pks))?,
+        key_map,
+        valid_networks,
+    ))
+}
+
+// Used internally by `bdk::descriptor!` to build `sortedmulti()` fragments
+#[doc(hidden)]
+pub fn make_sortedmulti_inner<Pk: ToDescriptorKey<Ctx>, Ctx: ScriptContext>(
+    thresh: usize,
+    pks: Vec<Pk>,
+    secp: &SecpCtx,
+) -> Result<
+    (
+        SortedMultiVec<DescriptorPublicKey, Ctx>,
+        KeyMap,
+        ValidNetworks,
+    ),
+    KeyError,
+> {
+    let (pks, key_map, valid_networks) = expand_multi_keys(pks, secp)?;
+
+    Ok((SortedMultiVec::new(thresh, pks)?, key_map, valid_networks))
+}
+
+/// The "identity" conversion is used internally by some `bdk::fragment`s
+impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorKey<Ctx> {
+    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        Ok(self)
+    }
+}
+
+impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorPublicKey {
+    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        let networks = match self {
+            DescriptorPublicKey::SinglePub(_) => any_network(),
+            DescriptorPublicKey::XPub(DescriptorXKey { xkey, .. })
+                if xkey.network == Network::Bitcoin =>
+            {
+                mainnet_network()
+            }
+            _ => test_networks(),
+        };
+
+        Ok(DescriptorKey::from_public(self, networks))
+    }
+}
+
+impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for PublicKey {
+    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        DescriptorPublicKey::SinglePub(DescriptorSinglePub {
+            key: self,
+            origin: None,
+        })
+        .to_descriptor_key()
+    }
+}
+
+impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorSecretKey {
+    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        let networks = match &self {
+            DescriptorSecretKey::SinglePriv(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> ToDescriptorKey<Ctx> for PrivateKey {
+    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
+        DescriptorSecretKey::SinglePriv(DescriptorSinglePriv {
+            key: self,
+            origin: None,
+        })
+        .to_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::util::bip32::Error),
+    /// Miniscript error
+    Miniscript(miniscript::Error),
+}
+
+impl_error!(miniscript::Error, Miniscript, KeyError);
+impl_error!(bitcoin::util::bip32::Error, BIP32, KeyError);
+
+impl std::fmt::Display for KeyError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for KeyError {}
+
+#[cfg(test)]
+pub mod test {
+    use bitcoin::util::bip32;
+
+    use super::*;
+
+    pub const TEST_ENTROPY: [u8; 32] = [0xAA; 32];
+
+    #[test]
+    fn test_keys_generate_xprv() {
+        let generated_xprv: GeneratedKey<_, miniscript::Segwitv0> =
+            bip32::ExtendedPrivKey::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"
+        );
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/lib.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/lib.rs.html new file mode 100644 index 0000000000..41b65ad153 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/lib.rs.html @@ -0,0 +1,548 @@ +lib.rs - source + +
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+// rustdoc will warn if there are missing docs
+#![warn(missing_docs)]
+// only enables the `doc_cfg` feature when
+// the `docsrs` configuration attribute is defined
+#![cfg_attr(docsrs, feature(doc_cfg))]
+// only enables the nightly `external_doc` feature when
+// `test-md-docs` is enabled
+#![cfg_attr(feature = "test-md-docs", feature(external_doc))]
+
+//! A modern, lightweight, descriptor-based wallet library written in Rust.
+//!
+//! # About
+//!
+//! The BDK library aims to be the core building block for Bitcoin wallets of any kind.
+//!
+//! * It uses [Miniscript](https://github.com/rust-bitcoin/rust-miniscript) to support descriptors with generalized conditions. This exact same library can be used to build
+//!   single-sig wallets, multisigs, timelocked contracts and more.
+//! * It supports multiple blockchain backends and databases, allowing developers to choose exactly what's right for their projects.
+//! * It is built to be cross-platform: the core logic works on desktop, mobile, and even WebAssembly.
+//! * It is very easy to extend: developers can implement customized logic for blockchain backends, databases, signers, coin selection, and more, without having to fork and modify this library.
+//!
+//! # A Tour of BDK
+//!
+//! BDK consists of a number of modules that provide a range of functionality
+//! essential for implementing descriptor based Bitcoin wallet applications in Rust. In this
+//! section, we will take a brief tour of BDK, summarizing the major APIs and
+//! their uses.
+//!
+//! The easiest way to get started is to add bdk to your dependencies with the default features.
+//! The default features include a simple key-value database ([`sled`](sled)) to cache
+//! blockchain data and an [electrum](https://docs.rs/electrum-client/) blockchain client to
+//! interact with the bitcoin P2P network.
+//!
+//! ```toml
+//! bdk = "0.2.0"
+//! ```
+//!
+//! ## Sync the balance of a descriptor
+//!
+//! ### Example
+//! ```ignore
+//! use bdk::Wallet;
+//! use bdk::database::MemoryDatabase;
+//! use bdk::blockchain::{noop_progress, ElectrumBlockchain};
+//!
+//! use bdk::electrum_client::Client;
+//!
+//! fn main() -> Result<(), bdk::Error> {
+//!     let client = Client::new("ssl://electrum.blockstream.info:60002")?;
+//!     let wallet = Wallet::new(
+//!         "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
+//!         Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
+//!         bitcoin::Network::Testnet,
+//!         MemoryDatabase::default(),
+//!         ElectrumBlockchain::from(client)
+//!     )?;
+//!
+//!     wallet.sync(noop_progress(), None)?;
+//!
+//!     println!("Descriptor balance: {} SAT", wallet.get_balance()?);
+//!
+//!     Ok(())
+//! }
+//! ```
+//!
+//! ## Generate a few addresses
+//!
+//! ### Example
+//! ```
+//! use bdk::{Wallet, OfflineWallet};
+//! use bdk::database::MemoryDatabase;
+//!
+//! fn main() -> Result<(), bdk::Error> {
+//!     let wallet: OfflineWallet<_> = Wallet::new_offline(
+//!         "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
+//!         Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
+//!         bitcoin::Network::Testnet,
+//!         MemoryDatabase::default(),
+//!     )?;
+//!
+//!     println!("Address #0: {}", wallet.get_new_address()?);
+//!     println!("Address #1: {}", wallet.get_new_address()?);
+//!     println!("Address #2: {}", wallet.get_new_address()?);
+//!
+//!     Ok(())
+//! }
+//! ```
+//!
+//! ## Create a transaction
+//!
+//! ### Example
+//! ```ignore
+//! use base64::decode;
+//! use bdk::{FeeRate, TxBuilder, Wallet};
+//! use bdk::database::MemoryDatabase;
+//! use bdk::blockchain::{noop_progress, ElectrumBlockchain};
+//!
+//! use bdk::electrum_client::Client;
+//!
+//! use bitcoin::consensus::serialize;
+//!
+//! fn main() -> Result<(), bdk::Error> {
+//!     let client = Client::new("ssl://electrum.blockstream.info:60002")?;
+//!     let wallet = Wallet::new(
+//!         "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
+//!         Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
+//!         bitcoin::Network::Testnet,
+//!         MemoryDatabase::default(),
+//!         ElectrumBlockchain::from(client)
+//!     )?;
+//!
+//!     wallet.sync(noop_progress(), None)?;
+//!
+//!     let send_to = wallet.get_new_address()?;
+//!     let (psbt, details) = wallet.create_tx(
+//!         TxBuilder::with_recipients(vec![(send_to.script_pubkey(), 50_000)])
+//!             .enable_rbf()
+//!             .do_not_spend_change()
+//!             .fee_rate(FeeRate::from_sat_per_vb(5.0))
+//!     )?;
+//!
+//!     println!("Transaction details: {:#?}", details);
+//!     println!("Unsigned PSBT: {}", base64::encode(&serialize(&psbt)));
+//!
+//!     Ok(())
+//! }
+//! ```
+//!
+//! ## Sign a transaction
+//!
+//! ### Example
+//! ```ignore
+//! use base64::decode;
+//! use bdk::{Wallet, OfflineWallet};
+//! use bdk::database::MemoryDatabase;
+//!
+//! use bitcoin::consensus::deserialize;
+//!
+//! fn main() -> Result<(), bdk::Error> {
+//!     let wallet: OfflineWallet<_> = Wallet::new_offline(
+//!         "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
+//!         Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
+//!         bitcoin::Network::Testnet,
+//!         MemoryDatabase::default(),
+//!     )?;
+//!
+//!     let psbt = "...";
+//!     let psbt = deserialize(&base64::decode(psbt).unwrap())?;
+//!
+//!     let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
+//!
+//!     Ok(())
+//! }
+//! ```
+//!
+//! # Feature flags
+//!
+//! BDK uses a set of [feature flags](https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section)
+//! to reduce the amount of compiled code by allowing projects to only enable the features they need.
+//! By default, BDK enables two internal features, `key-value-db` and `electrum`.
+//!
+//! If you are new to BDK we recommended that you use the default features which will enable
+//! basic descriptor wallet functionality. More advanced users can disable the `default` features
+//! (`--no-default-features`) and build the BDK library with only the features you need.
+
+//! Below is a list of the available feature flags and the additional functionality they provide.
+//!
+//! * `all-keys`: all features for working with bitcoin keys
+//! * `async-interface`: async functions in bdk traits
+//! * `cli-utils`: utilities for creating a command line interface wallet
+//! * `keys-bip39`: [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) mnemonic codes for generating deterministic keys
+//!
+//! ## Internal features
+//!
+//! These features do not expose any new API, but influence internal implementation aspects of
+//! BDK.
+//!
+//! * `compact_filters`: [`compact_filters`](crate::blockchain::compact_filters) client protocol for interacting with the bitcoin P2P network
+//! * `electrum`: [`electrum`](crate::blockchain::electrum) client protocol for interacting with electrum servers
+//! * `esplora`: [`esplora`](crate::blockchain::esplora) client protocol for interacting with blockstream [electrs](https://github.com/Blockstream/electrs) servers
+//! * `key-value-db`: key value [`database`](crate::database) based on [`sled`](crate::sled) for caching blockchain data
+
+pub extern crate bitcoin;
+extern crate log;
+pub extern crate miniscript;
+extern crate serde;
+#[macro_use]
+extern crate serde_json;
+
+#[cfg(feature = "keys-bip39")]
+extern crate bip39;
+
+#[cfg(any(target_arch = "wasm32", feature = "async-interface"))]
+#[macro_use]
+extern crate async_trait;
+#[macro_use]
+extern crate bdk_macros;
+
+#[cfg(feature = "compact_filters")]
+#[macro_use]
+extern crate lazy_static;
+
+#[cfg(feature = "electrum")]
+pub extern crate electrum_client;
+
+#[cfg(feature = "esplora")]
+pub extern crate reqwest;
+
+#[cfg(feature = "key-value-db")]
+pub extern crate sled;
+
+#[cfg(feature = "cli-utils")]
+pub mod cli;
+
+#[allow(unused_imports)]
+#[cfg(test)]
+#[macro_use]
+extern crate testutils;
+#[allow(unused_imports)]
+#[cfg(test)]
+#[macro_use]
+extern crate testutils_macros;
+#[allow(unused_imports)]
+#[cfg(test)]
+#[macro_use]
+extern crate serial_test;
+
+#[macro_use]
+pub(crate) mod error;
+pub mod blockchain;
+pub mod database;
+pub mod descriptor;
+#[cfg(feature = "test-md-docs")]
+mod doctest;
+pub mod keys;
+pub(crate) mod psbt;
+pub(crate) mod types;
+pub mod wallet;
+
+pub use descriptor::template;
+pub use descriptor::HDKeyPaths;
+pub use error::Error;
+pub use types::*;
+pub use wallet::address_validator;
+pub use wallet::signer;
+pub use wallet::tx_builder::TxBuilder;
+pub use wallet::{OfflineWallet, Wallet};
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/psbt/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/psbt/mod.rs.html new file mode 100644 index 0000000000..27b1f86e57 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/psbt/mod.rs.html @@ -0,0 +1,110 @@ +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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
+use bitcoin::TxOut;
+
+pub trait PSBTUtils {
+    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut>;
+}
+
+impl PSBTUtils for PSBT {
+    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut> {
+        let tx = &self.global.unsigned_tx;
+
+        if input_index >= tx.input.len() {
+            return None;
+        }
+
+        if let Some(input) = self.inputs.get(input_index) {
+            if let Some(wit_utxo) = &input.witness_utxo {
+                Some(wit_utxo.clone())
+            } else if let Some(in_tx) = &input.non_witness_utxo {
+                Some(in_tx.output[tx.input[input_index].previous_output.vout as usize].clone())
+            } else {
+                None
+            }
+        } else {
+            None
+        }
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/types.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/types.rs.html new file mode 100644 index 0000000000..4f731ccfd6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/types.rs.html @@ -0,0 +1,248 @@ +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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use std::convert::AsRef;
+
+use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxOut};
+use bitcoin::hash_types::Txid;
+
+use serde::{Deserialize, Serialize};
+
+/// Types of keychains
+#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum KeychainKind {
+    /// External
+    External = 0,
+    /// Internal, usually used for change outputs
+    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",
+        }
+    }
+}
+
+/// Fee rate
+#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
+// Internally stored as satoshi/vbyte
+pub struct FeeRate(f32);
+
+impl FeeRate {
+    /// Create a new instance of [`FeeRate`] given a float fee rate in btc/kvbytes
+    pub fn from_btc_per_kvb(btc_per_kvb: f32) -> Self {
+        FeeRate(btc_per_kvb * 1e5)
+    }
+
+    /// Create a new instance of [`FeeRate`] given a float fee rate in satoshi/vbyte
+    pub fn from_sat_per_vb(sat_per_vb: f32) -> Self {
+        FeeRate(sat_per_vb)
+    }
+
+    /// Create a new [`FeeRate`] with the default min relay fee value
+    pub fn default_min_relay_fee() -> Self {
+        FeeRate(1.0)
+    }
+
+    /// Return the value as satoshi/vbyte
+    pub fn as_sat_vb(&self) -> f32 {
+        self.0
+    }
+}
+
+impl std::default::Default for FeeRate {
+    fn default() -> Self {
+        FeeRate::default_min_relay_fee()
+    }
+}
+
+/// A wallet unspent output
+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
+pub struct UTXO {
+    /// Reference to a transaction output
+    pub outpoint: OutPoint,
+    /// Transaction output
+    pub txout: TxOut,
+    /// Type of keychain
+    pub keychain: KeychainKind,
+}
+
+/// A wallet transaction
+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
+pub struct TransactionDetails {
+    /// Optional transaction
+    pub transaction: Option<Transaction>,
+    /// Transaction id
+    pub txid: Txid,
+    /// Timestamp
+    pub timestamp: u64,
+    /// Received value (sats)
+    pub received: u64,
+    /// Sent value (sats)
+    pub sent: u64,
+    /// Fee value (sats)
+    pub fees: u64,
+    /// Confirmed in block height, `None` means unconfirmed
+    pub height: Option<u32>,
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/address_validator.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/address_validator.rs.html new file mode 100644 index 0000000000..de52fb046b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/address_validator.rs.html @@ -0,0 +1,340 @@ +address_validator.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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Address validation callbacks
+//!
+//! The typical usage of those callbacks is for displaying the newly-generated address on a
+//! hardware wallet, so that the user can cross-check its correctness.
+//!
+//! More generally speaking though, these callbacks can also be used to "do something" every time
+//! an address is generated, without necessarily checking or validating it.
+//!
+//! An address validator can be attached to a [`Wallet`](super::Wallet) by using the
+//! [`Wallet::add_address_validator`](super::Wallet::add_address_validator) method, and
+//! whenever a new address is generated (either explicitly by the user with
+//! [`Wallet::get_new_address`](super::Wallet::get_new_address) or internally to create a change
+//! address) all the attached validators will be polled, in sequence. All of them must complete
+//! successfully to continue.
+//!
+//! ## Example
+//!
+//! ```
+//! # use std::sync::Arc;
+//! # use bitcoin::*;
+//! # use bdk::address_validator::*;
+//! # use bdk::database::*;
+//! # use bdk::*;
+//! struct PrintAddressAndContinue;
+//!
+//! impl AddressValidator for PrintAddressAndContinue {
+//!     fn validate(
+//!         &self,
+//!         keychain: KeychainKind,
+//!         hd_keypaths: &HDKeyPaths,
+//!         script: &Script
+//!     ) -> Result<(), AddressValidatorError> {
+//!         let address = Address::from_script(script, Network::Testnet)
+//!             .as_ref()
+//!             .map(Address::to_string)
+//!             .unwrap_or(script.to_string());
+//!         println!("New address of type {:?}: {}", keychain, address);
+//!         println!("HD keypaths: {:#?}", hd_keypaths);
+//!
+//!         Ok(())
+//!     }
+//! }
+//!
+//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+//! let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+//! wallet.add_address_validator(Arc::new(PrintAddressAndContinue));
+//!
+//! let address = wallet.get_new_address()?;
+//! println!("Address: {}", address);
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use std::fmt;
+
+use bitcoin::Script;
+
+use crate::descriptor::HDKeyPaths;
+use crate::types::KeychainKind;
+
+/// Errors that can be returned to fail the validation of an address
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum AddressValidatorError {
+    /// User rejected the address
+    UserRejected,
+    /// Network connection error
+    ConnectionError,
+    /// Network request timeout error
+    TimeoutError,
+    /// Invalid script
+    InvalidScript,
+    /// A custom error message
+    Message(String),
+}
+
+impl fmt::Display for AddressValidatorError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for AddressValidatorError {}
+
+/// Trait to build address validators
+///
+/// All the address validators attached to a wallet with [`Wallet::add_address_validator`](super::Wallet::add_address_validator) will be polled
+/// every time an address (external or internal) is generated by the wallet. Errors returned in the
+/// validator will be propagated up to the original caller that triggered the address generation.
+///
+/// For a usage example see [this module](crate::address_validator)'s documentation.
+pub trait AddressValidator: Send + Sync {
+    /// Validate or inspect an address
+    fn validate(
+        &self,
+        keychain: KeychainKind,
+        hd_keypaths: &HDKeyPaths,
+        script: &Script,
+    ) -> Result<(), AddressValidatorError>;
+}
+
+#[cfg(test)]
+mod test {
+    use std::sync::Arc;
+
+    use super::*;
+    use crate::wallet::test::{get_funded_wallet, get_test_wpkh};
+    use crate::wallet::TxBuilder;
+
+    struct TestValidator;
+    impl AddressValidator for TestValidator {
+        fn validate(
+            &self,
+            _keychain: KeychainKind,
+            _hd_keypaths: &HDKeyPaths,
+            _script: &bitcoin::Script,
+        ) -> Result<(), AddressValidatorError> {
+            Err(AddressValidatorError::InvalidScript)
+        }
+    }
+
+    #[test]
+    #[should_panic(expected = "InvalidScript")]
+    fn test_address_validator_external() {
+        let (mut wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        wallet.add_address_validator(Arc::new(TestValidator));
+
+        wallet.get_new_address().unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "InvalidScript")]
+    fn test_address_validator_internal() {
+        let (mut wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        wallet.add_address_validator(Arc::new(TestValidator));
+
+        let addr = testutils!(@external descriptors, 10);
+        wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/coin_selection.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/coin_selection.rs.html new file mode 100644 index 0000000000..f52a1c8b9a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/coin_selection.rs.html @@ -0,0 +1,2000 @@ +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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Coin selection
+//!
+//! This module provides the trait [`CoinSelectionAlgorithm`] that can be implemented to
+//! define custom coin selection algorithms.
+//!
+//! The coin selection algorithm is not globally part of a [`Wallet`](super::Wallet), instead it
+//! is selected whenever a [`Wallet::create_tx`](super::Wallet::create_tx) call is made, through
+//! the use of the [`TxBuilder`] structure, specifically with
+//! [`TxBuilder::coin_selection`](super::tx_builder::TxBuilder::coin_selection) method.
+//!
+//! The [`DefaultCoinSelectionAlgorithm`] selects the default coin selection algorithm that
+//! [`TxBuilder`] uses, if it's not explicitly overridden.
+//!
+//! [`TxBuilder`]: super::tx_builder::TxBuilder
+//!
+//! ## Example
+//!
+//! ```no_run
+//! # use std::str::FromStr;
+//! # use bitcoin::*;
+//! # use bdk::wallet::coin_selection::*;
+//! # use bdk::database::Database;
+//! # use bdk::*;
+//! # const TXIN_BASE_WEIGHT: usize = (32 + 4 + 4 + 1) * 4;
+//! #[derive(Debug)]
+//! struct AlwaysSpendEverything;
+//!
+//! impl<D: Database> CoinSelectionAlgorithm<D> for AlwaysSpendEverything {
+//!     fn coin_select(
+//!         &self,
+//!         database: &D,
+//!         required_utxos: Vec<(UTXO, usize)>,
+//!         optional_utxos: Vec<(UTXO, usize)>,
+//!         fee_rate: FeeRate,
+//!         amount_needed: u64,
+//!         fee_amount: f32,
+//!     ) -> Result<CoinSelectionResult, bdk::Error> {
+//!         let mut selected_amount = 0;
+//!         let mut additional_weight = 0;
+//!         let all_utxos_selected = required_utxos
+//!             .into_iter().chain(optional_utxos)
+//!             .scan((&mut selected_amount, &mut additional_weight), |(selected_amount, additional_weight), (utxo, weight)| {
+//!                 **selected_amount += utxo.txout.value;
+//!                 **additional_weight += TXIN_BASE_WEIGHT + weight;
+//!
+//!                 Some(utxo)
+//!             })
+//!             .collect::<Vec<_>>();
+//!         let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0;
+//!
+//!         if (fee_amount + additional_fees).ceil() as u64 + amount_needed > selected_amount {
+//!             return Err(bdk::Error::InsufficientFunds);
+//!         }
+//!
+//!         Ok(CoinSelectionResult {
+//!             selected: all_utxos_selected,
+//!             selected_amount,
+//!             fee_amount: fee_amount + additional_fees,
+//!         })
+//!     }
+//! }
+//!
+//! # let wallet: OfflineWallet<_> = Wallet::new_offline("", None, Network::Testnet, bdk::database::MemoryDatabase::default())?;
+//! // create wallet, sync, ...
+//!
+//! let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+//! let (psbt, details) = wallet.create_tx(
+//!     TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+//!         .coin_selection(AlwaysSpendEverything),
+//! )?;
+//!
+//! // inspect, sign, broadcast, ...
+//!
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use crate::database::Database;
+use crate::error::Error;
+use crate::types::{FeeRate, UTXO};
+
+use rand::seq::SliceRandom;
+#[cfg(not(test))]
+use rand::thread_rng;
+#[cfg(test)]
+use rand::{rngs::StdRng, SeedableRng};
+
+/// Default coin selection algorithm used by [`TxBuilder`](super::tx_builder::TxBuilder) if not
+/// overridden
+#[cfg(not(test))]
+pub type DefaultCoinSelectionAlgorithm = BranchAndBoundCoinSelection;
+#[cfg(test)]
+pub type DefaultCoinSelectionAlgorithm = LargestFirstCoinSelection; // make the tests more predictable
+
+// Base weight of a Txin, not counting the weight needed for satisfying it.
+// prev_txid (32 bytes) + prev_vout (4 bytes) + sequence (4 bytes) + script_len (1 bytes)
+pub(crate) const TXIN_BASE_WEIGHT: usize = (32 + 4 + 4 + 1) * 4;
+
+/// Result of a successful coin selection
+#[derive(Debug)]
+pub struct CoinSelectionResult {
+    /// List of outputs selected for use as inputs
+    pub selected: Vec<UTXO>,
+    /// Sum of the selected inputs' value
+    pub selected_amount: u64,
+    /// Total fee amount in satoshi
+    pub fee_amount: f32,
+}
+
+/// 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<D: Database>: std::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 `amount_needed` with their
+    ///                     weight cost
+    /// - `optional_utxos`: the remaining available utxos to satisfy `amount_needed` with their
+    ///                     weight cost
+    /// - `fee_rate`: fee rate to use
+    /// - `amount_needed`: the amount in satoshi to select
+    /// - `fee_amount`: the amount of fees in satoshi already accumulated from adding outputs and
+    ///                 the transaction's header
+    fn coin_select(
+        &self,
+        database: &D,
+        required_utxos: Vec<(UTXO, usize)>,
+        optional_utxos: Vec<(UTXO, usize)>,
+        fee_rate: FeeRate,
+        amount_needed: u64,
+        fee_amount: f32,
+    ) -> 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)]
+pub struct LargestFirstCoinSelection;
+
+impl<D: Database> CoinSelectionAlgorithm<D> for LargestFirstCoinSelection {
+    fn coin_select(
+        &self,
+        _database: &D,
+        required_utxos: Vec<(UTXO, usize)>,
+        mut optional_utxos: Vec<(UTXO, usize)>,
+        fee_rate: FeeRate,
+        amount_needed: u64,
+        mut fee_amount: f32,
+    ) -> Result<CoinSelectionResult, Error> {
+        let calc_fee_bytes = |wu| (wu as f32) * fee_rate.as_sat_vb() / 4.0;
+
+        log::debug!(
+            "amount_needed = `{}`, fee_amount = `{}`, fee_rate = `{:?}`",
+            amount_needed,
+            fee_amount,
+            fee_rate
+        );
+
+        // 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(|(utxo, _)| utxo.txout.value);
+            required_utxos
+                .into_iter()
+                .map(|utxo| (true, utxo))
+                .chain(optional_utxos.into_iter().rev().map(|utxo| (false, utxo)))
+        };
+
+        // Keep including inputs until we've got enough.
+        // Store the total input value in selected_amount and the total fee being paid in fee_amount
+        let mut selected_amount = 0;
+        let selected = utxos
+            .scan(
+                (&mut selected_amount, &mut fee_amount),
+                |(selected_amount, fee_amount), (must_use, (utxo, weight))| {
+                    if must_use || **selected_amount < amount_needed + (fee_amount.ceil() as u64) {
+                        **fee_amount += calc_fee_bytes(TXIN_BASE_WEIGHT + weight);
+                        **selected_amount += utxo.txout.value;
+
+                        log::debug!(
+                            "Selected {}, updated fee_amount = `{}`",
+                            utxo.outpoint,
+                            fee_amount
+                        );
+
+                        Some(utxo)
+                    } else {
+                        None
+                    }
+                },
+            )
+            .collect::<Vec<_>>();
+
+        if selected_amount < amount_needed + (fee_amount.ceil() as u64) {
+            return Err(Error::InsufficientFunds);
+        }
+
+        Ok(CoinSelectionResult {
+            selected,
+            fee_amount,
+            selected_amount,
+        })
+    }
+}
+
+#[derive(Debug, Clone)]
+// Adds fee information to an UTXO.
+struct OutputGroup {
+    utxo: UTXO,
+    // weight needed to satisfy the UTXO, as described in `Descriptor::max_satisfaction_weight`
+    satisfaction_weight: usize,
+    // Amount of fees for spending a certain utxo, calculated using a certain FeeRate
+    fee: f32,
+    // The effective value of the UTXO, i.e., the utxo value minus the fee for spending it
+    effective_value: i64,
+}
+
+impl OutputGroup {
+    fn new(utxo: UTXO, satisfaction_weight: usize, fee_rate: FeeRate) -> Self {
+        let fee = (TXIN_BASE_WEIGHT + satisfaction_weight) as f32 / 4.0 * fee_rate.as_sat_vb();
+        let effective_value = utxo.txout.value as i64 - fee.ceil() as i64;
+        OutputGroup {
+            utxo,
+            satisfaction_weight,
+            effective_value,
+            fee,
+        }
+    }
+}
+
+/// 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)]
+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<D: Database> CoinSelectionAlgorithm<D> for BranchAndBoundCoinSelection {
+    fn coin_select(
+        &self,
+        _database: &D,
+        required_utxos: Vec<(UTXO, usize)>,
+        optional_utxos: Vec<(UTXO, usize)>,
+        fee_rate: FeeRate,
+        amount_needed: u64,
+        fee_amount: f32,
+    ) -> 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.0, u.1, fee_rate))
+            .collect();
+
+        // Mapping every (UTXO, usize) to an output group.
+        // Filtering UTXOs with an effective_value < 0, as the fee paid for
+        // adding them is more than their value
+        let optional_utxos: Vec<OutputGroup> = optional_utxos
+            .into_iter()
+            .map(|u| OutputGroup::new(u.0, u.1, fee_rate))
+            .filter(|u| u.effective_value > 0)
+            .collect();
+
+        let curr_value = required_utxos
+            .iter()
+            .fold(0, |acc, x| acc + x.effective_value as u64);
+
+        let curr_available_value = optional_utxos
+            .iter()
+            .fold(0, |acc, x| acc + x.effective_value as u64);
+
+        let actual_target = fee_amount.ceil() as u64 + amount_needed;
+        let cost_of_change = self.size_of_change as f32 * fee_rate.as_sat_vb();
+
+        if curr_available_value + curr_value < actual_target {
+            return Err(Error::InsufficientFunds);
+        }
+
+        Ok(self
+            .bnb(
+                required_utxos.clone(),
+                optional_utxos.clone(),
+                curr_value,
+                curr_available_value,
+                actual_target,
+                fee_amount,
+                cost_of_change,
+            )
+            .unwrap_or_else(|_| {
+                self.single_random_draw(
+                    required_utxos,
+                    optional_utxos,
+                    curr_value,
+                    actual_target,
+                    fee_amount,
+                )
+            }))
+    }
+}
+
+impl BranchAndBoundCoinSelection {
+    // TODO: make this more Rust-onic :)
+    // (And perhpaps refactor with less arguments?)
+    #[allow(clippy::too_many_arguments)]
+    fn bnb(
+        &self,
+        required_utxos: Vec<OutputGroup>,
+        mut optional_utxos: Vec<OutputGroup>,
+        mut curr_value: u64,
+        mut curr_available_value: u64,
+        actual_target: u64,
+        fee_amount: f32,
+        cost_of_change: f32,
+    ) -> 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 < actual_target
+                || curr_value > actual_target + cost_of_change as u64
+            {
+                backtrack = true;
+            } else if curr_value >= actual_target {
+                // 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 = current_selection.clone();
+                    best_selection_value = Some(curr_value);
+                }
+
+                // If we found a perfect match, break here
+                if curr_value == actual_target {
+                    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 as u64;
+                }
+
+                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 as u64;
+            } 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 as u64;
+
+                // Inclusion branch first (Largest First Exploration)
+                current_selection.push(true);
+                curr_value += utxo.effective_value as u64;
+            }
+        }
+
+        // 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();
+
+        Ok(BranchAndBoundCoinSelection::calculate_cs_result(
+            selected_utxos,
+            required_utxos,
+            fee_amount,
+        ))
+    }
+
+    fn single_random_draw(
+        &self,
+        required_utxos: Vec<OutputGroup>,
+        mut optional_utxos: Vec<OutputGroup>,
+        curr_value: u64,
+        actual_target: u64,
+        fee_amount: f32,
+    ) -> CoinSelectionResult {
+        #[cfg(not(test))]
+        optional_utxos.shuffle(&mut thread_rng());
+        #[cfg(test)]
+        {
+            let seed = [0; 32];
+            let mut rng: StdRng = SeedableRng::from_seed(seed);
+            optional_utxos.shuffle(&mut rng);
+        }
+
+        let selected_utxos = optional_utxos
+            .into_iter()
+            .scan(curr_value, |curr_value, utxo| {
+                if *curr_value >= actual_target {
+                    None
+                } else {
+                    *curr_value += utxo.effective_value as u64;
+                    Some(utxo)
+                }
+            })
+            .collect::<Vec<_>>();
+
+        BranchAndBoundCoinSelection::calculate_cs_result(selected_utxos, required_utxos, fee_amount)
+    }
+
+    fn calculate_cs_result(
+        mut selected_utxos: Vec<OutputGroup>,
+        mut required_utxos: Vec<OutputGroup>,
+        mut fee_amount: f32,
+    ) -> CoinSelectionResult {
+        selected_utxos.append(&mut required_utxos);
+        fee_amount += selected_utxos.iter().map(|u| u.fee).sum::<f32>();
+        let selected = selected_utxos
+            .into_iter()
+            .map(|u| u.utxo)
+            .collect::<Vec<_>>();
+        let selected_amount = selected.iter().map(|u| u.txout.value).sum();
+
+        CoinSelectionResult {
+            selected,
+            fee_amount,
+            selected_amount,
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::str::FromStr;
+
+    use bitcoin::{OutPoint, Script, TxOut};
+
+    use super::*;
+    use crate::database::MemoryDatabase;
+    use crate::types::*;
+
+    use rand::rngs::StdRng;
+    use rand::seq::SliceRandom;
+    use rand::{Rng, SeedableRng};
+
+    const P2WPKH_WITNESS_SIZE: usize = 73 + 33 + 2;
+
+    fn get_test_utxos() -> Vec<(UTXO, usize)> {
+        vec![
+            (
+                UTXO {
+                    outpoint: OutPoint::from_str(
+                        "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:0",
+                    )
+                    .unwrap(),
+                    txout: TxOut {
+                        value: 100_000,
+                        script_pubkey: Script::new(),
+                    },
+                    keychain: KeychainKind::External,
+                },
+                P2WPKH_WITNESS_SIZE,
+            ),
+            (
+                UTXO {
+                    outpoint: OutPoint::from_str(
+                        "65d92ddff6b6dc72c89624a6491997714b90f6004f928d875bc0fd53f264fa85:0",
+                    )
+                    .unwrap(),
+                    txout: TxOut {
+                        value: 200_000,
+                        script_pubkey: Script::new(),
+                    },
+                    keychain: KeychainKind::Internal,
+                },
+                P2WPKH_WITNESS_SIZE,
+            ),
+        ]
+    }
+
+    fn generate_random_utxos(rng: &mut StdRng, utxos_number: usize) -> Vec<(UTXO, usize)> {
+        let mut res = Vec::new();
+        for _ in 0..utxos_number {
+            res.push((
+                UTXO {
+                    outpoint: OutPoint::from_str(
+                        "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:0",
+                    )
+                    .unwrap(),
+                    txout: TxOut {
+                        value: rng.gen_range(0, 200000000),
+                        script_pubkey: Script::new(),
+                    },
+                    keychain: KeychainKind::External,
+                },
+                P2WPKH_WITNESS_SIZE,
+            ));
+        }
+        res
+    }
+
+    fn generate_same_value_utxos(utxos_value: u64, utxos_number: usize) -> Vec<(UTXO, usize)> {
+        let utxo = (
+            UTXO {
+                outpoint: OutPoint::from_str(
+                    "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:0",
+                )
+                .unwrap(),
+                txout: TxOut {
+                    value: utxos_value,
+                    script_pubkey: Script::new(),
+                },
+                keychain: KeychainKind::External,
+            },
+            P2WPKH_WITNESS_SIZE,
+        );
+        vec![utxo; utxos_number]
+    }
+
+    fn sum_random_utxos(mut rng: &mut StdRng, utxos: &mut Vec<(UTXO, usize)>) -> u64 {
+        let utxos_picked_len = rng.gen_range(2, utxos.len() / 2);
+        utxos.shuffle(&mut rng);
+        utxos[..utxos_picked_len]
+            .iter()
+            .fold(0, |acc, x| acc + x.0.txout.value)
+    }
+
+    #[test]
+    fn test_largest_first_coin_selection_success() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        let result = LargestFirstCoinSelection::default()
+            .coin_select(
+                &database,
+                utxos,
+                vec![],
+                FeeRate::from_sat_per_vb(1.0),
+                250_000,
+                50.0,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 2);
+        assert_eq!(result.selected_amount, 300_000);
+        assert_eq!(result.fee_amount, 186.0);
+    }
+
+    #[test]
+    fn test_largest_first_coin_selection_use_all() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        let result = LargestFirstCoinSelection::default()
+            .coin_select(
+                &database,
+                utxos,
+                vec![],
+                FeeRate::from_sat_per_vb(1.0),
+                20_000,
+                50.0,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 2);
+        assert_eq!(result.selected_amount, 300_000);
+        assert_eq!(result.fee_amount, 186.0);
+    }
+
+    #[test]
+    fn test_largest_first_coin_selection_use_only_necessary() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        let result = LargestFirstCoinSelection::default()
+            .coin_select(
+                &database,
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb(1.0),
+                20_000,
+                50.0,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 1);
+        assert_eq!(result.selected_amount, 200_000);
+        assert_eq!(result.fee_amount, 118.0);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_largest_first_coin_selection_insufficient_funds() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        LargestFirstCoinSelection::default()
+            .coin_select(
+                &database,
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb(1.0),
+                500_000,
+                50.0,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_largest_first_coin_selection_insufficient_funds_high_fees() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        LargestFirstCoinSelection::default()
+            .coin_select(
+                &database,
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb(1000.0),
+                250_000,
+                50.0,
+            )
+            .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 database = MemoryDatabase::default();
+
+        let result = BranchAndBoundCoinSelection::default()
+            .coin_select(
+                &database,
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb(1.0),
+                250_000,
+                50.0,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 3);
+        assert_eq!(result.selected_amount, 300_000);
+        assert_eq!(result.fee_amount, 254.0);
+    }
+
+    #[test]
+    fn test_bnb_coin_selection_required_are_enough() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        let result = BranchAndBoundCoinSelection::default()
+            .coin_select(
+                &database,
+                utxos.clone(),
+                utxos,
+                FeeRate::from_sat_per_vb(1.0),
+                20_000,
+                50.0,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 2);
+        assert_eq!(result.selected_amount, 300_000);
+        assert_eq!(result.fee_amount, 186.0);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_bnb_coin_selection_insufficient_funds() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        BranchAndBoundCoinSelection::default()
+            .coin_select(
+                &database,
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb(1.0),
+                500_000,
+                50.0,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_bnb_coin_selection_insufficient_funds_high_fees() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        BranchAndBoundCoinSelection::default()
+            .coin_select(
+                &database,
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb(1000.0),
+                250_000,
+                50.0,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_bnb_coin_selection_check_fee_rate() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        let result = BranchAndBoundCoinSelection::new(0)
+            .coin_select(
+                &database,
+                vec![],
+                utxos.clone(),
+                FeeRate::from_sat_per_vb(1.0),
+                99932, // first utxo's effective value
+                0.0,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 1);
+        assert_eq!(result.selected_amount, 100_000);
+        let input_size = (TXIN_BASE_WEIGHT as f32) / 4.0 + P2WPKH_WITNESS_SIZE as f32 / 4.0;
+        let epsilon = 0.5;
+        assert!((1.0 - (result.fee_amount / input_size)).abs() < epsilon);
+    }
+
+    #[test]
+    fn test_bnb_coin_selection_exact_match() {
+        let seed = [0; 32];
+        let mut rng: StdRng = SeedableRng::from_seed(seed);
+        let database = MemoryDatabase::default();
+
+        for _i in 0..200 {
+            let mut optional_utxos = generate_random_utxos(&mut rng, 16);
+            let target_amount = sum_random_utxos(&mut rng, &mut optional_utxos);
+            let result = BranchAndBoundCoinSelection::new(0)
+                .coin_select(
+                    &database,
+                    vec![],
+                    optional_utxos,
+                    FeeRate::from_sat_per_vb(0.0),
+                    target_amount,
+                    0.0,
+                )
+                .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(10.0);
+        let utxos: Vec<OutputGroup> = get_test_utxos()
+            .into_iter()
+            .map(|u| OutputGroup::new(u.0, u.1, fee_rate))
+            .collect();
+
+        let curr_available_value = utxos
+            .iter()
+            .fold(0, |acc, x| acc + x.effective_value as u64);
+
+        let size_of_change = 31;
+        let cost_of_change = size_of_change as f32 * fee_rate.as_sat_vb();
+        BranchAndBoundCoinSelection::new(size_of_change)
+            .bnb(
+                vec![],
+                utxos,
+                0,
+                curr_available_value,
+                20_000,
+                50.0,
+                cost_of_change,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "BnBTotalTriesExceeded")]
+    fn test_bnb_function_tries_exceeded() {
+        let fee_rate = FeeRate::from_sat_per_vb(10.0);
+        let utxos: Vec<OutputGroup> = generate_same_value_utxos(100_000, 100_000)
+            .into_iter()
+            .map(|u| OutputGroup::new(u.0, u.1, fee_rate))
+            .collect();
+
+        let curr_available_value = utxos
+            .iter()
+            .fold(0, |acc, x| acc + x.effective_value as u64);
+
+        let size_of_change = 31;
+        let cost_of_change = size_of_change as f32 * fee_rate.as_sat_vb();
+
+        BranchAndBoundCoinSelection::new(size_of_change)
+            .bnb(
+                vec![],
+                utxos,
+                0,
+                curr_available_value,
+                20_000,
+                50.0,
+                cost_of_change,
+            )
+            .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(1.0);
+        let size_of_change = 31;
+        let cost_of_change = size_of_change as f32 * fee_rate.as_sat_vb();
+        let fee_amount = 50.0;
+
+        let utxos: Vec<_> = generate_same_value_utxos(50_000, 10)
+            .into_iter()
+            .map(|u| OutputGroup::new(u.0, u.1, fee_rate))
+            .collect();
+
+        let curr_value = 0;
+
+        let curr_available_value = utxos
+            .iter()
+            .fold(0, |acc, x| acc + x.effective_value as u64);
+
+        // 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.ceil() as u64 + 5;
+
+        let result = BranchAndBoundCoinSelection::new(size_of_change)
+            .bnb(
+                vec![],
+                utxos,
+                curr_value,
+                curr_available_value,
+                target_amount,
+                fee_amount,
+                cost_of_change,
+            )
+            .unwrap();
+        assert_eq!(result.fee_amount, 186.0);
+        assert_eq!(result.selected_amount, 100_000);
+    }
+
+    // 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::from_sat_per_vb(0.0);
+
+        for _ in 0..200 {
+            let optional_utxos: Vec<_> = generate_random_utxos(&mut rng, 40)
+                .into_iter()
+                .map(|u| OutputGroup::new(u.0, u.1, fee_rate))
+                .collect();
+
+            let curr_value = 0;
+
+            let curr_available_value = optional_utxos
+                .iter()
+                .fold(0, |acc, x| acc + x.effective_value as u64);
+
+            let target_amount = optional_utxos[3].effective_value as u64
+                + optional_utxos[23].effective_value as u64;
+
+            let result = BranchAndBoundCoinSelection::new(0)
+                .bnb(
+                    vec![],
+                    optional_utxos,
+                    curr_value,
+                    curr_available_value,
+                    target_amount,
+                    0.0,
+                    0.0,
+                )
+                .unwrap();
+            assert_eq!(result.selected_amount, target_amount);
+        }
+    }
+
+    #[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);
+
+        let fee_rate = FeeRate::from_sat_per_vb(1.0);
+        let utxos: Vec<OutputGroup> = utxos
+            .into_iter()
+            .map(|u| OutputGroup::new(u.0, u.1, fee_rate))
+            .collect();
+
+        let result = BranchAndBoundCoinSelection::default().single_random_draw(
+            vec![],
+            utxos,
+            0,
+            target_amount,
+            50.0,
+        );
+
+        assert!(result.selected_amount > target_amount);
+        assert_eq!(
+            result.fee_amount,
+            50.0 + result.selected.len() as f32 * 68.0
+        );
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/export.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/export.rs.html new file mode 100644 index 0000000000..1f0ffc2e91 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/export.rs.html @@ -0,0 +1,692 @@ +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
+342
+343
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! 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::database::*;
+//! # use bdk::wallet::export::*;
+//! # use bdk::*;
+//! let import = r#"{
+//!     "descriptor": "wpkh([c258d2e4\/84h\/1h\/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe\/0\/*)",
+//!     "blockheight":1782088,
+//!     "label":"testnet"
+//! }"#;
+//!
+//! let import = WalletExport::from_str(import)?;
+//! let wallet: OfflineWallet<_> = Wallet::new_offline(
+//!     &import.descriptor(),
+//!     import.change_descriptor().as_ref(),
+//!     Network::Testnet,
+//!     MemoryDatabase::default(),
+//! )?;
+//! # Ok::<_, bdk::Error>(())
+//! ```
+//!
+//! ### Export a `Wallet`
+//! ```
+//! # use bitcoin::*;
+//! # use bdk::database::*;
+//! # use bdk::wallet::export::*;
+//! # use bdk::*;
+//! let wallet: OfflineWallet<_> = Wallet::new_offline(
+//!     "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
+//!     Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
+//!     Network::Testnet,
+//!     MemoryDatabase::default()
+//! )?;
+//! let export = WalletExport::export_wallet(&wallet, "exported wallet", true)
+//!     .map_err(ToString::to_string)
+//!     .map_err(bdk::Error::Generic)?;
+//!
+//! println!("Exported: {}", export.to_string());
+//! # Ok::<_, bdk::Error>(())
+//! ```
+
+use std::str::FromStr;
+
+use serde::{Deserialize, Serialize};
+
+use miniscript::{Descriptor, DescriptorPublicKey, ScriptContext, Terminal};
+
+use crate::blockchain::BlockchainMarker;
+use crate::database::BatchDatabase;
+use crate::wallet::Wallet;
+
+/// 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 WalletExport {
+    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 ToString for WalletExport {
+    fn to_string(&self) -> String {
+        serde_json::to_string(self).unwrap()
+    }
+}
+
+impl FromStr for WalletExport {
+    type Err = serde_json::Error;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        serde_json::from_str(s)
+    }
+}
+
+impl WalletExport {
+    /// 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<B: BlockchainMarker, D: BatchDatabase>(
+        wallet: &Wallet<B, D>,
+        label: &str,
+        include_blockheight: bool,
+    ) -> Result<Self, &'static str> {
+        let descriptor = wallet
+            .descriptor
+            .to_string_with_secret(&wallet.signers.as_key_map(wallet.secp_ctx()));
+        Self::is_compatible_with_core(&descriptor)?;
+
+        let blockheight = match wallet.database.borrow().iter_txs(false) {
+            _ if !include_blockheight => 0,
+            Err(_) => 0,
+            Ok(txs) => {
+                let mut heights = txs
+                    .into_iter()
+                    .map(|tx| tx.height.unwrap_or(0))
+                    .collect::<Vec<_>>();
+                heights.sort_unstable();
+
+                *heights.last().unwrap_or(&0)
+            }
+        };
+
+        let export = WalletExport {
+            descriptor,
+            label: label.into(),
+            blockheight,
+        };
+
+        let desc_to_string = |d: &Descriptor<DescriptorPublicKey>| {
+            d.to_string_with_secret(&wallet.change_signers.as_key_map(wallet.secp_ctx()))
+        };
+        if export.change_descriptor() != wallet.change_descriptor.as_ref().map(desc_to_string) {
+            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")
+            }
+        }
+
+        match Descriptor::<String>::from_str(descriptor).map_err(|_| "Invalid descriptor")? {
+            Descriptor::Pk(_)
+            | Descriptor::Pkh(_)
+            | Descriptor::Wpkh(_)
+            | Descriptor::ShWpkh(_) => Ok(()),
+            Descriptor::Sh(ms) => check_ms(ms.node),
+            Descriptor::Wsh(ms) | Descriptor::ShWsh(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 std::str::FromStr;
+
+    use bitcoin::{Network, Txid};
+
+    use super::*;
+    use crate::database::{memory::MemoryDatabase, BatchOperations};
+    use crate::types::TransactionDetails;
+    use crate::wallet::{OfflineWallet, Wallet};
+
+    fn get_test_db() -> MemoryDatabase {
+        let mut db = MemoryDatabase::new();
+        db.set_tx(&TransactionDetails {
+            transaction: None,
+            txid: Txid::from_str(
+                "4ddff1fa33af17f377f62b72357b43107c19110a8009b36fb832af505efed98a",
+            )
+            .unwrap(),
+            timestamp: 12345678,
+            received: 100_000,
+            sent: 0,
+            fees: 500,
+            height: Some(5000),
+        })
+        .unwrap();
+
+        db
+    }
+
+    #[test]
+    fn test_export_bip44() {
+        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
+        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
+
+        let wallet: OfflineWallet<_> = Wallet::new_offline(
+            descriptor,
+            Some(change_descriptor),
+            Network::Bitcoin,
+            get_test_db(),
+        )
+        .unwrap();
+        let export = WalletExport::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: OfflineWallet<_> =
+            Wallet::new_offline(descriptor, None, Network::Bitcoin, get_test_db()).unwrap();
+        WalletExport::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: OfflineWallet<_> = Wallet::new_offline(
+            descriptor,
+            Some(change_descriptor),
+            Network::Bitcoin,
+            get_test_db(),
+        )
+        .unwrap();
+        WalletExport::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: OfflineWallet<_> = Wallet::new_offline(
+            descriptor,
+            Some(change_descriptor),
+            Network::Testnet,
+            get_test_db(),
+        )
+        .unwrap();
+        let export = WalletExport::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: OfflineWallet<_> = Wallet::new_offline(
+            descriptor,
+            Some(change_descriptor),
+            Network::Bitcoin,
+            get_test_db(),
+        )
+        .unwrap();
+        let export = WalletExport::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 = WalletExport::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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/mod.rs.html new file mode 100644 index 0000000000..a6ebcf5de5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/mod.rs.html @@ -0,0 +1,6828 @@ +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
+2709
+2710
+2711
+2712
+2713
+2714
+2715
+2716
+2717
+2718
+2719
+2720
+2721
+2722
+2723
+2724
+2725
+2726
+2727
+2728
+2729
+2730
+2731
+2732
+2733
+2734
+2735
+2736
+2737
+2738
+2739
+2740
+2741
+2742
+2743
+2744
+2745
+2746
+2747
+2748
+2749
+2750
+2751
+2752
+2753
+2754
+2755
+2756
+2757
+2758
+2759
+2760
+2761
+2762
+2763
+2764
+2765
+2766
+2767
+2768
+2769
+2770
+2771
+2772
+2773
+2774
+2775
+2776
+2777
+2778
+2779
+2780
+2781
+2782
+2783
+2784
+2785
+2786
+2787
+2788
+2789
+2790
+2791
+2792
+2793
+2794
+2795
+2796
+2797
+2798
+2799
+2800
+2801
+2802
+2803
+2804
+2805
+2806
+2807
+2808
+2809
+2810
+2811
+2812
+2813
+2814
+2815
+2816
+2817
+2818
+2819
+2820
+2821
+2822
+2823
+2824
+2825
+2826
+2827
+2828
+2829
+2830
+2831
+2832
+2833
+2834
+2835
+2836
+2837
+2838
+2839
+2840
+2841
+2842
+2843
+2844
+2845
+2846
+2847
+2848
+2849
+2850
+2851
+2852
+2853
+2854
+2855
+2856
+2857
+2858
+2859
+2860
+2861
+2862
+2863
+2864
+2865
+2866
+2867
+2868
+2869
+2870
+2871
+2872
+2873
+2874
+2875
+2876
+2877
+2878
+2879
+2880
+2881
+2882
+2883
+2884
+2885
+2886
+2887
+2888
+2889
+2890
+2891
+2892
+2893
+2894
+2895
+2896
+2897
+2898
+2899
+2900
+2901
+2902
+2903
+2904
+2905
+2906
+2907
+2908
+2909
+2910
+2911
+2912
+2913
+2914
+2915
+2916
+2917
+2918
+2919
+2920
+2921
+2922
+2923
+2924
+2925
+2926
+2927
+2928
+2929
+2930
+2931
+2932
+2933
+2934
+2935
+2936
+2937
+2938
+2939
+2940
+2941
+2942
+2943
+2944
+2945
+2946
+2947
+2948
+2949
+2950
+2951
+2952
+2953
+2954
+2955
+2956
+2957
+2958
+2959
+2960
+2961
+2962
+2963
+2964
+2965
+2966
+2967
+2968
+2969
+2970
+2971
+2972
+2973
+2974
+2975
+2976
+2977
+2978
+2979
+2980
+2981
+2982
+2983
+2984
+2985
+2986
+2987
+2988
+2989
+2990
+2991
+2992
+2993
+2994
+2995
+2996
+2997
+2998
+2999
+3000
+3001
+3002
+3003
+3004
+3005
+3006
+3007
+3008
+3009
+3010
+3011
+3012
+3013
+3014
+3015
+3016
+3017
+3018
+3019
+3020
+3021
+3022
+3023
+3024
+3025
+3026
+3027
+3028
+3029
+3030
+3031
+3032
+3033
+3034
+3035
+3036
+3037
+3038
+3039
+3040
+3041
+3042
+3043
+3044
+3045
+3046
+3047
+3048
+3049
+3050
+3051
+3052
+3053
+3054
+3055
+3056
+3057
+3058
+3059
+3060
+3061
+3062
+3063
+3064
+3065
+3066
+3067
+3068
+3069
+3070
+3071
+3072
+3073
+3074
+3075
+3076
+3077
+3078
+3079
+3080
+3081
+3082
+3083
+3084
+3085
+3086
+3087
+3088
+3089
+3090
+3091
+3092
+3093
+3094
+3095
+3096
+3097
+3098
+3099
+3100
+3101
+3102
+3103
+3104
+3105
+3106
+3107
+3108
+3109
+3110
+3111
+3112
+3113
+3114
+3115
+3116
+3117
+3118
+3119
+3120
+3121
+3122
+3123
+3124
+3125
+3126
+3127
+3128
+3129
+3130
+3131
+3132
+3133
+3134
+3135
+3136
+3137
+3138
+3139
+3140
+3141
+3142
+3143
+3144
+3145
+3146
+3147
+3148
+3149
+3150
+3151
+3152
+3153
+3154
+3155
+3156
+3157
+3158
+3159
+3160
+3161
+3162
+3163
+3164
+3165
+3166
+3167
+3168
+3169
+3170
+3171
+3172
+3173
+3174
+3175
+3176
+3177
+3178
+3179
+3180
+3181
+3182
+3183
+3184
+3185
+3186
+3187
+3188
+3189
+3190
+3191
+3192
+3193
+3194
+3195
+3196
+3197
+3198
+3199
+3200
+3201
+3202
+3203
+3204
+3205
+3206
+3207
+3208
+3209
+3210
+3211
+3212
+3213
+3214
+3215
+3216
+3217
+3218
+3219
+3220
+3221
+3222
+3223
+3224
+3225
+3226
+3227
+3228
+3229
+3230
+3231
+3232
+3233
+3234
+3235
+3236
+3237
+3238
+3239
+3240
+3241
+3242
+3243
+3244
+3245
+3246
+3247
+3248
+3249
+3250
+3251
+3252
+3253
+3254
+3255
+3256
+3257
+3258
+3259
+3260
+3261
+3262
+3263
+3264
+3265
+3266
+3267
+3268
+3269
+3270
+3271
+3272
+3273
+3274
+3275
+3276
+3277
+3278
+3279
+3280
+3281
+3282
+3283
+3284
+3285
+3286
+3287
+3288
+3289
+3290
+3291
+3292
+3293
+3294
+3295
+3296
+3297
+3298
+3299
+3300
+3301
+3302
+3303
+3304
+3305
+3306
+3307
+3308
+3309
+3310
+3311
+3312
+3313
+3314
+3315
+3316
+3317
+3318
+3319
+3320
+3321
+3322
+3323
+3324
+3325
+3326
+3327
+3328
+3329
+3330
+3331
+3332
+3333
+3334
+3335
+3336
+3337
+3338
+3339
+3340
+3341
+3342
+3343
+3344
+3345
+3346
+3347
+3348
+3349
+3350
+3351
+3352
+3353
+3354
+3355
+3356
+3357
+3358
+3359
+3360
+3361
+3362
+3363
+3364
+3365
+3366
+3367
+3368
+3369
+3370
+3371
+3372
+3373
+3374
+3375
+3376
+3377
+3378
+3379
+3380
+3381
+3382
+3383
+3384
+3385
+3386
+3387
+3388
+3389
+3390
+3391
+3392
+3393
+3394
+3395
+3396
+3397
+3398
+3399
+3400
+3401
+3402
+3403
+3404
+3405
+3406
+3407
+3408
+3409
+3410
+3411
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Wallet
+//!
+//! This module defines the [`Wallet`] structure.
+
+use std::cell::RefCell;
+use std::collections::HashMap;
+use std::collections::{BTreeMap, HashSet};
+use std::ops::{Deref, DerefMut};
+use std::sync::Arc;
+
+use bitcoin::secp256k1::Secp256k1;
+
+use bitcoin::consensus::encode::serialize;
+use bitcoin::util::base58;
+use bitcoin::util::bip32::ChildNumber;
+use bitcoin::util::psbt::raw::Key as PSBTKey;
+use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
+use bitcoin::{Address, Network, OutPoint, Script, Transaction, TxOut, Txid};
+
+use miniscript::psbt::PsbtInputSatisfier;
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+pub mod address_validator;
+pub mod coin_selection;
+pub mod export;
+pub mod signer;
+pub mod time;
+pub mod tx_builder;
+pub(crate) mod utils;
+
+pub use utils::IsDust;
+
+use address_validator::AddressValidator;
+use signer::{Signer, SignerId, SignerOrdering, SignersContainer};
+use tx_builder::{BumpFee, CreateTx, FeePolicy, TxBuilder, TxBuilderContext};
+use utils::{check_nlocktime, check_nsequence_rbf, descriptor_to_pk_ctx, After, Older, SecpCtx};
+
+use crate::blockchain::{Blockchain, BlockchainMarker, OfflineBlockchain, Progress};
+use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
+use crate::descriptor::{
+    get_checksum, DescriptorMeta, DescriptorScripts, ExtendedDescriptor, ExtractPolicy, Policy,
+    ToWalletDescriptor, XKeyUtils,
+};
+use crate::error::Error;
+use crate::psbt::PSBTUtils;
+use crate::types::*;
+
+const CACHE_ADDR_BATCH_SIZE: u32 = 100;
+
+/// Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]
+pub type OfflineWallet<D> = Wallet<OfflineBlockchain, D>;
+
+/// A Bitcoin wallet
+///
+/// A wallet takes descriptors, a [`database`](trait@crate::database::Database) and a
+/// [`blockchain`](trait@crate::blockchain::Blockchain) and implements the basic functions that a Bitcoin wallets
+/// needs to operate, like [generating addresses](Wallet::get_new_address), [returning the balance](Wallet::get_balance),
+/// [creating transactions](Wallet::create_tx), etc.
+///
+/// A wallet can be either "online" if the [`blockchain`](crate::blockchain) type provided
+/// implements [`Blockchain`], or "offline" [`OfflineBlockchain`] is used. Offline wallets only expose
+/// methods that don't need any interaction with the blockchain to work.
+pub struct Wallet<B, D> {
+    descriptor: ExtendedDescriptor,
+    change_descriptor: Option<ExtendedDescriptor>,
+
+    signers: Arc<SignersContainer>,
+    change_signers: Arc<SignersContainer>,
+
+    address_validators: Vec<Arc<dyn AddressValidator>>,
+
+    network: Network,
+
+    current_height: Option<u32>,
+
+    client: Option<B>,
+    database: RefCell<D>,
+
+    secp: SecpCtx,
+}
+
+// offline actions, always available
+impl<B, D> Wallet<B, D>
+where
+    B: BlockchainMarker,
+    D: BatchDatabase,
+{
+    /// Create a new "offline" wallet
+    pub fn new_offline<E: ToWalletDescriptor>(
+        descriptor: E,
+        change_descriptor: Option<E>,
+        network: Network,
+        mut database: D,
+    ) -> Result<Self, Error> {
+        let (descriptor, keymap) = descriptor.to_wallet_descriptor(network)?;
+        database.check_descriptor_checksum(
+            KeychainKind::External,
+            get_checksum(&descriptor.to_string())?.as_bytes(),
+        )?;
+        let signers = Arc::new(SignersContainer::from(keymap));
+        let (change_descriptor, change_signers) = match change_descriptor {
+            Some(desc) => {
+                let (change_descriptor, change_keymap) = desc.to_wallet_descriptor(network)?;
+                database.check_descriptor_checksum(
+                    KeychainKind::Internal,
+                    get_checksum(&change_descriptor.to_string())?.as_bytes(),
+                )?;
+
+                let change_signers = Arc::new(SignersContainer::from(change_keymap));
+                // if !parsed.same_structure(descriptor.as_ref()) {
+                //     return Err(Error::DifferentDescriptorStructure);
+                // }
+
+                (Some(change_descriptor), change_signers)
+            }
+            None => (None, Arc::new(SignersContainer::new())),
+        };
+
+        Ok(Wallet {
+            descriptor,
+            change_descriptor,
+            signers,
+            change_signers,
+            address_validators: Vec::new(),
+
+            network,
+
+            current_height: None,
+
+            client: None,
+            database: RefCell::new(database),
+
+            secp: Secp256k1::new(),
+        })
+    }
+
+    /// Return a newly generated address using the external descriptor
+    pub fn get_new_address(&self) -> Result<Address, Error> {
+        let index = self.fetch_and_increment_index(KeychainKind::External)?;
+        let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
+
+        self.descriptor
+            .derive(ChildNumber::from_normal_idx(index)?)
+            .address(self.network, deriv_ctx)
+            .ok_or(Error::ScriptDoesntHaveAddressForm)
+    }
+
+    /// Return whether or not a `script` is part of this wallet (either internal or external)
+    pub fn is_mine(&self, script: &Script) -> Result<bool, Error> {
+        self.database.borrow().is_mine(script)
+    }
+
+    /// Return the list of unspent outputs of this wallet
+    ///
+    /// Note that this methods only operate on the internal database, which first needs to be
+    /// [`Wallet::sync`] manually.
+    pub fn list_unspent(&self) -> Result<Vec<UTXO>, Error> {
+        self.database.borrow().iter_utxos()
+    }
+
+    /// Return the list of transactions made and received by the wallet
+    ///
+    /// Optionally fill the [`TransactionDetails::transaction`] field with the raw transaction if
+    /// `include_raw` is `true`.
+    ///
+    /// Note that this methods only operate on the internal database, which first needs to be
+    /// [`Wallet::sync`] manually.
+    pub fn list_transactions(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
+        self.database.borrow().iter_txs(include_raw)
+    }
+
+    /// Return the balance, meaning the sum of this wallet's unspent outputs' values
+    ///
+    /// Note that this methods only operate on the internal database, which first needs to be
+    /// [`Wallet::sync`] manually.
+    pub fn get_balance(&self) -> Result<u64, Error> {
+        Ok(self
+            .list_unspent()?
+            .iter()
+            .fold(0, |sum, i| sum + i.txout.value))
+    }
+
+    /// Add an external signer
+    ///
+    /// See [the `signer` module](signer) for an example.
+    pub fn add_signer(
+        &mut self,
+        keychain: KeychainKind,
+        id: SignerId,
+        ordering: SignerOrdering,
+        signer: Arc<dyn Signer>,
+    ) {
+        let signers = match keychain {
+            KeychainKind::External => Arc::make_mut(&mut self.signers),
+            KeychainKind::Internal => Arc::make_mut(&mut self.change_signers),
+        };
+
+        signers.add_external(id, ordering, signer);
+    }
+
+    /// Add an address validator
+    ///
+    /// See [the `address_validator` module](address_validator) for an example.
+    pub fn add_address_validator(&mut self, validator: Arc<dyn AddressValidator>) {
+        self.address_validators.push(validator);
+    }
+
+    /// Create a new transaction following the options specified in the `builder`
+    ///
+    /// ## Example
+    ///
+    /// ```no_run
+    /// # use std::str::FromStr;
+    /// # use bitcoin::*;
+    /// # use bdk::*;
+    /// # use bdk::database::*;
+    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+    /// let (psbt, details) = wallet.create_tx(
+    ///     TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+    /// )?;
+    /// // sign and broadcast ...
+    /// # Ok::<(), bdk::Error>(())
+    /// ```
+    pub fn create_tx<Cs: coin_selection::CoinSelectionAlgorithm<D>>(
+        &self,
+        builder: TxBuilder<D, Cs, CreateTx>,
+    ) -> Result<(PSBT, TransactionDetails), Error> {
+        let external_policy = self
+            .descriptor
+            .extract_policy(&self.signers, &self.secp)?
+            .unwrap();
+        let internal_policy = self
+            .change_descriptor
+            .as_ref()
+            .map(|desc| {
+                Ok::<_, Error>(
+                    desc.extract_policy(&self.change_signers, &self.secp)?
+                        .unwrap(),
+                )
+            })
+            .transpose()?;
+
+        // The policy allows spending external outputs, but it requires a policy path that hasn't been
+        // provided
+        if builder.change_policy != tx_builder::ChangeSpendPolicy::OnlyChange
+            && external_policy.requires_path()
+            && builder.external_policy_path.is_none()
+        {
+            return Err(Error::SpendingPolicyRequired(KeychainKind::External));
+        };
+        // Same for the internal_policy path, if present
+        if let Some(internal_policy) = &internal_policy {
+            if builder.change_policy != tx_builder::ChangeSpendPolicy::ChangeForbidden
+                && internal_policy.requires_path()
+                && builder.internal_policy_path.is_none()
+            {
+                return Err(Error::SpendingPolicyRequired(KeychainKind::Internal));
+            };
+        }
+
+        let external_requirements = external_policy.get_condition(
+            builder
+                .external_policy_path
+                .as_ref()
+                .unwrap_or(&BTreeMap::new()),
+        )?;
+        let internal_requirements = internal_policy
+            .map(|policy| {
+                Ok::<_, Error>(
+                    policy.get_condition(
+                        builder
+                            .internal_policy_path
+                            .as_ref()
+                            .unwrap_or(&BTreeMap::new()),
+                    )?,
+                )
+            })
+            .transpose()?;
+
+        let requirements = external_requirements
+            .clone()
+            .merge(&internal_requirements.unwrap_or_default())?;
+        debug!("Policy requirements: {:?}", requirements);
+
+        let version = match builder.version {
+            Some(tx_builder::Version(0)) => {
+                return Err(Error::Generic("Invalid version `0`".into()))
+            }
+            Some(tx_builder::Version(1)) if requirements.csv.is_some() => {
+                return Err(Error::Generic(
+                    "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
+                        .into(),
+                ))
+            }
+            Some(tx_builder::Version(x)) => x,
+            None if requirements.csv.is_some() => 2,
+            _ => 1,
+        };
+
+        let lock_time = match builder.locktime {
+            // No nLockTime, default to 0
+            None => requirements.timelock.unwrap_or(0),
+            // 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 check_nlocktime(x, requirements.timelock.unwrap()) => x,
+            // Invalid nLockTime required
+            Some(x) => return Err(Error::Generic(format!("TxBuilder requested timelock of `{}`, but at least `{}` is required to spend from this script", x, requirements.timelock.unwrap())))
+        };
+
+        let n_sequence = match (builder.rbf, requirements.csv) {
+            // No RBF or CSV but there's an nLockTime, so the nSequence cannot be final
+            (None, None) if lock_time != 0 => 0xFFFFFFFE,
+            // No RBF, CSV or nLockTime, make the transaction final
+            (None, None) => 0xFFFFFFFF,
+
+            // 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 >= 0xFFFFFFFE => {
+                return Err(Error::Generic(
+                    "Cannot enable RBF with a nSequence >= 0xFFFFFFFE".into(),
+                ))
+            }
+            // 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(Error::Generic(format!(
+                    "Cannot enable RBF with nSequence `{}` given a required OP_CSV of `{}`",
+                    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 mut tx = Transaction {
+            version,
+            lock_time,
+            input: vec![],
+            output: vec![],
+        };
+
+        let (fee_rate, mut fee_amount) = match builder
+            .fee_policy
+            .as_ref()
+            .unwrap_or(&FeePolicy::FeeRate(FeeRate::default()))
+        {
+            FeePolicy::FeeAmount(amount) => (FeeRate::from_sat_per_vb(0.0), *amount as f32),
+            FeePolicy::FeeRate(rate) => (*rate, 0.0),
+        };
+
+        // try not to move from `builder` because we still need to use it later.
+        let recipients = match &builder.single_recipient {
+            Some(recipient) => vec![(recipient, 0)],
+            None => builder.recipients.iter().map(|(r, v)| (r, *v)).collect(),
+        };
+        if builder.single_recipient.is_some()
+            && !builder.manually_selected_only
+            && !builder.drain_wallet
+        {
+            return Err(Error::SingleRecipientNoInputs);
+        }
+        if recipients.is_empty() {
+            return Err(Error::NoRecipients);
+        }
+
+        if builder.manually_selected_only && builder.utxos.is_empty() {
+            return Err(Error::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 calc_fee_bytes = |wu| (wu as f32) * fee_rate.as_sat_vb() / 4.0;
+        fee_amount += calc_fee_bytes(tx.get_weight());
+
+        for (index, (script_pubkey, satoshi)) in recipients.into_iter().enumerate() {
+            let value = match builder.single_recipient {
+                Some(_) => 0,
+                None if satoshi.is_dust() => return Err(Error::OutputBelowDustLimit(index)),
+                None => satoshi,
+            };
+
+            if self.is_mine(script_pubkey)? {
+                received += value;
+            }
+
+            let new_out = TxOut {
+                script_pubkey: script_pubkey.clone(),
+                value,
+            };
+            fee_amount += calc_fee_bytes(serialize(&new_out).len() * 4);
+
+            tx.output.push(new_out);
+
+            outgoing += value;
+        }
+
+        if builder.change_policy != tx_builder::ChangeSpendPolicy::ChangeAllowed
+            && self.change_descriptor.is_none()
+        {
+            return Err(Error::Generic(
+                "The `change_policy` can be set only if the wallet has a change_descriptor".into(),
+            ));
+        }
+
+        let (required_utxos, optional_utxos) = self.preselect_utxos(
+            builder.change_policy,
+            &builder.unspendable,
+            &builder.utxos,
+            builder.drain_wallet,
+            builder.manually_selected_only,
+            false, // we don't mind using unconfirmed outputs here, hopefully coin selection will sort this out?
+        )?;
+
+        let coin_selection::CoinSelectionResult {
+            selected,
+            selected_amount,
+            mut fee_amount,
+        } = builder.coin_selection.coin_select(
+            self.database.borrow().deref(),
+            required_utxos,
+            optional_utxos,
+            fee_rate,
+            outgoing,
+            fee_amount,
+        )?;
+        tx.input = selected
+            .iter()
+            .map(|u| bitcoin::TxIn {
+                previous_output: u.outpoint,
+                script_sig: Script::default(),
+                sequence: n_sequence,
+                witness: vec![],
+            })
+            .collect();
+
+        // prepare the change output
+        let change_output = match builder.single_recipient {
+            Some(_) => None,
+            None => {
+                let change_script = self.get_change_address()?;
+                let change_output = TxOut {
+                    script_pubkey: change_script,
+                    value: 0,
+                };
+
+                // take the change into account for fees
+                fee_amount += calc_fee_bytes(serialize(&change_output).len() * 4);
+                Some(change_output)
+            }
+        };
+
+        let mut fee_amount = fee_amount.ceil() as u64;
+        let change_val = (selected_amount - outgoing).saturating_sub(fee_amount);
+
+        match change_output {
+            None if change_val.is_dust() => {
+                // single recipient, but the only output would be below dust limit
+                return Err(Error::InsufficientFunds); // TODO: or OutputBelowDustLimit?
+            }
+            Some(_) if change_val.is_dust() => {
+                // skip the change output because it's dust, this adds up to the fees
+                fee_amount += selected_amount - outgoing;
+            }
+            Some(mut change_output) => {
+                change_output.value = change_val;
+                received += change_val;
+
+                tx.output.push(change_output);
+            }
+            None => {
+                // there's only one output, send everything to it
+                tx.output[0].value = change_val;
+
+                // the single recipient is our address
+                if self.is_mine(&tx.output[0].script_pubkey)? {
+                    received = change_val;
+                }
+            }
+        }
+
+        // sort input/outputs according to the chosen algorithm
+        builder.ordering.sort_tx(&mut tx);
+
+        let txid = tx.txid();
+        let psbt = self.complete_transaction(tx, selected, builder)?;
+
+        let transaction_details = TransactionDetails {
+            transaction: None,
+            txid,
+            timestamp: time::get_timestamp(),
+            received,
+            sent: selected_amount,
+            fees: fee_amount,
+            height: None,
+        };
+
+        Ok((psbt, transaction_details))
+    }
+
+    /// Bump the fee of a transaction following the options specified in the `builder`
+    ///
+    /// Return an error if the transaction is already confirmed or doesn't explicitly signal RBF.
+    ///
+    /// **NOTE**: if the original transaction was made with [`TxBuilder::set_single_recipient`],
+    /// the [`TxBuilder::maintain_single_recipient`] flag should be enabled to correctly reduce the
+    /// only output's value in order to increase the fees.
+    ///
+    /// If the `builder` specifies some `utxos` that must be spent, they will be added to the
+    /// transaction regardless of whether they are necessary or not to cover additional fees.
+    ///
+    /// ## Example
+    ///
+    /// ```no_run
+    /// # use std::str::FromStr;
+    /// # use bitcoin::*;
+    /// # use bdk::*;
+    /// # use bdk::database::*;
+    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+    /// let txid = Txid::from_str("faff0a466b70f5d5f92bd757a92c1371d4838bdd5bc53a06764e2488e51ce8f8").unwrap();
+    /// let (psbt, details) = wallet.bump_fee(
+    ///     &txid,
+    ///     TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(5.0)),
+    /// )?;
+    /// // sign and broadcast ...
+    /// # Ok::<(), bdk::Error>(())
+    /// ```
+    // TODO: support for merging multiple transactions while bumping the fees
+    // TODO: option to force addition of an extra output? seems bad for privacy to update the
+    // change
+    pub fn bump_fee<Cs: coin_selection::CoinSelectionAlgorithm<D>>(
+        &self,
+        txid: &Txid,
+        builder: TxBuilder<D, Cs, BumpFee>,
+    ) -> Result<(PSBT, TransactionDetails), Error> {
+        let mut details = match self.database.borrow().get_tx(&txid, true)? {
+            None => return Err(Error::TransactionNotFound),
+            Some(tx) if tx.transaction.is_none() => return Err(Error::TransactionNotFound),
+            Some(tx) if tx.height.is_some() => return Err(Error::TransactionConfirmed),
+            Some(tx) => tx,
+        };
+        let mut tx = details.transaction.take().unwrap();
+        if !tx.input.iter().any(|txin| txin.sequence <= 0xFFFFFFFD) {
+            return Err(Error::IrreplaceableTransaction);
+        }
+
+        // the new tx must "pay for its bandwidth"
+        let vbytes = tx.get_weight() as f32 / 4.0;
+        let required_feerate = FeeRate::from_sat_per_vb(details.fees as f32 / vbytes + 1.0);
+
+        // find the index of the output that we can update. either the change or the only one if
+        // it's `single_recipient`
+        let updatable_output = match builder.single_recipient {
+            Some(_) if tx.output.len() != 1 => return Err(Error::SingleRecipientMultipleOutputs),
+            Some(_) => Some(0),
+            None => {
+                let mut change_output = None;
+                for (index, txout) in tx.output.iter().enumerate() {
+                    // look for an output that we know and that has the right KeychainKind. We use
+                    // `get_descriptor_for` to find what's the KeychainKind for `Internal`
+                    // addresses really is, because if there's no change_descriptor it's actually equal
+                    // to "External"
+                    let (_, change_type) = self.get_descriptor_for_keychain(KeychainKind::Internal);
+                    match self
+                        .database
+                        .borrow()
+                        .get_path_from_script_pubkey(&txout.script_pubkey)?
+                    {
+                        Some((keychain, _)) if keychain == change_type => {
+                            change_output = Some(index);
+                            break;
+                        }
+                        _ => {}
+                    }
+                }
+
+                change_output
+            }
+        };
+        let updatable_output = match updatable_output {
+            Some(updatable_output) => updatable_output,
+            None => {
+                // we need a change output, add one here and take into account the extra fees for it
+                let change_script = self.get_change_address()?;
+                let change_txout = TxOut {
+                    script_pubkey: change_script,
+                    value: 0,
+                };
+                tx.output.push(change_txout);
+
+                tx.output.len() - 1
+            }
+        };
+
+        // initially always remove the output we can change
+        let mut removed_updatable_output = tx.output.remove(updatable_output);
+        if self.is_mine(&removed_updatable_output.script_pubkey)? {
+            details.received -= removed_updatable_output.value;
+        }
+
+        let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
+        let original_sequence = tx.input[0].sequence;
+
+        // remove the inputs from the tx and process them
+        let original_txin = tx.input.drain(..).collect::<Vec<_>>();
+        let mut original_utxos = original_txin
+            .iter()
+            .map(|txin| -> Result<(UTXO, usize), Error> {
+                let txout = self
+                    .database
+                    .borrow()
+                    .get_previous_output(&txin.previous_output)?
+                    .ok_or(Error::UnknownUTXO)?;
+
+                let (weight, keychain) = match self
+                    .database
+                    .borrow()
+                    .get_path_from_script_pubkey(&txout.script_pubkey)?
+                {
+                    Some((keychain, _)) => (
+                        self.get_descriptor_for_keychain(keychain)
+                            .0
+                            .max_satisfaction_weight(deriv_ctx)
+                            .unwrap(),
+                        keychain,
+                    ),
+                    None => {
+                        // estimate the weight based on the scriptsig/witness size present in the
+                        // original transaction
+                        let weight =
+                            serialize(&txin.script_sig).len() * 4 + serialize(&txin.witness).len();
+                        (weight, KeychainKind::External)
+                    }
+                };
+
+                let utxo = UTXO {
+                    outpoint: txin.previous_output,
+                    txout,
+                    keychain,
+                };
+
+                Ok((utxo, weight))
+            })
+            .collect::<Result<Vec<_>, _>>()?;
+
+        if builder.manually_selected_only && builder.utxos.is_empty() {
+            return Err(Error::NoUtxosSelected);
+        }
+
+        let builder_extra_utxos = builder
+            .utxos
+            .iter()
+            .filter(|utxo| {
+                !original_txin
+                    .iter()
+                    .any(|txin| &&txin.previous_output == utxo)
+            })
+            .cloned()
+            .collect::<Vec<_>>();
+
+        let (mut required_utxos, optional_utxos) = self.preselect_utxos(
+            builder.change_policy,
+            &builder.unspendable,
+            &builder_extra_utxos[..],
+            builder.drain_wallet,
+            builder.manually_selected_only,
+            true, // we only want confirmed transactions for RBF
+        )?;
+
+        required_utxos.append(&mut original_utxos);
+
+        let amount_needed = tx.output.iter().fold(0, |acc, out| acc + out.value);
+        let (new_feerate, initial_fee) = match builder
+            .fee_policy
+            .as_ref()
+            .unwrap_or(&FeePolicy::FeeRate(FeeRate::default()))
+        {
+            FeePolicy::FeeAmount(amount) => {
+                if *amount < details.fees {
+                    return Err(Error::FeeTooLow {
+                        required: details.fees,
+                    });
+                }
+                (FeeRate::from_sat_per_vb(0.0), *amount as f32)
+            }
+            FeePolicy::FeeRate(rate) => {
+                if *rate < required_feerate {
+                    return Err(Error::FeeRateTooLow {
+                        required: required_feerate,
+                    });
+                }
+                (*rate, tx.get_weight() as f32 / 4.0 * rate.as_sat_vb())
+            }
+        };
+
+        let coin_selection::CoinSelectionResult {
+            selected,
+            selected_amount,
+            fee_amount,
+        } = builder.coin_selection.coin_select(
+            self.database.borrow().deref(),
+            required_utxos,
+            optional_utxos,
+            new_feerate,
+            amount_needed,
+            initial_fee,
+        )?;
+
+        tx.input = selected
+            .iter()
+            .map(|u| bitcoin::TxIn {
+                previous_output: u.outpoint,
+                script_sig: Script::default(),
+                // TODO: use builder.n_sequence??
+                sequence: original_sequence,
+                witness: vec![],
+            })
+            .collect();
+
+        details.sent = selected_amount;
+
+        let mut fee_amount = fee_amount.ceil() as u64;
+        let removed_output_fee_cost = (serialize(&removed_updatable_output).len() as f32
+            * new_feerate.as_sat_vb())
+        .ceil() as u64;
+
+        let change_val = selected_amount - amount_needed - fee_amount;
+        let change_val_after_add = change_val.saturating_sub(removed_output_fee_cost);
+        match builder.single_recipient {
+            None if change_val_after_add.is_dust() => {
+                // skip the change output because it's dust, this adds up to the fees
+                fee_amount += change_val;
+            }
+            Some(_) if change_val_after_add.is_dust() => {
+                // single_recipient but the only output would be below dust limit
+                return Err(Error::InsufficientFunds); // TODO: or OutputBelowDustLimit?
+            }
+            None => {
+                removed_updatable_output.value = change_val_after_add;
+                fee_amount += removed_output_fee_cost;
+                details.received += change_val_after_add;
+
+                tx.output.push(removed_updatable_output);
+            }
+            Some(_) => {
+                removed_updatable_output.value = change_val_after_add;
+                fee_amount += removed_output_fee_cost;
+
+                // single recipient and it's our address
+                if self.is_mine(&removed_updatable_output.script_pubkey)? {
+                    details.received = change_val_after_add;
+                }
+
+                tx.output.push(removed_updatable_output);
+            }
+        }
+
+        // sort input/outputs according to the chosen algorithm
+        builder.ordering.sort_tx(&mut tx);
+
+        // TODO: check that we are not replacing more than 100 txs from mempool
+
+        details.txid = tx.txid();
+        details.fees = fee_amount;
+        details.timestamp = time::get_timestamp();
+
+        let psbt = self.complete_transaction(tx, selected, builder)?;
+
+        Ok((psbt, details))
+    }
+
+    /// Sign a transaction with all the wallet's signers, in the order specified by every signer's
+    /// [`SignerOrdering`]
+    ///
+    /// ## Example
+    ///
+    /// ```no_run
+    /// # use std::str::FromStr;
+    /// # use bitcoin::*;
+    /// # use bdk::*;
+    /// # use bdk::database::*;
+    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+    /// # let (psbt, _) = wallet.create_tx(TxBuilder::new())?;
+    /// let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
+    /// # Ok::<(), bdk::Error>(())
+    pub fn sign(&self, mut psbt: PSBT, assume_height: Option<u32>) -> Result<(PSBT, bool), Error> {
+        // this helps us doing our job later
+        self.add_input_hd_keypaths(&mut psbt)?;
+
+        for signer in self
+            .signers
+            .signers()
+            .iter()
+            .chain(self.change_signers.signers().iter())
+        {
+            if signer.sign_whole_tx() {
+                signer.sign(&mut psbt, None, &self.secp)?;
+            } else {
+                for index in 0..psbt.inputs.len() {
+                    signer.sign(&mut psbt, Some(index), &self.secp)?;
+                }
+            }
+        }
+
+        // attempt to finalize
+        self.finalize_psbt(psbt, assume_height)
+    }
+
+    /// Return the spending policies for the wallet's descriptor
+    pub fn policies(&self, keychain: KeychainKind) -> Result<Option<Policy>, Error> {
+        match (keychain, self.change_descriptor.as_ref()) {
+            (KeychainKind::External, _) => {
+                Ok(self.descriptor.extract_policy(&self.signers, &self.secp)?)
+            }
+            (KeychainKind::Internal, None) => Ok(None),
+            (KeychainKind::Internal, Some(desc)) => {
+                Ok(desc.extract_policy(&self.change_signers, &self.secp)?)
+            }
+        }
+    }
+
+    /// 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,
+    ) -> Result<Option<ExtendedDescriptor>, Error> {
+        match (keychain, self.change_descriptor.as_ref()) {
+            (KeychainKind::External, _) => Ok(Some(self.descriptor.clone())),
+            (KeychainKind::Internal, None) => Ok(None),
+            (KeychainKind::Internal, Some(desc)) => Ok(Some(desc.clone())),
+        }
+    }
+
+    /// Try to finalize a PSBT
+    pub fn finalize_psbt(
+        &self,
+        mut psbt: PSBT,
+        assume_height: Option<u32>,
+    ) -> Result<(PSBT, bool), Error> {
+        let tx = &psbt.global.unsigned_tx;
+        let mut finished = true;
+
+        for (n, input) in tx.input.iter().enumerate() {
+            let psbt_input = &psbt.inputs[n];
+            if psbt_input.final_script_sig.is_some() || psbt_input.final_script_witness.is_some() {
+                continue;
+            }
+            // if the height is None in the database it means it's still unconfirmed, so consider
+            // that as a very high value
+            let create_height = self
+                .database
+                .borrow()
+                .get_tx(&input.previous_output.txid, false)?
+                .map(|tx| tx.height.unwrap_or(std::u32::MAX));
+            let current_height = assume_height.or(self.current_height);
+
+            debug!(
+                "Input #{} - {}, using `create_height` = {:?}, `current_height` = {:?}",
+                n, input.previous_output, create_height, current_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 `hd_keypaths`,
+            //   `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)
+                .map(|txout| self.get_descriptor_for_txout(&txout))
+                .transpose()?
+                .flatten()
+                .or_else(|| {
+                    self.descriptor.derive_from_psbt_input(
+                        psbt_input,
+                        psbt.get_utxo_for(n),
+                        &self.secp,
+                    )
+                })
+                .or_else(|| {
+                    self.change_descriptor.as_ref().and_then(|desc| {
+                        desc.derive_from_psbt_input(psbt_input, psbt.get_utxo_for(n), &self.secp)
+                    })
+                });
+
+            match desc {
+                Some(desc) => {
+                    let mut tmp_input = bitcoin::TxIn::default();
+                    let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
+                    match desc.satisfy(
+                        &mut tmp_input,
+                        (
+                            PsbtInputSatisfier::new(&psbt, n),
+                            After::new(current_height, false),
+                            Older::new(current_height, create_height, false),
+                        ),
+                        deriv_ctx,
+                    ) {
+                        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);
+                        }
+                        Err(e) => {
+                            debug!("satisfy error {:?} for input {}", e, n);
+                            finished = false
+                        }
+                    }
+                }
+                None => finished = false,
+            }
+        }
+
+        Ok((psbt, finished))
+    }
+
+    /// Return the secp256k1 context used for all signing operations
+    pub fn secp_ctx(&self) -> &SecpCtx {
+        &self.secp
+    }
+
+    // Internals
+
+    fn get_descriptor_for_keychain(
+        &self,
+        keychain: KeychainKind,
+    ) -> (&ExtendedDescriptor, KeychainKind) {
+        match keychain {
+            KeychainKind::Internal if self.change_descriptor.is_some() => (
+                self.change_descriptor.as_ref().unwrap(),
+                KeychainKind::Internal,
+            ),
+            _ => (&self.descriptor, KeychainKind::External),
+        }
+    }
+
+    fn get_descriptor_for_txout(&self, txout: &TxOut) -> Result<Option<ExtendedDescriptor>, Error> {
+        Ok(self
+            .database
+            .borrow()
+            .get_path_from_script_pubkey(&txout.script_pubkey)?
+            .map(|(keychain, child)| (self.get_descriptor_for_keychain(keychain).0, child))
+            .map(|(desc, child)| desc.derive(ChildNumber::from_normal_idx(child).unwrap())))
+    }
+
+    fn get_change_address(&self) -> Result<Script, Error> {
+        let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
+
+        let (desc, keychain) = self.get_descriptor_for_keychain(KeychainKind::Internal);
+        let index = self.fetch_and_increment_index(keychain)?;
+
+        Ok(desc
+            .derive(ChildNumber::from_normal_idx(index)?)
+            .script_pubkey(deriv_ctx))
+    }
+
+    fn fetch_and_increment_index(&self, keychain: KeychainKind) -> Result<u32, Error> {
+        let (descriptor, keychain) = self.get_descriptor_for_keychain(keychain);
+        let index = match descriptor.is_fixed() {
+            true => 0,
+            false => self.database.borrow_mut().increment_last_index(keychain)?,
+        };
+
+        if self
+            .database
+            .borrow()
+            .get_script_pubkey_from_path(keychain, index)?
+            .is_none()
+        {
+            self.cache_addresses(keychain, index, CACHE_ADDR_BATCH_SIZE)?;
+        }
+
+        let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
+
+        let hd_keypaths = descriptor.get_hd_keypaths(index, &self.secp)?;
+        let script = descriptor
+            .derive(ChildNumber::from_normal_idx(index)?)
+            .script_pubkey(deriv_ctx);
+        for validator in &self.address_validators {
+            validator.validate(keychain, &hd_keypaths, &script)?;
+        }
+
+        Ok(index)
+    }
+
+    fn cache_addresses(
+        &self,
+        keychain: KeychainKind,
+        from: u32,
+        mut count: u32,
+    ) -> Result<(), Error> {
+        let (descriptor, keychain) = self.get_descriptor_for_keychain(keychain);
+        if descriptor.is_fixed() {
+            if from > 0 {
+                return Ok(());
+            }
+
+            count = 1;
+        }
+
+        let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
+
+        let mut address_batch = self.database.borrow().begin_batch();
+
+        let start_time = time::Instant::new();
+        for i in from..(from + count) {
+            address_batch.set_script_pubkey(
+                &descriptor
+                    .derive(ChildNumber::from_normal_idx(i)?)
+                    .script_pubkey(deriv_ctx),
+                keychain,
+                i,
+            )?;
+        }
+
+        info!(
+            "Derivation of {} addresses from {} took {} ms",
+            count,
+            from,
+            start_time.elapsed().as_millis()
+        );
+
+        self.database.borrow_mut().commit_batch(address_batch)?;
+
+        Ok(())
+    }
+
+    fn get_available_utxos(&self) -> Result<Vec<(UTXO, usize)>, Error> {
+        let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
+        Ok(self
+            .list_unspent()?
+            .into_iter()
+            .map(|utxo| {
+                let keychain = utxo.keychain;
+                (
+                    utxo,
+                    self.get_descriptor_for_keychain(keychain)
+                        .0
+                        .max_satisfaction_weight(deriv_ctx)
+                        .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.
+    #[allow(clippy::type_complexity)]
+    fn preselect_utxos(
+        &self,
+        change_policy: tx_builder::ChangeSpendPolicy,
+        unspendable: &HashSet<OutPoint>,
+        manually_selected: &[OutPoint],
+        must_use_all_available: bool,
+        manual_only: bool,
+        must_only_use_confirmed_tx: bool,
+    ) -> Result<(Vec<(UTXO, usize)>, Vec<(UTXO, usize)>), Error> {
+        //    must_spend <- manually selected utxos
+        //    may_spend  <- all other available utxos
+        let mut may_spend = self.get_available_utxos()?;
+        let mut must_spend = {
+            let must_spend_idx = manually_selected
+                .iter()
+                .map(|manually_selected| {
+                    may_spend
+                        .iter()
+                        .position(|available| available.0.outpoint == *manually_selected)
+                        .ok_or(Error::UnknownUTXO)
+                })
+                .collect::<Result<Vec<_>, _>>()?;
+
+            must_spend_idx
+                .into_iter()
+                .map(|i| may_spend.remove(i))
+                .collect()
+        };
+
+        // NOTE: we are intentionally ignoring `unspendable` here. i.e manual
+        // selection overrides unspendable.
+        if manual_only {
+            return Ok((must_spend, vec![]));
+        }
+
+        let satisfies_confirmed = match must_only_use_confirmed_tx {
+            true => {
+                let database = self.database.borrow_mut();
+                may_spend
+                    .iter()
+                    .map(|u| {
+                        database
+                            .get_tx(&u.0.outpoint.txid, true)
+                            .map(|tx| match tx {
+                                None => false,
+                                Some(tx) => tx.height.is_some(),
+                            })
+                    })
+                    .collect::<Result<Vec<_>, _>>()?
+            }
+            false => vec![true; may_spend.len()],
+        };
+
+        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
+        });
+
+        if must_use_all_available {
+            must_spend.append(&mut may_spend);
+        }
+
+        Ok((must_spend, may_spend))
+    }
+
+    fn complete_transaction<
+        Cs: coin_selection::CoinSelectionAlgorithm<D>,
+        Ctx: TxBuilderContext,
+    >(
+        &self,
+        tx: Transaction,
+        selected: Vec<UTXO>,
+        builder: TxBuilder<D, Cs, Ctx>,
+    ) -> Result<PSBT, Error> {
+        use bitcoin::util::psbt::serialize::Serialize;
+
+        let mut psbt = PSBT::from_unsigned_tx(tx)?;
+
+        if builder.add_global_xpubs {
+            let mut all_xpubs = self.descriptor.get_extended_keys()?;
+            if let Some(change_descriptor) = &self.change_descriptor {
+                all_xpubs.extend(change_descriptor.get_extended_keys()?);
+            }
+
+            for xpub in all_xpubs {
+                let serialized_xpub = base58::from_check(&xpub.xkey.to_string())
+                    .expect("Internal serialization error");
+                let key = PSBTKey {
+                    type_value: 0x01,
+                    key: serialized_xpub,
+                };
+
+                let origin = match xpub.origin {
+                    Some(origin) => origin,
+                    None if xpub.xkey.depth == 0 => {
+                        (xpub.root_fingerprint(&self.secp), vec![].into())
+                    }
+                    _ => return Err(Error::MissingKeyOrigin(xpub.xkey.to_string())),
+                };
+
+                psbt.global.unknown.insert(key, origin.serialize());
+            }
+        }
+
+        let 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.global.unsigned_tx.input.iter())
+        {
+            let utxo = match lookup_output.get(&input.previous_output) {
+                Some(utxo) => utxo,
+                None => continue,
+            };
+
+            // Only set it if the builder has a custom one, otherwise leave blank which defaults to
+            // SIGHASH_ALL
+            if let Some(sighash_type) = builder.sighash {
+                psbt_input.sighash_type = Some(sighash_type);
+            }
+
+            // 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) = match self
+                .database
+                .borrow()
+                .get_path_from_script_pubkey(&utxo.txout.script_pubkey)?
+            {
+                Some(x) => x,
+                None => continue,
+            };
+
+            let (desc, _) = self.get_descriptor_for_keychain(keychain);
+            psbt_input.hd_keypaths = desc.get_hd_keypaths(child, &self.secp)?;
+            let derived_descriptor = desc.derive(ChildNumber::from_normal_idx(child)?);
+
+            psbt_input.redeem_script = derived_descriptor.psbt_redeem_script(&self.secp);
+            psbt_input.witness_script = derived_descriptor.psbt_witness_script(&self.secp);
+
+            let prev_output = input.previous_output;
+            if let Some(prev_tx) = self.database.borrow().get_raw_tx(&prev_output.txid)? {
+                if derived_descriptor.is_witness() {
+                    psbt_input.witness_utxo =
+                        Some(prev_tx.output[prev_output.vout as usize].clone());
+                }
+                if !derived_descriptor.is_witness() || builder.force_non_witness_utxo {
+                    psbt_input.non_witness_utxo = Some(prev_tx);
+                }
+            }
+        }
+
+        // probably redundant but it doesn't hurt...
+        self.add_input_hd_keypaths(&mut psbt)?;
+
+        // add metadata for the outputs
+        for (psbt_output, tx_output) in psbt
+            .outputs
+            .iter_mut()
+            .zip(psbt.global.unsigned_tx.output.iter())
+        {
+            if let Some((keychain, child)) = self
+                .database
+                .borrow()
+                .get_path_from_script_pubkey(&tx_output.script_pubkey)?
+            {
+                let (desc, _) = self.get_descriptor_for_keychain(keychain);
+                psbt_output.hd_keypaths = desc.get_hd_keypaths(child, &self.secp)?;
+                if builder.include_output_redeem_witness_script {
+                    let derived_descriptor = desc.derive(ChildNumber::from_normal_idx(child)?);
+                    psbt_output.witness_script = derived_descriptor.psbt_witness_script(&self.secp);
+                    psbt_output.redeem_script = derived_descriptor.psbt_redeem_script(&self.secp);
+                };
+            }
+        }
+
+        Ok(psbt)
+    }
+
+    fn add_input_hd_keypaths(&self, psbt: &mut PSBT) -> Result<(), Error> {
+        let mut input_utxos = Vec::with_capacity(psbt.inputs.len());
+        for n in 0..psbt.inputs.len() {
+            input_utxos.push(psbt.get_utxo_for(n).clone());
+        }
+
+        // try to add hd_keypaths if we've already seen the output
+        for (psbt_input, out) in psbt.inputs.iter_mut().zip(input_utxos.iter()) {
+            if let Some(out) = out {
+                if let Some((keychain, child)) = self
+                    .database
+                    .borrow()
+                    .get_path_from_script_pubkey(&out.script_pubkey)?
+                {
+                    debug!("Found descriptor {:?}/{}", keychain, child);
+
+                    // merge hd_keypaths
+                    let (desc, _) = self.get_descriptor_for_keychain(keychain);
+                    let mut hd_keypaths = desc.get_hd_keypaths(child, &self.secp)?;
+                    psbt_input.hd_keypaths.append(&mut hd_keypaths);
+                }
+            }
+        }
+
+        Ok(())
+    }
+}
+
+impl<B, D> Wallet<B, D>
+where
+    B: Blockchain,
+    D: BatchDatabase,
+{
+    /// Create a new "online" wallet
+    #[maybe_async]
+    pub fn new<E: ToWalletDescriptor>(
+        descriptor: E,
+        change_descriptor: Option<E>,
+        network: Network,
+        database: D,
+        client: B,
+    ) -> Result<Self, Error> {
+        let mut wallet = Self::new_offline(descriptor, change_descriptor, network, database)?;
+
+        wallet.current_height = Some(maybe_await!(client.get_height())? as u32);
+        wallet.client = Some(client);
+
+        Ok(wallet)
+    }
+
+    /// Sync the internal database with the blockchain
+    #[maybe_async]
+    pub fn sync<P: 'static + Progress>(
+        &self,
+        progress_update: P,
+        max_address_param: Option<u32>,
+    ) -> Result<(), Error> {
+        debug!("Begin sync...");
+
+        let mut run_setup = false;
+
+        let max_address = match self.descriptor.is_fixed() {
+            true => 0,
+            false => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
+        };
+        if self
+            .database
+            .borrow()
+            .get_script_pubkey_from_path(KeychainKind::External, max_address.saturating_sub(1))?
+            .is_none()
+        {
+            run_setup = true;
+            self.cache_addresses(KeychainKind::External, 0, max_address)?;
+        }
+
+        if let Some(change_descriptor) = &self.change_descriptor {
+            let max_address = match change_descriptor.is_fixed() {
+                true => 0,
+                false => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
+            };
+
+            if self
+                .database
+                .borrow()
+                .get_script_pubkey_from_path(KeychainKind::Internal, max_address.saturating_sub(1))?
+                .is_none()
+            {
+                run_setup = true;
+                self.cache_addresses(KeychainKind::Internal, 0, max_address)?;
+            }
+        }
+
+        // TODO: what if i generate an address first and cache some addresses?
+        // TODO: we should sync if generating an address triggers a new batch to be stored
+        if run_setup {
+            maybe_await!(self.client.as_ref().ok_or(Error::OfflineClient)?.setup(
+                None,
+                self.database.borrow_mut().deref_mut(),
+                progress_update,
+            ))
+        } else {
+            maybe_await!(self.client.as_ref().ok_or(Error::OfflineClient)?.sync(
+                None,
+                self.database.borrow_mut().deref_mut(),
+                progress_update,
+            ))
+        }
+    }
+
+    /// Return a reference to the internal blockchain client
+    pub fn client(&self) -> Option<&B> {
+        self.client.as_ref()
+    }
+
+    /// Get the Bitcoin network the wallet is using.
+    pub fn network(&self) -> Network {
+        self.network
+    }
+
+    /// Broadcast a transaction to the network
+    #[maybe_async]
+    pub fn broadcast(&self, tx: Transaction) -> Result<Txid, Error> {
+        maybe_await!(self
+            .client
+            .as_ref()
+            .ok_or(Error::OfflineClient)?
+            .broadcast(&tx))?;
+
+        Ok(tx.txid())
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::str::FromStr;
+
+    use bitcoin::Network;
+
+    use crate::database::memory::MemoryDatabase;
+    use crate::database::Database;
+    use crate::types::KeychainKind;
+
+    use super::*;
+
+    #[test]
+    fn test_cache_addresses_fixed() {
+        let db = MemoryDatabase::new();
+        let wallet: OfflineWallet<_> = Wallet::new_offline(
+            "wpkh(L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6)",
+            None,
+            Network::Testnet,
+            db,
+        )
+        .unwrap();
+
+        assert_eq!(
+            wallet.get_new_address().unwrap().to_string(),
+            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
+        );
+        assert_eq!(
+            wallet.get_new_address().unwrap().to_string(),
+            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
+        );
+
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(KeychainKind::External, 0)
+            .unwrap()
+            .is_some());
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(KeychainKind::Internal, 0)
+            .unwrap()
+            .is_none());
+    }
+
+    #[test]
+    fn test_cache_addresses() {
+        let db = MemoryDatabase::new();
+        let wallet: OfflineWallet<_> = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
+
+        assert_eq!(
+            wallet.get_new_address().unwrap().to_string(),
+            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
+        );
+        assert_eq!(
+            wallet.get_new_address().unwrap().to_string(),
+            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
+        );
+
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE - 1)
+            .unwrap()
+            .is_some());
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE)
+            .unwrap()
+            .is_none());
+    }
+
+    #[test]
+    fn test_cache_addresses_refill() {
+        let db = MemoryDatabase::new();
+        let wallet: OfflineWallet<_> = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
+
+        assert_eq!(
+            wallet.get_new_address().unwrap().to_string(),
+            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
+        );
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE - 1)
+            .unwrap()
+            .is_some());
+
+        for _ in 0..CACHE_ADDR_BATCH_SIZE {
+            wallet.get_new_address().unwrap();
+        }
+
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE * 2 - 1)
+            .unwrap()
+            .is_some());
+    }
+
+    pub(crate) fn get_test_wpkh() -> &'static str {
+        "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)"
+    }
+
+    pub(crate) fn get_test_single_sig_csv() -> &'static str {
+        // and(pk(Alice),older(6))
+        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),older(6)))"
+    }
+
+    pub(crate) fn get_test_a_or_b_plus_csv() -> &'static str {
+        // or(pk(Alice),and(pk(Bob),older(144)))
+        "wsh(or_d(pk(cRjo6jqfVNP33HhSS76UhXETZsGTZYx8FMFvR9kpbtCSV1PmdZdu),and_v(v:pk(cMnkdebixpXMPfkcNEjjGin7s94hiehAH4mLbYkZoh9KSiNNmqC8),older(144))))"
+    }
+
+    pub(crate) fn get_test_single_sig_cltv() -> &'static str {
+        // and(pk(Alice),after(100000))
+        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(100000)))"
+    }
+
+    pub(crate) fn get_funded_wallet(
+        descriptor: &str,
+    ) -> (
+        OfflineWallet<MemoryDatabase>,
+        (String, Option<String>),
+        bitcoin::Txid,
+    ) {
+        let descriptors = testutils!(@descriptors (descriptor));
+        let wallet: OfflineWallet<_> = Wallet::new_offline(
+            &descriptors.0,
+            None,
+            Network::Regtest,
+            MemoryDatabase::new(),
+        )
+        .unwrap();
+
+        let txid = wallet.database.borrow_mut().received_tx(
+            testutils! {
+                @tx ( (@external descriptors, 0) => 50_000 ) (@confirmations 1)
+            },
+            Some(100),
+        );
+
+        (wallet, descriptors, txid)
+    }
+
+    macro_rules! assert_fee_rate {
+        ($tx:expr, $fees:expr, $fee_rate:expr $( ,@dust_change $( $dust_change:expr )* )* $( ,@add_signature $( $add_signature:expr )* )* ) => ({
+            let mut tx = $tx.clone();
+            $(
+                $( $add_signature )*
+                for txin in &mut tx.input {
+                    txin.witness.push([0x00; 108].to_vec()); // fake signature
+                }
+            )*
+
+            #[allow(unused_mut)]
+            #[allow(unused_assignments)]
+            let mut dust_change = false;
+            $(
+                $( $dust_change )*
+                dust_change = true;
+            )*
+
+            let tx_fee_rate = $fees as f32 / (tx.get_weight() as f32 / 4.0);
+            let fee_rate = $fee_rate.as_sat_vb();
+
+            if !dust_change {
+                assert!((tx_fee_rate - fee_rate).abs() < 0.5, format!("Expected fee rate of {}, the tx has {}", fee_rate, tx_fee_rate));
+            } else {
+                assert!(tx_fee_rate >= fee_rate, format!("Expected fee rate of at least {}, the tx has {}", fee_rate, tx_fee_rate));
+            }
+        });
+    }
+
+    #[test]
+    #[should_panic(expected = "NoRecipients")]
+    fn test_create_tx_empty_recipients() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        wallet
+            .create_tx(TxBuilder::with_recipients(vec![]))
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "NoUtxosSelected")]
+    fn test_create_tx_manually_selected_empty_utxos() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .manually_selected_only()
+                    .utxos(vec![]),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "Invalid version `0`")]
+    fn test_create_tx_version_0() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(0))
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
+    )]
+    fn test_create_tx_version_1_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(1))
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_custom_version() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(42))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.version, 42);
+    }
+
+    #[test]
+    fn test_create_tx_default_locktime() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.lock_time, 0);
+    }
+
+    #[test]
+    fn test_create_tx_default_locktime_cltv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.lock_time, 100_000);
+    }
+
+    #[test]
+    fn test_create_tx_custom_locktime() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(630_000),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
+    }
+
+    #[test]
+    fn test_create_tx_custom_locktime_compatible_with_cltv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(630_000),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "TxBuilder requested timelock of `50000`, but at least `100000` is required to spend from this script"
+    )]
+    fn test_create_tx_custom_locktime_incompatible_with_cltv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(50000),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_no_rbf_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 6);
+    }
+
+    #[test]
+    fn test_create_tx_with_default_rbf_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
+            )
+            .unwrap();
+
+        // When CSV is enabled it takes precedence over the rbf value (unless forced by the user).
+        // It will be set to the OP_CSV value, in this case 6
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 6);
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "Cannot enable RBF with nSequence `3` given a required OP_CSV of `6`"
+    )]
+    fn test_create_tx_with_custom_rbf_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .enable_rbf_with_sequence(3),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_no_rbf_cltv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFE);
+    }
+
+    #[test]
+    #[should_panic(expected = "Cannot enable RBF with a nSequence >= 0xFFFFFFFE")]
+    fn test_create_tx_invalid_rbf_sequence() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .enable_rbf_with_sequence(0xFFFFFFFE),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_custom_rbf_sequence() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .enable_rbf_with_sequence(0xDEADBEEF),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xDEADBEEF);
+    }
+
+    #[test]
+    fn test_create_tx_default_sequence() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFF);
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "The `change_policy` can be set only if the wallet has a change_descriptor"
+    )]
+    fn test_create_tx_change_policy_no_internal() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .do_not_spend_change(),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_single_recipient_drain_wallet() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet(),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
+        assert_eq!(
+            psbt.global.unsigned_tx.output[0].value,
+            50_000 - details.fees
+        );
+    }
+
+    #[test]
+    fn test_create_tx_default_fee_rate() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::default(), @add_signature);
+    }
+
+    #[test]
+    fn test_create_tx_custom_fee_rate() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .fee_rate(FeeRate::from_sat_per_vb(5.0)),
+            )
+            .unwrap();
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(5.0), @add_signature);
+    }
+
+    #[test]
+    fn test_create_tx_absolute_fee() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet()
+                    .fee_absolute(100),
+            )
+            .unwrap();
+
+        assert_eq!(details.fees, 100);
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
+        assert_eq!(
+            psbt.global.unsigned_tx.output[0].value,
+            50_000 - details.fees
+        );
+    }
+
+    #[test]
+    fn test_create_tx_absolute_zero_fee() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet()
+                    .fee_absolute(0),
+            )
+            .unwrap();
+
+        assert_eq!(details.fees, 0);
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
+        assert_eq!(
+            psbt.global.unsigned_tx.output[0].value,
+            50_000 - details.fees
+        );
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_create_tx_absolute_high_fee() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (_psbt, _details) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet()
+                    .fee_absolute(60_000),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_add_change() {
+        use super::tx_builder::TxOrdering;
+
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
+                    .ordering(TxOrdering::Untouched),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 2);
+        assert_eq!(psbt.global.unsigned_tx.output[0].value, 25_000);
+        assert_eq!(
+            psbt.global.unsigned_tx.output[1].value,
+            25_000 - details.fees
+        );
+    }
+
+    #[test]
+    fn test_create_tx_skip_change_dust() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                49_800,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
+        assert_eq!(psbt.global.unsigned_tx.output[0].value, 49_800);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_create_tx_single_recipient_dust_amount() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        // very high fee rate, so that the only output would be below dust
+        wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet()
+                    .fee_rate(FeeRate::from_sat_per_vb(453.0)),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_ordering_respected() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![
+                    (addr.script_pubkey(), 30_000),
+                    (addr.script_pubkey(), 10_000),
+                ])
+                .ordering(super::tx_builder::TxOrdering::BIP69Lexicographic),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 3);
+        assert_eq!(
+            psbt.global.unsigned_tx.output[0].value,
+            10_000 - details.fees
+        );
+        assert_eq!(psbt.global.unsigned_tx.output[1].value, 10_000);
+        assert_eq!(psbt.global.unsigned_tx.output[2].value, 30_000);
+    }
+
+    #[test]
+    fn test_create_tx_default_sighash() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                30_000,
+            )]))
+            .unwrap();
+
+        assert_eq!(psbt.inputs[0].sighash_type, None);
+    }
+
+    #[test]
+    fn test_create_tx_custom_sighash() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 30_000)])
+                    .sighash(bitcoin::SigHashType::Single),
+            )
+            .unwrap();
+
+        assert_eq!(
+            psbt.inputs[0].sighash_type,
+            Some(bitcoin::SigHashType::Single)
+        );
+    }
+
+    #[test]
+    fn test_create_tx_input_hd_keypaths() {
+        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
+        use std::str::FromStr;
+
+        let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet(),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.inputs[0].hd_keypaths.len(), 1);
+        assert_eq!(
+            psbt.inputs[0].hd_keypaths.values().nth(0).unwrap(),
+            &(
+                Fingerprint::from_str("d34db33f").unwrap(),
+                DerivationPath::from_str("m/44'/0'/0'/0/0").unwrap()
+            )
+        );
+    }
+
+    #[test]
+    fn test_create_tx_output_hd_keypaths() {
+        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
+        use std::str::FromStr;
+
+        let (wallet, descriptors, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)");
+        // cache some addresses
+        wallet.get_new_address().unwrap();
+
+        let addr = testutils!(@external descriptors, 5);
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet(),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.outputs[0].hd_keypaths.len(), 1);
+        assert_eq!(
+            psbt.outputs[0].hd_keypaths.values().nth(0).unwrap(),
+            &(
+                Fingerprint::from_str("d34db33f").unwrap(),
+                DerivationPath::from_str("m/44'/0'/0'/0/5").unwrap()
+            )
+        );
+    }
+
+    #[test]
+    fn test_create_tx_set_redeem_script_p2sh() {
+        use bitcoin::hashes::hex::FromHex;
+
+        let (wallet, _, _) =
+            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet(),
+            )
+            .unwrap();
+
+        assert_eq!(
+            psbt.inputs[0].redeem_script,
+            Some(Script::from(
+                Vec::<u8>::from_hex(
+                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
+                )
+                .unwrap()
+            ))
+        );
+        assert_eq!(psbt.inputs[0].witness_script, None);
+    }
+
+    #[test]
+    fn test_create_tx_set_witness_script_p2wsh() {
+        use bitcoin::hashes::hex::FromHex;
+
+        let (wallet, _, _) =
+            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet(),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.inputs[0].redeem_script, None);
+        assert_eq!(
+            psbt.inputs[0].witness_script,
+            Some(Script::from(
+                Vec::<u8>::from_hex(
+                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
+                )
+                .unwrap()
+            ))
+        );
+    }
+
+    #[test]
+    fn test_create_tx_set_redeem_witness_script_p2wsh_p2sh() {
+        use bitcoin::hashes::hex::FromHex;
+
+        let (wallet, _, _) =
+            get_funded_wallet("sh(wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet(),
+            )
+            .unwrap();
+
+        let script = Script::from(
+            Vec::<u8>::from_hex(
+                "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac",
+            )
+            .unwrap(),
+        );
+
+        assert_eq!(psbt.inputs[0].redeem_script, Some(script.to_v0_p2wsh()));
+        assert_eq!(psbt.inputs[0].witness_script, Some(script));
+    }
+
+    #[test]
+    fn test_create_tx_non_witness_utxo() {
+        let (wallet, _, _) =
+            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet(),
+            )
+            .unwrap();
+
+        assert!(psbt.inputs[0].non_witness_utxo.is_some());
+        assert!(psbt.inputs[0].witness_utxo.is_none());
+    }
+
+    #[test]
+    fn test_create_tx_only_witness_utxo() {
+        let (wallet, _, _) =
+            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet(),
+            )
+            .unwrap();
+
+        assert!(psbt.inputs[0].non_witness_utxo.is_none());
+        assert!(psbt.inputs[0].witness_utxo.is_some());
+    }
+
+    #[test]
+    fn test_create_tx_shwpkh_has_witness_utxo() {
+        let (wallet, _, _) =
+            get_funded_wallet("sh(wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet(),
+            )
+            .unwrap();
+
+        assert!(psbt.inputs[0].non_witness_utxo.is_none());
+        assert!(psbt.inputs[0].witness_utxo.is_some());
+    }
+
+    #[test]
+    fn test_create_tx_both_non_witness_utxo_and_witness_utxo() {
+        let (wallet, _, _) =
+            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet()
+                    .force_non_witness_utxo(),
+            )
+            .unwrap();
+
+        assert!(psbt.inputs[0].non_witness_utxo.is_some());
+        assert!(psbt.inputs[0].witness_utxo.is_some());
+    }
+
+    #[test]
+    fn test_create_tx_add_utxo() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        let small_output_txid = wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 30_000)]).add_utxo(
+                    OutPoint {
+                        txid: small_output_txid,
+                        vout: 0,
+                    },
+                ),
+            )
+            .unwrap();
+
+        assert_eq!(
+            psbt.global.unsigned_tx.input.len(),
+            2,
+            "should add an additional input since 25_000 < 30_000"
+        );
+        assert_eq!(details.sent, 75_000, "total should be sum of both inputs");
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_create_tx_manually_selected_insufficient() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        let small_output_txid = wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 30_000)])
+                    .add_utxo(OutPoint {
+                        txid: small_output_txid,
+                        vout: 0,
+                    })
+                    .manually_selected_only(),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "SpendingPolicyRequired(External)")]
+    fn test_create_tx_policy_path_required() {
+        let (wallet, _, _) = get_funded_wallet(get_test_a_or_b_plus_csv());
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                30_000,
+            )]))
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_policy_path_no_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_a_or_b_plus_csv());
+
+        let external_policy = wallet.policies(KeychainKind::External).unwrap().unwrap();
+        let root_id = external_policy.id;
+        // child #0 is just the key "A"
+        let path = vec![(root_id, vec![0])].into_iter().collect();
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 30_000)])
+                    .policy_path(path, KeychainKind::External),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFF);
+    }
+
+    #[test]
+    fn test_create_tx_policy_path_use_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_a_or_b_plus_csv());
+
+        let external_policy = wallet.policies(KeychainKind::External).unwrap().unwrap();
+        let root_id = external_policy.id;
+        // child #1 is or(pk(B),older(144))
+        let path = vec![(root_id, vec![1])].into_iter().collect();
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 30_000)])
+                    .policy_path(path, KeychainKind::External),
+            )
+            .unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 144);
+    }
+
+    #[test]
+    fn test_create_tx_global_xpubs_with_origin() {
+        use bitcoin::hashes::hex::FromHex;
+        use bitcoin::util::base58;
+        use bitcoin::util::psbt::raw::Key;
+
+        let (wallet, _, _) = get_funded_wallet("wpkh([73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*)");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).add_global_xpubs(),
+            )
+            .unwrap();
+
+        let type_value = 0x01;
+        let key = base58::from_check("tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3").unwrap();
+
+        let psbt_key = Key { type_value, key };
+
+        // This key has an explicit origin, so it will be encoded here
+        let value_bytes = Vec::<u8>::from_hex("73756c7f30000080000000800000008002000080").unwrap();
+
+        assert_eq!(psbt.global.unknown.len(), 1);
+        assert_eq!(psbt.global.unknown.get(&psbt_key), Some(&value_bytes));
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "MissingKeyOrigin(\"tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3\")"
+    )]
+    fn test_create_tx_global_xpubs_origin_missing() {
+        let (wallet, _, _) = get_funded_wallet("wpkh(tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*)");
+        let addr = wallet.get_new_address().unwrap();
+        wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).add_global_xpubs(),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_global_xpubs_master_without_origin() {
+        use bitcoin::hashes::hex::FromHex;
+        use bitcoin::util::base58;
+        use bitcoin::util::psbt::raw::Key;
+
+        let (wallet, _, _) = get_funded_wallet("wpkh(tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL/0/*)");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).add_global_xpubs(),
+            )
+            .unwrap();
+
+        let type_value = 0x01;
+        let key = base58::from_check("tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL").unwrap();
+
+        let psbt_key = Key { type_value, key };
+
+        // This key doesn't have an explicit origin, but it's a master key (depth = 0). So we encode
+        // its fingerprint directly and an empty path
+        let value_bytes = Vec::<u8>::from_hex("997a323b").unwrap();
+
+        assert_eq!(psbt.global.unknown.len(), 1);
+        assert_eq!(psbt.global.unknown.get(&psbt_key), Some(&value_bytes));
+    }
+
+    #[test]
+    #[should_panic(expected = "IrreplaceableTransaction")]
+    fn test_bump_fee_irreplaceable_tx() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, mut details) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+        let tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the utxos, we know they can't be used anyways
+        details.transaction = Some(tx);
+        wallet.database.borrow_mut().set_tx(&details).unwrap();
+
+        wallet.bump_fee(&txid, TxBuilder::new()).unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "TransactionConfirmed")]
+    fn test_bump_fee_confirmed_tx() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, mut details) = wallet
+            .create_tx(TxBuilder::with_recipients(vec![(
+                addr.script_pubkey(),
+                25_000,
+            )]))
+            .unwrap();
+        let tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the utxos, we know they can't be used anyways
+        details.transaction = Some(tx);
+        details.height = Some(42);
+        wallet.database.borrow_mut().set_tx(&details).unwrap();
+
+        wallet.bump_fee(&txid, TxBuilder::new()).unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "FeeRateTooLow")]
+    fn test_bump_fee_low_fee_rate() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, mut details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the utxos, we know they can't be used anyways
+        details.transaction = Some(tx);
+        wallet.database.borrow_mut().set_tx(&details).unwrap();
+
+        wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(1.0)),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "FeeTooLow")]
+    fn test_bump_fee_low_abs() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, mut details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the utxos, we know they can't be used anyways
+        details.transaction = Some(tx);
+        wallet.database.borrow_mut().set_tx(&details).unwrap();
+
+        wallet
+            .bump_fee(&txid, TxBuilder::new().fee_absolute(10))
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "FeeTooLow")]
+    fn test_bump_fee_zero_abs() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, mut details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the utxos, we know they can't be used anyways
+        details.transaction = Some(tx);
+        wallet.database.borrow_mut().set_tx(&details).unwrap();
+
+        wallet
+            .bump_fee(&txid, TxBuilder::new().fee_absolute(0))
+            .unwrap();
+    }
+
+    #[test]
+    fn test_bump_fee_reduce_change() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(2.5)),
+            )
+            .unwrap();
+
+        assert_eq!(details.sent, original_details.sent);
+        assert_eq!(
+            details.received + details.fees,
+            original_details.received + original_details.fees
+        );
+        assert!(details.fees > original_details.fees);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            25_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(2.5), @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_absolute_reduce_change() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let (psbt, details) = wallet
+            .bump_fee(&txid, TxBuilder::new().fee_absolute(200))
+            .unwrap();
+
+        assert_eq!(details.sent, original_details.sent);
+        assert_eq!(
+            details.received + details.fees,
+            original_details.received + original_details.fees
+        );
+        assert!(
+            details.fees > original_details.fees,
+            "{} > {}",
+            details.fees,
+            original_details.fees
+        );
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            25_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_eq!(details.fees, 200);
+    }
+
+    #[test]
+    fn test_bump_fee_reduce_single_recipient() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet()
+                    .enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new()
+                    .maintain_single_recipient()
+                    .fee_rate(FeeRate::from_sat_per_vb(2.5)),
+            )
+            .unwrap();
+
+        assert_eq!(details.sent, original_details.sent);
+        assert!(details.fees > original_details.fees);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.output.len(), 1);
+        assert_eq!(tx.output[0].value + details.fees, details.sent);
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(2.5), @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_absolute_reduce_single_recipient() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet()
+                    .enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new()
+                    .maintain_single_recipient()
+                    .fee_absolute(300),
+            )
+            .unwrap();
+
+        assert_eq!(details.sent, original_details.sent);
+        assert!(details.fees > original_details.fees);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.output.len(), 1);
+        assert_eq!(tx.output[0].value + details.fees, details.sent);
+
+        assert_eq!(details.fees, 300);
+    }
+
+    #[test]
+    fn test_bump_fee_drain_wallet() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        // receive an extra tx so that our wallet has two utxos.
+        let incoming_txid = wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+        let outpoint = OutPoint {
+            txid: incoming_txid,
+            vout: 0,
+        };
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .utxos(vec![outpoint])
+                    .manually_selected_only()
+                    .enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+        assert_eq!(original_details.sent, 25_000);
+
+        // for the new feerate, it should be enough to reduce the output, but since we specify
+        // `drain_wallet` we expect to spend everything
+        let (_, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new()
+                    .drain_wallet()
+                    .maintain_single_recipient()
+                    .fee_rate(FeeRate::from_sat_per_vb(5.0)),
+            )
+            .unwrap();
+        assert_eq!(details.sent, 75_000);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_bump_fee_remove_output_manually_selected_only() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        // receive an extra tx so that our wallet has two utxos. then we manually pick only one of
+        // them, and make sure that `bump_fee` doesn't try to add more. eventually, it should fail
+        // because the fee rate is too high and the single utxo isn't enough to create a non-dust
+        // output
+        let incoming_txid = wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+        let outpoint = OutPoint {
+            txid: incoming_txid,
+            vout: 0,
+        };
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .utxos(vec![outpoint])
+                    .manually_selected_only()
+                    .enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+        assert_eq!(original_details.sent, 25_000);
+
+        wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new()
+                    .utxos(vec![outpoint])
+                    .manually_selected_only()
+                    .fee_rate(FeeRate::from_sat_per_vb(225.0)),
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_bump_fee_add_input() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(50.0)),
+            )
+            .unwrap();
+
+        assert_eq!(details.sent, original_details.sent + 25_000);
+        assert_eq!(details.fees + details.received, 30_000);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            45_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(50.0), @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_absolute_add_input() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let (psbt, details) = wallet
+            .bump_fee(&txid, TxBuilder::new().fee_absolute(6_000))
+            .unwrap();
+
+        assert_eq!(details.sent, original_details.sent + 25_000);
+        assert_eq!(details.fees + details.received, 30_000);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            45_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_eq!(details.fees, 6_000);
+    }
+
+    #[test]
+    fn test_bump_fee_no_change_add_input_and_change() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        let incoming_txid = wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        // initially make a tx without change by using `set_single_recipient`
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .add_utxo(OutPoint {
+                        txid: incoming_txid,
+                        vout: 0,
+                    })
+                    .manually_selected_only()
+                    .enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        // now bump the fees without using `maintain_single_recipient`. the wallet should add an
+        // extra input and a change output, and leave the original output untouched
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(50.0)),
+            )
+            .unwrap();
+
+        let original_send_all_amount = original_details.sent - original_details.fees;
+        assert_eq!(details.sent, original_details.sent + 50_000);
+        assert_eq!(
+            details.received,
+            75_000 - original_send_all_amount - details.fees
+        );
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            original_send_all_amount
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            75_000 - original_send_all_amount - details.fees
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(50.0), @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_add_input_change_dust() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        assert_eq!(tx.input.len(), 1);
+        assert_eq!(tx.output.len(), 2);
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(140.0)),
+            )
+            .unwrap();
+
+        assert_eq!(original_details.received, 5_000 - original_details.fees);
+
+        assert_eq!(details.sent, original_details.sent + 25_000);
+        assert_eq!(details.fees, 30_000);
+        assert_eq!(details.received, 0);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 1);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            45_000
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(140.0), @dust_change, @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_force_add_input() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        let incoming_txid = wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        // the new fee_rate is low enough that just reducing the change would be fine, but we force
+        // the addition of an extra input with `add_utxo()`
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new()
+                    .add_utxo(OutPoint {
+                        txid: incoming_txid,
+                        vout: 0,
+                    })
+                    .fee_rate(FeeRate::from_sat_per_vb(5.0)),
+            )
+            .unwrap();
+
+        assert_eq!(details.sent, original_details.sent + 25_000);
+        assert_eq!(details.fees + details.received, 30_000);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            45_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(5.0), @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_absolute_force_add_input() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        let incoming_txid = wallet.database.borrow_mut().received_tx(
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, mut original_details) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
+            )
+            .unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        // the new fee_rate is low enough that just reducing the change would be fine, but we force
+        // the addition of an extra input with `add_utxo()`
+        let (psbt, details) = wallet
+            .bump_fee(
+                &txid,
+                TxBuilder::new()
+                    .add_utxo(OutPoint {
+                        txid: incoming_txid,
+                        vout: 0,
+                    })
+                    .fee_absolute(250),
+            )
+            .unwrap();
+
+        assert_eq!(details.sent, original_details.sent + 25_000);
+        assert_eq!(details.fees + details.received, 30_000);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            45_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_eq!(details.fees, 250);
+    }
+
+    #[test]
+    fn test_sign_single_xprv() {
+        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet(),
+            )
+            .unwrap();
+
+        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
+        assert_eq!(finalized, true);
+
+        let extracted = signed_psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+
+    #[test]
+    fn test_sign_single_xprv_bip44_path() {
+        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/44'/0'/0'/0/*)");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet(),
+            )
+            .unwrap();
+
+        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
+        assert_eq!(finalized, true);
+
+        let extracted = signed_psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+
+    #[test]
+    fn test_sign_single_xprv_sh_wpkh() {
+        let (wallet, _, _) = get_funded_wallet("sh(wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*))");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet(),
+            )
+            .unwrap();
+
+        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
+        assert_eq!(finalized, true);
+
+        let extracted = signed_psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+
+    #[test]
+    fn test_sign_single_wif() {
+        let (wallet, _, _) =
+            get_funded_wallet("wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)");
+        let addr = wallet.get_new_address().unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet(),
+            )
+            .unwrap();
+
+        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
+        assert_eq!(finalized, true);
+
+        let extracted = signed_psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+
+    #[test]
+    fn test_sign_single_xprv_no_hd_keypaths() {
+        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
+        let addr = wallet.get_new_address().unwrap();
+        let (mut psbt, _) = wallet
+            .create_tx(
+                TxBuilder::new()
+                    .set_single_recipient(addr.script_pubkey())
+                    .drain_wallet(),
+            )
+            .unwrap();
+
+        psbt.inputs[0].hd_keypaths.clear();
+        assert_eq!(psbt.inputs[0].hd_keypaths.len(), 0);
+
+        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
+        assert_eq!(finalized, true);
+
+        let extracted = signed_psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+
+    #[test]
+    fn test_include_output_redeem_witness_script() {
+        let (wallet, _, _) = get_funded_wallet("sh(wsh(multi(1,cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW,cRjo6jqfVNP33HhSS76UhXETZsGTZYx8FMFvR9kpbtCSV1PmdZdu)))");
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)])
+                    .include_output_redeem_witness_script(),
+            )
+            .unwrap();
+
+        // p2sh-p2wsh transaction should contain both witness and redeem scripts
+        assert!(psbt
+            .outputs
+            .iter()
+            .any(|output| output.redeem_script.is_some() && output.witness_script.is_some()));
+    }
+
+    #[test]
+    fn test_signing_only_one_of_multiple_inputs() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let (mut psbt, _) = wallet
+            .create_tx(
+                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)])
+                    .include_output_redeem_witness_script(),
+            )
+            .unwrap();
+
+        // add another input to the psbt that is at least passable.
+        let mut dud_input = bitcoin::util::psbt::Input::default();
+        dud_input.witness_utxo = Some(TxOut {
+            value: 100_000,
+            script_pubkey: miniscript::Descriptor::<bitcoin::PublicKey>::from_str(
+                "wpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)",
+            )
+            .unwrap()
+            .script_pubkey(miniscript::NullCtx),
+        });
+        psbt.inputs.push(dud_input);
+        psbt.global.unsigned_tx.input.push(bitcoin::TxIn::default());
+        let (psbt, is_final) = wallet.sign(psbt, None).unwrap();
+        assert!(
+            !is_final,
+            "shouldn't be final since we can't sign one of the inputs"
+        );
+        assert!(
+            psbt.inputs[0].final_script_witness.is_some(),
+            "should finalized input it signed"
+        )
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/signer.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/signer.rs.html new file mode 100644 index 0000000000..76c505864f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/signer.rs.html @@ -0,0 +1,1358 @@ +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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! 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 std::sync::Arc;
+//! # use std::str::FromStr;
+//! # use bitcoin::secp256k1::{Secp256k1, All};
+//! # use bitcoin::*;
+//! # use bitcoin::util::psbt;
+//! # use bitcoin::util::bip32::Fingerprint;
+//! # use bdk::signer::*;
+//! # use bdk::database::*;
+//! # use bdk::*;
+//! # #[derive(Debug)]
+//! # struct CustomHSM;
+//! # impl CustomHSM {
+//! #     fn sign_input(&self, _psbt: &mut psbt::PartiallySignedTransaction, _input: usize) -> Result<(), SignerError> {
+//! #         Ok(())
+//! #     }
+//! #     fn connect() -> Self {
+//! #         CustomHSM
+//! #     }
+//! # }
+//! #[derive(Debug)]
+//! struct CustomSigner {
+//!     device: CustomHSM,
+//! }
+//!
+//! impl CustomSigner {
+//!     fn connect() -> Self {
+//!         CustomSigner { device: CustomHSM::connect() }
+//!     }
+//! }
+//!
+//! impl Signer for CustomSigner {
+//!     fn sign(
+//!         &self,
+//!         psbt: &mut psbt::PartiallySignedTransaction,
+//!         input_index: Option<usize>,
+//!         _secp: &Secp256k1<All>,
+//!     ) -> Result<(), SignerError> {
+//!         let input_index = input_index.ok_or(SignerError::InputIndexOutOfRange)?;
+//!         self.device.sign_input(psbt, input_index)?;
+//!
+//!         Ok(())
+//!     }
+//!
+//!     fn sign_whole_tx(&self) -> bool {
+//!         false
+//!     }
+//! }
+//!
+//! let custom_signer = CustomSigner::connect();
+//!
+//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+//! let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+//! wallet.add_signer(
+//!     KeychainKind::External,
+//!     Fingerprint::from_str("e30f11b8").unwrap().into(),
+//!     SignerOrdering(200),
+//!     Arc::new(custom_signer)
+//! );
+//!
+//! # Ok::<_, bdk::Error>(())
+//! ```
+
+use std::cmp::Ordering;
+use std::collections::BTreeMap;
+use std::fmt;
+use std::ops::Bound::Included;
+use std::sync::Arc;
+
+use bitcoin::blockdata::opcodes;
+use bitcoin::blockdata::script::Builder as ScriptBuilder;
+use bitcoin::hashes::{hash160, Hash};
+use bitcoin::secp256k1::{Message, Secp256k1};
+use bitcoin::util::bip32::{ExtendedPrivKey, Fingerprint};
+use bitcoin::util::{bip143, psbt};
+use bitcoin::{PrivateKey, Script, SigHash, SigHashType};
+
+use miniscript::descriptor::{DescriptorSecretKey, DescriptorSinglePriv, DescriptorXKey, KeyMap};
+use miniscript::{Legacy, MiniscriptKey, Segwitv0};
+
+use super::utils::SecpCtx;
+use crate::descriptor::XKeyUtils;
+
+/// 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),
+}
+
+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, PartialEq, Eq, Clone)]
+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 requied to sign this input
+    MissingWitnessScript,
+    /// The fingerprint and derivation path are missing from the psbt input
+    MissingHDKeypath,
+}
+
+impl fmt::Display for SignerError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for SignerError {}
+
+/// Trait for signers
+///
+/// This trait can be implemented to provide customized signers to the wallet. For an example see
+/// [`this module`](crate::wallet::signer)'s documentation.
+pub trait Signer: fmt::Debug + Send + Sync {
+    /// Sign a PSBT
+    ///
+    /// The `input_index` argument is only provided if the wallet doesn't declare to sign the whole
+    /// transaction in one go (see [`Signer::sign_whole_tx`]). Otherwise its value is `None` and
+    /// can be ignored.
+    fn sign(
+        &self,
+        psbt: &mut psbt::PartiallySignedTransaction,
+        input_index: Option<usize>,
+        secp: &SecpCtx,
+    ) -> Result<(), SignerError>;
+
+    /// Return whether or not the signer signs the whole transaction in one go instead of every
+    /// input individually
+    fn sign_whole_tx(&self) -> bool;
+
+    /// 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
+    }
+}
+
+impl Signer for DescriptorXKey<ExtendedPrivKey> {
+    fn sign(
+        &self,
+        psbt: &mut psbt::PartiallySignedTransaction,
+        input_index: Option<usize>,
+        secp: &SecpCtx,
+    ) -> Result<(), SignerError> {
+        let input_index = input_index.unwrap();
+        if input_index >= psbt.inputs.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let (public_key, deriv_path) = match psbt.inputs[input_index]
+            .hd_keypaths
+            .iter()
+            .filter_map(|(pk, &(fingerprint, ref path))| {
+                if self.matches(&(fingerprint, path.clone()), &secp).is_some() {
+                    Some((pk, path))
+                } else {
+                    None
+                }
+            })
+            .next()
+        {
+            Some((pk, full_path)) => (pk, full_path.clone()),
+            None => return Ok(()),
+        };
+
+        let derived_key = self.xkey.derive_priv(&secp, &deriv_path).unwrap();
+        if &derived_key.private_key.public_key(&secp) != public_key {
+            Err(SignerError::InvalidKey)
+        } else {
+            derived_key.private_key.sign(psbt, Some(input_index), secp)
+        }
+    }
+
+    fn sign_whole_tx(&self) -> bool {
+        false
+    }
+
+    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
+        Some(DescriptorSecretKey::XPrv(self.clone()))
+    }
+}
+
+impl Signer for PrivateKey {
+    fn sign(
+        &self,
+        psbt: &mut psbt::PartiallySignedTransaction,
+        input_index: Option<usize>,
+        secp: &SecpCtx,
+    ) -> Result<(), SignerError> {
+        let input_index = input_index.unwrap();
+        if input_index >= psbt.inputs.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let pubkey = self.public_key(&secp);
+        if psbt.inputs[input_index].partial_sigs.contains_key(&pubkey) {
+            return Ok(());
+        }
+
+        // FIXME: use the presence of `witness_utxo` as an indication that we should make a bip143
+        // sig. Does this make sense? Should we add an extra argument to explicitly swith between
+        // these? The original idea was to declare sign() as sign<Ctx: ScriptContex>() and use Ctx,
+        // but that violates the rules for trait-objects, so we can't do it.
+        let (hash, sighash) = match psbt.inputs[input_index].witness_utxo {
+            Some(_) => Segwitv0::sighash(psbt, input_index)?,
+            None => Legacy::sighash(psbt, input_index)?,
+        };
+
+        let signature = secp.sign(
+            &Message::from_slice(&hash.into_inner()[..]).unwrap(),
+            &self.key,
+        );
+
+        let mut final_signature = Vec::with_capacity(75);
+        final_signature.extend_from_slice(&signature.serialize_der());
+        final_signature.push(sighash.as_u32() as u8);
+
+        psbt.inputs[input_index]
+            .partial_sigs
+            .insert(pubkey, final_signature);
+
+        Ok(())
+    }
+
+    fn sign_whole_tx(&self) -> bool {
+        false
+    }
+
+    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
+        Some(DescriptorSecretKey::SinglePriv(DescriptorSinglePriv {
+            key: *self,
+            origin: None,
+        }))
+    }
+}
+
+/// 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 std::default::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 Signer>>);
+
+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.as_public(secp).ok().map(|public| (public, secret)))
+            .collect()
+    }
+}
+
+impl From<KeyMap> for SignersContainer {
+    fn from(keymap: KeyMap) -> SignersContainer {
+        let secp = Secp256k1::new();
+        let mut container = SignersContainer::new();
+
+        for (_, secret) in keymap {
+            match secret {
+                DescriptorSecretKey::SinglePriv(private_key) => container.add_external(
+                    SignerId::from(
+                        private_key
+                            .key
+                            .public_key(&Secp256k1::signing_only())
+                            .to_pubkeyhash(),
+                    ),
+                    SignerOrdering::default(),
+                    Arc::new(private_key.key),
+                ),
+                DescriptorSecretKey::XPrv(xprv) => container.add_external(
+                    SignerId::from(xprv.root_fingerprint(&secp)),
+                    SignerOrdering::default(),
+                    Arc::new(xprv),
+                ),
+            };
+        }
+
+        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 Signer>,
+    ) -> Option<Arc<dyn Signer>> {
+        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 Signer>> {
+        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 Signer>> {
+        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 Signer>> {
+        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()
+    }
+}
+
+pub(crate) trait ComputeSighash {
+    fn sighash(
+        psbt: &psbt::PartiallySignedTransaction,
+        input_index: usize,
+    ) -> Result<(SigHash, SigHashType), SignerError>;
+}
+
+impl ComputeSighash for Legacy {
+    fn sighash(
+        psbt: &psbt::PartiallySignedTransaction,
+        input_index: usize,
+    ) -> Result<(SigHash, SigHashType), SignerError> {
+        if input_index >= psbt.inputs.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let psbt_input = &psbt.inputs[input_index];
+        let tx_input = &psbt.global.unsigned_tx.input[input_index];
+
+        let sighash = psbt_input.sighash_type.unwrap_or(SigHashType::All);
+        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((
+            psbt.global
+                .unsigned_tx
+                .signature_hash(input_index, &script, sighash.as_u32()),
+            sighash,
+        ))
+    }
+}
+
+fn p2wpkh_script_code(script: &Script) -> Script {
+    ScriptBuilder::new()
+        .push_opcode(opcodes::all::OP_DUP)
+        .push_opcode(opcodes::all::OP_HASH160)
+        .push_slice(&script[2..])
+        .push_opcode(opcodes::all::OP_EQUALVERIFY)
+        .push_opcode(opcodes::all::OP_CHECKSIG)
+        .into_script()
+}
+
+impl ComputeSighash for Segwitv0 {
+    fn sighash(
+        psbt: &psbt::PartiallySignedTransaction,
+        input_index: usize,
+    ) -> Result<(SigHash, SigHashType), SignerError> {
+        if input_index >= psbt.inputs.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let psbt_input = &psbt.inputs[input_index];
+
+        let sighash = psbt_input.sighash_type.unwrap_or(SigHashType::All);
+
+        let witness_utxo = psbt_input
+            .witness_utxo
+            .as_ref()
+            .ok_or(SignerError::MissingNonWitnessUtxo)?;
+        let value = witness_utxo.value;
+
+        let script = match psbt_input.witness_script {
+            Some(ref witness_script) => witness_script.clone(),
+            None => {
+                if witness_utxo.script_pubkey.is_v0_p2wpkh() {
+                    p2wpkh_script_code(&witness_utxo.script_pubkey)
+                } else if psbt_input
+                    .redeem_script
+                    .as_ref()
+                    .map(Script::is_v0_p2wpkh)
+                    .unwrap_or(false)
+                {
+                    p2wpkh_script_code(&psbt_input.redeem_script.as_ref().unwrap())
+                } else {
+                    return Err(SignerError::MissingWitnessScript);
+                }
+            }
+        };
+
+        Ok((
+            bip143::SigHashCache::new(&psbt.global.unsigned_tx).signature_hash(
+                input_index,
+                &script,
+                value,
+                sighash,
+            ),
+            sighash,
+        ))
+    }
+}
+
+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::ToWalletDescriptor;
+    use crate::keys::{DescriptorKey, ToDescriptorKey};
+    use bitcoin::secp256k1::All;
+    use bitcoin::util::bip32;
+    use bitcoin::util::psbt::PartiallySignedTransaction;
+    use bitcoin::Network;
+    use miniscript::ScriptContext;
+    use std::str::FromStr;
+
+    // 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 (prvkey1, _, _) = setup_keys(TPRV0_STR);
+        let (prvkey2, _, _) = setup_keys(TPRV1_STR);
+        let desc = descriptor!(sh(multi 2, prvkey1, prvkey2)).unwrap();
+        let (_, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
+
+        let signers = SignersContainer::from(keymap);
+        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);
+        let signer2 = Arc::new(DummySigner);
+        let signer3 = Arc::new(DummySigner);
+
+        signers.add_external(
+            SignerId::Fingerprint(b"cafe"[..].into()),
+            SignerOrdering(1),
+            signer1.clone(),
+        );
+        signers.add_external(
+            SignerId::Fingerprint(b"babe"[..].into()),
+            SignerOrdering(2),
+            signer2.clone(),
+        );
+        signers.add_external(
+            SignerId::Fingerprint(b"feed"[..].into()),
+            SignerOrdering(3),
+            signer3.clone(),
+        );
+
+        // Check that signers are sorted from lowest to highest ordering
+        let signers = signers.signers();
+        assert_eq!(Arc::as_ptr(signers[0]), Arc::as_ptr(&signer1));
+        assert_eq!(Arc::as_ptr(signers[1]), Arc::as_ptr(&signer2));
+        assert_eq!(Arc::as_ptr(signers[2]), Arc::as_ptr(&signer3));
+    }
+
+    #[test]
+    fn find_signer_by_id() {
+        let mut signers = SignersContainer::new();
+        let signer1: Arc<dyn Signer> = Arc::new(DummySigner);
+        let signer2: Arc<dyn Signer> = Arc::new(DummySigner);
+        let signer3: Arc<dyn Signer> = Arc::new(DummySigner);
+        let signer4: Arc<dyn Signer> = Arc::new(DummySigner);
+
+        let id1 = SignerId::Fingerprint(b"cafe"[..].into());
+        let id2 = SignerId::Fingerprint(b"babe"[..].into());
+        let id3 = SignerId::Fingerprint(b"feed"[..].into());
+        let id_nonexistent = SignerId::Fingerprint(b"fefe"[..].into());
+
+        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 Arc::as_ptr(&signer1) == Arc::as_ptr(signer))
+        );
+        assert!(
+            matches!(signers.find(id2), Some(signer) if Arc::as_ptr(&signer2) == Arc::as_ptr(signer))
+        );
+        assert!(
+            matches!(signers.find(id3.clone()), Some(signer) if Arc::as_ptr(&signer3) == Arc::as_ptr(signer))
+        );
+
+        // 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 Arc::as_ptr(&signer4) == Arc::as_ptr(signer))
+        );
+
+        // Can't find anything with ID that doesn't exist
+        assert!(matches!(signers.find(id_nonexistent), None));
+    }
+
+    #[derive(Debug)]
+    struct DummySigner;
+    impl Signer for DummySigner {
+        fn sign(
+            &self,
+            _psbt: &mut PartiallySignedTransaction,
+            _input_index: Option<usize>,
+            _secp: &SecpCtx,
+        ) -> Result<(), SignerError> {
+            Ok(())
+        }
+
+        fn sign_whole_tx(&self) -> bool {
+            true
+        }
+    }
+
+    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::ExtendedPrivKey::from_str(tprv).unwrap();
+        let tpub = bip32::ExtendedPubKey::from_private(&secp, &tprv);
+        let fingerprint = tprv.fingerprint(&secp);
+        let prvkey = (tprv, path.clone()).to_descriptor_key().unwrap();
+        let pubkey = (tpub, path).to_descriptor_key().unwrap();
+
+        (prvkey, pubkey, fingerprint)
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/time.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/time.rs.html new file mode 100644 index 0000000000..d45d75e8a0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/time.rs.html @@ -0,0 +1,178 @@ +time.rs - source + +
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Cross-platform time
+//!
+//! This module provides a function to get the current timestamp that works on all the platforms
+//! supported by the library.
+//!
+//! It can be useful to compare it with the timestamps found in
+//! [`TransactionDetails`](crate::types::TransactionDetails).
+
+use std::time::Duration;
+
+#[cfg(target_arch = "wasm32")]
+use js_sys::Date;
+#[cfg(not(target_arch = "wasm32"))]
+use std::time::{Instant as SystemInstant, SystemTime, UNIX_EPOCH};
+
+/// Return the current timestamp in seconds
+#[cfg(not(target_arch = "wasm32"))]
+pub fn get_timestamp() -> u64 {
+    SystemTime::now()
+        .duration_since(UNIX_EPOCH)
+        .unwrap()
+        .as_secs()
+}
+/// Return the current timestamp in seconds
+#[cfg(target_arch = "wasm32")]
+pub fn get_timestamp() -> u64 {
+    let millis = Date::now();
+
+    (millis / 1000.0) as u64
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+pub(crate) struct Instant(SystemInstant);
+#[cfg(target_arch = "wasm32")]
+pub(crate) struct Instant(Duration);
+
+impl Instant {
+    #[cfg(not(target_arch = "wasm32"))]
+    pub fn new() -> Self {
+        Instant(SystemInstant::now())
+    }
+    #[cfg(target_arch = "wasm32")]
+    pub fn new() -> Self {
+        let millis = Date::now();
+
+        let secs = millis / 1000.0;
+        let nanos = (millis % 1000.0) * 1e6;
+
+        Instant(Duration::new(secs as u64, nanos as u32))
+    }
+
+    #[cfg(not(target_arch = "wasm32"))]
+    pub fn elapsed(&self) -> Duration {
+        self.0.elapsed()
+    }
+    #[cfg(target_arch = "wasm32")]
+    pub fn elapsed(&self) -> Duration {
+        let now = Instant::new();
+
+        now.0.checked_sub(self.0).unwrap_or(Duration::new(0, 0))
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/tx_builder.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/tx_builder.rs.html new file mode 100644 index 0000000000..eceb370c5a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/tx_builder.rs.html @@ -0,0 +1,1482 @@ +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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+//! Transaction builder
+//!
+//! ## Example
+//!
+//! ```
+//! # use std::str::FromStr;
+//! # use bitcoin::*;
+//! # use bdk::*;
+//! # use bdk::wallet::tx_builder::CreateTx;
+//! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+//! // Create a transaction with one output to `to_address` of 50_000 satoshi, with a custom fee rate
+//! // of 5.0 satoshi/vbyte, only spending non-change outputs and with RBF signaling
+//! // enabled
+//! let builder = TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+//!     .fee_rate(FeeRate::from_sat_per_vb(5.0))
+//!     .do_not_spend_change()
+//!     .enable_rbf();
+//! # let builder: TxBuilder<bdk::database::MemoryDatabase, _, CreateTx> = builder;
+//! ```
+
+use std::collections::BTreeMap;
+use std::collections::HashSet;
+use std::default::Default;
+use std::marker::PhantomData;
+
+use bitcoin::{OutPoint, Script, SigHashType, Transaction};
+
+use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm};
+use crate::database::Database;
+use crate::types::{FeeRate, KeychainKind, UTXO};
+
+/// Context in which the [`TxBuilder`] is valid
+pub trait TxBuilderContext: std::fmt::Debug + Default + Clone {}
+
+/// [`Wallet::create_tx`](super::Wallet::create_tx) context
+#[derive(Debug, Default, Clone)]
+pub struct CreateTx;
+impl TxBuilderContext for CreateTx {}
+
+/// [`Wallet::bump_fee`](super::Wallet::bump_fee) context
+#[derive(Debug, Default, Clone)]
+pub struct BumpFee;
+impl TxBuilderContext for BumpFee {}
+
+/// A transaction builder
+///
+/// This structure contains the configuration that the wallet must follow to build a transaction.
+///
+/// For an example see [this module](super::tx_builder)'s documentation;
+#[derive(Debug)]
+pub struct TxBuilder<D: Database, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext> {
+    pub(crate) recipients: Vec<(Script, u64)>,
+    pub(crate) drain_wallet: bool,
+    pub(crate) single_recipient: Option<Script>,
+    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<OutPoint>,
+    pub(crate) unspendable: HashSet<OutPoint>,
+    pub(crate) manually_selected_only: bool,
+    pub(crate) sighash: Option<SigHashType>,
+    pub(crate) ordering: TxOrdering,
+    pub(crate) locktime: Option<u32>,
+    pub(crate) rbf: Option<RBFValue>,
+    pub(crate) version: Option<Version>,
+    pub(crate) change_policy: ChangeSpendPolicy,
+    pub(crate) force_non_witness_utxo: bool,
+    pub(crate) add_global_xpubs: bool,
+    pub(crate) coin_selection: Cs,
+    pub(crate) include_output_redeem_witness_script: bool,
+
+    phantom: PhantomData<(D, Ctx)>,
+}
+
+#[derive(Debug)]
+pub(crate) enum FeePolicy {
+    FeeRate(FeeRate),
+    FeeAmount(u64),
+}
+
+impl std::default::Default for FeePolicy {
+    fn default() -> Self {
+        FeePolicy::FeeRate(FeeRate::default_min_relay_fee())
+    }
+}
+
+// Unfortunately derive doesn't work with `PhantomData`: https://github.com/rust-lang/rust/issues/26925
+impl<D: Database, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext> Default
+    for TxBuilder<D, Cs, Ctx>
+where
+    Cs: Default,
+{
+    fn default() -> Self {
+        TxBuilder {
+            recipients: Default::default(),
+            drain_wallet: Default::default(),
+            single_recipient: Default::default(),
+            fee_policy: Default::default(),
+            internal_policy_path: Default::default(),
+            external_policy_path: Default::default(),
+            utxos: Default::default(),
+            unspendable: Default::default(),
+            manually_selected_only: Default::default(),
+            sighash: Default::default(),
+            ordering: Default::default(),
+            locktime: Default::default(),
+            rbf: Default::default(),
+            version: Default::default(),
+            change_policy: Default::default(),
+            force_non_witness_utxo: Default::default(),
+            add_global_xpubs: Default::default(),
+            coin_selection: Default::default(),
+            include_output_redeem_witness_script: Default::default(),
+
+            phantom: PhantomData,
+        }
+    }
+}
+
+// methods supported by both contexts, but only for `DefaultCoinSelectionAlgorithm`
+impl<D: Database, Ctx: TxBuilderContext> TxBuilder<D, DefaultCoinSelectionAlgorithm, Ctx> {
+    /// Create an empty builder
+    pub fn new() -> Self {
+        Self::default()
+    }
+}
+
+// methods supported by both contexts, for any CoinSelectionAlgorithm
+impl<D: Database, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext> TxBuilder<D, Cs, Ctx> {
+    /// Set a custom fee rate
+    pub fn fee_rate(mut self, fee_rate: FeeRate) -> Self {
+        self.fee_policy = Some(FeePolicy::FeeRate(fee_rate));
+        self
+    }
+
+    /// Set an absolute fee
+    pub fn fee_absolute(mut self, fee_amount: u64) -> Self {
+        self.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();
+    /// let mut path = BTreeMap::new();
+    /// path.insert("aabbccdd".to_string(), vec![0, 1]);
+    ///
+    /// let builder = TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
+    ///     .policy_path(path, KeychainKind::External);
+    /// # let builder: TxBuilder<bdk::database::MemoryDatabase, _, _> = builder;
+    /// ```
+    pub fn policy_path(
+        mut self,
+        policy_path: BTreeMap<String, Vec<usize>>,
+        keychain: KeychainKind,
+    ) -> Self {
+        let to_update = match keychain {
+            KeychainKind::Internal => &mut self.internal_policy_path,
+            KeychainKind::External => &mut self.external_policy_path,
+        };
+
+        *to_update = Some(policy_path);
+        self
+    }
+
+    /// Replace the internal list of utxos that **must** be spent with a new list
+    ///
+    /// 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 utxos(mut self, utxos: Vec<OutPoint>) -> Self {
+        self.utxos = utxos;
+        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, utxo: OutPoint) -> Self {
+        self.utxos.push(utxo);
+        self
+    }
+
+    /// Only spend utxos added by [`add_utxo`] and [`utxos`].
+    ///
+    /// 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
+    /// [`utxos`]: Self::utxos
+    pub fn manually_selected_only(mut self) -> Self {
+        self.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::utxos`] and
+    /// [`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>) -> Self {
+        self.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::utxos`] and
+    /// [`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) -> Self {
+        self.unspendable.insert(unspendable);
+        self
+    }
+
+    /// Sign with a specific sig hash
+    ///
+    /// **Use this option very carefully**
+    pub fn sighash(mut self, sighash: SigHashType) -> Self {
+        self.sighash = Some(sighash);
+        self
+    }
+
+    /// Choose the ordering for inputs and outputs of the transaction
+    pub fn ordering(mut self, ordering: TxOrdering) -> Self {
+        self.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: u32) -> Self {
+        self.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) -> Self {
+        self.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) -> Self {
+        self.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) -> Self {
+        self.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) -> Self {
+        self.change_policy = change_policy;
+        self
+    }
+
+    /// Fill-in the [`psbt::Input::non_witness_utxo`](bitcoin::util::psbt::Input::non_witness_utxo) field even if the wallet only has SegWit
+    /// descriptors.
+    ///
+    /// This is useful for signers which always require it, like Trezor hardware wallets.
+    pub fn force_non_witness_utxo(mut self) -> Self {
+        self.force_non_witness_utxo = true;
+        self
+    }
+
+    /// Fill-in the [`psbt::Output::redeem_script`](bitcoin::util::psbt::Output::redeem_script) and
+    /// [`psbt::Output::witness_script`](bitcoin::util::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) -> Self {
+        self.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) -> Self {
+        self.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) -> Self {
+        self.drain_wallet = true;
+        self
+    }
+
+    /// Choose the coin selection algorithm
+    ///
+    /// Overrides the [`DefaultCoinSelectionAlgorithm`](super::coin_selection::DefaultCoinSelectionAlgorithm).
+    pub fn coin_selection<P: CoinSelectionAlgorithm<D>>(
+        self,
+        coin_selection: P,
+    ) -> TxBuilder<D, P, Ctx> {
+        TxBuilder {
+            recipients: self.recipients,
+            drain_wallet: self.drain_wallet,
+            single_recipient: self.single_recipient,
+            fee_policy: self.fee_policy,
+            internal_policy_path: self.internal_policy_path,
+            external_policy_path: self.external_policy_path,
+            utxos: self.utxos,
+            unspendable: self.unspendable,
+            manually_selected_only: self.manually_selected_only,
+            sighash: self.sighash,
+            ordering: self.ordering,
+            locktime: self.locktime,
+            rbf: self.rbf,
+            version: self.version,
+            change_policy: self.change_policy,
+            force_non_witness_utxo: self.force_non_witness_utxo,
+            add_global_xpubs: self.add_global_xpubs,
+            include_output_redeem_witness_script: self.include_output_redeem_witness_script,
+            coin_selection,
+
+            phantom: PhantomData,
+        }
+    }
+}
+
+// methods supported only by create_tx, and only for `DefaultCoinSelectionAlgorithm`
+impl<D: Database> TxBuilder<D, DefaultCoinSelectionAlgorithm, CreateTx> {
+    /// Create a builder starting from a list of recipients
+    pub fn with_recipients(recipients: Vec<(Script, u64)>) -> Self {
+        Self::default().set_recipients(recipients)
+    }
+}
+
+// methods supported only by create_tx, for any `CoinSelectionAlgorithm`
+impl<D: Database, Cs: CoinSelectionAlgorithm<D>> TxBuilder<D, Cs, CreateTx> {
+    /// Replace the recipients already added with a new list
+    pub fn set_recipients(mut self, recipients: Vec<(Script, u64)>) -> Self {
+        self.recipients = recipients;
+        self
+    }
+
+    /// Add a recipient to the internal list
+    pub fn add_recipient(mut self, script_pubkey: Script, amount: u64) -> Self {
+        self.recipients.push((script_pubkey, amount));
+        self
+    }
+
+    /// Set a single recipient that will get all the selected funds minus the fee. No change will
+    /// be created
+    ///
+    /// This method overrides any recipient set with [`set_recipients`](Self::set_recipients) or
+    /// [`add_recipient`](Self::add_recipient).
+    ///
+    /// It can only be used in conjunction with [`drain_wallet`](Self::drain_wallet) to send the
+    /// entire content of the wallet (minus filters) to a single recipient or with a
+    /// list of manually selected UTXOs by enabling [`manually_selected_only`](Self::manually_selected_only)
+    /// and selecting them with [`utxos`](Self::utxos) or [`add_utxo`](Self::add_utxo).
+    ///
+    /// When bumping the fees of a transaction made with this option, the user should remeber to
+    /// add [`maintain_single_recipient`](Self::maintain_single_recipient) to correctly update the
+    /// single output instead of adding one more for the change.
+    pub fn set_single_recipient(mut self, recipient: Script) -> Self {
+        self.single_recipient = Some(recipient);
+        self.recipients.clear();
+
+        self
+    }
+
+    /// Enable signaling RBF
+    ///
+    /// This will use the default nSequence value of `0xFFFFFFFD`.
+    pub fn enable_rbf(mut self) -> Self {
+        self.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: u32) -> Self {
+        self.rbf = Some(RBFValue::Value(nsequence));
+        self
+    }
+}
+
+// methods supported only by bump_fee
+impl<D: Database> TxBuilder<D, DefaultCoinSelectionAlgorithm, BumpFee> {
+    /// Bump the fees of a transaction made with [`set_single_recipient`](Self::set_single_recipient)
+    ///
+    /// Unless extra inputs are specified with [`add_utxo`] or [`utxos`], this flag will make
+    /// `bump_fee` reduce the value of the existing output, or fail if it would be consumed
+    /// entirely given the higher new fee rate.
+    ///
+    /// If extra inputs are added and they are not entirely consumed in fees, a change output will not
+    /// be added; the existing output will simply grow in value.
+    ///
+    /// Fails if the transaction has more than one outputs.
+    ///
+    /// [`add_utxo`]: Self::add_utxo
+    /// [`utxos`]: Self::utxos
+    pub fn maintain_single_recipient(mut self) -> Self {
+        self.single_recipient = Some(Script::default());
+        self
+    }
+}
+
+/// Ordering of the transaction's inputs and outputs
+#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
+pub enum TxOrdering {
+    /// Randomized (default)
+    Shuffle,
+    /// Unchanged
+    Untouched,
+    /// BIP69 / Lexicographic
+    BIP69Lexicographic,
+}
+
+impl Default for TxOrdering {
+    fn default() -> Self {
+        TxOrdering::Shuffle
+    }
+}
+
+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;
+                #[cfg(test)]
+                use rand::SeedableRng;
+
+                #[cfg(not(test))]
+                let mut rng = rand::thread_rng();
+                #[cfg(test)]
+                let mut rng = rand::rngs::StdRng::seed_from_u64(0);
+
+                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(u32),
+}
+
+impl RBFValue {
+    pub(crate) fn get_value(&self) -> u32 {
+        match self {
+            RBFValue::Default => 0xFFFFFFFD,
+            RBFValue::Value(v) => *v,
+        }
+    }
+}
+
+/// Policy regarding the use of change outputs when creating a transaction
+#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
+pub enum ChangeSpendPolicy {
+    /// Use both change and non-change outputs (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 Default for ChangeSpendPolicy {
+    fn default() -> Self {
+        ChangeSpendPolicy::ChangeAllowed
+    }
+}
+
+impl ChangeSpendPolicy {
+    pub(crate) fn is_satisfied_by(&self, utxo: &UTXO) -> 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: &'static 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 bitcoin::consensus::deserialize;
+    use bitcoin::hashes::hex::FromHex;
+
+    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();
+
+        TxOrdering::Shuffle.sort_tx(&mut tx);
+
+        assert_eq!(original_tx.input, tx.input);
+        assert_ne!(original_tx.output, tx.output);
+    }
+
+    #[test]
+    fn test_output_ordering_bip69() {
+        use std::str::FromStr;
+
+        let original_tx = ordering_test_tx!();
+        let mut tx = original_tx.clone();
+
+        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, 800);
+        assert_eq!(tx.output[1].script_pubkey, From::from(vec![0xAA]));
+        assert_eq!(tx.output[2].script_pubkey, From::from(vec![0xAA, 0xEE]));
+    }
+
+    fn get_test_utxos() -> Vec<UTXO> {
+        vec![
+            UTXO {
+                outpoint: OutPoint {
+                    txid: Default::default(),
+                    vout: 0,
+                },
+                txout: Default::default(),
+                keychain: KeychainKind::External,
+            },
+            UTXO {
+                outpoint: OutPoint {
+                    txid: Default::default(),
+                    vout: 1,
+                },
+                txout: Default::default(),
+                keychain: KeychainKind::Internal,
+            },
+        ]
+    }
+
+    #[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))
+            .collect::<Vec<_>>();
+
+        assert_eq!(filtered.len(), 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/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/utils.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/utils.rs.html new file mode 100644 index 0000000000..e077192fc2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/utils.rs.html @@ -0,0 +1,580 @@ +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
+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
+
+// Magical Bitcoin Library
+// Written in 2020 by
+//     Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020 Magical Bitcoin
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+// SOFTWARE.
+
+use bitcoin::secp256k1::{All, Secp256k1};
+use bitcoin::util::bip32;
+
+use miniscript::descriptor::DescriptorPublicKeyCtx;
+use miniscript::{MiniscriptKey, Satisfier, ToPublicKey};
+
+// De-facto standard "dust limit" (even though it should change based on the output type)
+const DUST_LIMIT_SATOSHI: u64 = 546;
+
+// MSB of the nSequence. If set there's no consensus-constraint, so it must be disabled when
+// spending using CSV in order to enforce CSV rules
+pub(crate) const SEQUENCE_LOCKTIME_DISABLE_FLAG: u32 = 1 << 31;
+// 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;
+// Mask for the bits used to express the timelock
+pub(crate) const SEQUENCE_LOCKTIME_MASK: u32 = 0x0000FFFF;
+
+// Threshold for nLockTime to be considered a block-height-based timelock rather than time-based
+pub(crate) const BLOCKS_TIMELOCK_THRESHOLD: u32 = 500000000;
+
+/// Trait to check if a value is below the dust limit
+// we implement this trait to make sure we don't mess up the comparison with off-by-one like a <
+// instead of a <= etc. The constant value for the dust limit is not public on purpose, to
+// encourage the usage of this trait.
+pub trait IsDust {
+    /// Check whether or not a value is below dust limit
+    fn is_dust(&self) -> bool;
+}
+
+impl IsDust for u64 {
+    fn is_dust(&self) -> bool {
+        *self <= DUST_LIMIT_SATOSHI
+    }
+}
+
+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: u32, csv: u32) -> bool {
+    // This flag cannot be set in the nSequence when spending using OP_CSV
+    if rbf & SEQUENCE_LOCKTIME_DISABLE_FLAG != 0 {
+        return false;
+    }
+
+    let mask = SEQUENCE_LOCKTIME_TYPE_FLAG | SEQUENCE_LOCKTIME_MASK;
+    let rbf = rbf & mask;
+    let csv = csv & mask;
+
+    // Both values should be represented in the same unit (either time-based or
+    // block-height based)
+    if (rbf < SEQUENCE_LOCKTIME_TYPE_FLAG) != (csv < SEQUENCE_LOCKTIME_TYPE_FLAG) {
+        return false;
+    }
+
+    // The value should be at least `csv`
+    if rbf < csv {
+        return false;
+    }
+
+    true
+}
+
+pub(crate) fn check_nlocktime(nlocktime: u32, required: u32) -> bool {
+    // Both values should be expressed in the same unit
+    if (nlocktime < BLOCKS_TIMELOCK_THRESHOLD) != (required < BLOCKS_TIMELOCK_THRESHOLD) {
+        return false;
+    }
+
+    // The value should be at least `required`
+    if nlocktime < required {
+        return false;
+    }
+
+    true
+}
+
+impl<ToPkCtx: Copy, Pk: MiniscriptKey + ToPublicKey<ToPkCtx>> Satisfier<ToPkCtx, Pk> for After {
+    fn check_after(&self, n: u32) -> bool {
+        if let Some(current_height) = self.current_height {
+            current_height >= n
+        } 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<ToPkCtx: Copy, Pk: MiniscriptKey + ToPublicKey<ToPkCtx>> Satisfier<ToPkCtx, Pk> for Older {
+    fn check_older(&self, n: u32) -> bool {
+        if let Some(current_height) = self.current_height {
+            // TODO: test >= / >
+            current_height as u64 >= self.create_height.unwrap_or(0) as u64 + n as u64
+        } else {
+            self.assume_height_reached
+        }
+    }
+}
+
+pub(crate) type SecpCtx = Secp256k1<All>;
+pub(crate) fn descriptor_to_pk_ctx(secp: &SecpCtx) -> DescriptorPublicKeyCtx<'_, All> {
+    // Create a `to_pk_ctx` with a dummy derivation index, since we always use this on descriptor
+    // that have already been derived with `Descriptor::derive()`, so the child number added here
+    // is ignored.
+    DescriptorPublicKeyCtx::new(secp, bip32::ChildNumber::Normal { index: 0 })
+}
+
+pub struct ChunksIterator<I: Iterator> {
+    iter: I,
+    size: usize,
+}
+
+impl<I: Iterator> ChunksIterator<I> {
+    #[allow(dead_code)]
+    pub fn new(iter: I, size: usize) -> Self {
+        ChunksIterator { iter, size }
+    }
+}
+
+impl<I: Iterator> Iterator for ChunksIterator<I> {
+    type Item = Vec<<I as std::iter::Iterator>::Item>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let mut v = Vec::new();
+        for _ in 0..self.size {
+            let e = self.iter.next();
+
+            match e {
+                None => break,
+                Some(val) => v.push(val),
+            }
+        }
+
+        if v.is_empty() {
+            return None;
+        }
+
+        Some(v)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::{
+        check_nlocktime, check_nsequence_rbf, BLOCKS_TIMELOCK_THRESHOLD,
+        SEQUENCE_LOCKTIME_TYPE_FLAG,
+    };
+    use crate::types::FeeRate;
+
+    #[test]
+    fn test_fee_from_btc_per_kb() {
+        let fee = FeeRate::from_btc_per_kvb(1e-5);
+        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
+    }
+
+    #[test]
+    fn test_fee_from_sats_vbyte() {
+        let fee = FeeRate::from_sat_per_vb(1.0);
+        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
+    }
+
+    #[test]
+    fn test_fee_default_min_relay_fee() {
+        let fee = FeeRate::default_min_relay_fee();
+        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_msb_set() {
+        let result = check_nsequence_rbf(0x80000000, 5000);
+        assert_eq!(result, false);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_lt_csv() {
+        let result = check_nsequence_rbf(4000, 5000);
+        assert_eq!(result, false);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_different_unit() {
+        let result = check_nsequence_rbf(SEQUENCE_LOCKTIME_TYPE_FLAG + 5000, 5000);
+        assert_eq!(result, false);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_mask() {
+        let result = check_nsequence_rbf(0x3f + 10_000, 5000);
+        assert_eq!(result, true);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_same_unit_blocks() {
+        let result = check_nsequence_rbf(10_000, 5000);
+        assert_eq!(result, true);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_same_unit_time() {
+        let result = check_nsequence_rbf(
+            SEQUENCE_LOCKTIME_TYPE_FLAG + 10_000,
+            SEQUENCE_LOCKTIME_TYPE_FLAG + 5000,
+        );
+        assert_eq!(result, true);
+    }
+
+    #[test]
+    fn test_check_nlocktime_lt_cltv() {
+        let result = check_nlocktime(4000, 5000);
+        assert_eq!(result, false);
+    }
+
+    #[test]
+    fn test_check_nlocktime_different_unit() {
+        let result = check_nlocktime(BLOCKS_TIMELOCK_THRESHOLD + 5000, 5000);
+        assert_eq!(result, false);
+    }
+
+    #[test]
+    fn test_check_nlocktime_same_unit_blocks() {
+        let result = check_nlocktime(10_000, 5000);
+        assert_eq!(result, true);
+    }
+
+    #[test]
+    fn test_check_nlocktime_same_unit_time() {
+        let result = check_nlocktime(
+            BLOCKS_TIMELOCK_THRESHOLD + 10_000,
+            BLOCKS_TIMELOCK_THRESHOLD + 5000,
+        );
+        assert_eq!(result, true);
+    }
+}
+
+
\ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/storage.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/storage.js new file mode 100644 index 0000000000..318275ed34 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/storage.js @@ -0,0 +1 @@ +var resourcesSuffix="";var darkThemes=["dark","ayu"];var currentTheme=document.getElementById("themeStyle");var mainTheme=document.getElementById("mainThemeStyle");var settingsDataset=(function(){var settingsElement=document.getElementById("default-settings");if(settingsElement===null){return null}var dataset=settingsElement.dataset;if(dataset===undefined){return null}return dataset})();function getSettingValue(settingName){var current=getCurrentValue('rustdoc-'+settingName);if(current!==null){return current}if(settingsDataset!==null){var def=settingsDataset[settingName.replace(/-/g,'_')];if(def!==undefined){return def}}return null}var localStoredTheme=getSettingValue("theme");var savedHref=[];function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(!elem||!elem.classList){return}elem.classList.add(className)}function removeClass(elem,className){if(!elem||!elem.classList){return}elem.classList.remove(className)}function onEach(arr,func,reversed){if(arr&&arr.length>0&&func){var length=arr.length;var i;if(reversed!==true){for(i=0;i=0;--i){if(func(arr[i])===true){return true}}}}return false}function onEachLazy(lazyArray,func,reversed){return onEach(Array.prototype.slice.call(lazyArray),func,reversed)}function hasOwnProperty(obj,property){return Object.prototype.hasOwnProperty.call(obj,property)}function usableLocalStorage(){if(typeof Storage==="undefined"){return false}try{return window.localStorage!==null&&window.localStorage!==undefined}catch(err){return false}}function updateLocalStorage(name,value){if(usableLocalStorage()){localStorage[name]=value}else{}}function getCurrentValue(name){if(usableLocalStorage()&&localStorage[name]!==undefined){return localStorage[name]}return null}function switchTheme(styleElem,mainStyleElem,newTheme,saveTheme){var fullBasicCss="rustdoc"+resourcesSuffix+".css";var fullNewTheme=newTheme+resourcesSuffix+".css";var newHref=mainStyleElem.href.replace(fullBasicCss,fullNewTheme);if(saveTheme===true){updateLocalStorage("rustdoc-theme",newTheme)}if(styleElem.href===newHref){return}var found=false;if(savedHref.length===0){onEachLazy(document.getElementsByTagName("link"),function(el){savedHref.push(el.href)})}onEach(savedHref,function(el){if(el===newHref){found=true;return true}});if(found===true){styleElem.href=newHref}}function useSystemTheme(value){if(value===undefined){value=true}updateLocalStorage("rustdoc-use-system-theme",value);var toggle=document.getElementById("use-system-theme");if(toggle&&toggle instanceof HTMLInputElement){toggle.checked=value}}var updateSystemTheme=(function(){if(!window.matchMedia){return function(){let cssTheme=getComputedStyle(document.documentElement).getPropertyValue('content');switchTheme(currentTheme,mainTheme,JSON.parse(cssTheme)||light,true)}}var mql=window.matchMedia("(prefers-color-scheme: dark)");function handlePreferenceChange(mql){if(getSettingValue("use-system-theme")!=="false"){var lightTheme=getSettingValue("preferred-light-theme")||"light";var darkTheme=getSettingValue("preferred-dark-theme")||"dark";if(mql.matches){switchTheme(currentTheme,mainTheme,darkTheme,true)}else{switchTheme(currentTheme,mainTheme,lightTheme,true)}}}mql.addListener(handlePreferenceChange);return function(){handlePreferenceChange(mql)}})();if(getSettingValue("use-system-theme")!=="false"&&window.matchMedia){if(getSettingValue("use-system-theme")===null&&getSettingValue("preferred-dark-theme")===null&&darkThemes.indexOf(localStoredTheme)>=0){updateLocalStorage("rustdoc-preferred-dark-theme",localStoredTheme)}updateSystemTheme()}else{switchTheme(currentTheme,mainTheme,getSettingValue("theme")||"light",false)} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/theme.js b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/theme.js new file mode 100644 index 0000000000..8f9c49a429 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/theme.js @@ -0,0 +1 @@ +var themes=document.getElementById("theme-choices");var themePicker=document.getElementById("theme-picker");function showThemeButtonState(){themes.style.display="block";themePicker.style.borderBottomRightRadius="0";themePicker.style.borderBottomLeftRadius="0"}function hideThemeButtonState(){themes.style.display="none";themePicker.style.borderBottomRightRadius="3px";themePicker.style.borderBottomLeftRadius="3px"}function switchThemeButtonState(){if(themes.style.display==="block"){hideThemeButtonState()}else{showThemeButtonState()}};function handleThemeButtonsBlur(e){var active=document.activeElement;var related=e.relatedTarget;if(active.id!=="theme-picker"&&(!active.parentNode||active.parentNode.id!=="theme-choices")&&(!related||(related.id!=="theme-picker"&&(!related.parentNode||related.parentNode.id!=="theme-choices")))){hideThemeButtonState()}}themePicker.onclick=switchThemeButtonState;themePicker.onblur=handleThemeButtonsBlur;["ayu","dark","light"].forEach(function(item){var but=document.createElement("button");but.textContent=item;but.onclick=function(el){switchTheme(currentTheme,mainTheme,item,true);useSystemTheme(false)};but.onblur=handleThemeButtonsBlur;themes.appendChild(but)}) \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/wheel.svg b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/wheel.svg new file mode 100644 index 0000000000..01da3b24c7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/wheel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/.lock b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/.lock new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/COPYRIGHT.txt b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/COPYRIGHT.txt new file mode 100644 index 0000000000..c2629a83f7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/COPYRIGHT.txt @@ -0,0 +1,50 @@ +These documentation pages include resources by third parties. This copyright +file applies only to those resources. The following third party resources are +included, and carry their own copyright notices and license terms: + +* Fira Sans (FiraSans-Regular.woff2, FiraSans-Medium.woff2, + FiraSans-Regular.woff, FiraSans-Medium.woff): + + Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ + with Reserved Font Name Fira Sans. + + Copyright (c) 2014, Telefonica S.A. + + Licensed under the SIL Open Font License, Version 1.1. + See FiraSans-LICENSE.txt. + +* rustdoc.css, main.js, and playpen.js: + + Copyright 2015 The Rust Developers. + Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or + the MIT license (LICENSE-MIT.txt) at your option. + +* normalize.css: + + Copyright (c) Nicolas Gallagher and Jonathan Neal. + Licensed under the MIT license (see LICENSE-MIT.txt). + +* Source Code Pro (SourceCodePro-Regular.ttf.woff2, + SourceCodePro-Semibold.ttf.woff2, SourceCodePro-It.ttf.woff2, + SourceCodePro-Regular.ttf.woff, SourceCodePro-Semibold.ttf.woff, + SourceCodePro-It.ttf.woff): + + Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), + with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark + of Adobe Systems Incorporated in the United States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceCodePro-LICENSE.txt. + +* Source Serif 4 (SourceSerif4-Regular.ttf.woff2, SourceSerif4-Bold.ttf.woff2, + SourceSerif4-It.ttf.woff2, SourceSerif4-Regular.ttf.woff, + SourceSerif4-Bold.ttf.woff, SourceSerif4-It.ttf.woff): + + Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name + 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United + States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceSerif4-LICENSE.md. + +This copyright file is intended to be distributed with rustdoc output. diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/FiraSans-LICENSE.txt b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/FiraSans-LICENSE.txt new file mode 100644 index 0000000000..ff9afab064 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/FiraSans-LICENSE.txt @@ -0,0 +1,94 @@ +Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. +with Reserved Font Name < Fira >, + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/FiraSans-Medium.woff b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/FiraSans-Medium.woff new file mode 100644 index 0000000000..7d742c5fb7 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/FiraSans-Medium.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/FiraSans-Medium.woff2 b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/FiraSans-Medium.woff2 new file mode 100644 index 0000000000..7a1e5fc548 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/FiraSans-Medium.woff2 differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/FiraSans-Regular.woff b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/FiraSans-Regular.woff new file mode 100644 index 0000000000..d8e0363f4e Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/FiraSans-Regular.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/FiraSans-Regular.woff2 b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/FiraSans-Regular.woff2 new file mode 100644 index 0000000000..e766e06ccb Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/FiraSans-Regular.woff2 differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/LICENSE-APACHE.txt b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/LICENSE-APACHE.txt new file mode 100644 index 0000000000..16fe87b06e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/LICENSE-APACHE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/LICENSE-MIT.txt b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/LICENSE-MIT.txt new file mode 100644 index 0000000000..31aa79387f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/LICENSE-MIT.txt @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-It.ttf.woff b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-It.ttf.woff new file mode 100644 index 0000000000..8d68f2febd Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-It.ttf.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-It.ttf.woff2 b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-It.ttf.woff2 new file mode 100644 index 0000000000..462c34efcd Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-It.ttf.woff2 differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-LICENSE.txt b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-LICENSE.txt new file mode 100644 index 0000000000..07542572e3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-LICENSE.txt @@ -0,0 +1,93 @@ +Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-Regular.ttf.woff b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-Regular.ttf.woff new file mode 100644 index 0000000000..7be076e1fc Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-Regular.ttf.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-Regular.ttf.woff2 b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-Regular.ttf.woff2 new file mode 100644 index 0000000000..10b558e0b6 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-Regular.ttf.woff2 differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-Semibold.ttf.woff b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-Semibold.ttf.woff new file mode 100644 index 0000000000..61bc67b802 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-Semibold.ttf.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-Semibold.ttf.woff2 b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-Semibold.ttf.woff2 new file mode 100644 index 0000000000..5ec64eef0e Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceCodePro-Semibold.ttf.woff2 differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-Bold.ttf.woff b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-Bold.ttf.woff new file mode 100644 index 0000000000..8ad41888e6 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-Bold.ttf.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-Bold.ttf.woff2 b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-Bold.ttf.woff2 new file mode 100644 index 0000000000..db57d21455 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-Bold.ttf.woff2 differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-It.ttf.woff b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-It.ttf.woff new file mode 100644 index 0000000000..2a34b5c42a Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-It.ttf.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-It.ttf.woff2 b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-It.ttf.woff2 new file mode 100644 index 0000000000..1cbc021a3a Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-It.ttf.woff2 differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-LICENSE.md b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-LICENSE.md new file mode 100644 index 0000000000..68ea189240 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-LICENSE.md @@ -0,0 +1,93 @@ +Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-Regular.ttf.woff b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-Regular.ttf.woff new file mode 100644 index 0000000000..45a5521ab0 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-Regular.ttf.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-Regular.ttf.woff2 b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-Regular.ttf.woff2 new file mode 100644 index 0000000000..2db73fe2b4 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/SourceSerif4-Regular.ttf.woff2 differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/ayu.css b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/ayu.css new file mode 100644 index 0000000000..af24cd6cca --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/ayu.css @@ -0,0 +1 @@ + body{background-color:#0f1419;color:#c5c5c5;}h1,h2,h3,h4{color:white;}h1.fqn{border-bottom-color:#5c6773;}h1.fqn a{color:#fff;}h2,h3,h4{border-bottom-color:#5c6773;}h4{border:none;}.in-band{background-color:#0f1419;}.invisible{background:rgba(0,0,0,0);}.docblock code{color:#ffb454;}.code-header{color:#e6e1cf;}.docblock pre>code,pre>code{color:#e6e1cf;}span code{color:#e6e1cf;}.docblock a>code{color:#39AFD7 !important;}.docblock code,.docblock-short code{background-color:#191f26;}pre,.rustdoc.source .example-wrap{color:#e6e1cf;background-color:#191f26;}.sidebar{background-color:#14191f;}.logo-container.rust-logo>img{filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);}*{scrollbar-color:#5c6773 transparent;}.sidebar{scrollbar-color:#5c6773 transparent;}::-webkit-scrollbar-track{background-color:transparent;}::-webkit-scrollbar-thumb{background-color:#5c6773;}.sidebar::-webkit-scrollbar-track{background-color:transparent;}.sidebar::-webkit-scrollbar-thumb{background-color:#5c6773;}.sidebar .current{background-color:transparent;color:#ffb44c;}.source .sidebar{background-color:#0f1419;}.sidebar .location{border-color:#000;background-color:#0f1419;color:#fff;}.sidebar-elems .location{color:#ff7733;}.sidebar-elems .location a{color:#fff;}.sidebar .version{border-bottom-color:#424c57;}.sidebar-title{border-top-color:#5c6773;border-bottom-color:#5c6773;}.block a:hover{background:transparent;color:#ffb44c;}.line-numbers span{color:#5c6773;}.line-numbers .line-highlighted{color:#708090;background-color:rgba(255,236,164,0.06);padding-right:4px;border-right:1px solid #ffb44c;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#5c6773;}.docblock table td,.docblock table th{border-color:#5c6773;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#c5c5c5;}.search-results a:hover{background-color:#777;}.search-results a:focus{color:#000 !important;background-color:#c6afb3;}.search-results a{color:#0096cf;}.search-results a div.desc{color:#c5c5c5;}.content .item-info::before{color:#ccc;}.content span.foreigntype,.content a.foreigntype{color:#ef57ff;}.content span.union,.content a.union{color:#98a01c;}.content span.constant,.content a.constant,.content span.static,.content a.static{color:#6380a0;}.content span.primitive,.content a.primitive{color:#32889b;}.content span.traitalias,.content a.traitalias{color:#57d399;}.content span.keyword,.content a.keyword{color:#de5249;}.content span.externcrate,.content span.mod,.content a.mod{color:#acccf9;}.content span.struct,.content a.struct{color:#ffa0a5;}.content span.enum,.content a.enum{color:#99e0c9;}.content span.trait,.content a.trait{color:#39AFD7;}.content span.type,.content a.type{color:#cfbcf5;}.content span.fn,.content a.fn,.content span.method,.content a.method,.content span.tymethod,.content a.tymethod,.content .fnname{color:#fdd687;}.content span.attr,.content a.attr,.content span.derive,.content a.derive,.content span.macro,.content a.macro{color:#a37acc;}pre.rust .comment{color:#788797;}pre.rust .doccomment{color:#a1ac88;}nav:not(.sidebar){border-bottom-color:#424c57;}nav.main .current{border-top-color:#5c6773;border-bottom-color:#5c6773;}nav.main .separator{border:1px solid #5c6773;}a{color:#c5c5c5;}body.source .example-wrap pre.rust a{background:#333;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.item-info a,#help a{color:#39AFD7;}details.rustdoc-toggle>summary.hideme>span,details.rustdoc-toggle>summary::before,details.undocumented>summary::before{color:#999;}details.rustdoc-toggle>summary::before,details.undocumented>summary::before{filter:invert(100%);}#crate-search{color:#c5c5c5;background-color:#141920;box-shadow:0 0 0 1px #424c57,0 0 0 2px transparent;border-color:#424c57;}.search-input{color:#ffffff;background-color:#141920;box-shadow:0 0 0 1px #424c57,0 0 0 2px transparent;transition:box-shadow 150ms ease-in-out;}#crate-search+.search-input:focus{box-shadow:0 0 0 1px #148099,0 0 0 2px transparent;}.search-input:disabled{background-color:#3e3e3e;}.module-item .stab,.import-item .stab{color:#000;}.stab.unstable,.stab.deprecated,.stab.portability{color:#c5c5c5;background:#314559 !important;border-style:none !important;border-radius:4px;padding:3px 6px 3px 6px;}.stab.portability>code{color:#e6e1cf;background:none;}#help>div{background:#14191f;box-shadow:0px 6px 20px 0px black;border:none;border-radius:4px;}#help span.bottom,#help span.top{border-color:#5c6773;}.since{color:grey;}.result-name .primitive>i,.result-name .keyword>i{color:#788797;}.line-numbers :target{background-color:transparent;}pre.rust .number,pre.rust .string{color:#b8cc52;}pre.rust .kw,pre.rust .kw-2,pre.rust .prelude-ty,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .op,pre.rust .lifetime{color:#ff7733;}pre.rust .macro,pre.rust .macro-nonterminal{color:#a37acc;}pre.rust .question-mark{color:#ff9011;}pre.rust .self{color:#36a3d9;font-style:italic;}pre.rust .attribute{color:#e6e1cf;}pre.rust .attribute .ident,pre.rust .attribute .op{color:#e6e1cf;}.example-wrap>pre.line-number{color:#5c67736e;border:none;}a.test-arrow{font-size:100%;color:#788797;border-radius:4px;background-color:rgba(57,175,215,0.09);}a.test-arrow:hover{background-color:rgba(57,175,215,0.368);color:#c5c5c5;}.toggle-label,.code-attribute{color:#999;}:target,:target>*{background:rgba(255,236,164,0.06);}:target{border-right:3px solid rgba(255,180,76,0.85);}pre.compile_fail{border-left:2px solid rgba(255,0,0,.4);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.4);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.5);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#39AFD7;}.tooltip::after{background-color:#314559;color:#c5c5c5;border:1px solid #5c6773;}.tooltip::before{border-color:transparent #314559 transparent transparent;}.notable-traits-tooltiptext{background-color:#314559;border-color:#5c6773;}.notable-traits-tooltiptext .notable{border-bottom-color:#5c6773;}#titles>button.selected{background-color:#141920 !important;border-bottom:1px solid #ffb44c !important;border-top:none;}#titles>button:not(.selected){background-color:transparent !important;border:none;}#titles>button:hover{border-bottom:1px solid rgba(242,151,24,0.3);}#titles>button>div.count{color:#888;}.search-input:focus{}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{}.content span.struct,.content a.struct,.block a.current.struct{}#titles>button:hover,#titles>button.selected{}.content span.type,.content a.type,.block a.current.type{}.content span.union,.content a.union,.block a.current.union{}pre.rust .lifetime{}.stab.unstable{}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){}.content span.enum,.content a.enum,.block a.current.enum{}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{}.content span.keyword,.content a.keyword,.block a.current.keyword{}pre.rust .comment{}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{}pre.rust .kw{}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{}pre.rust .doccomment{}.stab.deprecated{}.content a.attr,.content a.derive,.content a.macro{}.stab.portability{}.content span.primitive,.content a.primitive,.block a.current.primitive{}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{}pre.rust .kw-2,pre.rust .prelude-ty{}.content span.trait,.content a.trait,.block a.current.trait{}.search-results a:focus span{}a.result-trait:focus{}a.result-traitalias:focus{}a.result-mod:focus,a.result-externcrate:focus{}a.result-mod:focus{}a.result-externcrate:focus{}a.result-enum:focus{}a.result-struct:focus{}a.result-union:focus{}a.result-fn:focus,a.result-method:focus,a.result-tymethod:focus{}a.result-type:focus{}a.result-foreigntype:focus{}a.result-attr:focus,a.result-derive:focus,a.result-macro:focus{}a.result-constant:focus,a.result-static:focus{}a.result-primitive:focus{}a.result-keyword:focus{}@media (max-width:700px){.sidebar-menu{background-color:#14191f;border-bottom-color:#5c6773;border-right-color:#5c6773;}.sidebar-elems{background-color:#14191f;border-right-color:#5c6773;}#sidebar-filler{background-color:#14191f;border-bottom-color:#5c6773;}}kbd{color:#c5c5c5;background-color:#314559;border-color:#5c6773;border-bottom-color:#5c6773;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu,#help-button{border-color:#5c6773;background-color:#0f1419;color:#fff;}#theme-picker>img,#settings-menu>img{filter:invert(100);}#copy-path{color:#fff;}#copy-path>img{filter:invert(70%);}#copy-path:hover>img{filter:invert(100%);}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus,#help-button:hover,#help-button:focus{border-color:#e0e0e0;}#theme-choices{border-color:#5c6773;background-color:#0f1419;}#theme-choices>button:not(:first-child){border-top-color:#5c6773;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:rgba(110,110,110,0.33);}@media (max-width:700px){#theme-picker{background:#0f1419;}}#all-types{background-color:#14191f;}#all-types:hover{background-color:rgba(70,70,70,0.33);}.search-results .result-name span.alias{color:#c5c5c5;}.search-results .result-name span.grey{color:#999;}#sidebar-toggle{background-color:#14191f;}#sidebar-toggle:hover{background-color:rgba(70,70,70,0.33);}#source-sidebar{background-color:#14191f;}#source-sidebar>.title{color:#fff;border-bottom-color:#5c6773;}div.files>a:hover,div.name:hover{background-color:#14191f;color:#ffb44c;}div.files>.selected{background-color:#14191f;color:#ffb44c;}.setting-line>.title{border-bottom-color:#5c6773;}input:checked+.slider{background-color:#ffb454 !important;} \ No newline at end of file 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 new file mode 100644 index 0000000000..473787d6bb --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/all.html @@ -0,0 +1,5 @@ +List of all items in this crate

List of all items[] + +

Structs

Enums

Traits

Macros

Functions

Typedefs

+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchain.html new file mode 100644 index 0000000000..86b743a374 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchain.html @@ -0,0 +1,41 @@ +AnyBlockchain in bdk::blockchain::any - Rust

Enum bdk::blockchain::any::AnyBlockchain[][src]

pub enum AnyBlockchain {
+    Electrum(ElectrumBlockchain),
+    Esplora(EsploraBlockchain),
+    CompactFilters(CompactFiltersBlockchain),
+}
Expand description

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

+

It allows switching backend at runtime

+

See this module’s documentation for a usage example.

+

Variants

This is supported on crate feature electrum only.

Electrum client

+

Tuple Fields of Electrum

This is supported on crate feature esplora only.

Esplora client

+

Tuple Fields of Esplora

CompactFilters(CompactFiltersBlockchain)
This is supported on crate feature compact_filters only.

Compact filters client

+

Tuple Fields of CompactFilters

Trait Implementations

Return the set of Capability supported by this backend

+

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

+

Populate the internal database with transactions and UTXOs Read more

+

Fetch a transaction from the blockchain given its txid

+

Broadcast a transaction

+

Return the current height

+

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

+

Type that contains the configuration

+

Create a new instance given a configuration

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchainConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchainConfig.html new file mode 100644 index 0000000000..bacd1a1623 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchainConfig.html @@ -0,0 +1,67 @@ +AnyBlockchainConfig in bdk::blockchain::any - Rust

Enum bdk::blockchain::any::AnyBlockchainConfig[][src]

pub enum AnyBlockchainConfig {
+    Electrum(ElectrumBlockchainConfig),
+    Esplora(EsploraBlockchainConfig),
+    CompactFilters(CompactFiltersBlockchainConfig),
+}
Expand description

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

+

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

+

This type can be serialized from a JSON object like:

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

Variants

This is supported on crate feature electrum only.

Electrum client

+

Tuple Fields of Electrum

This is supported on crate feature esplora only.

Esplora client

+

Tuple Fields of Esplora

This is supported on crate feature compact_filters only.

Compact filters client

+

Tuple Fields of CompactFilters

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

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

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

Module bdk::blockchain::any[][src]

Expand description

Runtime-checked blockchain types

+

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

+

Example

+

In this example both wallet_electrum and wallet_esplora have the same type of +Wallet<AnyBlockchain, MemoryDatabase>. This means that they could both, for instance, be +assigned to a struct member.

+ +
let electrum_blockchain = ElectrumBlockchain::from(electrum_client::Client::new("...")?);
+let wallet_electrum: Wallet<AnyBlockchain, _> = Wallet::new(
+    "...",
+    None,
+    Network::Testnet,
+    MemoryDatabase::default(),
+    electrum_blockchain.into(),
+)?;
+
+let esplora_blockchain = EsploraBlockchain::new("...", 20);
+let wallet_esplora: Wallet<AnyBlockchain, _> = Wallet::new(
+    "...",
+    None,
+    Network::Testnet,
+    MemoryDatabase::default(),
+    esplora_blockchain.into(),
+)?;
+
+

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

+ +
let config = serde_json::from_str("...")?;
+let blockchain = AnyBlockchain::from_config(&config)?;
+let wallet = Wallet::new(
+    "...",
+    None,
+    Network::Testnet,
+    MemoryDatabase::default(),
+    blockchain,
+)?;
+

Enums

+

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

+

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

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/sidebar-items.js new file mode 100644 index 0000000000..14144cf693 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/any/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["AnyBlockchain","Type that can contain any of the [`Blockchain`] types defined by the library"],["AnyBlockchainConfig","Type that can contain any of the blockchain configurations defined by the library"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/enum.CompactFiltersError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/enum.CompactFiltersError.html new file mode 100644 index 0000000000..d1bf965657 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/enum.CompactFiltersError.html @@ -0,0 +1,73 @@ +CompactFiltersError in bdk::blockchain::compact_filters - Rust

Enum bdk::blockchain::compact_filters::CompactFiltersError[][src]

pub enum CompactFiltersError {
+
Show 15 variants InvalidResponse, + InvalidHeaders, + InvalidFilterHeader, + InvalidFilter, + MissingBlock, + DataCorruption, + NotConnected, + Timeout, + PeerBloomDisabled, + NoPeers, + Db(Error), + Io(Error), + Bip158(Error), + Time(SystemTimeError), + Global(Box<Error>), +
}
This is supported on crate feature compact_filters only.
Expand description

An error that can occur during sync with a CompactFiltersBlockchain

+

Variants

InvalidResponse

A peer sent an invalid or unexpected response

+
InvalidHeaders

The headers returned are invalid

+
InvalidFilterHeader

The compact filter headers returned are invalid

+
InvalidFilter

The compact filter returned is invalid

+
MissingBlock

The peer is missing a block in the valid chain

+
DataCorruption

The data stored in the block filters storage are corrupted

+
NotConnected

A peer is not connected

+
Timeout

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

+
PeerBloomDisabled

The peer doesn’t advertise the BLOOM service flag

+
NoPeers

No peers have been specified

+
Db(Error)

Internal database error

+

Tuple Fields of Db

0: Error
Io(Error)

Internal I/O error

+

Tuple Fields of Io

0: Error
Bip158(Error)

Invalid BIP158 filter

+

Tuple Fields of Bip158

0: Error

Internal system time error

+

Tuple Fields of Time

Global(Box<Error>)

Wrapper for crate::error::Error

+

Tuple Fields of Global

0: Box<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

+
🔬 This is a nightly-only experimental API. (backtrace)

Returns a stack backtrace, if available, of where this error occurred. 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

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Converts a reference to Self into a dynamic trait object of Fail.

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the “name” of the error. Read more

+

Returns a reference to the underlying cause of this failure, if it +is an error that wraps other errors. Read more

+

Returns a reference to the Backtrace carried by this failure, if it +carries one. Read more

+

Provides context for this failure. Read more

+

Wraps this failure in a compatibility wrapper that implements +std::error::Error. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

Converts the given value to a String. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

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

Module bdk::blockchain::compact_filters[][src]

This is supported on crate feature compact_filters only.
Expand description

Compact Filters

+

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

+

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

+

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

+

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

+

Example

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

Structs

+

Data to connect to a Bitcoin P2P peer

+

Structure implementing the required blockchain traits

+

Configuration for a CompactFiltersBlockchain

+

Container for unconfirmed, but valid Bitcoin transactions

+

A Bitcoin peer

+

Enums

+

An error that can occur during sync with a CompactFiltersBlockchain

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

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

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

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

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/sidebar-items.js new file mode 100644 index 0000000000..187af79563 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["CompactFiltersError","An error that can occur during sync with a [`CompactFiltersBlockchain`]"]],"struct":[["BitcoinPeerConfig","Data to connect to a Bitcoin P2P peer"],["CompactFiltersBlockchain","Structure implementing the required blockchain traits"],["CompactFiltersBlockchainConfig","Configuration for a [`CompactFiltersBlockchain`]"],["Mempool","Container for unconfirmed, but valid Bitcoin transactions"],["Peer","A Bitcoin peer"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.BitcoinPeerConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.BitcoinPeerConfig.html new file mode 100644 index 0000000000..529f5ba605 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.BitcoinPeerConfig.html @@ -0,0 +1,39 @@ +BitcoinPeerConfig in bdk::blockchain::compact_filters - Rust

Struct bdk::blockchain::compact_filters::BitcoinPeerConfig[][src]

pub struct BitcoinPeerConfig {
+    pub address: String,
+    pub socks5: Option<String>,
+    pub socks5_credentials: Option<(String, String)>,
+}
This is supported on crate feature compact_filters only.
Expand description

Data to connect to a Bitcoin P2P peer

+

Fields

address: String

Peer address such as 127.0.0.1:18333

+
socks5: Option<String>

Optional socks5 proxy

+
socks5_credentials: Option<(String, String)>

Optional socks5 proxy credentials

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Deserialize this value from the given Serde deserializer. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html new file mode 100644 index 0000000000..ebd9e1bb42 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html @@ -0,0 +1,40 @@ +CompactFiltersBlockchain in bdk::blockchain::compact_filters - Rust

Struct bdk::blockchain::compact_filters::CompactFiltersBlockchain[][src]

pub struct CompactFiltersBlockchain { /* fields omitted */ }
This is supported on crate feature compact_filters only.
Expand description

Structure implementing the required blockchain traits

+

Example

+

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

+

Implementations

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

+

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

+

Trait Implementations

Return the set of Capability supported by this backend

+

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

+

Fetch a transaction from the blockchain given its txid

+

Broadcast a transaction

+

Return the current height

+

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

+

Populate the internal database with transactions and UTXOs Read more

+

Type that contains the configuration

+

Create a new instance given a configuration

+

Formats the value using the given formatter. Read more

+

Performs the conversion.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchainConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchainConfig.html new file mode 100644 index 0000000000..b9abcf5a31 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchainConfig.html @@ -0,0 +1,42 @@ +CompactFiltersBlockchainConfig in bdk::blockchain::compact_filters - Rust

Struct bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig[][src]

pub struct CompactFiltersBlockchainConfig {
+    pub peers: Vec<BitcoinPeerConfig>,
+    pub network: Network,
+    pub storage_dir: String,
+    pub skip_blocks: Option<usize>,
+}
This is supported on crate feature compact_filters only.
Expand description

Configuration for a CompactFiltersBlockchain

+

Fields

peers: Vec<BitcoinPeerConfig>

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

+
network: Network

Network used

+
storage_dir: String

Storage dir to save partially downloaded headers and full blocks

+
skip_blocks: Option<usize>

Optionally skip initial skip_blocks blocks (default: 0)

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Deserialize this value from the given Serde deserializer. Read more

+

Performs the conversion.

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Mempool.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Mempool.html new file mode 100644 index 0000000000..cfa16dc28d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Mempool.html @@ -0,0 +1,31 @@ +Mempool in bdk::blockchain::compact_filters - Rust

Struct bdk::blockchain::compact_filters::Mempool[][src]

pub struct Mempool(_);
This is supported on crate feature compact_filters only.
Expand description

Container for unconfirmed, but valid Bitcoin transactions

+

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

+

Implementations

Create a new empty mempool

+

Add a transaction to the mempool

+

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

+

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

+

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

+

Return the list of transactions contained in the mempool

+

Trait Implementations

Formats the value using the given formatter. Read more

+

Returns the “default value” for a type. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Peer.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Peer.html new file mode 100644 index 0000000000..c19b1edd4d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Peer.html @@ -0,0 +1,34 @@ +Peer in bdk::blockchain::compact_filters - Rust

Struct bdk::blockchain::compact_filters::Peer[][src]

pub struct Peer { /* fields omitted */ }
This is supported on crate feature compact_filters only.
Expand description

A Bitcoin peer

+

Implementations

Connect to a peer over a plaintext TCP connection

+

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

+

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

+

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

+

Return the [VersionMessage] sent by the peer

+

Return the Bitcoin [Network] in use

+

Return the mempool used by this peer

+

Return whether or not the peer is still connected

+

Send a raw Bitcoin message to the peer

+

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

+

Trait Implementations

Formats the value using the given formatter. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

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

Module bdk::blockchain::electrum[][src]

This is supported on crate feature electrum only.
Expand description

Electrum

+

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

+

Example

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

Structs

+

Wrapper over an Electrum Client that implements the required blockchain traits

+

Configuration for an ElectrumBlockchain

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/sidebar-items.js new file mode 100644 index 0000000000..1bd5458912 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["ElectrumBlockchain","Wrapper over an Electrum Client that implements the required blockchain traits"],["ElectrumBlockchainConfig","Configuration for an [`ElectrumBlockchain`]"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchain.html new file mode 100644 index 0000000000..50327ac0ae --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchain.html @@ -0,0 +1,33 @@ +ElectrumBlockchain in bdk::blockchain::electrum - Rust

Struct bdk::blockchain::electrum::ElectrumBlockchain[][src]

pub struct ElectrumBlockchain { /* fields omitted */ }
This is supported on crate feature electrum only.
Expand description

Wrapper over an Electrum Client that implements the required blockchain traits

+

Example

+

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

+

Trait Implementations

Return the set of Capability supported by this backend

+

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

+

Fetch a transaction from the blockchain given its txid

+

Broadcast a transaction

+

Return the current height

+

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

+

Populate the internal database with transactions and UTXOs Read more

+

Type that contains the configuration

+

Create a new instance given a configuration

+

Performs the conversion.

+

Performs the conversion.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchainConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchainConfig.html new file mode 100644 index 0000000000..214df70de2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchainConfig.html @@ -0,0 +1,45 @@ +ElectrumBlockchainConfig in bdk::blockchain::electrum - Rust

Struct bdk::blockchain::electrum::ElectrumBlockchainConfig[][src]

pub struct ElectrumBlockchainConfig {
+    pub url: String,
+    pub socks5: Option<String>,
+    pub retry: u8,
+    pub timeout: Option<u8>,
+    pub stop_gap: usize,
+}
This is supported on crate feature electrum only.
Expand description

Configuration for an ElectrumBlockchain

+

Fields

url: String

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

+

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

+
socks5: Option<String>

URL of the socks5 proxy server or a Tor service

+
retry: u8

Request retry count

+
timeout: Option<u8>

Request timeout (seconds)

+
stop_gap: usize

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

+

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

+

Performs the conversion.

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

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

Enum bdk::blockchain::Capability[][src]

pub enum Capability {
+    FullHistory,
+    GetAnyTx,
+    AccurateFees,
+}
Expand description

Capabilities that can be supported by a Blockchain backend

+

Variants

FullHistory

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

+
GetAnyTx

Can fetch any historical transaction given its txid

+
AccurateFees

Can compute accurate fees for the transactions found during sync

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Feeds this value into the given Hasher. Read more

+

Feeds a slice of this type into the given Hasher. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/enum.EsploraError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/enum.EsploraError.html new file mode 100644 index 0000000000..6b4fabb600 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/enum.EsploraError.html @@ -0,0 +1,66 @@ +EsploraError in bdk::blockchain::esplora - Rust

Enum bdk::blockchain::esplora::EsploraError[][src]

pub enum EsploraError {
+    Ureq(Error),
+    UreqTransport(Transport),
+    HttpResponse(u16),
+    Io(Error),
+    NoHeader,
+    Parsing(ParseIntError),
+    BitcoinEncoding(Error),
+    Hex(Error),
+    TransactionNotFound(Txid),
+    HeaderHeightNotFound(u32),
+    HeaderHashNotFound(BlockHash),
+}
This is supported on crate feature esplora only.
Expand description

Errors that can happen during a sync with EsploraBlockchain

+

Variants

Ureq(Error)

Error during ureq HTTP request

+

Tuple Fields of Ureq

0: Error
UreqTransport(Transport)

Transport error during the ureq HTTP call

+

Tuple Fields of UreqTransport

0: Transport
HttpResponse(u16)

HTTP response error

+

Tuple Fields of HttpResponse

0: u16
Io(Error)

IO error during ureq response read

+

Tuple Fields of Io

0: Error
NoHeader

No header found in ureq response

+
Parsing(ParseIntError)

Invalid number returned

+

Tuple Fields of Parsing

BitcoinEncoding(Error)

Invalid Bitcoin data returned

+

Tuple Fields of BitcoinEncoding

0: Error
Hex(Error)

Invalid Hex data returned

+

Tuple Fields of Hex

0: Error
TransactionNotFound(Txid)

Transaction not found

+

Tuple Fields of TransactionNotFound

0: Txid
HeaderHeightNotFound(u32)

Header height not found

+

Tuple Fields of HeaderHeightNotFound

0: u32
HeaderHashNotFound(BlockHash)

Header hash not found

+

Tuple Fields of HeaderHashNotFound

0: BlockHash

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

+
🔬 This is a nightly-only experimental API. (backtrace)

Returns a stack backtrace, if available, of where this error occurred. 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

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Converts a reference to Self into a dynamic trait object of Fail.

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the “name” of the error. Read more

+

Returns a reference to the underlying cause of this failure, if it +is an error that wraps other errors. Read more

+

Returns a reference to the Backtrace carried by this failure, if it +carries one. Read more

+

Provides context for this failure. Read more

+

Wraps this failure in a compatibility wrapper that implements +std::error::Error. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

Converts the given value to a String. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

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

Module bdk::blockchain::esplora[][src]

This is supported on crate feature esplora only.
Expand description

Esplora

+

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

+

Example

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

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

+

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

+

Structs

+

Structure that implements the logic to sync with Esplora

+

Configuration for an EsploraBlockchain

+

Data type used when fetching transaction history from Esplora.

+

Enums

+

Errors that can happen during a sync with EsploraBlockchain

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/sidebar-items.js new file mode 100644 index 0000000000..bf88a1a159 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["EsploraError","Errors that can happen during a sync with [`EsploraBlockchain`]"]],"struct":[["EsploraBlockchain","Structure that implements the logic to sync with Esplora"],["EsploraBlockchainConfig","Configuration for an [`EsploraBlockchain`]"],["EsploraGetHistory","Data type used when fetching transaction history from Esplora."]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchain.html new file mode 100644 index 0000000000..d275ec2a49 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchain.html @@ -0,0 +1,35 @@ +EsploraBlockchain in bdk::blockchain::esplora - Rust

Struct bdk::blockchain::esplora::EsploraBlockchain[][src]

pub struct EsploraBlockchain { /* fields omitted */ }
This is supported on crate feature esplora only.
Expand description

Structure that implements the logic to sync with Esplora

+

Example

+

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

+

Implementations

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

+

Set the inner ureq agent.

+

Trait Implementations

Return the set of Capability supported by this backend

+

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

+

Fetch a transaction from the blockchain given its txid

+

Broadcast a transaction

+

Return the current height

+

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

+

Populate the internal database with transactions and UTXOs Read more

+

Type that contains the configuration

+

Create a new instance given a configuration

+

Formats the value using the given formatter. Read more

+

Performs the conversion.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchainConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchainConfig.html new file mode 100644 index 0000000000..d8dc87b5e7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchainConfig.html @@ -0,0 +1,50 @@ +EsploraBlockchainConfig in bdk::blockchain::esplora - Rust

Struct bdk::blockchain::esplora::EsploraBlockchainConfig[][src]

pub struct EsploraBlockchainConfig {
+    pub base_url: String,
+    pub proxy: Option<String>,
+    pub timeout_read: u64,
+    pub timeout_write: u64,
+    pub stop_gap: usize,
+}
This is supported on crate feature esplora only.
Expand description

Configuration for an EsploraBlockchain

+

Fields

base_url: String

Base URL of the esplora service eg. https://blockstream.info/api/

+
proxy: Option<String>

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

+

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

+

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

+

The proxy is ignored when targeting wasm32.

+
timeout_read: u64

Socket read timeout.

+
timeout_write: u64

Socket write timeout.

+
stop_gap: usize

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

+

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

+

Performs the conversion.

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraGetHistory.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraGetHistory.html new file mode 100644 index 0000000000..02fa3f15f5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraGetHistory.html @@ -0,0 +1,21 @@ +EsploraGetHistory in bdk::blockchain::esplora - Rust

Struct bdk::blockchain::esplora::EsploraGetHistory[][src]

pub struct EsploraGetHistory { /* fields omitted */ }
This is supported on crate feature esplora only.
Expand description

Data type used when fetching transaction history from Esplora.

+

Trait Implementations

Deserialize this value from the given Serde deserializer. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/ureq/struct.EsploraBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/ureq/struct.EsploraBlockchain.html new file mode 100644 index 0000000000..9e118ac7a5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/ureq/struct.EsploraBlockchain.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

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

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/ureq/struct.EsploraBlockchainConfig.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/ureq/struct.EsploraBlockchainConfig.html new file mode 100644 index 0000000000..40575d9a80 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/ureq/struct.EsploraBlockchainConfig.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

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

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

Function bdk::blockchain::log_progress[][src]

pub fn log_progress() -> LogProgress
Expand description

Create a new instance of LogProgress

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

Function bdk::blockchain::noop_progress[][src]

pub fn noop_progress() -> NoopProgress
Expand description

Create a new instance of NoopProgress

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

Function bdk::blockchain::progress[][src]

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

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

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

Module bdk::blockchain[][src]

Expand description

Blockchain backends

+

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

+

Re-exports

+
pub use any::AnyBlockchain;
pub use any::AnyBlockchainConfig;
pub use self::electrum::ElectrumBlockchain;
pub use self::electrum::ElectrumBlockchainConfig;
pub use self::compact_filters::CompactFiltersBlockchain;

Modules

+

Runtime-checked blockchain types

+
compact_filterscompact_filters

Compact Filters

+
electrumelectrum

Electrum

+
esploraesplora

Esplora

+

Structs

+

Structure that implements the logic to sync with Esplora

+

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

+

Type that implements Progress and drops every update received

+

Enums

+

Capabilities that can be supported by a Blockchain backend

+

Traits

+

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

+

Trait for Blockchain types that can be created given a configuration

+

Trait for types that can receive and process progress updates during Blockchain::sync and +Blockchain::setup

+

Functions

+

Create a new instance of LogProgress

+

Create a new instance of NoopProgress

+

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

+

Type Definitions

+

Data sent with a progress update over a channel

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/sidebar-items.js new file mode 100644 index 0000000000..8667824b32 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["Capability","Capabilities that can be supported by a [`Blockchain`] backend"]],"fn":[["log_progress","Create a new instance of [`LogProgress`]"],["noop_progress","Create a new instance of [`NoopProgress`]"],["progress","Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]"]],"mod":[["any","Runtime-checked blockchain types"],["compact_filters","Compact Filters"],["electrum","Electrum"],["esplora","Esplora"]],"struct":[["EsploraBlockchain","Structure that implements the logic to sync with Esplora"],["LogProgress","Type that implements [`Progress`] and logs at level `INFO` every update received"],["NoopProgress","Type that implements [`Progress`] and drops every update received"]],"trait":[["Blockchain","Trait that defines the actions that must be supported by a blockchain backend"],["ConfigurableBlockchain","Trait for [`Blockchain`] types that can be created given a configuration"],["Progress","Trait for types that can receive and process progress updates during [`Blockchain::sync`] and [`Blockchain::setup`]"]],"type":[["ProgressData","Data sent with a progress update over a [`channel`]"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.EsploraBlockchain.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.EsploraBlockchain.html new file mode 100644 index 0000000000..c7a19a2bed --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.EsploraBlockchain.html @@ -0,0 +1,35 @@ +EsploraBlockchain in bdk::blockchain - Rust

Struct bdk::blockchain::EsploraBlockchain[][src]

pub struct EsploraBlockchain { /* fields omitted */ }
Expand description

Structure that implements the logic to sync with Esplora

+

Example

+

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

+

Implementations

This is supported on crate feature esplora only.

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

+
This is supported on crate feature esplora only.

Set the inner ureq agent.

+

Trait Implementations

Return the set of Capability supported by this backend

+

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

+

Fetch a transaction from the blockchain given its txid

+

Broadcast a transaction

+

Return the current height

+

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

+

Populate the internal database with transactions and UTXOs Read more

+

Type that contains the configuration

+

Create a new instance given a configuration

+

Formats the value using the given formatter. Read more

+

Performs the conversion.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.LogProgress.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.LogProgress.html new file mode 100644 index 0000000000..d09f52c3c4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.LogProgress.html @@ -0,0 +1,27 @@ +LogProgress in bdk::blockchain - Rust

Struct bdk::blockchain::LogProgress[][src]

pub struct LogProgress;
Expand description

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

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Send a new progress update Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

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

Struct bdk::blockchain::NoopProgress[][src]

pub struct NoopProgress;
Expand description

Type that implements Progress and drops every update received

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Send a new progress update Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

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

Trait bdk::blockchain::Blockchain[][src]

pub trait Blockchain {
+    fn get_capabilities(&self) -> HashSet<Capability>;
+
fn setup<D: BatchDatabase, P: 'static + Progress>(
        &self,
        database: &mut D,
        progress_update: P
    ) -> Result<(), Error>; +
fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>; +
fn broadcast(&self, tx: &Transaction) -> Result<(), Error>; +
fn get_height(&self) -> Result<u32, Error>; +
fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>; + + fn sync<D: BatchDatabase, P: 'static + Progress>(
        &self,
        database: &mut D,
        progress_update: P
    ) -> Result<(), Error> { ... } +}
Expand description

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

+

Required methods

Return the set of Capability supported by this backend

+

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

+

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

+

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

+

For types that do not have that distinction, only this method can be implemented, since +Blockchain::sync defaults to calling this internally if not overridden.

+

Fetch a transaction from the blockchain given its txid

+

Broadcast a transaction

+

Return the current height

+

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

+

Provided methods

Populate the internal database with transactions and UTXOs

+

If not overridden, it defaults to calling Blockchain::setup internally.

+

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

+

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

+

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

+

Implementations on Foreign Types

Implementors

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

Trait bdk::blockchain::ConfigurableBlockchain[][src]

pub trait ConfigurableBlockchain: Blockchain + Sized {
+    type Config: Debug;
+    fn from_config(config: &Self::Config) -> Result<Self, Error>;
+}
Expand description

Trait for Blockchain types that can be created given a configuration

+

Associated Types

Type that contains the configuration

+

Required methods

Create a new instance given a configuration

+

Implementors

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

Trait bdk::blockchain::Progress[][src]

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

Trait for types that can receive and process progress updates during Blockchain::sync and +Blockchain::setup

+

Required methods

Send a new progress update

+

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

+

Implementations on Foreign Types

Implementors

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

Type Definition bdk::blockchain::ProgressData[][src]

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

Data sent with a progress update over a channel

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

Enum bdk::database::any::AnyBatch[][src]

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

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

+

Variants

In-memory ephemeral database

+

Tuple Fields of Memory

Sled(<Tree as BatchDatabase>::Batch)
This is supported on crate feature key-value-db only.

Simple key-value embedded database based on [sled]

+

Tuple Fields of Sled

0: <Tree as BatchDatabase>::Batch
This is supported on crate feature sqlite only.

Sqlite embedded database using [rusqlite]

+

Tuple Fields of Sqlite

Trait Implementations

Store a script_pubkey along with its keychain and child number.

+

Store a LocalUtxo

+

Store a raw transaction

+

Store the metadata of a transaction

+

Store the last derivation index for a given keychain.

+

Delete a script_pubkey given the keychain and its child number.

+

Delete the data related to a specific script_pubkey, meaning the keychain and the child +number. Read more

+

Delete a LocalUtxo given its [OutPoint]

+

Delete a raw transaction given its [Txid]

+

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

+

Delete the last derivation index for a keychain.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

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

Enum bdk::database::any::AnyDatabase[][src]

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

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

+

It allows switching database type at runtime.

+

See this module’s documentation for a usage example.

+

Variants

In-memory ephemeral database

+

Tuple Fields of Memory

Sled(Tree)
This is supported on crate feature key-value-db only.

Simple key-value embedded database based on [sled]

+

Tuple Fields of Sled

0: Tree
This is supported on crate feature sqlite only.

Sqlite embedded database using [rusqlite]

+

Tuple Fields of Sqlite

Trait Implementations

Container for the operations

+

Create a new batch container

+

Consume and apply a batch of operations

+

Store a script_pubkey along with its keychain and child number.

+

Store a LocalUtxo

+

Store a raw transaction

+

Store the metadata of a transaction

+

Store the last derivation index for a given keychain.

+

Delete a script_pubkey given the keychain and its child number.

+

Delete the data related to a specific script_pubkey, meaning the keychain and the child +number. Read more

+

Delete a LocalUtxo given its [OutPoint]

+

Delete a raw transaction given its [Txid]

+

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

+

Delete the last derivation index for a keychain.

+

Type that contains the configuration

+

Create a new instance given a configuration

+

Read and checks the descriptor checksum for a given keychain. Read more

+

Return the list of script_pubkeys

+

Return the list of LocalUtxos

+

Return the list of raw transactions

+

Return the list of transactions metadata

+

Fetch a script_pubkey given the child number of a keychain.

+

Fetch the keychain and child number of a given script_pubkey

+

Fetch a LocalUtxo given its [OutPoint]

+

Fetch a raw transaction given its [Txid]

+

Fetch the transaction metadata and optionally also the raw transaction

+

Return the last defivation index for a keychain.

+

Increment the last derivation index for a keychain and return it Read more

+

Force changes to be written to disk

+

Formats the value using the given formatter. Read more

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

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

Enum bdk::database::any::AnyDatabaseConfig[][src]

pub enum AnyDatabaseConfig {
+    Memory(()),
+    Sled(SledDbConfiguration),
+    Sqlite(SqliteDbConfiguration),
+}
Expand description

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

+

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

+

Variants

Memory(())

Memory database has no config

+

Tuple Fields of Memory

0: ()
This is supported on crate feature key-value-db only.

Simple key-value embedded database based on [sled]

+

Tuple Fields of Sled

This is supported on crate feature sqlite only.

Sqlite embedded database using [rusqlite]

+

Tuple Fields of Sqlite

Trait Implementations

Formats the value using the given formatter. Read more

+

Deserialize this value from the given Serde deserializer. Read more

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/index.html new file mode 100644 index 0000000000..32a137b083 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/index.html @@ -0,0 +1,27 @@ +bdk::database::any - Rust

Module bdk::database::any[][src]

Expand description

Runtime-checked database types

+

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

+

Example

+

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

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

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

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

Structs

+

Configuration type for a [sled::Tree] database

+

Configuration type for a sqlite::SqliteDatabase database

+

Enums

+

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

+

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

+

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

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/sidebar-items.js new file mode 100644 index 0000000000..b10a47631b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["AnyBatch","Type that contains any of the [`BatchDatabase::Batch`] types defined by the library"],["AnyDatabase","Type that can contain any of the [`Database`] types defined by the library"],["AnyDatabaseConfig","Type that can contain any of the database configurations defined by the library"]],"struct":[["SledDbConfiguration","Configuration type for a [`sled::Tree`] database"],["SqliteDbConfiguration","Configuration type for a [`sqlite::SqliteDatabase`] database"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SledDbConfiguration.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SledDbConfiguration.html new file mode 100644 index 0000000000..b6e90414ab --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SledDbConfiguration.html @@ -0,0 +1,29 @@ +SledDbConfiguration in bdk::database::any - Rust

Struct bdk::database::any::SledDbConfiguration[][src]

pub struct SledDbConfiguration {
+    pub path: String,
+    pub tree_name: String,
+}
Expand description

Configuration type for a [sled::Tree] database

+

Fields

path: String

Main directory of the db

+
tree_name: String

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

+

Trait Implementations

Formats the value using the given formatter. Read more

+

Deserialize this value from the given Serde deserializer. Read more

+

Performs the conversion.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SqliteDbConfiguration.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SqliteDbConfiguration.html new file mode 100644 index 0000000000..9afc907488 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SqliteDbConfiguration.html @@ -0,0 +1,27 @@ +SqliteDbConfiguration in bdk::database::any - Rust

Struct bdk::database::any::SqliteDbConfiguration[][src]

pub struct SqliteDbConfiguration {
+    pub path: String,
+}
Expand description

Configuration type for a sqlite::SqliteDatabase database

+

Fields

path: String

Main directory of the db

+

Trait Implementations

Formats the value using the given formatter. Read more

+

Deserialize this value from the given Serde deserializer. Read more

+

Performs the conversion.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

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

Module bdk::database[][src]

Expand description

Database types

+

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

+

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

+

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

+

Re-exports

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

Modules

+

Runtime-checked database types

+

In-memory ephemeral database

+

Structs

+

Sqlite database stored on filesystem

+

Traits

+

Trait for a database that supports batch operations

+

Trait for operations that can be batched

+

Trait for Database types that can be created given a configuration

+

Trait for reading data from a database

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

Module bdk::database::memory[][src]

Expand description

In-memory ephemeral database

+

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

+

Structs

+

In-memory ephemeral database

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/memory/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/memory/sidebar-items.js new file mode 100644 index 0000000000..665f6718d0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/memory/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["MemoryDatabase","In-memory ephemeral database"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/memory/struct.MemoryDatabase.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/memory/struct.MemoryDatabase.html new file mode 100644 index 0000000000..afb930e59e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/memory/struct.MemoryDatabase.html @@ -0,0 +1,60 @@ +MemoryDatabase in bdk::database::memory - Rust

Struct bdk::database::memory::MemoryDatabase[][src]

pub struct MemoryDatabase { /* fields omitted */ }
Expand description

In-memory ephemeral database

+

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

+

Once it’s dropped its content will be lost.

+

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

+

Implementations

Create a new empty database

+

Trait Implementations

Container for the operations

+

Create a new batch container

+

Consume and apply a batch of operations

+

Store a script_pubkey along with its keychain and child number.

+

Store a LocalUtxo

+

Store a raw transaction

+

Store the metadata of a transaction

+

Store the last derivation index for a given keychain.

+

Delete a script_pubkey given the keychain and its child number.

+

Delete the data related to a specific script_pubkey, meaning the keychain and the child +number. Read more

+

Delete a LocalUtxo given its [OutPoint]

+

Delete a raw transaction given its [Txid]

+

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

+

Delete the last derivation index for a keychain.

+

Type that contains the configuration

+

Create a new instance given a configuration

+

Read and checks the descriptor checksum for a given keychain. Read more

+

Return the list of script_pubkeys

+

Return the list of LocalUtxos

+

Return the list of raw transactions

+

Return the list of transactions metadata

+

Fetch a script_pubkey given the child number of a keychain.

+

Fetch the keychain and child number of a given script_pubkey

+

Fetch a LocalUtxo given its [OutPoint]

+

Fetch a raw transaction given its [Txid]

+

Fetch the transaction metadata and optionally also the raw transaction

+

Return the last defivation index for a keychain.

+

Increment the last derivation index for a keychain and return it Read more

+

Force changes to be written to disk

+

Formats the value using the given formatter. Read more

+

Returns the “default value” for a type. Read more

+

Performs the conversion.

+

Performs the conversion.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/sidebar-items.js new file mode 100644 index 0000000000..3856fe121b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"mod":[["any","Runtime-checked database types"],["memory","In-memory ephemeral database"]],"struct":[["SqliteDatabase","Sqlite database stored on filesystem"]],"trait":[["BatchDatabase","Trait for a database that supports batch operations"],["BatchOperations","Trait for operations that can be batched"],["ConfigurableDatabase","Trait for [`Database`] types that can be created given a configuration"],["Database","Trait for reading data from a database"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/sqlite/struct.SqliteDatabase.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/sqlite/struct.SqliteDatabase.html new file mode 100644 index 0000000000..803ba38ba6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/sqlite/struct.SqliteDatabase.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

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

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

Struct bdk::database::SqliteDatabase[][src]

pub struct SqliteDatabase {
+    pub path: String,
+    pub connection: Connection,
+}
Expand description

Sqlite database stored on filesystem

+

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

+

Fields

path: String

Path on the local filesystem to store the sqlite file

+
connection: Connection

A rusqlite connection object to the sqlite database

+

Implementations

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

+

Trait Implementations

Container for the operations

+

Create a new batch container

+

Consume and apply a batch of operations

+

Store a script_pubkey along with its keychain and child number.

+

Store a LocalUtxo

+

Store a raw transaction

+

Store the metadata of a transaction

+

Store the last derivation index for a given keychain.

+

Delete a script_pubkey given the keychain and its child number.

+

Delete the data related to a specific script_pubkey, meaning the keychain and the child +number. Read more

+

Delete a LocalUtxo given its [OutPoint]

+

Delete a raw transaction given its [Txid]

+

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

+

Delete the last derivation index for a keychain.

+

Type that contains the configuration

+

Create a new instance given a configuration

+

Read and checks the descriptor checksum for a given keychain. Read more

+

Return the list of script_pubkeys

+

Return the list of LocalUtxos

+

Return the list of raw transactions

+

Return the list of transactions metadata

+

Fetch a script_pubkey given the child number of a keychain.

+

Fetch the keychain and child number of a given script_pubkey

+

Fetch a LocalUtxo given its [OutPoint]

+

Fetch a raw transaction given its [Txid]

+

Fetch the transaction metadata and optionally also the raw transaction

+

Return the last defivation index for a keychain.

+

Increment the last derivation index for a keychain and return it Read more

+

Force changes to be written to disk

+

Formats the value using the given formatter. Read more

+

Performs the conversion.

+

Performs the conversion.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

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

Trait bdk::database::BatchDatabase[][src]

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

Trait for a database that supports batch operations

+

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

+

Associated Types

Container for the operations

+

Required methods

Create a new batch container

+

Consume and apply a batch of operations

+

Implementations on Foreign Types

Implementors

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

Trait bdk::database::BatchOperations[][src]

pub trait BatchOperations {
+    fn set_script_pubkey(
        &mut self,
        script: &Script,
        keychain: KeychainKind,
        child: u32
    ) -> Result<(), Error>; +
fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error>; +
fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>; +
fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>; +
fn set_last_index(
        &mut self,
        keychain: KeychainKind,
        value: u32
    ) -> Result<(), Error>; +
fn del_script_pubkey_from_path(
        &mut self,
        keychain: KeychainKind,
        child: u32
    ) -> Result<Option<Script>, Error>; +
fn del_path_from_script_pubkey(
        &mut self,
        script: &Script
    ) -> Result<Option<(KeychainKind, u32)>, Error>; +
fn del_utxo(
        &mut self,
        outpoint: &OutPoint
    ) -> Result<Option<LocalUtxo>, Error>; +
fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>; +
fn del_tx(
        &mut self,
        txid: &Txid,
        include_raw: bool
    ) -> Result<Option<TransactionDetails>, Error>; +
fn del_last_index(
        &mut self,
        keychain: KeychainKind
    ) -> Result<Option<u32>, Error>; +}
Expand description

Trait for operations that can be batched

+

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

+

Required methods

Store a script_pubkey along with its keychain and child number.

+

Store a LocalUtxo

+

Store a raw transaction

+

Store the metadata of a transaction

+

Store the last derivation index for a given keychain.

+

Delete a script_pubkey given the keychain and its child number.

+

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

+

Delete a LocalUtxo given its [OutPoint]

+

Delete a raw transaction given its [Txid]

+

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

+

Delete the last derivation index for a keychain.

+

Implementations on Foreign Types

Implementors

+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/trait.ConfigurableDatabase.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/trait.ConfigurableDatabase.html new file mode 100644 index 0000000000..230a6c5ae1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/database/trait.ConfigurableDatabase.html @@ -0,0 +1,9 @@ +ConfigurableDatabase in bdk::database - Rust

Trait bdk::database::ConfigurableDatabase[][src]

pub trait ConfigurableDatabase: Database + Sized {
+    type Config: Debug;
+    fn from_config(config: &Self::Config) -> Result<Self, Error>;
+}
Expand description

Trait for Database types that can be created given a configuration

+

Associated Types

Type that contains the configuration

+

Required methods

Create a new instance given a configuration

+

Implementations on Foreign Types

Implementors

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

Trait bdk::database::Database[][src]

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

Trait for reading data from a database

+

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

+

Required methods

Read and checks the descriptor checksum for a given keychain.

+

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

+

Return the list of script_pubkeys

+

Return the list of LocalUtxos

+

Return the list of raw transactions

+

Return the list of transactions metadata

+

Fetch a script_pubkey given the child number of a keychain.

+

Fetch the keychain and child number of a given script_pubkey

+

Fetch a LocalUtxo given its [OutPoint]

+

Fetch a raw transaction given its [Txid]

+

Fetch the transaction metadata and optionally also the raw transaction

+

Return the last defivation index for a keychain.

+

Increment the last derivation index for a keychain and return it

+

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

+

Force changes to be written to disk

+

Implementations on Foreign Types

Implementors

+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.get_checksum.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.get_checksum.html new file mode 100644 index 0000000000..55ce0b83b6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.get_checksum.html @@ -0,0 +1,4 @@ +get_checksum in bdk::descriptor::checksum - Rust

Function bdk::descriptor::checksum::get_checksum[][src]

pub fn get_checksum(desc: &str) -> Result<String, DescriptorError>
Expand description

Compute the checksum of a descriptor

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

Module bdk::descriptor::checksum[][src]

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

+
+ + \ 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 new file mode 100644 index 0000000000..e1add094a5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"fn":[["get_checksum","Compute the checksum of a descriptor"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Descriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Descriptor.html new file mode 100644 index 0000000000..d0003f40ac --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Descriptor.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../bdk/descriptor/enum.Descriptor.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.DescriptorPublicKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.DescriptorPublicKey.html new file mode 100644 index 0000000000..05f9388e84 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.DescriptorPublicKey.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../bdk/keys/enum.DescriptorPublicKey.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Legacy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Legacy.html new file mode 100644 index 0000000000..fb2dd3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Legacy.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../bdk/descriptor/enum.Legacy.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Segwitv0.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Segwitv0.html new file mode 100644 index 0000000000..194aba17ab --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Segwitv0.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../bdk/descriptor/enum.Segwitv0.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/struct.DerivedDescriptorKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/struct.DerivedDescriptorKey.html new file mode 100644 index 0000000000..3d9e091385 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/struct.DerivedDescriptorKey.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../bdk/descriptor/struct.DerivedDescriptorKey.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/struct.Miniscript.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/struct.Miniscript.html new file mode 100644 index 0000000000..ca1ccb5a6e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/struct.Miniscript.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../bdk/descriptor/struct.Miniscript.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/trait.ScriptContext.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/trait.ScriptContext.html new file mode 100644 index 0000000000..08af1d1289 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/trait.ScriptContext.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../bdk/keys/trait.ScriptContext.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/type.KeyMap.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/type.KeyMap.html new file mode 100644 index 0000000000..2fdaa9d33d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/type.KeyMap.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../../bdk/keys/type.KeyMap.html...

+ + + \ 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 new file mode 100644 index 0000000000..7bdf70a2ad --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Descriptor.html @@ -0,0 +1,153 @@ +Descriptor in bdk::descriptor - Rust

Enum bdk::descriptor::Descriptor[]

pub enum Descriptor<Pk> where
    Pk: MiniscriptKey, 
{ + Bare(Bare<Pk>), + Pkh(Pkh<Pk>), + Wpkh(Wpkh<Pk>), + Sh(Sh<Pk>), + Wsh(Wsh<Pk>), +}
Expand description

Script descriptor

+

Variants

Bare(Bare<Pk>)

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

+

Tuple Fields of Bare

0: Bare<Pk>
Pkh(Pkh<Pk>)

Pay-to-PubKey-Hash

+

Tuple Fields of Pkh

0: Pkh<Pk>
Wpkh(Wpkh<Pk>)

Pay-to-Witness-PubKey-Hash

+

Tuple Fields of Wpkh

0: Wpkh<Pk>
Sh(Sh<Pk>)

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

+

Tuple Fields of Sh

0: Sh<Pk>
Wsh(Wsh<Pk>)

Pay-to-Witness-ScriptHash with Segwitv0 context

+

Tuple Fields of Wsh

0: Wsh<Pk>

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

+

Get the [DescriptorType] of Descriptor

+

Whether or not the descriptor has any wildcards

+

Derives all wildcard keys in the descriptor using the supplied index

+

Panics if given an index ≥ 2^31

+

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

+

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

+

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 signauture on all spend paths +And whether the script is malleable. +In general, all the guarantees of miniscript hold only for safe scripts. +All the analysis guarantees of miniscript only hold safe scripts. +The signer may not be able to find satisfactions even if one exists

+

Computes the Bitcoin address of the descriptor, if one exists

+

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 “witness script” of the descriptor, i.e. 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.

+

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

+

Computes an upper bound on the weight of a satisfying witness to the +transaction. Assumes all signatures are 73 bytes, including push opcode +and sighash suffix. Includes the weight of the VarInts encoding the +scriptSig and witness stack length.

+

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

+

Attempts to produce a satisfying witness and scriptSig to spend an +output controlled by the given descriptor; add the data to a given +TxIn output. 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

+

The associated error which can be returned from parsing.

+

Parses a string s to return a value of this type. Read more

+

Parse an expression tree into a descriptor

+

Feeds this value into the given Hasher. Read more

+

Feeds a slice of this type into the given Hasher. Read more

+

Convert the object into an abstract policy

+

This method returns an Ordering between self and other. Read more

+

Compares and returns the maximum of two values. Read more

+

Compares and returns the minimum of two values. Read more

+

Restrict a value to a certain interval. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

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

+

Convert a descriptor using abstract keys to one using specific keys +This will panic if translatefpk returns an uncompressed key when +converting to a Segwit descriptor. To prevent this panic, ensure +translatefpk returns an error in this case instead.

+

The associated output type. This must be Self

+

Calls translate_pk with conversion functions that cannot fail

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

Converts the given value to a String. Read more

+

Translate a struct from one generic to another where the +translation for Pk is provided by translatefpk Read more

+

Translate a struct from one generic to another where the +translation for Pk is provided by translatefpk Read more

+

Translate a struct from one generic to another where the +translation for Pk is provided by translatefpk Read more

+

Translate a struct from one generic to another where the +translation for Pk is provided by translatefpk Read more

+

Translate a struct from one generic to another where the +translation for Pk is provided by translatefpk Read more

+

Translate a struct from one generic to another where the +translation for Pk is provided by translatefpk Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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 new file mode 100644 index 0000000000..839a91fcf1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Legacy.html @@ -0,0 +1,95 @@ +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 !=.

+

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

+

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

+

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.

+

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 the ScriptContext as a ScriptContextEnum

+

Returns whether the script context is Legacy

+

Returns whether the script context is Segwitv0

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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 new file mode 100644 index 0000000000..11e3d518c9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Segwitv0.html @@ -0,0 +1,92 @@ +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 !=.

+

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

+

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

+

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.

+

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 the ScriptContext as a ScriptContextEnum

+

Returns whether the script context is Legacy

+

Returns whether the script context is Segwitv0

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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

Enum bdk::descriptor::error::Error[][src]

pub enum Error {
+    InvalidHdKeyPath,
+    InvalidDescriptorChecksum,
+    HardenedDerivationXpub,
+    DuplicatedKeys,
+    Key(KeyError),
+    Policy(PolicyError),
+    InvalidDescriptorCharacter(char),
+    Bip32(Error),
+    Base58(Error),
+    Pk(Error),
+    Miniscript(Error),
+    Hex(Error),
+}
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

+
DuplicatedKeys

The descriptor contains multiple keys with the same BIP32 fingerprint

+

Error thrown while working with keys

+

Tuple Fields of Key

Policy(PolicyError)

Error while extracting and manipulating policies

+

Tuple Fields of Policy

InvalidDescriptorCharacter(char)

Invalid character found in the descriptor checksum

+

Tuple Fields of InvalidDescriptorCharacter

0: char
Bip32(Error)

BIP32 error

+

Tuple Fields of Bip32

0: Error
Base58(Error)

Error during base58 decoding

+

Tuple Fields of Base58

0: Error
Pk(Error)

Key-related error

+

Tuple Fields of Pk

0: Error
Miniscript(Error)

Miniscript error

+

Tuple Fields of Miniscript

0: Error
Hex(Error)

Hex decoding error

+

Tuple Fields of Hex

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

+
🔬 This is a nightly-only experimental API. (backtrace)

Returns a stack backtrace, if available, of where this error occurred. 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

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Converts a reference to Self into a dynamic trait object of Fail.

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the “name” of the error. Read more

+

Returns a reference to the underlying cause of this failure, if it +is an error that wraps other errors. Read more

+

Returns a reference to the Backtrace carried by this failure, if it +carries one. Read more

+

Provides context for this failure. Read more

+

Wraps this failure in a compatibility wrapper that implements +std::error::Error. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

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

Module bdk::descriptor::error[][src]

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 new file mode 100644 index 0000000000..1ad99d4faf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/error/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"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 new file mode 100644 index 0000000000..4c2d3b96f0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/index.html @@ -0,0 +1,35 @@ +bdk::descriptor - Rust

Module bdk::descriptor[][src]

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::get_checksum;
pub use self::error::Error as DescriptorError;
pub use self::policy::Policy;

Modules

+

Descriptor checksum

+

Descriptor errors

+

Descriptor policy

+

Descriptor templates

+

Structs

+

Extended DescriptorPublicKey that has been derived

+

Top-level script AST type

+

Enums

+

Script descriptor

+

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 type for a map of public key to secret key

+
+ + \ 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 new file mode 100644 index 0000000000..fd9eddbd4f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.BuildSatisfaction.html @@ -0,0 +1,42 @@ +BuildSatisfaction in bdk::descriptor::policy - Rust

Enum bdk::descriptor::policy::BuildSatisfaction[][src]

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

+

Tuple Fields of Psbt

0: &'a Psbt
PsbtTimelocks

Like Psbt variant and also check for expired timelocks

+

Fields of PsbtTimelocks

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

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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 new file mode 100644 index 0000000000..0412f4a82f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.PolicyError.html @@ -0,0 +1,54 @@ +PolicyError in bdk::descriptor::policy - Rust

Enum bdk::descriptor::policy::PolicyError[][src]

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

+

Tuple Fields of NotEnoughItemsSelected

0: String
IndexOutOfRange(usize)

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

+

Tuple Fields of IndexOutOfRange

0: usize
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

+
🔬 This is a nightly-only experimental API. (backtrace)

Returns a stack backtrace, if available, of where this error occurred. 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

+

Performs the conversion.

+

Performs the conversion.

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Converts a reference to Self into a dynamic trait object of Fail.

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the “name” of the error. Read more

+

Returns a reference to the underlying cause of this failure, if it +is an error that wraps other errors. Read more

+

Returns a reference to the Backtrace carried by this failure, if it +carries one. Read more

+

Provides context for this failure. Read more

+

Wraps this failure in a compatibility wrapper that implements +std::error::Error. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

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

Enum bdk::descriptor::policy::Satisfaction[][src]

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

Only a partial satisfaction of some kind of threshold policy

+

Fields of Partial

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

+
PartialComplete

Can reach the threshold of some kind of threshold policy

+

Fields of PartialComplete

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

+
Complete

Can satisfy the policy item

+

Fields of Complete

condition: Condition

Extra conditions that also need to be satisfied

+
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

+

Performs the conversion.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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 new file mode 100644 index 0000000000..10e4daecb0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.SatisfiableItem.html @@ -0,0 +1,80 @@ +SatisfiableItem in bdk::descriptor::policy - Rust

Enum bdk::descriptor::policy::SatisfiableItem[][src]

pub enum SatisfiableItem {
+    Signature(PkOrF),
+    SignatureKey(PkOrF),
+    Sha256Preimage {
+        hash: Hash,
+    },
+    Hash256Preimage {
+        hash: Hash,
+    },
+    Ripemd160Preimage {
+        hash: Hash,
+    },
+    Hash160Preimage {
+        hash: Hash,
+    },
+    AbsoluteTimelock {
+        value: u32,
+    },
+    RelativeTimelock {
+        value: u32,
+    },
+    Multisig {
+        keys: Vec<PkOrF>,
+        threshold: usize,
+    },
+    Thresh {
+        items: Vec<Policy>,
+        threshold: usize,
+    },
+}
Expand description

An item that needs to be satisfied

+

Variants

Signature(PkOrF)

Signature for a raw public key

+

Tuple Fields of Signature

0: PkOrF
SignatureKey(PkOrF)

Signature for an extended key fingerprint

+

Tuple Fields of SignatureKey

0: PkOrF
Sha256Preimage

SHA256 preimage hash

+

Fields of Sha256Preimage

hash: Hash

The digest value

+
Hash256Preimage

Double SHA256 preimage hash

+

Fields of Hash256Preimage

hash: Hash

The digest value

+
Ripemd160Preimage

RIPEMD160 preimage hash

+

Fields of Ripemd160Preimage

hash: Hash

The digest value

+
Hash160Preimage

SHA256 then RIPEMD160 preimage hash

+

Fields of Hash160Preimage

hash: Hash

The digest value

+
AbsoluteTimelock

Absolute timeclock timestamp

+

Fields of AbsoluteTimelock

value: u32

The timestamp value

+
RelativeTimelock

Relative timelock locktime

+

Fields of RelativeTimelock

value: u32

The locktime value

+
Multisig

Multi-signature public keys with threshold count

+

Fields of Multisig

keys: Vec<PkOrF>

The raw public key or extended key fingerprint

+
threshold: usize

The required threshold count

+
Thresh

Threshold items with threshold count

+

Fields of Thresh

items: Vec<Policy>

The policy items

+
threshold: usize

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

+

Performs the conversion.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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

Module bdk::descriptor::policy[][src]

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(key_map.into());
+let policy = extended_desc.extract_policy(&signers, BuildSatisfaction::None, &secp)?;
+println!("policy: {}", serde_json::to_string(&policy)?);
+

Structs

+

An extra condition that must be satisfied but that is out of control of the user

+

Raw public key or extended key fingerprint

+

Descriptor spending policy

+

Enums

+

Options to build the satisfaction field in the policy

+

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 new file mode 100644 index 0000000000..40fd0e48aa --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["BuildSatisfaction","Options to build the satisfaction field in the policy"],["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"],["PkOrF","Raw public key or extended key fingerprint"],["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 new file mode 100644 index 0000000000..accab7d501 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Condition.html @@ -0,0 +1,51 @@ +Condition in bdk::descriptor::policy - Rust

Struct bdk::descriptor::policy::Condition[][src]

pub struct Condition {
+    pub csv: Option<u32>,
+    pub timelock: Option<u32>,
+}
Expand description

An extra condition that must be satisfied but that is out of control of the user

+

Fields

csv: Option<u32>

Optional CheckSequenceVerify condition

+
timelock: Option<u32>

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

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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

Struct bdk::descriptor::policy::PkOrF[][src]

pub struct PkOrF { /* fields omitted */ }
Expand description

Raw public key or 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

+

Returns the “default value” for a 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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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

Struct bdk::descriptor::policy::Policy[][src]

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

+

Performs the conversion.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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

Type Definition bdk::descriptor::policy::ConditionMap[][src]

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

Type Definition bdk::descriptor::policy::FoldedConditionMap[][src]

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 new file mode 100644 index 0000000000..e324d2a835 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["Descriptor","Script descriptor"],["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":[["DerivedDescriptorKey","Extended [`DescriptorPublicKey`] that has been derived"],["Miniscript","Top-level script AST type"]],"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`"],["KeyMap","Alias type for a map of public key to secret key"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.DerivedDescriptorKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.DerivedDescriptorKey.html new file mode 100644 index 0000000000..9cdf7671f9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.DerivedDescriptorKey.html @@ -0,0 +1,71 @@ +DerivedDescriptorKey in bdk::descriptor - Rust

Struct bdk::descriptor::DerivedDescriptorKey[][src]

pub struct DerivedDescriptorKey<'s>(_, _);
Expand description

Extended DescriptorPublicKey that has been derived

+

Derived keys are guaranteed to never contain wildcards of any kind

+

Implementations

Construct a new derived key

+

Panics if the key is wildcard

+

Methods from Deref<Target = DescriptorPublicKey>

The fingerprint of the master key associated with this key

+

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)

+

Whether or not the key has a wildcards

+

Computes the public key corresponding to this descriptor key

+

Will return an error if the descriptor key has any hardened +derivation steps in its path, or if the key has any wildcards.

+

To ensure there are no wildcards, call .derive(0) or similar; +to avoid hardened derivation steps, start from a DescriptorSecretKey +and call as_public, or call TranslatePk2::translate_pk2 with +some function which has access to secret key data.

+

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.

+

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

+

The associated Hash type with the publicKey

+

Converts an object to PublicHash

+

Check if the publicKey is uncompressed. The default +implementation returns false Read more

+

Computes the size of a public key when serialized in a script, +including the length bytes 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 !=.

+

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

+

Converts an object to a public key

+

Converts a hashed version of the public key to a hash160 hash. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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

Struct bdk::descriptor::Miniscript[]

pub struct Miniscript<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey, 
{ + pub node: Terminal<Pk, Ctx>, + pub ty: Type, + pub ext: ExtData, + // some fields omitted +}
Expand description

Top-level script AST type

+

Fields

node: Terminal<Pk, Ctx>

A node in the Abstract Syntax Tree(

+
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

+

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

+

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.

+

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

+

Creates a new [PkPkhIter] iterator that will iterate over all plain public keys and +key hash values present in Miniscript items within AST by traversing all its branches. +For the specific algorithm please see [PkPkhIter::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 Vec with cloned version of all public keys from the current miniscript item, +if any. Otherwise returns an empty Vec.

+

NB: The function analyzes only single miniscript item and not any of its descendants in AST. +To obtain a list of all public keys within AST use Miniscript::iter_pk() function, for example +miniscript.iter_pubkeys().collect().

+

Returns Vec with hashes of all public keys from the current miniscript item, if any. +Otherwise returns an empty Vec.

+

For each public key the function computes hash; for each hash of the public key the function +returns its cloned copy.

+

NB: The function analyzes only single miniscript item and not any of its descendants in AST. +To obtain a list of all public key hashes within AST use Miniscript::iter_pkh() function, +for example miniscript.iter_pubkey_hashes().collect().

+

Returns Vec of [PkPkh] entries, representing either public keys or public key +hashes, depending on the data from the current miniscript item. If there is no public +keys or hashes, the function returns an empty Vec.

+

NB: The function analyzes only single miniscript item and not any of its descendants in AST. +To obtain a list of all public keys or hashes within AST use Miniscript::iter_pk_pkh() +function, for example miniscript.iter_pubkeys_and_hashes().collect().

+

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.

+

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

+

For each public key the function computes hash; for each hash of the public key the function +returns it cloned copy.

+

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

+

Returns Option::Some with hash of n’th public key or hash 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.

+

Extracts the AstElem representing the root of the miniscript

+

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

+

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

+

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

+

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

+
    +
  1. Timelock combination
  2. +
  3. Contains 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.

+

Parses a string s to return a value of this type. Read more

+

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

+

Feeds this value into the given Hasher. Read more

+

Feeds a slice of this type into the given Hasher. Read more

+

Convert the object into an abstract policy

+

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

+

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 can be deterministically determined +by the ast.

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

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

+

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

+

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

+

The associated output type. This must be Self

+

Calls translate_pk with conversion functions that cannot fail

+

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

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

Converts the given value to a String. Read more

+

Translate a struct from one generic to another where the +translation for Pk is provided by translatefpk Read more

+

Translate a struct from one generic to another where the +translation for Pk is provided by translatefpk Read more

+

Translate a struct from one generic to another where the +translation for Pk is provided by translatefpk Read more

+

Translate a struct from one generic to another where the +translation for Pk is provided by translatefpk Read more

+

Translate a struct from one generic to another where the +translation for Pk is provided by translatefpk Read more

+

Translate a struct from one generic to another where the +translation for Pk is provided by translatefpk Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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 new file mode 100644 index 0000000000..2edd73980f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/index.html @@ -0,0 +1,20 @@ +bdk::descriptor::template - Rust

Module bdk::descriptor::template[][src]

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'/0'/{0,1}/*)

+

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

+

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

+

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

+

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

+

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

+

P2PKH template. Expands to a descriptor pkh(key)

+

P2WPKH template. Expands to a descriptor wpkh(key)

+

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

+

Traits

+

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

+

Type Definitions

+

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

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/sidebar-items.js new file mode 100644 index 0000000000..4ea3e793ef --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["Bip44","BIP44 template. Expands to `pkh(key/44'/0'/0'/{0,1}/*)`"],["Bip44Public","BIP44 public template. Expands to `pkh(key/{0,1}/*)`"],["Bip49","BIP49 template. Expands to `sh(wpkh(key/49'/0'/0'/{0,1}/*))`"],["Bip49Public","BIP49 public template. Expands to `sh(wpkh(key/{0,1}/*))`"],["Bip84","BIP84 template. Expands to `wpkh(key/84'/0'/0'/{0,1}/*)`"],["Bip84Public","BIP84 public template. Expands to `wpkh(key/{0,1}/*)`"],["P2Pkh","P2PKH template. Expands to a descriptor `pkh(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 new file mode 100644 index 0000000000..5f7c8bbff0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44.html @@ -0,0 +1,37 @@ +Bip44 in bdk::descriptor::template - Rust

Struct bdk::descriptor::template::Bip44[][src]

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

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

+

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

+

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

+

Example

+
use bdk::template::Bip44;
+
+let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+let wallet = Wallet::new_offline(
+    Bip44(key.clone(), KeychainKind::External),
+    Some(Bip44(key, KeychainKind::Internal)),
+    Network::Testnet,
+    MemoryDatabase::default()
+)?;
+
+assert_eq!(wallet.get_address(New)?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
+assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#xgaaevjx");
+

Tuple Fields

0: K1: 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

+

Performs the conversion.

+

Performs the conversion.

+

Convert to wallet descriptor

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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 new file mode 100644 index 0000000000..28874d293e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44Public.html @@ -0,0 +1,40 @@ +Bip44Public in bdk::descriptor::template - Rust

Struct bdk::descriptor::template::Bip44Public[][src]

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

+

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::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
+let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
+let wallet = Wallet::new_offline(
+    Bip44Public(key.clone(), fingerprint, KeychainKind::External),
+    Some(Bip44Public(key, fingerprint, KeychainKind::Internal)),
+    Network::Testnet,
+    MemoryDatabase::default()
+)?;
+
+assert_eq!(wallet.get_address(New)?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
+assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#xgaaevjx");
+

Tuple Fields

0: K1: Fingerprint2: KeychainKind

Trait Implementations

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

Convert to wallet descriptor

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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 new file mode 100644 index 0000000000..bdf6d79374 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49.html @@ -0,0 +1,37 @@ +Bip49 in bdk::descriptor::template - Rust

Struct bdk::descriptor::template::Bip49[][src]

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

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

+

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

+

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

+

Example

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

Tuple Fields

0: K1: 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

+

Performs the conversion.

+

Performs the conversion.

+

Convert to wallet descriptor

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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 new file mode 100644 index 0000000000..990701de24 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49Public.html @@ -0,0 +1,40 @@ +Bip49Public in bdk::descriptor::template - Rust

Struct bdk::descriptor::template::Bip49Public[][src]

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

+

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::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
+let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
+let wallet = Wallet::new_offline(
+    Bip49Public(key.clone(), fingerprint, KeychainKind::External),
+    Some(Bip49Public(key, fingerprint, KeychainKind::Internal)),
+    Network::Testnet,
+    MemoryDatabase::default()
+)?;
+
+assert_eq!(wallet.get_address(New)?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
+assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))#gsmdv4xr");
+

Tuple Fields

0: K1: Fingerprint2: KeychainKind

Trait Implementations

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

Convert to wallet descriptor

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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 new file mode 100644 index 0000000000..340052e2f1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84.html @@ -0,0 +1,37 @@ +Bip84 in bdk::descriptor::template - Rust

Struct bdk::descriptor::template::Bip84[][src]

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

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

+

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

+

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

+

Example

+
use bdk::template::Bip84;
+
+let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+let wallet = Wallet::new_offline(
+    Bip84(key.clone(), KeychainKind::External),
+    Some(Bip84(key, KeychainKind::Internal)),
+    Network::Testnet,
+    MemoryDatabase::default()
+)?;
+
+assert_eq!(wallet.get_address(New)?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
+assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#nkk5dtkg");
+

Tuple Fields

0: K1: 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

+

Performs the conversion.

+

Performs the conversion.

+

Convert to wallet descriptor

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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 new file mode 100644 index 0000000000..d946de1a23 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84Public.html @@ -0,0 +1,40 @@ +Bip84Public in bdk::descriptor::template - Rust

Struct bdk::descriptor::template::Bip84Public[][src]

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

+

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::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
+let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
+let wallet = Wallet::new_offline(
+    Bip84Public(key.clone(), fingerprint, KeychainKind::External),
+    Some(Bip84Public(key, fingerprint, KeychainKind::Internal)),
+    Network::Testnet,
+    MemoryDatabase::default()
+)?;
+
+assert_eq!(wallet.get_address(New)?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
+assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#nkk5dtkg");
+

Tuple Fields

0: K1: Fingerprint2: KeychainKind

Trait Implementations

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

Convert to wallet descriptor

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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 new file mode 100644 index 0000000000..9f00d81a24 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Pkh.html @@ -0,0 +1,38 @@ +P2Pkh in bdk::descriptor::template - Rust

Struct bdk::descriptor::template::P2Pkh[][src]

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

P2PKH template. Expands to a descriptor pkh(key)

+

Example

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

Tuple Fields

0: K

Trait Implementations

Build the complete descriptor

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

Convert to wallet descriptor

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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 new file mode 100644 index 0000000000..cdb5cf12c8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh.html @@ -0,0 +1,38 @@ +P2Wpkh in bdk::descriptor::template - Rust

Struct bdk::descriptor::template::P2Wpkh[][src]

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 wallet = Wallet::new_offline(
+    P2Wpkh(key),
+    None,
+    Network::Testnet,
+    MemoryDatabase::default(),
+)?;
+
+assert_eq!(
+    wallet.get_address(New)?.to_string(),
+    "tb1q4525hmgw265tl3drrl8jjta7ayffu6jf68ltjd"
+);
+

Tuple Fields

0: K

Trait Implementations

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

Convert to wallet descriptor

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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 new file mode 100644 index 0000000000..3caa912c30 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh_P2Sh.html @@ -0,0 +1,38 @@ +P2Wpkh_P2Sh in bdk::descriptor::template - Rust

Struct bdk::descriptor::template::P2Wpkh_P2Sh[][src]

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 wallet = Wallet::new_offline(
+    P2Wpkh_P2Sh(key),
+    None,
+    Network::Testnet,
+    MemoryDatabase::default(),
+)?;
+
+assert_eq!(
+    wallet.get_address(New)?.to_string(),
+    "2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"
+);
+

Tuple Fields

0: K

Trait Implementations

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

Convert to wallet descriptor

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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 new file mode 100644 index 0000000000..4fcbe7b52c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/trait.DescriptorTemplate.html @@ -0,0 +1,22 @@ +DescriptorTemplate in bdk::descriptor::template - Rust

Trait bdk::descriptor::template::DescriptorTemplate[][src]

pub trait DescriptorTemplate {
+    fn build(self) -> 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};
+
+struct MyP2PKH<K: IntoDescriptorKey<Legacy>>(K);
+
+impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for MyP2PKH<K> {
+    fn build(self) -> 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 new file mode 100644 index 0000000000..d5a999d18b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/template/type.DescriptorTemplateOut.html @@ -0,0 +1,5 @@ +DescriptorTemplateOut in bdk::descriptor::template - Rust

Type Definition bdk::descriptor::template::DescriptorTemplateOut[][src]

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 new file mode 100644 index 0000000000..6e9c6f1081 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ExtractPolicy.html @@ -0,0 +1,7 @@ +ExtractPolicy in bdk::descriptor - Rust

Trait bdk::descriptor::ExtractPolicy[][src]

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 new file mode 100644 index 0000000000..29b6762f60 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.IntoWalletDescriptor.html @@ -0,0 +1,9 @@ +IntoWalletDescriptor in bdk::descriptor - Rust

Trait bdk::descriptor::IntoWalletDescriptor[][src]

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 new file mode 100644 index 0000000000..92abbd0176 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ScriptContext.html @@ -0,0 +1,77 @@ +ScriptContext in bdk::descriptor - Rust

Trait bdk::descriptor::ScriptContext[]

pub trait ScriptContext: Debug + Clone + Ord + PartialOrd<Self> + Eq + PartialEq<Self> + Hash + Sealed {
+    fn check_terminal_non_malleable<Pk, Ctx>(
        _frag: &Terminal<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
; +
fn max_satisfaction_size<Pk, Ctx>(ms: &Miniscript<Pk, Ctx>) -> Option<usize>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
; + + fn check_witness<Pk, Ctx>(
        _witness: &[Vec<u8, Global>]
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn check_global_consensus_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn check_global_policy_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn check_local_consensus_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn check_local_policy_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn check_global_validity<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn check_local_validity<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn top_level_type_check<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), Error>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn other_top_level_checks<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), Error>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn top_level_checks<Pk, Ctx>(ms: &Miniscript<Pk, Ctx>) -> Result<(), Error>
    where
        Ctx: ScriptContext,
        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 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.

+

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

+

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.

+

Implementations on Foreign Types

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 new file mode 100644 index 0000000000..97508febab --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.DerivedDescriptor.html @@ -0,0 +1,4 @@ +DerivedDescriptor in bdk::descriptor - Rust

Type Definition bdk::descriptor::DerivedDescriptor[][src]

pub type DerivedDescriptor<'s> = Descriptor<DerivedDescriptorKey<'s>>;
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 new file mode 100644 index 0000000000..207f54a03e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/descriptor/type.ExtendedDescriptor.html @@ -0,0 +1,5 @@ +ExtendedDescriptor in bdk::descriptor - Rust

Type Definition bdk::descriptor::ExtendedDescriptor[][src]

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

Type Definition bdk::descriptor::HdKeyPaths[][src]

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

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

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

Type Definition bdk::descriptor::KeyMap[]

pub type KeyMap = HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>;
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/enum.Error.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.Error.html new file mode 100644 index 0000000000..a383630561 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.Error.html @@ -0,0 +1,158 @@ +Error in bdk - Rust

Enum bdk::Error[][src]

pub enum Error {
+
Show 41 variants InvalidU32Bytes(Vec<u8>), + Generic(String), + ScriptDoesntHaveAddressForm, + NoRecipients, + NoUtxosSelected, + OutputBelowDustLimit(usize), + InsufficientFunds { + needed: u64, + available: u64, + }, + BnBTotalTriesExceeded, + BnBNoExactMatch, + UnknownUtxo, + TransactionNotFound, + TransactionConfirmed, + IrreplaceableTransaction, + FeeRateTooLow { + required: FeeRate, + }, + FeeTooLow { + required: u64, + }, + FeeRateUnavailable, + MissingKeyOrigin(String), + Key(KeyError), + ChecksumMismatch, + SpendingPolicyRequired(KeychainKind), + InvalidPolicyPathError(PolicyError), + Signer(SignerError), + InvalidNetwork { + requested: Network, + found: Network, + }, + InvalidProgressValue(f32), + ProgressUpdateError, + InvalidOutpoint(OutPoint), + Descriptor(Error), + AddressValidator(AddressValidatorError), + Encode(Error), + Miniscript(Error), + Bip32(Error), + Secp256k1(Error), + Json(Error), + Hex(Error), + Psbt(Error), + PsbtParse(PsbtParseError), + Electrum(Error), + Esplora(Box<EsploraError>), + CompactFilters(CompactFiltersError), + Sled(Error), + Rusqlite(Error), +
}
Expand description

Errors that can be thrown by the Wallet

+

Variants

InvalidU32Bytes(Vec<u8>)

Wrong number of bytes found when trying to convert to u32

+

Tuple Fields of InvalidU32Bytes

0: Vec<u8>
Generic(String)

Generic error

+

Tuple Fields of Generic

0: String
ScriptDoesntHaveAddressForm

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

+
NoRecipients

Cannot build a tx without recipients

+
NoUtxosSelected

manually_selected_only option is selected but no utxo has been passed

+
OutputBelowDustLimit(usize)

Output created is under the dust limit, 546 satoshis

+

Tuple Fields of OutputBelowDustLimit

0: usize
InsufficientFunds

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

+

Fields of InsufficientFunds

needed: u64

Sats needed for some transaction

+
available: u64

Sats available for spending

+
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

+
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

+
UnknownUtxo

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

+
TransactionNotFound

Thrown when a tx is not found in the internal database

+
TransactionConfirmed

Happens when trying to bump a transaction that is already confirmed

+
IrreplaceableTransaction

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

+
FeeRateTooLow

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

+

Fields of FeeRateTooLow

required: FeeRate

Required fee rate (satoshi/vbyte)

+
FeeTooLow

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

+

Fields of FeeTooLow

required: u64

Required fee absolute value (satoshi)

+
FeeRateUnavailable

Node doesn’t have data to estimate a fee rate

+
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

+

Tuple Fields of MissingKeyOrigin

0: String

Error while working with keys

+

Tuple Fields of Key

ChecksumMismatch

Descriptor checksum mismatch

+
SpendingPolicyRequired(KeychainKind)

Spending policy is not compatible with this KeychainKind

+

Tuple Fields of SpendingPolicyRequired

InvalidPolicyPathError(PolicyError)

Error while extracting and manipulating policies

+

Tuple Fields of InvalidPolicyPathError

Signer(SignerError)

Signing error

+

Tuple Fields of Signer

InvalidNetwork

Invalid network

+

Fields of InvalidNetwork

requested: Network

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

+
found: Network

found network, for example the network of the bitcoin node

+
InvalidProgressValue(f32)

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

+

Tuple Fields of InvalidProgressValue

0: f32
ProgressUpdateError

Progress update error (maybe the channel has been closed)

+
InvalidOutpoint(OutPoint)

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

+

Tuple Fields of InvalidOutpoint

0: OutPoint
Descriptor(Error)

Error related to the parsing and usage of descriptors

+

Tuple Fields of Descriptor

0: Error
AddressValidator(AddressValidatorError)

Error that can be returned to fail the validation of an address

+

Tuple Fields of AddressValidator

Encode(Error)

Encoding error

+

Tuple Fields of Encode

0: Error
Miniscript(Error)

Miniscript error

+

Tuple Fields of Miniscript

0: Error
Bip32(Error)

BIP32 error

+

Tuple Fields of Bip32

0: Error
Secp256k1(Error)

An ECDSA error

+

Tuple Fields of Secp256k1

0: Error
Json(Error)

Error serializing or deserializing JSON data

+

Tuple Fields of Json

0: Error
Hex(Error)

Hex decoding error

+

Tuple Fields of Hex

0: Error
Psbt(Error)

Partially signed bitcoin transaction error

+

Tuple Fields of Psbt

0: Error
PsbtParse(PsbtParseError)

Partially signed bitcoin transaction parseerror

+

Tuple Fields of PsbtParse

0: PsbtParseError
Electrum(Error)

Electrum client error

+

Tuple Fields of Electrum

0: Error
Esplora(Box<EsploraError>)

Esplora client error

+

Tuple Fields of Esplora

CompactFilters(CompactFiltersError)

Compact filters client error)

+

Tuple Fields of CompactFilters

Sled(Error)

Sled database error

+

Tuple Fields of Sled

0: Error
Rusqlite(Error)

Rusqlite client error

+

Tuple Fields of Rusqlite

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

+
🔬 This is a nightly-only experimental API. (backtrace)

Returns a stack backtrace, if available, of where this error occurred. 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

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Converts a reference to Self into a dynamic trait object of Fail.

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the “name” of the error. Read more

+

Returns a reference to the underlying cause of this failure, if it +is an error that wraps other errors. Read more

+

Returns a reference to the Backtrace carried by this failure, if it +carries one. Read more

+

Provides context for this failure. Read more

+

Wraps this failure in a compatibility wrapper that implements +std::error::Error. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

Converts the given value to a String. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.KeychainKind.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.KeychainKind.html new file mode 100644 index 0000000000..b7202193d0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/enum.KeychainKind.html @@ -0,0 +1,47 @@ +KeychainKind in bdk - Rust

Enum bdk::KeychainKind[][src]

pub enum KeychainKind {
+    External,
+    Internal,
+}
Expand description

Types of keychains

+

Variants

External

External

+
Internal

Internal, usually used for change outputs

+

Implementations

Return KeychainKind as a byte

+

Trait Implementations

Performs the conversion.

+

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

+

Serialize this value into the given Serde serializer. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Calculate the base32 serialized length

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Error type if conversion fails

+

Check if all values are in range and return array-like struct of u5 values

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

Encode as base32 and write it to the supplied writer +Implementations shouldn’t allocate. Read more

+

Convert Self to base32 vector

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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

Enum bdk::Utxo[][src]

pub enum Utxo {
+    Local(LocalUtxo),
+    Foreign {
+        outpoint: OutPoint,
+        psbt_input: Box<Input>,
+    },
+}
Expand description

An unspent transaction output (UTXO).

+

Variants

Local(LocalUtxo)

A UTXO owned by the local wallet.

+

Tuple Fields of Local

Foreign

A UTXO owned by another wallet.

+

Fields of Foreign

outpoint: OutPoint

The location of the output.

+
psbt_input: Box<Input>

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

+

Implementations

Get the location of the UTXO

+

Get the TxOut of the UTXO

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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/error/enum.Error.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/error/enum.Error.html new file mode 100644 index 0000000000..9abf6d4a9c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/error/enum.Error.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../bdk/enum.Error.html...

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

Function bdk::version[][src]

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

Crate bdk[][src]

Expand description

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

+

About

+

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

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

A Tour of BDK

+

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

+

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

+
bdk = "0.11.0"

Sync the balance of a descriptor

Example

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

Generate a few addresses

Example

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

Create a transaction

Example

+
use bdk::{FeeRate, Wallet};
+use bdk::database::MemoryDatabase;
+use bdk::blockchain::{noop_progress, ElectrumBlockchain};
+use bdk::electrum_client::Client;
+
+use bitcoin::consensus::serialize;
+use bdk::wallet::AddressIndex::New;
+
+fn main() -> Result<(), bdk::Error> {
+    let client = Client::new("ssl://electrum.blockstream.info:60002")?;
+    let wallet = Wallet::new(
+        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
+        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
+        bitcoin::Network::Testnet,
+        MemoryDatabase::default(),
+        ElectrumBlockchain::from(client)
+    )?;
+
+    wallet.sync(noop_progress(), None)?;
+
+    let send_to = wallet.get_address(New)?;
+    let (psbt, details) = {
+        let mut builder =  wallet.build_tx();
+        builder
+            .add_recipient(send_to.script_pubkey(), 50_000)
+            .enable_rbf()
+            .do_not_spend_change()
+            .fee_rate(FeeRate::from_sat_per_vb(5.0));
+        builder.finish()?
+    };
+
+    println!("Transaction details: {:#?}", details);
+    println!("Unsigned PSBT: {}", &psbt);
+
+    Ok(())
+}
+

Sign a transaction

Example

+
use std::str::FromStr;
+
+use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
+
+use bdk::{Wallet, SignOptions};
+use bdk::database::MemoryDatabase;
+
+fn main() -> Result<(), bdk::Error> {
+    let wallet = Wallet::new_offline(
+        "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
+        Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
+        bitcoin::Network::Testnet,
+        MemoryDatabase::default(),
+    )?;
+
+    let psbt = "...";
+    let mut psbt = Psbt::from_str(psbt)?;
+
+    let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
+
+    Ok(())
+}
+

Feature flags

+

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

+

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

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

Internal features

+

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

+
    +
  • compact_filters: compact_filters client protocol for interacting with the bitcoin P2P network
  • +
  • electrum: electrum client protocol for interacting with electrum servers
  • +
  • esplora: esplora client protocol for interacting with blockstream electrs servers
  • +
  • key-value-db: key value database based on sled for caching blockchain data
  • +
+

Re-exports

+
pub extern crate bitcoin;
pub extern crate electrum_client;
pub extern crate miniscript;
pub extern crate rusqlite;
pub extern crate sled;
pub use descriptor::template;
pub use descriptor::HdKeyPaths;
pub use wallet::address_validator;
pub use wallet::signer;
pub use wallet::signer::SignOptions;
pub use wallet::tx_builder::TxBuilder;
pub use wallet::Wallet;

Modules

+

Blockchain backends

+

Database types

+

Descriptors

+

Key formats

+

Wallet

+

Macros

+

Macro to write full descriptors with code

+

Macro to write descriptor fragments with code

+

Structs

+

Block height and timestamp of the block containing the confirmed transaction

+

Fee rate

+

An unspent output owned by a Wallet.

+

A wallet transaction

+

A Utxo with its satisfaction_weight.

+

Enums

+

Errors that can be thrown by the Wallet

+

Types of keychains

+

An unspent transaction output (UTXO).

+

Traits

+

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

+

Functions

+

Get the version of BDK at runtime

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.Language.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.Language.html new file mode 100644 index 0000000000..64cd628ef5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.Language.html @@ -0,0 +1,49 @@ +Language in bdk::keys::bip39 - Rust

Enum bdk::keys::bip39::Language[]

pub enum Language {
+    English,
+    ChineseSimplified,
+    ChineseTraditional,
+    French,
+    Italian,
+    Japanese,
+    Korean,
+    Spanish,
+}
This is supported on crate feature keys-bip39 only.
Expand description

The language determines which words will be used in a mnemonic phrase, but also indirectly +determines the binary value of each word when a Mnemonic is turned into a Seed.

+

These are not of much use right now, and may even be removed from the crate, as there is no +official language specified by the standard except English.

+

Variants

English
ChineseSimplified
ChineseTraditional
French
Italian
Japanese
Korean
Spanish

Implementations

Construct a word list from its language code. Returns None +if the language code is not valid or not supported.

+

Get the word list for this language

+

Get a [WordMap][WordMap] that allows word -> index lookups in the word list

+

The index of an individual word in the word list is used as the binary value of that word +when the phrase is turned into a [Seed][Seed].

+

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

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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/bip39/enum.MnemonicType.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.MnemonicType.html new file mode 100644 index 0000000000..f7c6746c0e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.MnemonicType.html @@ -0,0 +1,111 @@ +MnemonicType in bdk::keys::bip39 - Rust

Enum bdk::keys::bip39::MnemonicType[]

pub enum MnemonicType {
+    Words12,
+    Words15,
+    Words18,
+    Words21,
+    Words24,
+}
This is supported on crate feature keys-bip39 only.
Expand description

Determines the number of words that will be present in a Mnemonic phrase

+

Also directly affects the amount of entropy that will be used to create a Mnemonic, +and therefore the cryptographic strength of the HD wallet keys/addresses that can be derived from +it using the Seed.

+

For example, a 12 word mnemonic phrase is essentially a friendly representation of a 128-bit key, +while a 24 word mnemonic phrase is essentially a 256-bit key.

+

If you know you want a specific phrase length, you can use the enum variant directly, for example +MnemonicType::Words12.

+

You can also get a MnemonicType that corresponds to one of the standard BIP39 key sizes by +passing arbitrary usize values:

+ +
use bip39::{MnemonicType};
+
+let mnemonic_type = MnemonicType::for_key_size(128).unwrap();
+

Variants

Words12
Words15
Words18
Words21
Words24

Implementations

Get a MnemonicType for a mnemonic phrase with a specific number of words

+

Specifying a word count not provided for by the BIP39 standard will return an Error +of kind ErrorKind::InvalidWordLength.

+

Example

+
use bip39::{MnemonicType};
+
+let mnemonic_type = MnemonicType::for_word_count(12).unwrap();
+

Get a MnemonicType for a mnemonic phrase representing the given key size as bits

+

Specifying a key size not provided for by the BIP39 standard will return an Error +of kind ErrorKind::InvalidKeysize.

+

Example

+
use bip39::{MnemonicType};
+
+let mnemonic_type = MnemonicType::for_key_size(128).unwrap();
+

Get a MnemonicType for an existing mnemonic phrase

+

This can be used when you need information about a mnemonic phrase based on the number of +words, for example you can get the entropy value using MnemonicType::entropy_bits.

+

Specifying a phrase that does not match one of the standard BIP39 phrase lengths will return +an Error of kind ErrorKind::InvalidWordLength. The phrase will not be validated in any +other way.

+

Example

+
use bip39::{MnemonicType};
+
+let test_mnemonic = "park remain person kitchen mule spell knee armed position rail grid ankle";
+
+let mnemonic_type = MnemonicType::for_phrase(test_mnemonic).unwrap();
+
+let entropy_bits = mnemonic_type.entropy_bits();
+

Return the number of entropy+checksum bits

+

Example

+
use bip39::{MnemonicType};
+
+let test_mnemonic = "park remain person kitchen mule spell knee armed position rail grid ankle";
+
+let mnemonic_type = MnemonicType::for_phrase(test_mnemonic).unwrap();
+
+let total_bits = mnemonic_type.total_bits();
+

Return the number of entropy bits

+

Example

+
use bip39::{MnemonicType};
+
+let test_mnemonic = "park remain person kitchen mule spell knee armed position rail grid ankle";
+
+let mnemonic_type = MnemonicType::for_phrase(test_mnemonic).unwrap();
+
+let entropy_bits = mnemonic_type.entropy_bits();
+

Return the number of checksum bits

+

Example

+
use bip39::{MnemonicType};
+
+let test_mnemonic = "park remain person kitchen mule spell knee armed position rail grid ankle";
+
+let mnemonic_type = MnemonicType::for_phrase(test_mnemonic).unwrap();
+
+let checksum_bits = mnemonic_type.checksum_bits();
+

Return the number of words

+

Example

+
use bip39::{MnemonicType};
+
+let mnemonic_type = MnemonicType::Words12;
+
+let word_count = mnemonic_type.word_count();
+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Returns the “default value” for a type. Read more

+

Formats the value using the given formatter. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

Converts the given value to a String. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/index.html new file mode 100644 index 0000000000..01e929c430 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/index.html @@ -0,0 +1,13 @@ +bdk::keys::bip39 - Rust

Module bdk::keys::bip39[][src]

This is supported on crate feature keys-bip39 only.
Expand description

BIP-0039

+

Structs

+

The primary type in this crate, most tasks require creating or using one.

+

The secret value used to derive HD wallet addresses from a Mnemonic phrase.

+

Enums

+

The language determines which words will be used in a mnemonic phrase, but also indirectly +determines the binary value of each word when a Mnemonic is turned into a Seed.

+

Determines the number of words that will be present in a Mnemonic phrase

+

Type Definitions

+

Type for a BIP39 mnemonic with an optional passphrase

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/sidebar-items.js new file mode 100644 index 0000000000..4c0779de63 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["Language","The language determines which words will be used in a mnemonic phrase, but also indirectly determines the binary value of each word when a `Mnemonic` is turned into a `Seed`."],["MnemonicType","Determines the number of words that will be present in a `Mnemonic` phrase"]],"struct":[["Mnemonic","The primary type in this crate, most tasks require creating or using one."],["Seed","The secret value used to derive HD wallet addresses from a `Mnemonic` phrase."]],"type":[["MnemonicWithPassphrase","Type for a BIP39 mnemonic with an optional passphrase"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/struct.Mnemonic.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/struct.Mnemonic.html new file mode 100644 index 0000000000..c7b3c9a84c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/struct.Mnemonic.html @@ -0,0 +1,104 @@ +Mnemonic in bdk::keys::bip39 - Rust

Struct bdk::keys::bip39::Mnemonic[]

pub struct Mnemonic { /* fields omitted */ }
This is supported on crate feature keys-bip39 only.
Expand description

The primary type in this crate, most tasks require creating or using one.

+

To create a new Mnemonic from a randomly generated key, call Mnemonic::new().

+

To get a Mnemonic instance for an existing mnemonic phrase, including +those generated by other software or hardware wallets, use Mnemonic::from_phrase().

+

You can get the HD wallet Seed from a Mnemonic by calling Seed::new(). +From there you can either get the raw byte value with Seed::as_bytes(), or the hex +representation using Rust formatting: format!("{:X}", seed).

+

You can also get the original entropy value back from a Mnemonic with Mnemonic::entropy(), +but beware that the entropy value is not the same thing as an HD wallet seed, and should +never be used that way.

+

Implementations

Generates a new Mnemonic

+

Use Mnemonic::phrase() to get an str slice of the generated phrase.

+

Example

+
use bip39::{Mnemonic, MnemonicType, Language};
+
+let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English);
+let phrase = mnemonic.phrase();
+
+println!("phrase: {}", phrase);
+
+assert_eq!(phrase.split(" ").count(), 12);
+

Create a Mnemonic from pre-generated entropy

+

Example

+
use bip39::{Mnemonic, MnemonicType, Language};
+
+let entropy = &[0x33, 0xE4, 0x6B, 0xB1, 0x3A, 0x74, 0x6E, 0xA4, 0x1C, 0xDD, 0xE4, 0x5C, 0x90, 0x84, 0x6A, 0x79];
+let mnemonic = Mnemonic::from_entropy(entropy, Language::English).unwrap();
+
+assert_eq!("crop cash unable insane eight faith inflict route frame loud box vibrant", mnemonic.phrase());
+assert_eq!("33E46BB13A746EA41CDDE45C90846A79", format!("{:X}", mnemonic));
+

Create a Mnemonic from an existing mnemonic phrase

+

The phrase supplied will be checked for word length and validated according to the checksum +specified in BIP0039

+

Example

+
use bip39::{Mnemonic, Language};
+
+let phrase = "park remain person kitchen mule spell knee armed position rail grid ankle";
+let mnemonic = Mnemonic::from_phrase(phrase, Language::English).unwrap();
+
+assert_eq!(phrase, mnemonic.phrase());
+

Validate a mnemonic phrase

+

The phrase supplied will be checked for word length and validated according to the checksum +specified in BIP0039.

+

Example

+
use bip39::{Mnemonic, Language};
+
+let test_mnemonic = "park remain person kitchen mule spell knee armed position rail grid ankle";
+
+assert!(Mnemonic::validate(test_mnemonic, Language::English).is_ok());
+

Get the mnemonic phrase as a string reference.

+

Consume the Mnemonic and return the phrase as a String.

+

This operation doesn’t perform any allocations.

+

Get the original entropy value of the mnemonic phrase as a slice.

+

Example

+
use bip39::{Mnemonic, Language};
+
+let phrase = "park remain person kitchen mule spell knee armed position rail grid ankle";
+
+let mnemonic = Mnemonic::from_phrase(phrase, Language::English).unwrap();
+
+let entropy: &[u8] = mnemonic.entropy();
+

Note: You shouldn’t use the generated entropy as secrets, for that generate a new +Seed from the Mnemonic.

+

Get the Language

+

Trait Implementations

Performs the conversion.

+

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Consume self and turn it into an ExtendedKey Read more

+

Consume self and turn it into a DescriptorKey by adding the extra metadata, such as +key origin and derivation path Read more

+

Formats the value using the given formatter. Read more

+

Type specifying the amount of entropy required e.g. [u8;32]

+

Extra options required by the generate_with_entropy

+

Returned error in case of failure

+

Generate a key given the extra options and the entropy

+

Generate a key given the options with a random entropy

+

Formats the value using the given formatter.

+

Formats the value using the given formatter.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

Outputs the hash in hexadecimal form

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

Converts the given value to a String. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/struct.Seed.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/struct.Seed.html new file mode 100644 index 0000000000..383c9685a5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/struct.Seed.html @@ -0,0 +1,48 @@ +Seed in bdk::keys::bip39 - Rust

Struct bdk::keys::bip39::Seed[]

pub struct Seed { /* fields omitted */ }
This is supported on crate feature keys-bip39 only.
Expand description

The secret value used to derive HD wallet addresses from a Mnemonic phrase.

+

Because it is not possible to create a Mnemonic instance that is invalid, it is +therefore impossible to have a Seed instance that is invalid. This guarantees that only +a valid, intact mnemonic phrase can be used to derive HD wallet addresses.

+

To get the raw byte value use Seed::as_bytes(). These can be used to derive +HD wallet addresses using another crate (deriving HD wallet addresses is outside the scope of this +crate and the BIP39 standard).

+

Implementations

Generates the seed from the Mnemonic and the password.

+

Get the seed value as a byte slice

+

Trait Implementations

Performs the conversion.

+

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Consume self and turn it into an ExtendedKey Read more

+

Consume self and turn it into a DescriptorKey by adding the extra metadata, such as +key origin and derivation path Read more

+

Formats the value using the given formatter.

+

Formats the value using the given formatter.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Calculate the base32 serialized length

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Error type if conversion fails

+

Check if all values are in range and return array-like struct of u5 values

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

Encode as base32 and write it to the supplied writer +Implementations shouldn’t allocate. Read more

+

Convert Self to base32 vector

+

Outputs the hash in hexadecimal form

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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/bip39/type.MnemonicWithPassphrase.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/type.MnemonicWithPassphrase.html new file mode 100644 index 0000000000..1b98adebbf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/bip39/type.MnemonicWithPassphrase.html @@ -0,0 +1,7 @@ +MnemonicWithPassphrase in bdk::keys::bip39 - Rust

Type Definition bdk::keys::bip39::MnemonicWithPassphrase[][src]

pub type MnemonicWithPassphrase = (Mnemonic, Option<String>);
This is supported on crate feature keys-bip39 only.
Expand description

Type for a BIP39 mnemonic with an optional passphrase

+

Trait Implementations

Consume self and turn it into an ExtendedKey Read more

+

Consume self and turn it into a DescriptorKey by adding the extra metadata, such as +key origin and derivation path Read more

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorKey.html new file mode 100644 index 0000000000..8a5149114e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorKey.html @@ -0,0 +1,28 @@ +DescriptorKey in bdk::keys - Rust

Enum bdk::keys::DescriptorKey[][src]

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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 new file mode 100644 index 0000000000..4253281299 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorPublicKey.html @@ -0,0 +1,75 @@ +DescriptorPublicKey in bdk::keys - Rust

Enum bdk::keys::DescriptorPublicKey[]

pub enum DescriptorPublicKey {
+    SinglePub(DescriptorSinglePub),
+    XPub(DescriptorXKey<ExtendedPubKey>),
+}
Expand description

The MiniscriptKey corresponding to Descriptors. This can +either be Single public key or a Xpub

+

Variants

Single Public Key

+

Tuple Fields of SinglePub

XPub(DescriptorXKey<ExtendedPubKey>)

Xpub

+

Tuple Fields of XPub

0: DescriptorXKey<ExtendedPubKey>

Implementations

The fingerprint of the master key associated with this key

+

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)

+

Whether or not the key has a wildcards

+

If this public key has a wildcard, replace it by the given index

+

Panics if given an index ≥ 2^31

+

Computes the public key corresponding to this descriptor key

+

Will return an error if the descriptor key has any hardened +derivation steps in its path, or if the key has any wildcards.

+

To ensure there are no wildcards, call .derive(0) or similar; +to avoid hardened derivation steps, start from a DescriptorSecretKey +and call as_public, or call TranslatePk2::translate_pk2 with +some function which has access to secret key data.

+

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

+

Feeds this value into the given Hasher. Read more

+

Feeds a slice of this type into the given Hasher. Read more

+

Turn the key into a DescriptorKey within the requested ScriptContext

+

The associated Hash type with the publicKey

+

Check if the publicKey is uncompressed. The default +implementation returns false Read more

+

Converts an object to PublicHash

+

Computes the size of a public key when serialized in a script, +including the length bytes 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 !=.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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 new file mode 100644 index 0000000000..9359492fb1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorSecretKey.html @@ -0,0 +1,37 @@ +DescriptorSecretKey in bdk::keys - Rust

Enum bdk::keys::DescriptorSecretKey[]

pub enum DescriptorSecretKey {
+    SinglePriv(DescriptorSinglePriv),
+    XPrv(DescriptorXKey<ExtendedPrivKey>),
+}
Expand description

A Secret Key that can be either a single key or an Xprv

+

Variants

Single Secret Key

+

Tuple Fields of SinglePriv

XPrv(DescriptorXKey<ExtendedPrivKey>)

Xprv

+

Tuple Fields of XPrv

0: DescriptorXKey<ExtendedPrivKey>

Implementations

Return the public version of this key, by applying either +DescriptorSinglePriv::as_public or [DescriptorXKey<bip32::ExtendedPrivKey>::as_public] +depending on the type of key.

+

If the key is an “XPrv”, the hardened derivation steps will be applied before converting it +to a public key. See the documentation of [DescriptorXKey<bip32::ExtendedPrivKey>::as_public] +for more details.

+

Trait Implementations

Formats the value using the given formatter. Read more

+

Formats the value using the given formatter. Read more

+

The associated error which can be returned from parsing.

+

Parses a string s to return a value of this type. Read more

+

Turn the key into a DescriptorKey within the requested ScriptContext

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

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

Enum bdk::keys::ExtendedKey[][src]

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

Enum for extended keys that can be either xprv or xpub

+

An instance of ExtendedKey can be constructed from an ExtendedPrivKey +or an ExtendedPubKey by using the From trait.

+

Defaults to the Legacy context.

+

Variants

Private((ExtendedPrivKey, PhantomData<Ctx>))

A private extended key, aka an xprv

+

Tuple Fields of Private

0: (ExtendedPrivKey, PhantomData<Ctx>)
Public((ExtendedPubKey, PhantomData<Ctx>))

A public extended key, aka an xpub

+

Tuple Fields of Public

0: (ExtendedPubKey, PhantomData<Ctx>)

Implementations

Return whether or not the key contains the private data

+

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

+

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

+

Trait Implementations

Identity conversion

+

Consume self and turn it into an ExtendedKey Read more

+

Consume self and turn it into a DescriptorKey by adding the extra metadata, such as +key origin and derivation path Read more

+

Performs the conversion.

+

Performs the conversion.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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 new file mode 100644 index 0000000000..e06474c06f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/enum.KeyError.html @@ -0,0 +1,53 @@ +KeyError in bdk::keys - Rust

Enum bdk::keys::KeyError[][src]

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

+

Tuple Fields of Message

0: String
Bip32(Error)

BIP32 error

+

Tuple Fields of Bip32

0: Error
Miniscript(Error)

Miniscript error

+

Tuple Fields of Miniscript

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

+
🔬 This is a nightly-only experimental API. (backtrace)

Returns a stack backtrace, if available, of where this error occurred. 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

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Performs the conversion.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Converts a reference to Self into a dynamic trait object of Fail.

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the “name” of the error. Read more

+

Returns a reference to the underlying cause of this failure, if it +is an error that wraps other errors. Read more

+

Returns a reference to the Backtrace carried by this failure, if it +carries one. Read more

+

Provides context for this failure. Read more

+

Wraps this failure in a compatibility wrapper that implements +std::error::Error. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

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

Enum bdk::keys::ScriptContextEnum[][src]

pub enum ScriptContextEnum {
+    Legacy,
+    Segwitv0,
+}
Expand description

Enum representation of the known valid ScriptContexts

+

Variants

Legacy

Legacy scripts

+
Segwitv0

Segwitv0 scripts

+

Implementations

Returns whether the script context is ScriptContextEnum::Legacy

+

Returns whether the script context is ScriptContextEnum::Segwitv0

+

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

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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

Function bdk::keys::any_network[][src]

pub fn any_network() -> ValidNetworks
Expand description

Create a set containing mainnet, testnet 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 new file mode 100644 index 0000000000..5753bd5e40 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.mainnet_network.html @@ -0,0 +1,4 @@ +mainnet_network in bdk::keys - Rust

Function bdk::keys::mainnet_network[][src]

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 new file mode 100644 index 0000000000..9b15a7abda --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.merge_networks.html @@ -0,0 +1,4 @@ +merge_networks in bdk::keys - Rust

Function bdk::keys::merge_networks[][src]

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 new file mode 100644 index 0000000000..efa8335377 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/fn.test_networks.html @@ -0,0 +1,4 @@ +test_networks in bdk::keys - Rust

Function bdk::keys::test_networks[][src]

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 new file mode 100644 index 0000000000..45a9223788 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/index.html @@ -0,0 +1,38 @@ +bdk::keys - Rust

Module bdk::keys[][src]

Expand description

Key formats

+

Modules

+
bip39keys-bip39

BIP-0039

+

Structs

+

A Single Descriptor Secret Key with optional origin information

+

A Single Descriptor Key with optional origin information

+

Output of a GeneratableKey key generation

+

Options for generating a [PrivateKey]

+

Contents of a “sortedmulti” descriptor

+

Enums

+

Container for public or secret keys

+

The MiniscriptKey corresponding to Descriptors. This can +either be Single public key or a Xpub

+

A Secret Key that can be either a single 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

+

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 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 new file mode 100644 index 0000000000..9b1ae8b56f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["DescriptorKey","Container for public or secret keys"],["DescriptorPublicKey","The MiniscriptKey corresponding to Descriptors. This can either be Single public key or a Xpub"],["DescriptorSecretKey","A Secret Key that can be either a single 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"]],"fn":[["any_network","Create a set containing mainnet, testnet and regtest"],["mainnet_network","Create a set only containing mainnet"],["merge_networks","Compute the intersection of two sets"],["test_networks","Create a set containing testnet and regtest"]],"mod":[["bip39","BIP-0039"]],"struct":[["DescriptorSinglePriv","A Single Descriptor Secret Key with optional origin information"],["DescriptorSinglePub","A Single Descriptor Key with optional origin information"],["GeneratedKey","Output of a [`GeneratableKey`] key generation"],["PrivateKeyGenerateOptions","Options for generating a [`PrivateKey`]"],["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.DescriptorSinglePriv.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.DescriptorSinglePriv.html new file mode 100644 index 0000000000..cafc8126d2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.DescriptorSinglePriv.html @@ -0,0 +1,26 @@ +DescriptorSinglePriv in bdk::keys - Rust

Struct bdk::keys::DescriptorSinglePriv[]

pub struct DescriptorSinglePriv {
+    pub origin: Option<(Fingerprint, DerivationPath)>,
+    pub key: PrivateKey,
+}
Expand description

A Single Descriptor Secret Key with optional origin information

+

Fields

origin: Option<(Fingerprint, DerivationPath)>

Origin information

+
key: PrivateKey

The key

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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.DescriptorSinglePub.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.DescriptorSinglePub.html new file mode 100644 index 0000000000..c568502a7d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.DescriptorSinglePub.html @@ -0,0 +1,48 @@ +DescriptorSinglePub in bdk::keys - Rust

Struct bdk::keys::DescriptorSinglePub[]

pub struct DescriptorSinglePub {
+    pub origin: Option<(Fingerprint, DerivationPath)>,
+    pub key: PublicKey,
+}
Expand description

A Single Descriptor Key with optional origin information

+

Fields

origin: Option<(Fingerprint, DerivationPath)>

Origin information

+
key: PublicKey

The 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 !=.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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.GeneratedKey.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.GeneratedKey.html new file mode 100644 index 0000000000..8f36f2d9a5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.GeneratedKey.html @@ -0,0 +1,27 @@ +GeneratedKey in bdk::keys - Rust

Struct bdk::keys::GeneratedKey[][src]

pub struct GeneratedKey<K, Ctx: ScriptContext> { /* fields omitted */ }
Expand description

Output of a GeneratableKey key generation

+

Implementations

Consumes self and returns the key

+

Trait Implementations

The resulting type after dereferencing.

+

Dereferences the value.

+

Consume self and turn it into an ExtendedKey Read more

+

Consume self and turn it into a DescriptorKey by adding the extra metadata, such as +key origin and derivation path Read more

+

Turn the key into a DescriptorKey within the requested ScriptContext

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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 new file mode 100644 index 0000000000..672f14fa46 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.PrivateKeyGenerateOptions.html @@ -0,0 +1,32 @@ +PrivateKeyGenerateOptions in bdk::keys - Rust

Struct bdk::keys::PrivateKeyGenerateOptions[][src]

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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 new file mode 100644 index 0000000000..3b6320d80b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/struct.SortedMultiVec.html @@ -0,0 +1,87 @@ +SortedMultiVec in bdk::keys - Rust

Struct bdk::keys::SortedMultiVec[]

pub struct SortedMultiVec<Pk, Ctx> where
    Ctx: ScriptContext,
    Pk: MiniscriptKey, 
{ + pub k: usize, + pub pks: Vec<Pk, Global>, + // some fields omitted +}
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 translatefpk returns an uncompressed key when +converting to a Segwit descriptor. To prevent this panic, ensure +translatefpk 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

+

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

+

Convert the object into an abstract policy

+

This method returns an Ordering between self and other. Read more

+

Compares and returns the maximum of two values. Read more

+

Compares and returns the minimum of two values. Read more

+

Restrict a value to a certain interval. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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 new file mode 100644 index 0000000000..cff040115c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.DerivableKey.html @@ -0,0 +1,103 @@ +DerivableKey in bdk::keys - Rust

Trait bdk::keys::DerivableKey[][src]

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 transofrmed 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 implemented 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 ExtendedPrivKey or +an ExtendedPubKey can implement only the required into_extended_key() method.

+ +
use bdk::bitcoin;
+use bdk::bitcoin::util::bip32;
+use bdk::keys::{DerivableKey, ExtendedKey, KeyError, ScriptContext};
+
+struct MyCustomKeyType {
+    key_data: bitcoin::PrivateKey,
+    chain_code: Vec<u8>,
+    network: bitcoin::Network,
+}
+
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
+    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+        let xprv = bip32::ExtendedPrivKey {
+            network: self.network,
+            depth: 0,
+            parent_fingerprint: bip32::Fingerprint::default(),
+            private_key: self.key_data,
+            chain_code: bip32::ChainCode::from(self.chain_code.as_ref()),
+            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 +ExtendedPrivKey or ExtendedPubKey will be considered valid.

+ +
use bdk::bitcoin;
+use bdk::bitcoin::util::bip32;
+use bdk::keys::{
+    any_network, DerivableKey, DescriptorKey, ExtendedKey, KeyError, ScriptContext,
+};
+
+struct MyCustomKeyType {
+    key_data: bitcoin::PrivateKey,
+    chain_code: Vec<u8>,
+}
+
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
+    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+        let xprv = bip32::ExtendedPrivKey {
+            network: bitcoin::Network::Bitcoin, // pick an arbitrary network here
+            depth: 0,
+            parent_fingerprint: bip32::Fingerprint::default(),
+            private_key: self.key_data,
+            chain_code: bip32::ChainCode::from(self.chain_code.as_ref()),
+            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

+

This can be used to get direct access to xprvs and xpubs for types that implement this trait, +like Mnemonic when the keys-bip39 feature is enabled.

+ +
use bdk::bitcoin::Network;
+use bdk::keys::{DerivableKey, ExtendedKey};
+use bdk::keys::bip39::{Mnemonic, Language};
+
+let xkey: ExtendedKey =
+    Mnemonic::from_phrase(
+        "jelly crash boy whisper mouse ecology tuna soccer memory million news short",
+        Language::English
+    )?
+    .into_extended_key()?;
+let xprv = xkey.into_xprv(Network::Bitcoin).unwrap();
+

Provided methods

Consume self and turn it into a DescriptorKey by adding the extra metadata, such as +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 new file mode 100644 index 0000000000..80e9abffa1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.ExtScriptContext.html @@ -0,0 +1,12 @@ +ExtScriptContext in bdk::keys - Rust

Trait bdk::keys::ExtScriptContext[][src]

pub trait ExtScriptContext: ScriptContext {
+    fn as_enum() -> ScriptContextEnum;
+
+    fn is_legacy() -> bool { ... }
+
fn is_segwit_v0() -> 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

+

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 new file mode 100644 index 0000000000..4e6cf622b1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableDefaultOptions.html @@ -0,0 +1,12 @@ +GeneratableDefaultOptions in bdk::keys - Rust

Trait bdk::keys::GeneratableDefaultOptions[][src]

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 new file mode 100644 index 0000000000..49dc544363 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableKey.html @@ -0,0 +1,21 @@ +GeneratableKey in bdk::keys - Rust

Trait bdk::keys::GeneratableKey[][src]

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.

+

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 new file mode 100644 index 0000000000..5287a61afd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.IntoDescriptorKey.html @@ -0,0 +1,107 @@ +IntoDescriptorKey in bdk::keys - Rust

Trait bdk::keys::IntoDescriptorKey[][src]

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, DescriptorSinglePub,
+    IntoDescriptorKey, KeyError, ScriptContext,
+};
+
+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::SinglePub(DescriptorSinglePub {
+                origin: None,
+                key: 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 std::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 new file mode 100644 index 0000000000..b7710b728e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/trait.ScriptContext.html @@ -0,0 +1,77 @@ +ScriptContext in bdk::keys - Rust

Trait bdk::keys::ScriptContext[]

pub trait ScriptContext: Debug + Clone + Ord + PartialOrd<Self> + Eq + PartialEq<Self> + Hash + Sealed {
+    fn check_terminal_non_malleable<Pk, Ctx>(
        _frag: &Terminal<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
; +
fn max_satisfaction_size<Pk, Ctx>(ms: &Miniscript<Pk, Ctx>) -> Option<usize>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
; + + fn check_witness<Pk, Ctx>(
        _witness: &[Vec<u8, Global>]
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn check_global_consensus_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn check_global_policy_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn check_local_consensus_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn check_local_policy_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn check_global_validity<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn check_local_validity<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn top_level_type_check<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), Error>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn other_top_level_checks<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), Error>
    where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
, + { ... } +
fn top_level_checks<Pk, Ctx>(ms: &Miniscript<Pk, Ctx>) -> Result<(), Error>
    where
        Ctx: ScriptContext,
        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 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.

+

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

+

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.

+

Implementations on Foreign Types

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 new file mode 100644 index 0000000000..29c7f03dff --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/type.KeyMap.html @@ -0,0 +1,8 @@ +KeyMap in bdk::keys - Rust

Type Definition bdk::keys::KeyMap[]

pub type KeyMap = HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>;
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 new file mode 100644 index 0000000000..9265ef2898 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/keys/type.ValidNetworks.html @@ -0,0 +1,4 @@ +ValidNetworks in bdk::keys - Rust

Type Definition bdk::keys::ValidNetworks[][src]

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 new file mode 100644 index 0000000000..976e018bd9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/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/macro.descriptor.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/macro.descriptor.html new file mode 100644 index 0000000000..c5d8ac8e4a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/macro.descriptor.html @@ -0,0 +1,79 @@ +descriptor in bdk - Rust

Macro bdk::descriptor[][src]

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) *)) => { ... };
+}
+
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(...),sdv: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: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: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 new file mode 100644 index 0000000000..6eeebba321 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/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/macro.fragment.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/macro.fragment.html new file mode 100644 index 0000000000..9f748be2b1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/macro.fragment.html @@ -0,0 +1,35 @@ +fragment in bdk - Rust

Macro bdk::fragment[][src]

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) +)) => { ... };
+    (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/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/sidebar-items.js new file mode 100644 index 0000000000..5670daf604 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["Error","Errors that can be thrown by the `Wallet`"],["KeychainKind","Types of keychains"],["Utxo","An unspent transaction output (UTXO)."]],"externcrate":[["bitcoin",""],["electrum_client",""],["miniscript",""],["rusqlite",""],["sled",""]],"fn":[["version","Get the version of BDK at runtime"]],"macro":[["descriptor","Macro to write full descriptors with code"],["fragment","Macro to write descriptor fragments with code"]],"mod":[["blockchain","Blockchain backends"],["database","Database types"],["descriptor","Descriptors"],["keys","Key formats"],["wallet","Wallet"]],"struct":[["ConfirmationTime","Block height and timestamp of the block containing the confirmed transaction"],["FeeRate","Fee rate"],["LocalUtxo","An unspent output owned by a `Wallet`."],["TransactionDetails","A wallet transaction"],["WeightedUtxo","A [`Utxo`] with its `satisfaction_weight`."]],"trait":[["Vbytes","Trait implemented by types that can be used to measure weight units."]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.ConfirmationTime.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.ConfirmationTime.html new file mode 100644 index 0000000000..492d39ca1a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.ConfirmationTime.html @@ -0,0 +1,39 @@ +ConfirmationTime in bdk - Rust

Struct bdk::ConfirmationTime[][src]

pub struct ConfirmationTime {
+    pub height: u32,
+    pub timestamp: u64,
+}
Expand description

Block height and timestamp of the block containing the confirmed transaction

+

Fields

height: u32

confirmation block height

+
timestamp: u64

confirmation block timestamp

+

Implementations

Returns Some ConfirmationTime if both height and timestamp are Some

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Returns the “default value” for a type. Read more

+

Deserialize this value from the given Serde deserializer. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.FeeRate.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.FeeRate.html new file mode 100644 index 0000000000..2edd5a044f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.FeeRate.html @@ -0,0 +1,48 @@ +FeeRate in bdk - Rust

Struct bdk::FeeRate[][src]

pub struct FeeRate(_);
Expand description

Fee rate

+

Implementations

Create a new instance of FeeRate given a float fee rate in btc/kvbytes

+

Create a new instance of FeeRate given a float fee rate in satoshi/vbyte

+

Create a new FeeRate with the default min relay fee value

+

Calculate fee rate from fee and weight units (wu).

+

Calculate fee rate from fee and vbytes.

+

Return the value as satoshi/vbyte

+

Calculate absolute fee in Satoshis using size in weight units.

+

Calculate absolute fee in Satoshis using size in virtual bytes.

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Returns the “default value” for a type. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

This method returns an ordering between self and other values if one exists. Read more

+

This method tests less than (for self and other) and is used by the < operator. Read more

+

This method tests less than or equal to (for self and other) and is used by the <= +operator. Read more

+

This method tests greater than (for self and other) and is used by the > operator. Read more

+

This method tests greater than or equal to (for self and other) and is used by the >= +operator. Read more

+

The resulting type after applying the - operator.

+

Performs the - operation. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.LocalUtxo.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.LocalUtxo.html new file mode 100644 index 0000000000..2ec1e93e00 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.LocalUtxo.html @@ -0,0 +1,41 @@ +LocalUtxo in bdk - Rust

Struct bdk::LocalUtxo[][src]

pub struct LocalUtxo {
+    pub outpoint: OutPoint,
+    pub txout: TxOut,
+    pub keychain: KeychainKind,
+}
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

+

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

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.TransactionDetails.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.TransactionDetails.html new file mode 100644 index 0000000000..c15c400d81 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.TransactionDetails.html @@ -0,0 +1,56 @@ +TransactionDetails in bdk - Rust

Struct bdk::TransactionDetails[][src]

pub struct TransactionDetails {
+    pub transaction: Option<Transaction>,
+    pub txid: Txid,
+    pub received: u64,
+    pub sent: u64,
+    pub fee: Option<u64>,
+    pub confirmation_time: Option<ConfirmationTime>,
+    pub verified: bool,
+}
Expand description

A wallet transaction

+

Fields

transaction: Option<Transaction>

Optional transaction

+
txid: Txid

Transaction id

+
received: u64

Received value (sats)

+
sent: u64

Sent value (sats)

+
fee: Option<u64>

Fee value (sats) if available. +The availability of the fee depends on the backend. It’s never None with an Electrum +Server backend, but it could be None with a Bitcoin RPC node without txindex that receive +funds while offline.

+
confirmation_time: Option<ConfirmationTime>

If the transaction is confirmed, contains height and timestamp of the block containing the +transaction, unconfirmed transaction contains None.

+
verified: bool

Whether the tx has been verified against the consensus rules

+

Confirmed txs are considered “verified” by default, while unconfirmed txs are checked to +ensure an unstrusted Blockchain backend can’t trick the +wallet into using an invalid tx as an RBF template.

+

The check is only perfomed when the verify feature is enabled.

+

Trait Implementations

Returns a copy of the value. Read more

+

Performs copy-assignment from source. Read more

+

Formats the value using the given formatter. Read more

+

Returns the “default value” for a type. Read more

+

Deserialize this value from the given Serde deserializer. Read more

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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 new file mode 100644 index 0000000000..219f9a145b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/struct.WeightedUtxo.html @@ -0,0 +1,36 @@ +WeightedUtxo in bdk - Rust

Struct bdk::WeightedUtxo[][src]

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

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/trait.Vbytes.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/trait.Vbytes.html new file mode 100644 index 0000000000..3248bdd2a4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/trait.Vbytes.html @@ -0,0 +1,7 @@ +Vbytes in bdk - Rust

Trait bdk::Vbytes[][src]

pub trait Vbytes {
+    fn vbytes(self) -> usize;
+}
Expand description

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

+

Required methods

Convert weight units to virtual bytes.

+

Implementations on Foreign Types

Implementors

+ + \ No newline at end of file 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 new file mode 100644 index 0000000000..03524a9b17 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/enum.KeychainKind.html @@ -0,0 +1,11 @@ + + + + + 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 new file mode 100644 index 0000000000..03f5add737 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/enum.Utxo.html @@ -0,0 +1,11 @@ + + + + + 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.ConfirmationTime.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/struct.ConfirmationTime.html new file mode 100644 index 0000000000..31758b8f04 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/struct.ConfirmationTime.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../bdk/struct.ConfirmationTime.html...

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

Redirecting to ../../bdk/struct.FeeRate.html...

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

Redirecting to ../../bdk/struct.LocalUtxo.html...

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

Redirecting to ../../bdk/struct.TransactionDetails.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 new file mode 100644 index 0000000000..5e7d643399 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/struct.WeightedUtxo.html @@ -0,0 +1,11 @@ + + + + + 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/types/trait.Vbytes.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/trait.Vbytes.html new file mode 100644 index 0000000000..1074aa3d4a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/types/trait.Vbytes.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../bdk/trait.Vbytes.html...

+ + + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/enum.AddressValidatorError.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/enum.AddressValidatorError.html new file mode 100644 index 0000000000..91c9903c60 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/enum.AddressValidatorError.html @@ -0,0 +1,57 @@ +AddressValidatorError in bdk::wallet::address_validator - Rust

Enum bdk::wallet::address_validator::AddressValidatorError[][src]

pub enum AddressValidatorError {
+    UserRejected,
+    ConnectionError,
+    TimeoutError,
+    InvalidScript,
+    Message(String),
+}
Expand description

Errors that can be returned to fail the validation of an address

+

Variants

UserRejected

User rejected the address

+
ConnectionError

Network connection error

+
TimeoutError

Network request timeout error

+
InvalidScript

Invalid script

+
Message(String)

A custom error message

+

Tuple Fields of Message

0: String

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

+
🔬 This is a nightly-only experimental API. (backtrace)

Returns a stack backtrace, if available, of where this error occurred. 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

+

Performs the conversion.

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Converts a reference to Self into a dynamic trait object of Fail.

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the “name” of the error. Read more

+

Returns a reference to the underlying cause of this failure, if it +is an error that wraps other errors. Read more

+

Returns a reference to the Backtrace carried by this failure, if it +carries one. Read more

+

Provides context for this failure. Read more

+

Wraps this failure in a compatibility wrapper that implements +std::error::Error. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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/address_validator/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/index.html new file mode 100644 index 0000000000..f4f4da08f3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/index.html @@ -0,0 +1,46 @@ +bdk::wallet::address_validator - Rust

Module bdk::wallet::address_validator[][src]

Expand description

Address validation callbacks

+

The typical usage of those callbacks is for displaying the newly-generated address on a +hardware wallet, so that the user can cross-check its correctness.

+

More generally speaking though, these callbacks can also be used to “do something” every time +an address is generated, without necessarily checking or validating it.

+

An address validator can be attached to a Wallet by using the +Wallet::add_address_validator method, and +whenever a new address is generated (either explicitly by the user with +Wallet::get_address or internally to create a change +address) all the attached validators will be polled, in sequence. All of them must complete +successfully to continue.

+

Example

+
#[derive(Debug)]
+struct PrintAddressAndContinue;
+
+impl AddressValidator for PrintAddressAndContinue {
+    fn validate(
+        &self,
+        keychain: KeychainKind,
+        hd_keypaths: &HdKeyPaths,
+        script: &Script
+    ) -> Result<(), AddressValidatorError> {
+        let address = Address::from_script(script, Network::Testnet)
+            .as_ref()
+            .map(Address::to_string)
+            .unwrap_or(script.to_string());
+        println!("New address of type {:?}: {}", keychain, address);
+        println!("HD keypaths: {:#?}", hd_keypaths);
+
+        Ok(())
+    }
+}
+
+let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+let mut wallet = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+wallet.add_address_validator(Arc::new(PrintAddressAndContinue));
+
+let address = wallet.get_address(New)?;
+println!("Address: {}", address);
+

Enums

+

Errors that can be returned to fail the validation of an address

+

Traits

+

Trait to build address validators

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/sidebar-items.js new file mode 100644 index 0000000000..58959ba340 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["AddressValidatorError","Errors that can be returned to fail the validation of an address"]],"trait":[["AddressValidator","Trait to build address validators"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/trait.AddressValidator.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/trait.AddressValidator.html new file mode 100644 index 0000000000..6938b2051d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/trait.AddressValidator.html @@ -0,0 +1,11 @@ +AddressValidator in bdk::wallet::address_validator - Rust

Trait bdk::wallet::address_validator::AddressValidator[][src]

pub trait AddressValidator: Send + Sync + Debug {
+    fn validate(
        &self,
        keychain: KeychainKind,
        hd_keypaths: &HdKeyPaths,
        script: &Script
    ) -> Result<(), AddressValidatorError>; +}
Expand description

Trait to build address validators

+

All the address validators attached to a wallet with Wallet::add_address_validator will be polled +every time an address (external or internal) is generated by the wallet. Errors returned in the +validator will be propagated up to the original caller that triggered the address generation.

+

For a usage example see this module’s documentation.

+

Required methods

Validate or inspect an address

+

Implementors

+ + \ 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 new file mode 100644 index 0000000000..03cda120cd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/index.html @@ -0,0 +1,73 @@ +bdk::wallet::coin_selection - Rust

Module bdk::wallet::coin_selection[][src]

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<D: Database> CoinSelectionAlgorithm<D> for AlwaysSpendEverything {
+    fn coin_select(
+        &self,
+        database: &D,
+        required_utxos: Vec<WeightedUtxo>,
+        optional_utxos: Vec<WeightedUtxo>,
+        fee_rate: FeeRate,
+        amount_needed: u64,
+        fee_amount: u64,
+    ) -> Result<CoinSelectionResult, bdk::Error> {
+        let mut selected_amount = 0;
+        let mut additional_weight = 0;
+        let all_utxos_selected = required_utxos
+            .into_iter()
+            .chain(optional_utxos)
+            .scan(
+                (&mut selected_amount, &mut additional_weight),
+                |(selected_amount, additional_weight), weighted_utxo| {
+                    **selected_amount += weighted_utxo.utxo.txout().value;
+                    **additional_weight += TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight;
+                    Some(weighted_utxo.utxo)
+                },
+            )
+            .collect::<Vec<_>>();
+        let additional_fees = fee_rate.fee_wu(additional_weight);
+        let amount_needed_with_fees = (fee_amount + additional_fees) + amount_needed;
+        if amount_needed_with_fees > selected_amount {
+            return Err(bdk::Error::InsufficientFunds {
+                needed: amount_needed_with_fees,
+                available: selected_amount,
+            });
+        }
+
+        Ok(CoinSelectionResult {
+            selected: all_utxos_selected,
+            fee_amount: fee_amount + additional_fees,
+        })
+    }
+}
+
+// create wallet, sync, ...
+
+let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+let (psbt, details) = {
+    let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
+    builder.add_recipient(to_address.script_pubkey(), 50_000);
+    builder.finish()?
+};
+
+// inspect, sign, broadcast, ...
+
+

Structs

+

Branch and bound coin selection

+

Result of a successful coin selection

+

Simple and dumb coin selection

+

Traits

+

Trait for generalized coin selection algorithms

+

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 new file mode 100644 index 0000000000..8e7e293b89 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["BranchAndBoundCoinSelection","Branch and bound coin selection"],["CoinSelectionResult","Result of a successful coin selection"],["LargestFirstCoinSelection","Simple and dumb coin selection"]],"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 new file mode 100644 index 0000000000..da3d47f8fc --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html @@ -0,0 +1,25 @@ +BranchAndBoundCoinSelection in bdk::wallet::coin_selection - Rust

Struct bdk::wallet::coin_selection::BranchAndBoundCoinSelection[][src]

pub struct BranchAndBoundCoinSelection { /* fields omitted */ }
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

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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 new file mode 100644 index 0000000000..2fc68a28c6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.CoinSelectionResult.html @@ -0,0 +1,28 @@ +CoinSelectionResult in bdk::wallet::coin_selection - Rust

Struct bdk::wallet::coin_selection::CoinSelectionResult[][src]

pub struct CoinSelectionResult {
+    pub selected: Vec<Utxo>,
+    pub fee_amount: u64,
+}
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 in satoshi

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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 new file mode 100644 index 0000000000..2967b66122 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html @@ -0,0 +1,31 @@ +LargestFirstCoinSelection in bdk::wallet::coin_selection - Rust

Struct bdk::wallet::coin_selection::LargestFirstCoinSelection[][src]

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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 new file mode 100644 index 0000000000..1aadde9c06 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html @@ -0,0 +1,22 @@ +CoinSelectionAlgorithm in bdk::wallet::coin_selection - Rust

Trait bdk::wallet::coin_selection::CoinSelectionAlgorithm[][src]

pub trait CoinSelectionAlgorithm<D: Database>: Debug {
+    fn coin_select(
        &self,
        database: &D,
        required_utxos: Vec<WeightedUtxo>,
        optional_utxos: Vec<WeightedUtxo>,
        fee_rate: FeeRate,
        amount_needed: u64,
        fee_amount: u64
    ) -> 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 amount_needed with their +weight cost
  • +
  • optional_utxos: the remaining available utxos to satisfy amount_needed with their +weight cost
  • +
  • fee_rate: fee rate to use
  • +
  • amount_needed: the amount in satoshi to select
  • +
  • fee_amount: the amount of fees in satoshi already accumulated from adding outputs and +the transaction’s header
  • +
+

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 new file mode 100644 index 0000000000..2a7cee4c38 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html @@ -0,0 +1,5 @@ +DefaultCoinSelectionAlgorithm in bdk::wallet::coin_selection - Rust

Type Definition bdk::wallet::coin_selection::DefaultCoinSelectionAlgorithm[][src]

pub type DefaultCoinSelectionAlgorithm = BranchAndBoundCoinSelection;
Expand description

Default coin selection algorithm used by TxBuilder if not +overridden

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.AddressIndex.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.AddressIndex.html new file mode 100644 index 0000000000..d20d05b94a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/enum.AddressIndex.html @@ -0,0 +1,45 @@ +AddressIndex in bdk::wallet - Rust

Enum bdk::wallet::AddressIndex[][src]

pub enum AddressIndex {
+    New,
+    LastUnused,
+    Peek(u32),
+    Reset(u32),
+}
Expand description

The address index selection strategy to use to derived an address from the wallet’s external +descriptor. See Wallet::get_address. If you’re unsure which one to use use WalletIndex::New.

+

Variants

New

Return a new address after incrementing the current descriptor index.

+
LastUnused

Return the address for the current descriptor index if it has not been used in a received +transaction. Otherwise return a new address as with AddressIndex::New.

+

Use with caution, if the wallet has not yet detected an address has been used it could +return an already used address. This function is primarily meant for situations where the +caller is untrusted; for example when deriving donation addresses on-demand for a public +web page.

+
Peek(u32)

Return the address for a specific descriptor index. Does not change the current descriptor +index used by AddressIndex::New and AddressIndex::LastUsed.

+

Use with caution, if an index is given that is less than the current descriptor index +then the returned address may have already been used.

+

Tuple Fields of Peek

0: u32
Reset(u32)

Return the address for a specific descriptor index and reset the current descriptor index +used by AddressIndex::New and AddressIndex::LastUsed to this value.

+

Use with caution, if an index is given that is less than the current descriptor index +then the returned address and subsequent addresses returned by calls to AddressIndex::New +and AddressIndex::LastUsed may have already been used. Also if the index is reset to a +value earlier than the crate::blockchain::Blockchain stop_gap (default is 20) then a +larger stop_gap should be used to monitor for all possibly used addresses.

+

Tuple Fields of Reset

0: u32

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/index.html new file mode 100644 index 0000000000..f5d42285ff --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/index.html @@ -0,0 +1,33 @@ +bdk::wallet::export - Rust

Module bdk::wallet::export[][src]

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 = WalletExport::from_str(import)?;
+let wallet = Wallet::new_offline(
+    &import.descriptor(),
+    import.change_descriptor().as_ref(),
+    Network::Testnet,
+    MemoryDatabase::default(),
+)?;
+

Export a Wallet

+
let wallet = Wallet::new_offline(
+    "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
+    Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
+    Network::Testnet,
+    MemoryDatabase::default()
+)?;
+let export = WalletExport::export_wallet(&wallet, "exported wallet", true)
+    .map_err(ToString::to_string)
+    .map_err(bdk::Error::Generic)?;
+
+println!("Exported: {}", export.to_string());
+

Structs

+

Structure that contains the export of a wallet

+
+ + \ 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 new file mode 100644 index 0000000000..06abb3c4ee --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"struct":[["WalletExport","Structure that contains the export of a wallet"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/struct.WalletExport.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/struct.WalletExport.html new file mode 100644 index 0000000000..6ff227a440 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/export/struct.WalletExport.html @@ -0,0 +1,43 @@ +WalletExport in bdk::wallet::export - Rust

Struct bdk::wallet::export::WalletExport[][src]

pub struct WalletExport {
+    pub blockheight: u32,
+    pub label: String,
+    // some fields omitted
+}
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

+

The associated error which can be returned from parsing.

+

Parses a string s to return a value of this type. Read more

+

Serialize this value into the given Serde serializer. Read more

+

Converts the given value to a String. Read more

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of 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.get_funded_wallet.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/fn.get_funded_wallet.html new file mode 100644 index 0000000000..e93825a76c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/fn.get_funded_wallet.html @@ -0,0 +1,4 @@ +get_funded_wallet in bdk::wallet - Rust

Function bdk::wallet::get_funded_wallet[][src]

pub fn get_funded_wallet(
    descriptor: &str
) -> (Wallet<(), MemoryDatabase>, (String, Option<String>), Txid)
Expand description

Return a fake wallet that appears to be funded for testing.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/index.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/index.html new file mode 100644 index 0000000000..0d5803ce8c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/index.html @@ -0,0 +1,23 @@ +bdk::wallet - Rust

Module bdk::wallet[][src]

Expand description

Wallet

+

This module defines the Wallet structure.

+

Modules

+

Address validation callbacks

+

Coin selection

+

Wallet export

+

Generalized signers

+

Cross-platform time

+

Transaction builder

+

Structs

+

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

+

A Bitcoin wallet

+

Enums

+

The address index selection strategy to use to derived an address from the wallet’s external +descriptor. See Wallet::get_address. If you’re unsure which one to use use WalletIndex::New.

+

Traits

+

Trait to check if a value is below the dust limit

+

Functions

+

Return a fake wallet that appears to be funded for testing.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/sidebar-items.js new file mode 100644 index 0000000000..20bdf7e32f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["AddressIndex","The address index selection strategy to use to derived an address from the wallet’s external descriptor. See [`Wallet::get_address`]. If you’re unsure which one to use use `WalletIndex::New`."]],"fn":[["get_funded_wallet","Return a fake wallet that appears to be funded for testing."]],"mod":[["address_validator","Address validation callbacks"],["coin_selection","Coin selection"],["export","Wallet export"],["signer","Generalized signers"],["time","Cross-platform time"],["tx_builder","Transaction builder"]],"struct":[["AddressInfo","A derived address and the index it was found at For convenience this automatically derefs to `Address`"],["Wallet","A Bitcoin wallet"]],"trait":[["IsDust","Trait to check if a value is below the dust limit"]]}); \ 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 new file mode 100644 index 0000000000..3d4cceccd5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerError.html @@ -0,0 +1,70 @@ +SignerError in bdk::wallet::signer - Rust

Enum bdk::wallet::signer::SignerError[][src]

pub enum SignerError {
+    MissingKey,
+    InvalidKey,
+    UserCanceled,
+    InputIndexOutOfRange,
+    MissingNonWitnessUtxo,
+    InvalidNonWitnessUtxo,
+    MissingWitnessUtxo,
+    MissingWitnessScript,
+    MissingHdKeypath,
+    NonStandardSighash,
+}
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 requied 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.

+

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

+
🔬 This is a nightly-only experimental API. (backtrace)

Returns a stack backtrace, if available, of where this error occurred. 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

+

Performs the conversion.

+

This method tests for self and other values to be equal, and is used +by ==. Read more

+

This method tests for !=.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Converts a reference to Self into a dynamic trait object of Fail.

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Returns the “name” of the error. Read more

+

Returns a reference to the underlying cause of this failure, if it +is an error that wraps other errors. Read more

+

Returns a reference to the Backtrace carried by this failure, if it +carries one. Read more

+

Provides context for this failure. Read more

+

Wraps this failure in a compatibility wrapper that implements +std::error::Error. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

Uses borrowed data to replace owned data, usually by cloning. Read more

+

Converts the given value to a String. Read more

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerId.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerId.html new file mode 100644 index 0000000000..291dc0fd42 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerId.html @@ -0,0 +1,53 @@ +SignerId in bdk::wallet::signer - Rust

Enum bdk::wallet::signer::SignerId[][src]

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

+

Tuple Fields of PkHash

0: Hash
Fingerprint(Fingerprint)

The fingerprint of a BIP32 extended key

+

Tuple Fields of Fingerprint

0: Fingerprint
Dummy(u64)

Dummy identifier

+

Tuple Fields of Dummy

0: u64

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

+

Performs the conversion.

+

Performs the conversion.

+

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

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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 new file mode 100644 index 0000000000..7554ca0ff6 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/index.html @@ -0,0 +1,60 @@ +bdk::wallet::signer - Rust

Module bdk::wallet::signer[][src]

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 Signer for CustomSigner {
+    fn sign(
+        &self,
+        psbt: &mut psbt::PartiallySignedTransaction,
+        input_index: Option<usize>,
+        _secp: &Secp256k1<All>,
+    ) -> Result<(), SignerError> {
+        let input_index = input_index.ok_or(SignerError::InputIndexOutOfRange)?;
+        self.device.sign_input(psbt, input_index)?;
+
+        Ok(())
+    }
+
+    fn id(&self, _secp: &Secp256k1<All>) -> SignerId {
+        self.device.get_id()
+    }
+
+    fn sign_whole_tx(&self) -> bool {
+        false
+    }
+}
+
+let custom_signer = CustomSigner::connect();
+
+let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+let mut wallet = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+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

+

Container for multiple signers

+

Enums

+

Signing error

+

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

+

Traits

+

Trait for signers

+
+ + \ 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 new file mode 100644 index 0000000000..5700429cf3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["SignerError","Signing error"],["SignerId","Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among multiple of them"]],"struct":[["SignOptions","Options for a software signer"],["SignerOrdering","Defines the order in which signers are called"],["SignersContainer","Container for multiple signers"]],"trait":[["Signer","Trait for signers"]]}); \ 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 new file mode 100644 index 0000000000..e981dcc3d4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignOptions.html @@ -0,0 +1,50 @@ +SignOptions in bdk::wallet::signer - Rust

Struct bdk::wallet::signer::SignOptions[][src]

pub struct SignOptions {
+    pub trust_witness_utxo: bool,
+    pub assume_height: Option<u32>,
+    pub allow_all_sighashes: 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 chould 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.

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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 new file mode 100644 index 0000000000..05b7104659 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignerOrdering.html @@ -0,0 +1,45 @@ +SignerOrdering in bdk::wallet::signer - Rust

Struct bdk::wallet::signer::SignerOrdering[][src]

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

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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.SignersContainer.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignersContainer.html new file mode 100644 index 0000000000..3f8eae4d00 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignersContainer.html @@ -0,0 +1,37 @@ +SignersContainer in bdk::wallet::signer - Rust

Struct bdk::wallet::signer::SignersContainer[][src]

pub struct SignersContainer(_);
Expand description

Container for multiple signers

+

Implementations

Create a map of public keys to secret keys

+

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

+

Performs the conversion.

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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

Trait bdk::wallet::signer::Signer[][src]

pub trait Signer: Debug + Send + Sync {
+    fn sign(
        &self,
        psbt: &mut PartiallySignedTransaction,
        input_index: Option<usize>,
        secp: &Secp256k1<All>
    ) -> Result<(), SignerError>; +
fn sign_whole_tx(&self) -> bool; +
fn id(&self, secp: &Secp256k1<All>) -> SignerId; + + fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> { ... } +}
Expand description

Trait for signers

+

This trait can be implemented to provide customized signers to the wallet. For an example see +this module’s documentation.

+

Required methods

Sign a PSBT

+

The input_index argument is only provided if the wallet doesn’t declare to sign the whole +transaction in one go (see Signer::sign_whole_tx). Otherwise its value is None and +can be ignored.

+

Return whether or not the signer signs the whole transaction in one go instead of every +input individually

+

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

+

Implementations on Foreign Types

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

Struct bdk::wallet::AddressInfo[][src]

pub struct AddressInfo {
+    pub index: u32,
+    pub address: Address,
+}
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

+

Methods from Deref<Target = Address>

Get the address type of the address. +None if unknown or non-standard.

+

Check whether or not the address is following Bitcoin +standardness rules.

+

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, both the schema and the address become uppercase. +If the address is base58, the schema is lowercase and 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.”

+

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

+

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

+

Immutably borrows from an owned value. Read more

+

Mutably borrows from an owned value. Read more

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

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

Struct bdk::wallet::Wallet[][src]

pub struct Wallet<B, D> { /* fields omitted */ }
Expand description

A Bitcoin wallet

+

A wallet takes descriptors, a database and a +blockchain and implements the basic functions that a Bitcoin wallets +needs to operate, like generating addresses, returning the balance, +creating transactions, etc.

+

A wallet can be either “online” if the blockchain type provided +implements Blockchain, or “offline” if it is the unit type (). Offline wallets only expose +methods that don’t need any interaction with the blockchain to work.

+

Implementations

Create a new “offline” wallet

+

Get the Bitcoin network the wallet is using.

+

Return a derived address using the external descriptor, see AddressIndex for +available address index selection strategies. If none of the keys in the descriptor are derivable +(ie. does not end with /*) then the same address will always be returned for any AddressIndex.

+

Return whether or not a script is part of this wallet (either internal or external)

+

Return the list of unspent outputs of this wallet

+

Note that this methods only operate on the internal database, which first needs to be +Wallet::sync manually.

+

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

+

Return the list of transactions made and received by the wallet

+

Optionally fill the TransactionDetails::transaction field with the raw transaction if +include_raw is true.

+

Note that this methods only operate on the internal database, which first needs to be +Wallet::sync manually.

+

Return the balance, meaning the sum of this wallet’s unspent outputs’ values

+

Note that this methods only operate on the internal database, which first needs to be +Wallet::sync manually.

+

Add an external signer

+

See the signer module for an example.

+

Add an address validator

+

See the address_validator module for an example.

+

Start building a transaction.

+

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

+

Example

+
let (psbt, details) = {
+   let mut builder =  wallet.build_tx();
+   builder
+       .add_recipient(to_address.script_pubkey(), 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 +repalce 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(), 50_000)
+        .enable_rbf();
+    builder.finish()?
+};
+let _ = wallet.sign(&mut psbt, SignOptions::default())?;
+let tx = psbt.extract_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.0));
+    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

+

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(), 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

+

Try to finalize a PSBT

+

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 adddresses for a particular keychain.

+

get the corresponding PSBT Input for a LocalUtxo

+

Create a new “online” wallet

+

Sync the internal database with the blockchain

+

Return a reference to the internal blockchain client

+

Broadcast a transaction to the network

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+

The type returned in the event of a conversion error.

+

Performs the conversion.

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/time/fn.get_timestamp.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/time/fn.get_timestamp.html new file mode 100644 index 0000000000..b08cbaaa2a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/time/fn.get_timestamp.html @@ -0,0 +1,4 @@ +get_timestamp in bdk::wallet::time - Rust

Function bdk::wallet::time::get_timestamp[][src]

pub fn get_timestamp() -> u64
Expand description

Return the current timestamp in seconds

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

Module bdk::wallet::time[][src]

Expand description

Cross-platform time

+

This module provides a function to get the current timestamp that works on all the platforms +supported by the library.

+

It can be useful to compare it with the timestamps found in +TransactionDetails.

+

Functions

+

Return the current timestamp in seconds

+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/time/sidebar-items.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/time/sidebar-items.js new file mode 100644 index 0000000000..22164ef49f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/time/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"fn":[["get_timestamp","Return the current timestamp in seconds"]]}); \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/trait.IsDust.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/trait.IsDust.html new file mode 100644 index 0000000000..368609d8ab --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/trait.IsDust.html @@ -0,0 +1,7 @@ +IsDust in bdk::wallet - Rust

Trait bdk::wallet::IsDust[][src]

pub trait IsDust {
+    fn is_dust(&self) -> bool;
+}
Expand description

Trait to check if a value is below the dust limit

+

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.ChangeSpendPolicy.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html new file mode 100644 index 0000000000..ee7b4f8ee2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html @@ -0,0 +1,51 @@ +ChangeSpendPolicy in bdk::wallet::tx_builder - Rust

Enum bdk::wallet::tx_builder::ChangeSpendPolicy[][src]

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

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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 new file mode 100644 index 0000000000..dbc248f800 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.TxOrdering.html @@ -0,0 +1,52 @@ +TxOrdering in bdk::wallet::tx_builder - Rust

Enum bdk::wallet::tx_builder::TxOrdering[][src]

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

+

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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 new file mode 100644 index 0000000000..abe616a8c4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/index.html @@ -0,0 +1,28 @@ +bdk::wallet::tx_builder - Rust

Module bdk::wallet::tx_builder[][src]

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(), 50_000)
+    // With a custom fee rate of 5.0 satoshi/vbyte
+    .fee_rate(FeeRate::from_sat_per_vb(5.0))
+    // Only spend non-change outputs
+    .do_not_spend_change()
+    // Turn on RBF signaling
+    .enable_rbf();
+let (psbt, tx_details) = 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 new file mode 100644 index 0000000000..dcd52e5dff --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["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 new file mode 100644 index 0000000000..82a9195942 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.BumpFee.html @@ -0,0 +1,28 @@ +BumpFee in bdk::wallet::tx_builder - Rust

Struct bdk::wallet::tx_builder::BumpFee[][src]

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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 new file mode 100644 index 0000000000..bc3c167a86 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.CreateTx.html @@ -0,0 +1,29 @@ +CreateTx in bdk::wallet::tx_builder - Rust

Struct bdk::wallet::tx_builder::CreateTx[][src]

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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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

Struct bdk::wallet::tx_builder::TxBuilder[][src]

pub struct TxBuilder<'a, B, D, Cs, Ctx> { /* fields omitted */ }
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, details) = {
+    let mut builder = wallet.build_tx();
+    builder
+        .ordering(TxOrdering::Untouched)
+        .add_recipient(addr1.script_pubkey(), 50_000)
+        .add_recipient(addr2.script_pubkey(), 50_000);
+    builder.finish()?
+};
+
+// non-chaining
+let (psbt2, details) = {
+    let mut builder = wallet.build_tx();
+    builder.ordering(TxOrdering::Untouched);
+    for addr in &[addr1, addr2] {
+        builder.add_recipient(addr.script_pubkey(), 50_000);
+    }
+    builder.finish()?
+};
+
+assert_eq!(
+    psbt1.global.unsigned_tx.output[..2],
+    psbt2.global.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

+

Set an absolute fee

+

Set the policy path to use while creating the transaction for a given keychain.

+

This method accepts a map where the key is the policy node id (see +Policy::id) and the value is the list of the indexes of +the items that are intended to be satisfied from the policy node (see +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.

+ +
let mut path = BTreeMap::new();
+path.insert("aabbccdd".to_string(), vec![0, 1]);
+
+let builder = wallet
+    .build_tx()
+    .add_recipient(to_address.script_pubkey(), 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 foregin 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 satisfaction_weight 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_satisfaction_weight.

+

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

+

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 psbt_input you pass to this method must +have non_witness_utxo set otherwise you will get an error when finish is called.

+

Only spend utxos added by add_utxo.

+

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.

+

Finish the building the transaction.

+

Returns the BIP174 “PSBT” and summary details about the transaction.

+

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.

+

Replace the recipients already added with a new list

+

Add a recipient to the internal list

+

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

+

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.

+ +
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.0))
+    .enable_rbf();
+let (psbt, tx_details) = tx_builder.finish()?;
+

Explicitly tells the wallet that it is allowed to reduce the fee 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

+

Performs the conversion.

+

Performs the conversion.

+

The alignment of pointer.

+

The type for initializers.

+

Initializes a with the given initializer. Read more

+

Dereferences the given pointer. Read more

+

Mutably dereferences the given pointer. Read more

+

Drops the object pointed to by the given pointer. Read more

+

Should always be Self

+

The resulting type after obtaining ownership.

+

Creates owned data from borrowed data, usually by cloning. Read more

+
🔬 This is a nightly-only experimental API. (toowned_clone_into)

recently added

+

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 new file mode 100644 index 0000000000..15e506e385 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/trait.TxBuilderContext.html @@ -0,0 +1,4 @@ +TxBuilderContext in bdk::wallet::tx_builder - Rust

Trait bdk::wallet::tx_builder::TxBuilderContext[][src]

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 new file mode 100644 index 0000000000..c0e56858e7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/bdk/wallet/utils/trait.IsDust.html @@ -0,0 +1,11 @@ + + + + + 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/brush.svg b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/brush.svg new file mode 100644 index 0000000000..ea266e856a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/brush.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/clipboard.svg b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/clipboard.svg new file mode 100644 index 0000000000..8adbd99630 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/clipboard.svg @@ -0,0 +1 @@ + diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/crates.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/crates.js new file mode 100644 index 0000000000..0abc2ef87a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/crates.js @@ -0,0 +1 @@ +window.ALL_CRATES = ["bdk"]; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/dark.css b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/dark.css new file mode 100644 index 0000000000..56782e49a2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/dark.css @@ -0,0 +1 @@ +body{background-color:#353535;color:#ddd;}h1,h2,h3,h4{color:#ddd;}h1.fqn{border-bottom-color:#d2d2d2;}h2,h3,h4{border-bottom-color:#d2d2d2;}.in-band{background-color:#353535;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#2A2A2A;}pre,.rustdoc.source .example-wrap{background-color:#2A2A2A;}.sidebar{background-color:#505050;}.logo-container.rust-logo>img{filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff)}*{scrollbar-color:rgb(64,65,67) #717171;}.sidebar{scrollbar-color:rgba(32,34,37,.6) transparent;}::-webkit-scrollbar-track{background-color:#717171;}::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar::-webkit-scrollbar-track{background-color:#717171;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar .current{background-color:#333;}.source .sidebar{background-color:#353535;}.sidebar .location{border-color:#fff;background:#575757;color:#DDD;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#444;}.line-numbers span{color:#3B91E2;}.line-numbers .line-highlighted{background-color:#0a042f !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#DDD;}.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#ddd;}.search-results a:hover{background-color:#777;}.search-results a:focus{color:#eee !important;background-color:#616161;}.search-results a:focus span{color:#eee !important;}a.result-trait:focus{background-color:#013191;}a.result-traitalias:focus{background-color:#013191;}a.result-mod:focus,a.result-externcrate:focus{background-color:#afc6e4;}a.result-mod:focus{background-color:#803a1b;}a.result-externcrate:focus{background-color:#396bac;}a.result-enum:focus{background-color:#5b4e68;}a.result-struct:focus{background-color:#194e9f;}a.result-union:focus{background-color:#b7bd49;}a.result-fn:focus,a.result-method:focus,a.result-tymethod:focus{background-color:#4950ed;}a.result-type:focus{background-color:#38902c;}a.result-foreigntype:focus{background-color:#b200d6;}a.result-attr:focus,a.result-derive:focus,a.result-macro:focus{background-color:#217d1c;}a.result-constant:focus,a.result-static:focus{background-color:#0063cc;}a.result-primitive:focus{background-color:#00708a;}a.result-keyword:focus{background-color:#884719;}.content .item-info::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#82b089;}.content span.struct,.content a.struct,.block a.current.struct{color:#2dbfb8;}.content span.type,.content a.type,.block a.current.type{color:#ff7f00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#dd7de8;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#09bd00;}.content span.union,.content a.union,.block a.current.union{color:#a6ae37;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#82a5c9;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#43aec7;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#bda000;}.content span.trait,.content a.trait,.block a.current.trait{color:#b78cf2;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#b397da;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#2BAB63;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}pre.rust .comment{color:#8d8d8b;}pre.rust .doccomment{color:#8ca375;}nav:not(.sidebar){border-bottom-color:#4e4e4e;}nav.main .current{border-top-color:#eee;border-bottom-color:#eee;}nav.main .separator{border-color:#eee;}a{color:#ddd;}body.source .example-wrap pre.rust a{background:#333;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.item-info a,#help a{color:#D2991D;}a.test-arrow{color:#dedede;}details.rustdoc-toggle>summary.hideme>span,details.rustdoc-toggle>summary::before,details.undocumented>summary::before{color:#999;}details.rustdoc-toggle>summary::before,details.undocumented>summary::before{filter:invert(100%);}#crate-search{color:#111;background-color:#f0f0f0;border-color:#000;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input{color:#111;background-color:#f0f0f0;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input:focus{border-color:#008dfd;}.search-input:disabled{background-color:#c5c4c4;}#crate-search+.search-input:focus{box-shadow:0 0 8px 4px #078dd8;}.module-item .stab,.import-item .stab{color:#ddd;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;color:#2f2f2f;}.stab.deprecated{background:#ffc4c4;border-color:#db7b7b;color:#2f2f2f;}.stab.portability{background:#F3DFFF;border-color:#b07bdb;color:#2f2f2f;}.stab.portability>code{background:none;}#help>div{background:#4d4d4d;border-color:#bfbfbf;}#help span.bottom,#help span.top{border-color:#bfbfbf;}#help dt{border-color:#bfbfbf;background:rgba(0,0,0,0);}.since{color:grey;}.result-name .primitive>i,.result-name .keyword>i{color:#ddd;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#ab8ac1;}pre.rust .kw-2,pre.rust .prelude-ty{color:#769acb;}pre.rust .number,pre.rust .string{color:#83a300;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#ee6868;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#d97f26;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#4a4949;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label,.code-attribute{color:#999;}:target,:target>*{background-color:#494a3d;}:target{border-right:3px solid #bb7410;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.8);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.8);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.8);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.8);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip::after{background-color:#000;color:#fff;border-color:#000;}.tooltip::before{border-color:transparent black transparent transparent;}.notable-traits-tooltiptext{background-color:#111;border-color:#777;}.notable-traits-tooltiptext .notable{border-bottom-color:#d2d2d2;}#titles>button:not(.selected){background-color:#252525;border-top-color:#252525;}#titles>button:hover,#titles>button.selected{border-top-color:#0089ff;background-color:#353535;}#titles>button>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#505050;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#505050;border-right-color:#000;}#sidebar-filler{background-color:#505050;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu,#help-button{border-color:#e0e0e0;background:#f0f0f0;color:#000;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus,#help-button:hover,#help-button:focus{border-color:#ffb900;}#copy-path{color:#999;}#copy-path>img{filter:invert(50%);}#copy-path:hover>img{filter:invert(65%);}#theme-choices{border-color:#e0e0e0;background-color:#353535;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#4e4e4e;}@media (max-width:700px){#theme-picker{background:#f0f0f0;}}#all-types{background-color:#505050;}#all-types:hover{background-color:#606060;}.search-results .result-name span.alias{color:#fff;}.search-results .result-name span.grey{color:#ccc;}#sidebar-toggle{background-color:#565656;}#sidebar-toggle:hover{background-color:#676767;}#source-sidebar{background-color:#565656;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#444;}div.files>.selected{background-color:#333;}.setting-line>.title{border-bottom-color:#ddd;} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/down-arrow.svg b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/down-arrow.svg new file mode 100644 index 0000000000..35437e77a7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/down-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/favicon-16x16.png b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/favicon-16x16.png new file mode 100644 index 0000000000..7cfe6c1355 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/favicon-16x16.png differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/favicon-32x32.png b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/favicon-32x32.png new file mode 100644 index 0000000000..5109c1de8b Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/favicon-32x32.png differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/favicon.svg b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/favicon.svg new file mode 100644 index 0000000000..8b34b51198 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/favicon.svg @@ -0,0 +1,24 @@ + + + + + diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/alloc/string/trait.ToString.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/alloc/string/trait.ToString.js new file mode 100644 index 0000000000..f3e935dbe1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/alloc/string/trait.ToString.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl ToString for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Blockchain.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Blockchain.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Blockchain.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.ConfigurableBlockchain.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.ConfigurableBlockchain.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.ConfigurableBlockchain.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Progress.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Progress.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Progress.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchDatabase.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchDatabase.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchDatabase.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchOperations.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchOperations.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchOperations.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.ConfigurableDatabase.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.ConfigurableDatabase.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.ConfigurableDatabase.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = []; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.Database.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.Database.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.Database.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/template/trait.DescriptorTemplate.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/template/trait.DescriptorTemplate.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/template/trait.DescriptorTemplate.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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 new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/trait.ExtractPolicy.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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 new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/trait.IntoWalletDescriptor.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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 new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.DerivableKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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 new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.ExtScriptContext.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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 new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.GeneratableDefaultOptions.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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 new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.GeneratableKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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 new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.IntoDescriptorKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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.ScriptContext.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.ScriptContext.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.ScriptContext.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/trait.Vbytes.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/trait.Vbytes.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/trait.Vbytes.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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 new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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.Signer.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.Signer.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.Signer.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/trait.IsDust.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/trait.IsDust.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/trait.IsDust.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/tx_builder/trait.TxBuilderContext.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/tx_builder/trait.TxBuilderContext.js new file mode 100644 index 0000000000..8262d3bea5 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/tx_builder/trait.TxBuilderContext.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +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/core/clone/trait.Clone.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/clone/trait.Clone.js new file mode 100644 index 0000000000..fc88bc958d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/clone/trait.Clone.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Clone for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl Clone for ElectrumBlockchainConfig","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl Clone for EsploraBlockchainConfig","synthetic":false,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl Clone for BitcoinPeerConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl Clone for CompactFiltersBlockchainConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl Clone for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Clone for NoopProgress","synthetic":false,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Clone for LogProgress","synthetic":false,"types":["bdk::blockchain::LogProgress"]},{"text":"impl<'s> Clone for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Clone for PkOrF","synthetic":false,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl Clone for SatisfiableItem","synthetic":false,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Clone for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Clone for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Clone for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl<'a> Clone for BuildSatisfaction<'a>","synthetic":false,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl Clone for ScriptContextEnum","synthetic":false,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl Clone for PrivateKeyGenerateOptions","synthetic":false,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl Clone for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl Clone for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Clone for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl Clone for WeightedUtxo","synthetic":false,"types":["bdk::types::WeightedUtxo"]},{"text":"impl Clone for Utxo","synthetic":false,"types":["bdk::types::Utxo"]},{"text":"impl Clone for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Clone for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Clone for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Clone for LargestFirstCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl Clone for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Clone for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Clone for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Clone for SignersContainer","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Clone for SignOptions","synthetic":false,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl Clone for CreateTx","synthetic":false,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl Clone for BumpFee","synthetic":false,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl<'a, Cs: Clone, Ctx, B, D> Clone for TxBuilder<'a, B, D, Cs, Ctx>","synthetic":false,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Clone for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Clone for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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/cmp/trait.Eq.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Eq.js new file mode 100644 index 0000000000..f7925a3bf8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Eq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Eq for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl<'s> Eq for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Eq for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Eq for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl Eq for ScriptContextEnum","synthetic":false,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl Eq for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl Eq for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl Eq for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Eq for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Eq for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Eq for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Eq for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Eq for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Eq for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Eq for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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/cmp/trait.Ord.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Ord.js new file mode 100644 index 0000000000..d19ffc9f15 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Ord.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl<'s> Ord for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Ord for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Ord for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Ord for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Ord for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Ord for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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/cmp/trait.PartialEq.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialEq.js new file mode 100644 index 0000000000..d505fe207f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialEq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl PartialEq<AnyBlockchainConfig> for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl PartialEq<ElectrumBlockchainConfig> for ElectrumBlockchainConfig","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl PartialEq<EsploraBlockchainConfig> for EsploraBlockchainConfig","synthetic":false,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl PartialEq<BitcoinPeerConfig> for BitcoinPeerConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl PartialEq<CompactFiltersBlockchainConfig> for CompactFiltersBlockchainConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl PartialEq<Capability> for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl<'s> PartialEq<DerivedDescriptorKey<'s>> for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl PartialEq<Condition> for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl PartialEq<PolicyError> for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl PartialEq<ScriptContextEnum> for ScriptContextEnum","synthetic":false,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl PartialEq<KeychainKind> for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl PartialEq<FeeRate> for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl PartialEq<LocalUtxo> for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl PartialEq<WeightedUtxo> for WeightedUtxo","synthetic":false,"types":["bdk::types::WeightedUtxo"]},{"text":"impl PartialEq<Utxo> for Utxo","synthetic":false,"types":["bdk::types::Utxo"]},{"text":"impl PartialEq<TransactionDetails> for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl PartialEq<ConfirmationTime> for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl PartialEq<AddressValidatorError> for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl PartialEq<SignerId> for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl PartialEq<SignerError> for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl PartialEq<SignerOrdering> for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl PartialEq<TxOrdering> for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl PartialEq<ChangeSpendPolicy> for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl PartialEq<AddressInfo> for AddressInfo","synthetic":false,"types":["bdk::wallet::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/cmp/trait.PartialOrd.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialOrd.js new file mode 100644 index 0000000000..1e33ba386e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialOrd.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl<'s> PartialOrd<DerivedDescriptorKey<'s>> for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl PartialOrd<Condition> for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl PartialOrd<FeeRate> for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl PartialOrd<SignerId> for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl PartialOrd<SignerOrdering> for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl PartialOrd<TxOrdering> for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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/convert/trait.AsRef.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.AsRef.js new file mode 100644 index 0000000000..cc88354e83 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.AsRef.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl AsRef<[u8]> for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]}]; +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 new file mode 100644 index 0000000000..ee9e5bfa5c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.From.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<AddressValidatorError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<PolicyError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<SignerError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<KeyError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<PsbtParseError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<CompactFiltersError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<EsploraError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<ElectrumBlockchain> for AnyBlockchain","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl From<EsploraBlockchain> for AnyBlockchain","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl From<CompactFiltersBlockchain> for AnyBlockchain","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl From<ElectrumBlockchainConfig> for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl From<EsploraBlockchainConfig> for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl From<CompactFiltersBlockchainConfig> for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl From<Client> for ElectrumBlockchain","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<Transport> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<ParseIntError> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<SystemTimeError> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<MemoryDatabase> for AnyDatabase","synthetic":false,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl From<Tree> for AnyDatabase","synthetic":false,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl From<SqliteDatabase> for AnyDatabase","synthetic":false,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl From<<MemoryDatabase as BatchDatabase>::Batch> for AnyBatch","synthetic":false,"types":["bdk::database::any::AnyBatch"]},{"text":"impl From<<Tree as BatchDatabase>::Batch> for AnyBatch","synthetic":false,"types":["bdk::database::any::AnyBatch"]},{"text":"impl From<<SqliteDatabase as BatchDatabase>::Batch> for AnyBatch","synthetic":false,"types":["bdk::database::any::AnyBatch"]},{"text":"impl From<()> for AnyDatabaseConfig","synthetic":false,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl From<SledDbConfiguration> for AnyDatabaseConfig","synthetic":false,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl From<SqliteDbConfiguration> for AnyDatabaseConfig","synthetic":false,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl From<KeyError> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<PolicyError> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<bool> for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl From<SatisfiableItem> for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl<Ctx: ScriptContext> From<ExtendedPubKey> for ExtendedKey<Ctx>","synthetic":false,"types":["bdk::keys::ExtendedKey"]},{"text":"impl<Ctx: ScriptContext> From<ExtendedPrivKey> for ExtendedKey<Ctx>","synthetic":false,"types":["bdk::keys::ExtendedKey"]},{"text":"impl From<Error> for KeyError","synthetic":false,"types":["bdk::keys::KeyError"]},{"text":"impl From<Error> for KeyError","synthetic":false,"types":["bdk::keys::KeyError"]},{"text":"impl From<Hash> for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl From<Fingerprint> for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl From<HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>> for SignersContainer","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]}]; +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 new file mode 100644 index 0000000000..f8973ba8b2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/default/trait.Default.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Default for Mempool","synthetic":false,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Default for MemoryDatabase","synthetic":false,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Default for PkOrF","synthetic":false,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl Default for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Default for PrivateKeyGenerateOptions","synthetic":false,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl Default for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Default for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Default for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Default for LargestFirstCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl Default for BranchAndBoundCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]},{"text":"impl Default for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Default for SignersContainer","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Default for SignOptions","synthetic":false,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl Default for CreateTx","synthetic":false,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl Default for BumpFee","synthetic":false,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl Default for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Default for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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/fmt/trait.Debug.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Debug.js new file mode 100644 index 0000000000..f8b8e915aa --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Debug.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Debug for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl Debug for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl Debug for ElectrumBlockchainConfig","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl Debug for EsploraBlockchain","synthetic":false,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchain"]},{"text":"impl Debug for EsploraBlockchainConfig","synthetic":false,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl Debug for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Debug for Mempool","synthetic":false,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Debug for Peer","synthetic":false,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Debug for CompactFiltersBlockchain","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Debug for BitcoinPeerConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl Debug for CompactFiltersBlockchainConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl Debug for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Debug for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Debug for AnyDatabase","synthetic":false,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl Debug for SledDbConfiguration","synthetic":false,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl Debug for SqliteDbConfiguration","synthetic":false,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl Debug for AnyDatabaseConfig","synthetic":false,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl Debug for SqliteDatabase","synthetic":false,"types":["bdk::database::sqlite::SqliteDatabase"]},{"text":"impl Debug for MemoryDatabase","synthetic":false,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl<'s> Debug for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Debug for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl Debug for PkOrF","synthetic":false,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl Debug for SatisfiableItem","synthetic":false,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Debug for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Debug for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Debug for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Debug for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<'a> Debug for BuildSatisfaction<'a>","synthetic":false,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl<Ctx: Debug + ScriptContext> Debug for DescriptorKey<Ctx>","synthetic":false,"types":["bdk::keys::DescriptorKey"]},{"text":"impl Debug for ScriptContextEnum","synthetic":false,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl Debug for PrivateKeyGenerateOptions","synthetic":false,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl Debug for KeyError","synthetic":false,"types":["bdk::keys::KeyError"]},{"text":"impl Debug for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl Debug for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Debug for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl Debug for WeightedUtxo","synthetic":false,"types":["bdk::types::WeightedUtxo"]},{"text":"impl Debug for Utxo","synthetic":false,"types":["bdk::types::Utxo"]},{"text":"impl Debug for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Debug for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Debug for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Debug for CoinSelectionResult","synthetic":false,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Debug for LargestFirstCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl Debug for BranchAndBoundCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]},{"text":"impl Debug for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Debug for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Debug for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Debug for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Debug for SignersContainer","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Debug for SignOptions","synthetic":false,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl Debug for CreateTx","synthetic":false,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl Debug for BumpFee","synthetic":false,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl<'a, B: Debug, D: Debug, Cs: Debug, Ctx: Debug> Debug for TxBuilder<'a, B, D, Cs, Ctx>","synthetic":false,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Debug for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Debug for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl<B: Debug, D: Debug> Debug for Wallet<B, D>","synthetic":false,"types":["bdk::wallet::Wallet"]},{"text":"impl Debug for AddressIndex","synthetic":false,"types":["bdk::wallet::AddressIndex"]},{"text":"impl Debug for AddressInfo","synthetic":false,"types":["bdk::wallet::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/fmt/trait.Display.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Display.js new file mode 100644 index 0000000000..01fb89d0ac --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Display.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Display for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl Display for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Display for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl<'s> Display for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Display for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl Display for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl Display for KeyError","synthetic":false,"types":["bdk::keys::KeyError"]},{"text":"impl Display for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Display for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Display for AddressInfo","synthetic":false,"types":["bdk::wallet::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/hash/trait.Hash.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/hash/trait.Hash.js new file mode 100644 index 0000000000..c02f002754 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/hash/trait.Hash.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Hash for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl<'s> Hash for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Hash for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Hash for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl Hash for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl Hash for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Hash for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Hash for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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 new file mode 100644 index 0000000000..b95912a278 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Copy.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Copy for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Copy for NoopProgress","synthetic":false,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Copy for LogProgress","synthetic":false,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Copy for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl<'a> Copy for BuildSatisfaction<'a>","synthetic":false,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl Copy for ScriptContextEnum","synthetic":false,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl Copy for PrivateKeyGenerateOptions","synthetic":false,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl Copy for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl Copy for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Copy for LargestFirstCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl Copy for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Copy for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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.Freeze.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Freeze.js new file mode 100644 index 0000000000..469a139430 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Freeze.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Freeze for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl !Freeze for AnyBlockchain","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl Freeze for AnyBlockchainConfig","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl !Freeze for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Freeze for ElectrumBlockchainConfig","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl Freeze for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchain"]},{"text":"impl Freeze for EsploraBlockchainConfig","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl Freeze for EsploraGetHistory","synthetic":true,"types":["bdk::blockchain::esplora::EsploraGetHistory"]},{"text":"impl Freeze for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl !Freeze for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Freeze for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Freeze for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Freeze for BitcoinPeerConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl Freeze for CompactFiltersBlockchainConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl Freeze for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Freeze for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Freeze for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Freeze for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl !Freeze for AnyDatabase","synthetic":true,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl !Freeze for AnyBatch","synthetic":true,"types":["bdk::database::any::AnyBatch"]},{"text":"impl Freeze for SledDbConfiguration","synthetic":true,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl Freeze for SqliteDbConfiguration","synthetic":true,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl Freeze for AnyDatabaseConfig","synthetic":true,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl !Freeze for SqliteDatabase","synthetic":true,"types":["bdk::database::sqlite::SqliteDatabase"]},{"text":"impl Freeze for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl<'s> Freeze for DerivedDescriptorKey<'s>","synthetic":true,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Freeze for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Freeze for PkOrF","synthetic":true,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl Freeze for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Freeze for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Freeze for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Freeze for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Freeze for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<'a> Freeze for BuildSatisfaction<'a>","synthetic":true,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl<K> Freeze for P2Pkh<K> where
    K: Freeze, 
","synthetic":true,"types":["bdk::descriptor::template::P2Pkh"]},{"text":"impl<K> Freeze for P2Wpkh_P2Sh<K> where
    K: Freeze, 
","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh_P2Sh"]},{"text":"impl<K> Freeze for P2Wpkh<K> where
    K: Freeze, 
","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh"]},{"text":"impl<K> Freeze for Bip44<K> where
    K: Freeze, 
","synthetic":true,"types":["bdk::descriptor::template::Bip44"]},{"text":"impl<K> Freeze for Bip44Public<K> where
    K: Freeze, 
","synthetic":true,"types":["bdk::descriptor::template::Bip44Public"]},{"text":"impl<K> Freeze for Bip49<K> where
    K: Freeze, 
","synthetic":true,"types":["bdk::descriptor::template::Bip49"]},{"text":"impl<K> Freeze for Bip49Public<K> where
    K: Freeze, 
","synthetic":true,"types":["bdk::descriptor::template::Bip49Public"]},{"text":"impl<K> Freeze for Bip84<K> where
    K: Freeze, 
","synthetic":true,"types":["bdk::descriptor::template::Bip84"]},{"text":"impl<K> Freeze for Bip84Public<K> where
    K: Freeze, 
","synthetic":true,"types":["bdk::descriptor::template::Bip84Public"]},{"text":"impl<Ctx> Freeze for DescriptorKey<Ctx>","synthetic":true,"types":["bdk::keys::DescriptorKey"]},{"text":"impl Freeze for ScriptContextEnum","synthetic":true,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl<Ctx> Freeze for ExtendedKey<Ctx>","synthetic":true,"types":["bdk::keys::ExtendedKey"]},{"text":"impl<K, Ctx> Freeze for GeneratedKey<K, Ctx> where
    K: Freeze, 
","synthetic":true,"types":["bdk::keys::GeneratedKey"]},{"text":"impl Freeze for PrivateKeyGenerateOptions","synthetic":true,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl Freeze for KeyError","synthetic":true,"types":["bdk::keys::KeyError"]},{"text":"impl Freeze for KeychainKind","synthetic":true,"types":["bdk::types::KeychainKind"]},{"text":"impl Freeze for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Freeze for LocalUtxo","synthetic":true,"types":["bdk::types::LocalUtxo"]},{"text":"impl Freeze for WeightedUtxo","synthetic":true,"types":["bdk::types::WeightedUtxo"]},{"text":"impl Freeze for Utxo","synthetic":true,"types":["bdk::types::Utxo"]},{"text":"impl Freeze for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Freeze for ConfirmationTime","synthetic":true,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Freeze for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Freeze for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Freeze for LargestFirstCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl Freeze for BranchAndBoundCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]},{"text":"impl Freeze for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Freeze for SignerId","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Freeze for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Freeze for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Freeze for SignersContainer","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Freeze for SignOptions","synthetic":true,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl Freeze for CreateTx","synthetic":true,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl Freeze for BumpFee","synthetic":true,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl<'a, B, D, Cs, Ctx> Freeze for TxBuilder<'a, B, D, Cs, Ctx> where
    Cs: Freeze, 
","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Freeze for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Freeze for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl<B, D> !Freeze for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Freeze for AddressIndex","synthetic":true,"types":["bdk::wallet::AddressIndex"]},{"text":"impl Freeze for AddressInfo","synthetic":true,"types":["bdk::wallet::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/marker/trait.Send.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Send.js new file mode 100644 index 0000000000..8af424700c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Send.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Send for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Send for AnyBlockchain","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl Send for AnyBlockchainConfig","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl Send for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Send for ElectrumBlockchainConfig","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl Send for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchain"]},{"text":"impl Send for EsploraBlockchainConfig","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl Send for EsploraGetHistory","synthetic":true,"types":["bdk::blockchain::esplora::EsploraGetHistory"]},{"text":"impl Send for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Send for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Send for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Send for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Send for BitcoinPeerConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl Send for CompactFiltersBlockchainConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl Send for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Send for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Send for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Send for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl !Send for AnyDatabase","synthetic":true,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl !Send for AnyBatch","synthetic":true,"types":["bdk::database::any::AnyBatch"]},{"text":"impl Send for SledDbConfiguration","synthetic":true,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl Send for SqliteDbConfiguration","synthetic":true,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl Send for AnyDatabaseConfig","synthetic":true,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl Send for SqliteDatabase","synthetic":true,"types":["bdk::database::sqlite::SqliteDatabase"]},{"text":"impl !Send for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl<'s> Send for DerivedDescriptorKey<'s>","synthetic":true,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Send for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Send for PkOrF","synthetic":true,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl Send for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Send for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Send for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Send for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Send for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<'a> Send for BuildSatisfaction<'a>","synthetic":true,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl<K> Send for P2Pkh<K> where
    K: Send
","synthetic":true,"types":["bdk::descriptor::template::P2Pkh"]},{"text":"impl<K> Send for P2Wpkh_P2Sh<K> where
    K: Send
","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh_P2Sh"]},{"text":"impl<K> Send for P2Wpkh<K> where
    K: Send
","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh"]},{"text":"impl<K> Send for Bip44<K> where
    K: Send
","synthetic":true,"types":["bdk::descriptor::template::Bip44"]},{"text":"impl<K> Send for Bip44Public<K> where
    K: Send
","synthetic":true,"types":["bdk::descriptor::template::Bip44Public"]},{"text":"impl<K> Send for Bip49<K> where
    K: Send
","synthetic":true,"types":["bdk::descriptor::template::Bip49"]},{"text":"impl<K> Send for Bip49Public<K> where
    K: Send
","synthetic":true,"types":["bdk::descriptor::template::Bip49Public"]},{"text":"impl<K> Send for Bip84<K> where
    K: Send
","synthetic":true,"types":["bdk::descriptor::template::Bip84"]},{"text":"impl<K> Send for Bip84Public<K> where
    K: Send
","synthetic":true,"types":["bdk::descriptor::template::Bip84Public"]},{"text":"impl<Ctx> Send for DescriptorKey<Ctx> where
    Ctx: Send
","synthetic":true,"types":["bdk::keys::DescriptorKey"]},{"text":"impl Send for ScriptContextEnum","synthetic":true,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl<Ctx> Send for ExtendedKey<Ctx> where
    Ctx: Send
","synthetic":true,"types":["bdk::keys::ExtendedKey"]},{"text":"impl<K, Ctx> Send for GeneratedKey<K, Ctx> where
    Ctx: Send,
    K: Send
","synthetic":true,"types":["bdk::keys::GeneratedKey"]},{"text":"impl Send for PrivateKeyGenerateOptions","synthetic":true,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl Send for KeyError","synthetic":true,"types":["bdk::keys::KeyError"]},{"text":"impl Send for KeychainKind","synthetic":true,"types":["bdk::types::KeychainKind"]},{"text":"impl Send for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Send for LocalUtxo","synthetic":true,"types":["bdk::types::LocalUtxo"]},{"text":"impl Send for WeightedUtxo","synthetic":true,"types":["bdk::types::WeightedUtxo"]},{"text":"impl Send for Utxo","synthetic":true,"types":["bdk::types::Utxo"]},{"text":"impl Send for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Send for ConfirmationTime","synthetic":true,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Send for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Send for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Send for LargestFirstCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl Send for BranchAndBoundCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]},{"text":"impl Send for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Send for SignerId","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Send for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Send for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Send for SignersContainer","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Send for SignOptions","synthetic":true,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl Send for CreateTx","synthetic":true,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl Send for BumpFee","synthetic":true,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl<'a, B, D, Cs, Ctx> !Send for TxBuilder<'a, B, D, Cs, Ctx>","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Send for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Send for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl<B, D> Send for Wallet<B, D> where
    B: Send,
    D: Send
","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Send for AddressIndex","synthetic":true,"types":["bdk::wallet::AddressIndex"]},{"text":"impl Send for AddressInfo","synthetic":true,"types":["bdk::wallet::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/marker/trait.StructuralEq.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralEq.js new file mode 100644 index 0000000000..f0a5dbaf05 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralEq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl StructuralEq for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl StructuralEq for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl StructuralEq for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl StructuralEq for ScriptContextEnum","synthetic":false,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl StructuralEq for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl StructuralEq for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl StructuralEq for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl StructuralEq for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl StructuralEq for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl StructuralEq for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl StructuralEq for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl StructuralEq for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl StructuralEq for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl StructuralEq for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::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.StructuralPartialEq.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralPartialEq.js new file mode 100644 index 0000000000..faa39c8c1e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralPartialEq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl StructuralPartialEq for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl StructuralPartialEq for ElectrumBlockchainConfig","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl StructuralPartialEq for EsploraBlockchainConfig","synthetic":false,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl StructuralPartialEq for BitcoinPeerConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl StructuralPartialEq for CompactFiltersBlockchainConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl StructuralPartialEq for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl StructuralPartialEq for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl StructuralPartialEq for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl StructuralPartialEq for ScriptContextEnum","synthetic":false,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl StructuralPartialEq for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl StructuralPartialEq for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl StructuralPartialEq for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl StructuralPartialEq for WeightedUtxo","synthetic":false,"types":["bdk::types::WeightedUtxo"]},{"text":"impl StructuralPartialEq for Utxo","synthetic":false,"types":["bdk::types::Utxo"]},{"text":"impl StructuralPartialEq for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl StructuralPartialEq for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl StructuralPartialEq for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl StructuralPartialEq for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl StructuralPartialEq for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl StructuralPartialEq for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl StructuralPartialEq for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl StructuralPartialEq for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl StructuralPartialEq for AddressInfo","synthetic":false,"types":["bdk::wallet::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/marker/trait.Sync.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Sync.js new file mode 100644 index 0000000000..2d66194d8d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Sync.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Sync for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Sync for AnyBlockchain","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl Sync for AnyBlockchainConfig","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl Sync for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Sync for ElectrumBlockchainConfig","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl Sync for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchain"]},{"text":"impl Sync for EsploraBlockchainConfig","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl Sync for EsploraGetHistory","synthetic":true,"types":["bdk::blockchain::esplora::EsploraGetHistory"]},{"text":"impl Sync for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Sync for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Sync for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Sync for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Sync for BitcoinPeerConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl Sync for CompactFiltersBlockchainConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl Sync for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Sync for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Sync for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Sync for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl !Sync for AnyDatabase","synthetic":true,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl !Sync for AnyBatch","synthetic":true,"types":["bdk::database::any::AnyBatch"]},{"text":"impl Sync for SledDbConfiguration","synthetic":true,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl Sync for SqliteDbConfiguration","synthetic":true,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl Sync for AnyDatabaseConfig","synthetic":true,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl !Sync for SqliteDatabase","synthetic":true,"types":["bdk::database::sqlite::SqliteDatabase"]},{"text":"impl !Sync for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl<'s> Sync for DerivedDescriptorKey<'s>","synthetic":true,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Sync for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Sync for PkOrF","synthetic":true,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl Sync for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Sync for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Sync for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Sync for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Sync for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<'a> Sync for BuildSatisfaction<'a>","synthetic":true,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl<K> Sync for P2Pkh<K> where
    K: Sync
","synthetic":true,"types":["bdk::descriptor::template::P2Pkh"]},{"text":"impl<K> Sync for P2Wpkh_P2Sh<K> where
    K: Sync
","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh_P2Sh"]},{"text":"impl<K> Sync for P2Wpkh<K> where
    K: Sync
","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh"]},{"text":"impl<K> Sync for Bip44<K> where
    K: Sync
","synthetic":true,"types":["bdk::descriptor::template::Bip44"]},{"text":"impl<K> Sync for Bip44Public<K> where
    K: Sync
","synthetic":true,"types":["bdk::descriptor::template::Bip44Public"]},{"text":"impl<K> Sync for Bip49<K> where
    K: Sync
","synthetic":true,"types":["bdk::descriptor::template::Bip49"]},{"text":"impl<K> Sync for Bip49Public<K> where
    K: Sync
","synthetic":true,"types":["bdk::descriptor::template::Bip49Public"]},{"text":"impl<K> Sync for Bip84<K> where
    K: Sync
","synthetic":true,"types":["bdk::descriptor::template::Bip84"]},{"text":"impl<K> Sync for Bip84Public<K> where
    K: Sync
","synthetic":true,"types":["bdk::descriptor::template::Bip84Public"]},{"text":"impl<Ctx> Sync for DescriptorKey<Ctx> where
    Ctx: Sync
","synthetic":true,"types":["bdk::keys::DescriptorKey"]},{"text":"impl Sync for ScriptContextEnum","synthetic":true,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl<Ctx> Sync for ExtendedKey<Ctx> where
    Ctx: Sync
","synthetic":true,"types":["bdk::keys::ExtendedKey"]},{"text":"impl<K, Ctx> Sync for GeneratedKey<K, Ctx> where
    Ctx: Sync,
    K: Sync
","synthetic":true,"types":["bdk::keys::GeneratedKey"]},{"text":"impl Sync for PrivateKeyGenerateOptions","synthetic":true,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl Sync for KeyError","synthetic":true,"types":["bdk::keys::KeyError"]},{"text":"impl Sync for KeychainKind","synthetic":true,"types":["bdk::types::KeychainKind"]},{"text":"impl Sync for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Sync for LocalUtxo","synthetic":true,"types":["bdk::types::LocalUtxo"]},{"text":"impl Sync for WeightedUtxo","synthetic":true,"types":["bdk::types::WeightedUtxo"]},{"text":"impl Sync for Utxo","synthetic":true,"types":["bdk::types::Utxo"]},{"text":"impl Sync for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Sync for ConfirmationTime","synthetic":true,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Sync for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Sync for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Sync for LargestFirstCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl Sync for BranchAndBoundCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]},{"text":"impl Sync for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Sync for SignerId","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Sync for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Sync for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Sync for SignersContainer","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Sync for SignOptions","synthetic":true,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl Sync for CreateTx","synthetic":true,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl Sync for BumpFee","synthetic":true,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl<'a, B, D, Cs, Ctx> !Sync for TxBuilder<'a, B, D, Cs, Ctx>","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Sync for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Sync for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl<B, D> !Sync for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Sync for AddressIndex","synthetic":true,"types":["bdk::wallet::AddressIndex"]},{"text":"impl Sync for AddressInfo","synthetic":true,"types":["bdk::wallet::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/marker/trait.Unpin.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Unpin.js new file mode 100644 index 0000000000..834a73d904 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Unpin.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Unpin for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Unpin for AnyBlockchain","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl Unpin for AnyBlockchainConfig","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl Unpin for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Unpin for ElectrumBlockchainConfig","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl Unpin for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchain"]},{"text":"impl Unpin for EsploraBlockchainConfig","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl Unpin for EsploraGetHistory","synthetic":true,"types":["bdk::blockchain::esplora::EsploraGetHistory"]},{"text":"impl Unpin for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Unpin for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Unpin for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Unpin for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Unpin for BitcoinPeerConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl Unpin for CompactFiltersBlockchainConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl Unpin for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Unpin for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Unpin for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Unpin for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Unpin for AnyDatabase","synthetic":true,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl Unpin for AnyBatch","synthetic":true,"types":["bdk::database::any::AnyBatch"]},{"text":"impl Unpin for SledDbConfiguration","synthetic":true,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl Unpin for SqliteDbConfiguration","synthetic":true,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl Unpin for AnyDatabaseConfig","synthetic":true,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl Unpin for SqliteDatabase","synthetic":true,"types":["bdk::database::sqlite::SqliteDatabase"]},{"text":"impl Unpin for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl<'s> Unpin for DerivedDescriptorKey<'s>","synthetic":true,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Unpin for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Unpin for PkOrF","synthetic":true,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl Unpin for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Unpin for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Unpin for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Unpin for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Unpin for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<'a> Unpin for BuildSatisfaction<'a>","synthetic":true,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl<K> Unpin for P2Pkh<K> where
    K: Unpin
","synthetic":true,"types":["bdk::descriptor::template::P2Pkh"]},{"text":"impl<K> Unpin for P2Wpkh_P2Sh<K> where
    K: Unpin
","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh_P2Sh"]},{"text":"impl<K> Unpin for P2Wpkh<K> where
    K: Unpin
","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh"]},{"text":"impl<K> Unpin for Bip44<K> where
    K: Unpin
","synthetic":true,"types":["bdk::descriptor::template::Bip44"]},{"text":"impl<K> Unpin for Bip44Public<K> where
    K: Unpin
","synthetic":true,"types":["bdk::descriptor::template::Bip44Public"]},{"text":"impl<K> Unpin for Bip49<K> where
    K: Unpin
","synthetic":true,"types":["bdk::descriptor::template::Bip49"]},{"text":"impl<K> Unpin for Bip49Public<K> where
    K: Unpin
","synthetic":true,"types":["bdk::descriptor::template::Bip49Public"]},{"text":"impl<K> Unpin for Bip84<K> where
    K: Unpin
","synthetic":true,"types":["bdk::descriptor::template::Bip84"]},{"text":"impl<K> Unpin for Bip84Public<K> where
    K: Unpin
","synthetic":true,"types":["bdk::descriptor::template::Bip84Public"]},{"text":"impl<Ctx> Unpin for DescriptorKey<Ctx> where
    Ctx: Unpin
","synthetic":true,"types":["bdk::keys::DescriptorKey"]},{"text":"impl Unpin for ScriptContextEnum","synthetic":true,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl<Ctx> Unpin for ExtendedKey<Ctx> where
    Ctx: Unpin
","synthetic":true,"types":["bdk::keys::ExtendedKey"]},{"text":"impl<K, Ctx> Unpin for GeneratedKey<K, Ctx> where
    Ctx: Unpin,
    K: Unpin
","synthetic":true,"types":["bdk::keys::GeneratedKey"]},{"text":"impl Unpin for PrivateKeyGenerateOptions","synthetic":true,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl Unpin for KeyError","synthetic":true,"types":["bdk::keys::KeyError"]},{"text":"impl Unpin for KeychainKind","synthetic":true,"types":["bdk::types::KeychainKind"]},{"text":"impl Unpin for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Unpin for LocalUtxo","synthetic":true,"types":["bdk::types::LocalUtxo"]},{"text":"impl Unpin for WeightedUtxo","synthetic":true,"types":["bdk::types::WeightedUtxo"]},{"text":"impl Unpin for Utxo","synthetic":true,"types":["bdk::types::Utxo"]},{"text":"impl Unpin for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Unpin for ConfirmationTime","synthetic":true,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Unpin for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Unpin for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Unpin for LargestFirstCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl Unpin for BranchAndBoundCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]},{"text":"impl Unpin for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Unpin for SignerId","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Unpin for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Unpin for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Unpin for SignersContainer","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Unpin for SignOptions","synthetic":true,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl Unpin for CreateTx","synthetic":true,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl Unpin for BumpFee","synthetic":true,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl<'a, B, D, Cs, Ctx> Unpin for TxBuilder<'a, B, D, Cs, Ctx> where
    Cs: Unpin,
    Ctx: Unpin
","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Unpin for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Unpin for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl<B, D> Unpin for Wallet<B, D> where
    B: Unpin,
    D: Unpin
","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Unpin for AddressIndex","synthetic":true,"types":["bdk::wallet::AddressIndex"]},{"text":"impl Unpin for AddressInfo","synthetic":true,"types":["bdk::wallet::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/ops/arith/trait.Sub.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/ops/arith/trait.Sub.js new file mode 100644 index 0000000000..0527a76602 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/ops/arith/trait.Sub.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Sub<FeeRate> for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/ops/deref/trait.Deref.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/ops/deref/trait.Deref.js new file mode 100644 index 0000000000..172ef72b01 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/ops/deref/trait.Deref.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl<'s> Deref for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl<K, Ctx: ScriptContext> Deref for GeneratedKey<K, Ctx>","synthetic":false,"types":["bdk::keys::GeneratedKey"]},{"text":"impl Deref for AddressInfo","synthetic":false,"types":["bdk::wallet::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 new file mode 100644 index 0000000000..43f5c13951 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.RefUnwindSafe.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl !RefUnwindSafe for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl !RefUnwindSafe for AnyBlockchain","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl RefUnwindSafe for AnyBlockchainConfig","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl RefUnwindSafe for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl RefUnwindSafe for ElectrumBlockchainConfig","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl !RefUnwindSafe for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchain"]},{"text":"impl RefUnwindSafe for EsploraBlockchainConfig","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl RefUnwindSafe for EsploraGetHistory","synthetic":true,"types":["bdk::blockchain::esplora::EsploraGetHistory"]},{"text":"impl !RefUnwindSafe for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl RefUnwindSafe for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl !RefUnwindSafe for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl !RefUnwindSafe for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl RefUnwindSafe for BitcoinPeerConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl RefUnwindSafe for CompactFiltersBlockchainConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl !RefUnwindSafe for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl RefUnwindSafe for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl RefUnwindSafe for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl RefUnwindSafe for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl !RefUnwindSafe for AnyDatabase","synthetic":true,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl !RefUnwindSafe for AnyBatch","synthetic":true,"types":["bdk::database::any::AnyBatch"]},{"text":"impl RefUnwindSafe for SledDbConfiguration","synthetic":true,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl RefUnwindSafe for SqliteDbConfiguration","synthetic":true,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl RefUnwindSafe for AnyDatabaseConfig","synthetic":true,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl !RefUnwindSafe for SqliteDatabase","synthetic":true,"types":["bdk::database::sqlite::SqliteDatabase"]},{"text":"impl !RefUnwindSafe for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl<'s> RefUnwindSafe for DerivedDescriptorKey<'s>","synthetic":true,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl RefUnwindSafe for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl RefUnwindSafe for PkOrF","synthetic":true,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl RefUnwindSafe for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl RefUnwindSafe for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl RefUnwindSafe for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl RefUnwindSafe for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl RefUnwindSafe for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<'a> RefUnwindSafe for BuildSatisfaction<'a>","synthetic":true,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl<K> RefUnwindSafe for P2Pkh<K> where
    K: RefUnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::P2Pkh"]},{"text":"impl<K> RefUnwindSafe for P2Wpkh_P2Sh<K> where
    K: RefUnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh_P2Sh"]},{"text":"impl<K> RefUnwindSafe for P2Wpkh<K> where
    K: RefUnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh"]},{"text":"impl<K> RefUnwindSafe for Bip44<K> where
    K: RefUnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::Bip44"]},{"text":"impl<K> RefUnwindSafe for Bip44Public<K> where
    K: RefUnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::Bip44Public"]},{"text":"impl<K> RefUnwindSafe for Bip49<K> where
    K: RefUnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::Bip49"]},{"text":"impl<K> RefUnwindSafe for Bip49Public<K> where
    K: RefUnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::Bip49Public"]},{"text":"impl<K> RefUnwindSafe for Bip84<K> where
    K: RefUnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::Bip84"]},{"text":"impl<K> RefUnwindSafe for Bip84Public<K> where
    K: RefUnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::Bip84Public"]},{"text":"impl<Ctx> RefUnwindSafe for DescriptorKey<Ctx> where
    Ctx: RefUnwindSafe
","synthetic":true,"types":["bdk::keys::DescriptorKey"]},{"text":"impl RefUnwindSafe for ScriptContextEnum","synthetic":true,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl<Ctx> RefUnwindSafe for ExtendedKey<Ctx> where
    Ctx: RefUnwindSafe
","synthetic":true,"types":["bdk::keys::ExtendedKey"]},{"text":"impl<K, Ctx> RefUnwindSafe for GeneratedKey<K, Ctx> where
    Ctx: RefUnwindSafe,
    K: RefUnwindSafe
","synthetic":true,"types":["bdk::keys::GeneratedKey"]},{"text":"impl RefUnwindSafe for PrivateKeyGenerateOptions","synthetic":true,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl RefUnwindSafe for KeyError","synthetic":true,"types":["bdk::keys::KeyError"]},{"text":"impl RefUnwindSafe for KeychainKind","synthetic":true,"types":["bdk::types::KeychainKind"]},{"text":"impl RefUnwindSafe for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl RefUnwindSafe for LocalUtxo","synthetic":true,"types":["bdk::types::LocalUtxo"]},{"text":"impl RefUnwindSafe for WeightedUtxo","synthetic":true,"types":["bdk::types::WeightedUtxo"]},{"text":"impl RefUnwindSafe for Utxo","synthetic":true,"types":["bdk::types::Utxo"]},{"text":"impl RefUnwindSafe for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl RefUnwindSafe for ConfirmationTime","synthetic":true,"types":["bdk::types::ConfirmationTime"]},{"text":"impl RefUnwindSafe for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl RefUnwindSafe for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl RefUnwindSafe for LargestFirstCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl RefUnwindSafe for BranchAndBoundCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]},{"text":"impl RefUnwindSafe for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl RefUnwindSafe for SignerId","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl RefUnwindSafe for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl RefUnwindSafe for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl !RefUnwindSafe for SignersContainer","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl RefUnwindSafe for SignOptions","synthetic":true,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl RefUnwindSafe for CreateTx","synthetic":true,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl RefUnwindSafe for BumpFee","synthetic":true,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl<'a, B, D, Cs, Ctx> !RefUnwindSafe for TxBuilder<'a, B, D, Cs, Ctx>","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl RefUnwindSafe for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl RefUnwindSafe for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl<B, D> !RefUnwindSafe for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl RefUnwindSafe for AddressIndex","synthetic":true,"types":["bdk::wallet::AddressIndex"]},{"text":"impl RefUnwindSafe for AddressInfo","synthetic":true,"types":["bdk::wallet::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.UnwindSafe.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.UnwindSafe.js new file mode 100644 index 0000000000..8eff90f98d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.UnwindSafe.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl !UnwindSafe for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl !UnwindSafe for AnyBlockchain","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl UnwindSafe for AnyBlockchainConfig","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl UnwindSafe for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl UnwindSafe for ElectrumBlockchainConfig","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl !UnwindSafe for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchain"]},{"text":"impl UnwindSafe for EsploraBlockchainConfig","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl UnwindSafe for EsploraGetHistory","synthetic":true,"types":["bdk::blockchain::esplora::EsploraGetHistory"]},{"text":"impl !UnwindSafe for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl UnwindSafe for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl !UnwindSafe for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl !UnwindSafe for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl UnwindSafe for BitcoinPeerConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl UnwindSafe for CompactFiltersBlockchainConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl !UnwindSafe for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl UnwindSafe for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl UnwindSafe for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl UnwindSafe for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl !UnwindSafe for AnyDatabase","synthetic":true,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl !UnwindSafe for AnyBatch","synthetic":true,"types":["bdk::database::any::AnyBatch"]},{"text":"impl UnwindSafe for SledDbConfiguration","synthetic":true,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl UnwindSafe for SqliteDbConfiguration","synthetic":true,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl UnwindSafe for AnyDatabaseConfig","synthetic":true,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl !UnwindSafe for SqliteDatabase","synthetic":true,"types":["bdk::database::sqlite::SqliteDatabase"]},{"text":"impl !UnwindSafe for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl<'s> UnwindSafe for DerivedDescriptorKey<'s>","synthetic":true,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl UnwindSafe for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl UnwindSafe for PkOrF","synthetic":true,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl UnwindSafe for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl UnwindSafe for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl UnwindSafe for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl UnwindSafe for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl UnwindSafe for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<'a> UnwindSafe for BuildSatisfaction<'a>","synthetic":true,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl<K> UnwindSafe for P2Pkh<K> where
    K: UnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::P2Pkh"]},{"text":"impl<K> UnwindSafe for P2Wpkh_P2Sh<K> where
    K: UnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh_P2Sh"]},{"text":"impl<K> UnwindSafe for P2Wpkh<K> where
    K: UnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh"]},{"text":"impl<K> UnwindSafe for Bip44<K> where
    K: UnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::Bip44"]},{"text":"impl<K> UnwindSafe for Bip44Public<K> where
    K: UnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::Bip44Public"]},{"text":"impl<K> UnwindSafe for Bip49<K> where
    K: UnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::Bip49"]},{"text":"impl<K> UnwindSafe for Bip49Public<K> where
    K: UnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::Bip49Public"]},{"text":"impl<K> UnwindSafe for Bip84<K> where
    K: UnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::Bip84"]},{"text":"impl<K> UnwindSafe for Bip84Public<K> where
    K: UnwindSafe
","synthetic":true,"types":["bdk::descriptor::template::Bip84Public"]},{"text":"impl<Ctx> UnwindSafe for DescriptorKey<Ctx> where
    Ctx: UnwindSafe
","synthetic":true,"types":["bdk::keys::DescriptorKey"]},{"text":"impl UnwindSafe for ScriptContextEnum","synthetic":true,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl<Ctx> UnwindSafe for ExtendedKey<Ctx> where
    Ctx: UnwindSafe
","synthetic":true,"types":["bdk::keys::ExtendedKey"]},{"text":"impl<K, Ctx> UnwindSafe for GeneratedKey<K, Ctx> where
    Ctx: UnwindSafe,
    K: UnwindSafe
","synthetic":true,"types":["bdk::keys::GeneratedKey"]},{"text":"impl UnwindSafe for PrivateKeyGenerateOptions","synthetic":true,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl UnwindSafe for KeyError","synthetic":true,"types":["bdk::keys::KeyError"]},{"text":"impl UnwindSafe for KeychainKind","synthetic":true,"types":["bdk::types::KeychainKind"]},{"text":"impl UnwindSafe for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl UnwindSafe for LocalUtxo","synthetic":true,"types":["bdk::types::LocalUtxo"]},{"text":"impl UnwindSafe for WeightedUtxo","synthetic":true,"types":["bdk::types::WeightedUtxo"]},{"text":"impl UnwindSafe for Utxo","synthetic":true,"types":["bdk::types::Utxo"]},{"text":"impl UnwindSafe for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl UnwindSafe for ConfirmationTime","synthetic":true,"types":["bdk::types::ConfirmationTime"]},{"text":"impl UnwindSafe for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl UnwindSafe for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl UnwindSafe for LargestFirstCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl UnwindSafe for BranchAndBoundCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]},{"text":"impl UnwindSafe for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl UnwindSafe for SignerId","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl UnwindSafe for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl UnwindSafe for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl !UnwindSafe for SignersContainer","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl UnwindSafe for SignOptions","synthetic":true,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl UnwindSafe for CreateTx","synthetic":true,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl UnwindSafe for BumpFee","synthetic":true,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl<'a, B, D, Cs, Ctx> !UnwindSafe for TxBuilder<'a, B, D, Cs, Ctx>","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl UnwindSafe for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl UnwindSafe for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl<B, D> !UnwindSafe for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl UnwindSafe for AddressIndex","synthetic":true,"types":["bdk::wallet::AddressIndex"]},{"text":"impl UnwindSafe for AddressInfo","synthetic":true,"types":["bdk::wallet::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/str/traits/trait.FromStr.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/str/traits/trait.FromStr.js new file mode 100644 index 0000000000..b76335d1f3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/core/str/traits/trait.FromStr.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl FromStr for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; +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/trait.MiniscriptKey.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/miniscript/trait.MiniscriptKey.js new file mode 100644 index 0000000000..15310a1788 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/miniscript/trait.MiniscriptKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl<'s> MiniscriptKey for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]}]; +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/trait.ToPublicKey.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/miniscript/trait.ToPublicKey.js new file mode 100644 index 0000000000..6c57ee9682 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/miniscript/trait.ToPublicKey.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl<'s> ToPublicKey for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]}]; +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 new file mode 100644 index 0000000000..4dddf8a258 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/serde/de/trait.Deserialize.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl<'de> Deserialize<'de> for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl<'de> Deserialize<'de> for ElectrumBlockchainConfig","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl<'de> Deserialize<'de> for EsploraBlockchainConfig","synthetic":false,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl<'de> Deserialize<'de> for EsploraGetHistory","synthetic":false,"types":["bdk::blockchain::esplora::EsploraGetHistory"]},{"text":"impl<'de> Deserialize<'de> for BitcoinPeerConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl<'de> Deserialize<'de> for CompactFiltersBlockchainConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl<'de> Deserialize<'de> for SledDbConfiguration","synthetic":false,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl<'de> Deserialize<'de> for SqliteDbConfiguration","synthetic":false,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl<'de> Deserialize<'de> for AnyDatabaseConfig","synthetic":false,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl<'de> Deserialize<'de> for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl<'de> Deserialize<'de> for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl<'de> Deserialize<'de> for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl<'de> Deserialize<'de> for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl<'de> Deserialize<'de> for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; +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 new file mode 100644 index 0000000000..11272bbb51 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/serde/ser/trait.Serialize.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Serialize for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl Serialize for ElectrumBlockchainConfig","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl Serialize for EsploraBlockchainConfig","synthetic":false,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl Serialize for BitcoinPeerConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl Serialize for CompactFiltersBlockchainConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl Serialize for SledDbConfiguration","synthetic":false,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl Serialize for SqliteDbConfiguration","synthetic":false,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl Serialize for AnyDatabaseConfig","synthetic":false,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl Serialize for PkOrF","synthetic":false,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl Serialize for SatisfiableItem","synthetic":false,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Serialize for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Serialize for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Serialize for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Serialize for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl Serialize for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl Serialize for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Serialize for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Serialize for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; +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/std/error/trait.Error.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/std/error/trait.Error.js new file mode 100644 index 0000000000..a772f567ff --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/implementors/std/error/trait.Error.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["bdk"] = [{"text":"impl Error for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl Error for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Error for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Error for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl Error for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl Error for KeyError","synthetic":false,"types":["bdk::keys::KeyError"]},{"text":"impl Error for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Error for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]}]; +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/light.css b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/light.css new file mode 100644 index 0000000000..14c65509e8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/light.css @@ -0,0 +1 @@ + body{background-color:white;color:black;}h1,h2,h3,h4{color:black;}h1.fqn{border-bottom-color:#D5D5D5;}h2,h3,h4{border-bottom-color:#DDDDDD;}.in-band{background-color:white;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#F5F5F5;}pre,.rustdoc.source .example-wrap{background-color:#F5F5F5;}.sidebar{background-color:#F1F1F1;}*{scrollbar-color:rgba(36,37,39,0.6) #e6e6e6;}.sidebar{scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;}.logo-container.rust-logo>img{}::-webkit-scrollbar-track{background-color:#ecebeb;}::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar::-webkit-scrollbar-track{background-color:#dcdcdc;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar .current{background-color:#fff;}.source .sidebar{background-color:#fff;}.sidebar .location{border-color:#000;background-color:#fff;color:#333;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#F5F5F5;}.line-numbers span{color:#c67e2d;}.line-numbers .line-highlighted{background-color:#f6fdb0 !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#ddd;}.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#4E4C4C;}.search-results a:hover{background-color:#ddd;}.search-results a:focus{color:#000 !important;background-color:#ccc;}.search-results a:focus span{color:#000 !important;}a.result-trait:focus{background-color:#c7b6ff;}a.result-traitalias:focus{background-color:#c7b6ff;}a.result-mod:focus,a.result-externcrate:focus{background-color:#afc6e4;}a.result-enum:focus{background-color:#b4d1b9;}a.result-struct:focus{background-color:#e7b1a0;}a.result-union:focus{background-color:#b7bd49;}a.result-fn:focus,a.result-method:focus,a.result-tymethod:focus{background-color:#c6afb3;}a.result-type:focus{background-color:#ffc891;}a.result-foreigntype:focus{background-color:#f5c4ff;}a.result-attr:focus,a.result-derive:focus,a.result-macro:focus{background-color:#8ce488;}a.result-constant:focus,a.result-static:focus{background-color:#c3e0ff;}a.result-primitive:focus{background-color:#9aecff;}a.result-keyword:focus{background-color:#f99650;}.content .item-info::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#508157;}.content span.struct,.content a.struct,.block a.current.struct{color:#ad448e;}.content span.type,.content a.type,.block a.current.type{color:#ba5d00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#cd00e2;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#068000;}.content span.union,.content a.union,.block a.current.union{color:#767b27;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#546e8a;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#2c8093;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#4d76ae;}.content span.trait,.content a.trait,.block a.current.trait{color:#7c5af3;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#6841f1;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#9a6e31;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}nav:not(.sidebar){border-bottom-color:#e0e0e0;}nav.main .current{border-top-color:#000;border-bottom-color:#000;}nav.main .separator{border:1px solid #000;}a{color:#000;}body.source .example-wrap pre.rust a{background:#eee;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.item-info a,#help a{color:#3873AD;}a.test-arrow{color:#f5f5f5;}details.rustdoc-toggle>summary.hideme>span,details.rustdoc-toggle>summary::before,details.undocumented>summary::before{color:#999;}#crate-search{color:#555;background-color:white;border-color:#e0e0e0;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input{color:#555;background-color:white;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input:focus{border-color:#66afe9;}.search-input:disabled{background-color:#e6e6e6;}#crate-search+.search-input:focus{box-shadow:0 0 8px #078dd8;}.module-item .stab,.import-item .stab{color:#000;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;}.stab.deprecated{background:#ffc4c4;border-color:#db7b7b;}.stab.portability{background:#F3DFFF;border-color:#b07bdb;}.stab.portability>code{background:none;}#help>div{background:#e9e9e9;border-color:#bfbfbf;}#help span.bottom,#help span.top{border-color:#bfbfbf;}.since{color:grey;}.result-name .primitive>i,.result-name .keyword>i{color:black;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#8959A8;}pre.rust .kw-2,pre.rust .prelude-ty{color:#4271AE;}pre.rust .number,pre.rust .string{color:#718C00;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#C82829;}pre.rust .comment{color:#8E908C;}pre.rust .doccomment{color:#4D4D4C;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#B76514;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#c7c7c7;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label,.code-attribute{color:#999;}:target,:target>*{background:#FDFFD3;}:target{border-right:3px solid #ffb44c;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.5);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.5);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.5);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip::after{background-color:#000;color:#fff;}.tooltip::before{border-color:transparent black transparent transparent;}.notable-traits-tooltiptext{background-color:#eee;border-color:#999;}.notable-traits-tooltiptext .notable{border-bottom-color:#DDDDDD;}#titles>button:not(.selected){background-color:#e6e6e6;border-top-color:#e6e6e6;}#titles>button:hover,#titles>button.selected{background-color:#ffffff;border-top-color:#0089ff;}#titles>button>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#F1F1F1;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#F1F1F1;border-right-color:#000;}#sidebar-filler{background-color:#F1F1F1;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu,#help-button{border-color:#e0e0e0;background-color:#fff;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus,#help-button:hover,#help-button:focus{border-color:#717171;}#copy-path{color:#999;}#copy-path>img{filter:invert(50%);}#copy-path:hover>img{filter:invert(35%);}#theme-choices{border-color:#ccc;background-color:#fff;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#eee;}@media (max-width:700px){#theme-picker{background:#fff;}}#all-types{background-color:#fff;}#all-types:hover{background-color:#f9f9f9;}.search-results .result-name span.alias{color:#000;}.search-results .result-name span.grey{color:#999;}#sidebar-toggle{background-color:#F1F1F1;}#sidebar-toggle:hover{background-color:#E0E0E0;}#source-sidebar{background-color:#F1F1F1;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#E0E0E0;}div.files>.selected{background-color:#fff;}.setting-line>.title{border-bottom-color:#D5D5D5;} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/main.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/main.js new file mode 100644 index 0000000000..8ccfe56500 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/main.js @@ -0,0 +1,8 @@ +if(!String.prototype.startsWith){String.prototype.startsWith=function(searchString,position){position=position||0;return this.indexOf(searchString,position)===position}}if(!String.prototype.endsWith){String.prototype.endsWith=function(suffix,length){var l=length||this.length;return this.indexOf(suffix,l-suffix.length)!==-1}}if(!DOMTokenList.prototype.add){DOMTokenList.prototype.add=function(className){if(className&&!hasClass(this,className)){if(this.className&&this.className.length>0){this.className+=" "+className}else{this.className=className}}}}if(!DOMTokenList.prototype.remove){DOMTokenList.prototype.remove=function(className){if(className&&this.className){this.className=(" "+this.className+" ").replace(" "+className+" "," ").trim()}}}(function(){var rustdocVars=document.getElementById("rustdoc-vars");if(rustdocVars){window.rootPath=rustdocVars.attributes["data-root-path"].value;window.currentCrate=rustdocVars.attributes["data-current-crate"].value;window.searchJS=rustdocVars.attributes["data-search-js"].value;window.searchIndexJS=rustdocVars.attributes["data-search-index-js"].value}var sidebarVars=document.getElementById("sidebar-vars");if(sidebarVars){window.sidebarCurrent={name:sidebarVars.attributes["data-name"].value,ty:sidebarVars.attributes["data-ty"].value,relpath:sidebarVars.attributes["data-relpath"].value,}}}());function getVirtualKey(ev){if("key"in ev&&typeof ev.key!="undefined"){return ev.key}var c=ev.charCode||ev.keyCode;if(c==27){return"Escape"}return String.fromCharCode(c)}var THEME_PICKER_ELEMENT_ID="theme-picker";var THEMES_ELEMENT_ID="theme-choices";function getThemesElement(){return document.getElementById(THEMES_ELEMENT_ID)}function getThemePickerElement(){return document.getElementById(THEME_PICKER_ELEMENT_ID)}function getNakedUrl(){return window.location.href.split("?")[0].split("#")[0]}function showThemeButtonState(){var themePicker=getThemePickerElement();var themeChoices=getThemesElement();themeChoices.style.display="block";themePicker.style.borderBottomRightRadius="0";themePicker.style.borderBottomLeftRadius="0"}function hideThemeButtonState(){var themePicker=getThemePickerElement();var themeChoices=getThemesElement();themeChoices.style.display="none";themePicker.style.borderBottomRightRadius="3px";themePicker.style.borderBottomLeftRadius="3px"}(function(){var themeChoices=getThemesElement();var themePicker=getThemePickerElement();var availableThemes=["ayu","dark","light"];function switchThemeButtonState(){if(themeChoices.style.display==="block"){hideThemeButtonState()}else{showThemeButtonState()}}function handleThemeButtonsBlur(e){var active=document.activeElement;var related=e.relatedTarget;if(active.id!==THEME_PICKER_ELEMENT_ID&&(!active.parentNode||active.parentNode.id!==THEMES_ELEMENT_ID)&&(!related||(related.id!==THEME_PICKER_ELEMENT_ID&&(!related.parentNode||related.parentNode.id!==THEMES_ELEMENT_ID)))){hideThemeButtonState()}}themePicker.onclick=switchThemeButtonState;themePicker.onblur=handleThemeButtonsBlur;availableThemes.forEach(function(item){var but=document.createElement("button");but.textContent=item;but.onclick=function(){switchTheme(window.currentTheme,window.mainTheme,item,true);useSystemTheme(false)};but.onblur=handleThemeButtonsBlur;themeChoices.appendChild(but)})}());(function(){"use strict";window.searchState={loadingText:"Loading search results...",input:document.getElementsByClassName("search-input")[0],outputElement:function(){return document.getElementById("search")},title:document.title,titleBeforeSearch:document.title,timeout:null,currentTab:0,focusedByTab:[null,null,null],clearInputTimeout:function(){if(searchState.timeout!==null){clearTimeout(searchState.timeout);searchState.timeout=null}},focus:function(){searchState.input.focus()},defocus:function(){searchState.input.blur()},showResults:function(search){if(search===null||typeof search==='undefined'){search=searchState.outputElement()}addClass(main,"hidden");removeClass(search,"hidden");searchState.mouseMovedAfterSearch=false;document.title=searchState.title},hideResults:function(search){if(search===null||typeof search==='undefined'){search=searchState.outputElement()}addClass(search,"hidden");removeClass(main,"hidden");document.title=searchState.titleBeforeSearch;if(searchState.browserSupportsHistoryApi()){history.replaceState("",window.currentCrate+" - Rust",getNakedUrl()+window.location.hash)}},getQueryStringParams:function(){var params={};window.location.search.substring(1).split("&").map(function(s){var pair=s.split("=");params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params},putBackSearch:function(search_input){var search=searchState.outputElement();if(search_input.value!==""&&hasClass(search,"hidden")){searchState.showResults(search);if(searchState.browserSupportsHistoryApi()){var extra="?search="+encodeURIComponent(search_input.value);history.replaceState(search_input.value,"",getNakedUrl()+extra+window.location.hash)}document.title=searchState.title}},browserSupportsHistoryApi:function(){return window.history&&typeof window.history.pushState==="function"},setup:function(){var search_input=searchState.input;if(!searchState.input){return}function loadScript(url){var script=document.createElement('script');script.src=url;document.head.append(script)}var searchLoaded=false;function loadSearch(){if(!searchLoaded){searchLoaded=true;loadScript(window.searchJS);loadScript(window.searchIndexJS)}}search_input.addEventListener("focus",function(){searchState.putBackSearch(this);search_input.origPlaceholder=searchState.input.placeholder;search_input.placeholder="Type your search here.";loadSearch()});search_input.addEventListener("blur",function(){search_input.placeholder=searchState.input.origPlaceholder});search_input.removeAttribute('disabled');searchState.addCrateDropdown(window.ALL_CRATES);var params=searchState.getQueryStringParams();if(params.search!==undefined){var search=searchState.outputElement();search.innerHTML="

"+searchState.loadingText+"

";searchState.showResults(search);loadSearch()}},addCrateDropdown:function(crates){var elem=document.getElementById("crate-search");if(!elem){return}var savedCrate=getSettingValue("saved-filter-crate");for(var i=0,len=crates.length;i0){return tmp}}return null}function showSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){addClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];if(sidebar){addClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(!filler){var div=document.createElement("div");div.id="sidebar-filler";sidebar.appendChild(div)}}}function hideSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){removeClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(filler){filler.remove()}document.getElementsByTagName("body")[0].style.marginTop=""}var toggleAllDocsId="toggle-all-docs";var main=document.getElementById("main");var savedHash="";function handleHashes(ev){var elem;var search=searchState.outputElement();if(ev!==null&&search&&!hasClass(search,"hidden")&&ev.newURL){searchState.hideResults(search);var hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(searchState.browserSupportsHistoryApi()){history.replaceState(hash,"",getNakedUrl()+window.location.search+"#"+hash)}elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}if(savedHash!==window.location.hash){savedHash=window.location.hash;if(savedHash.length===0){return}expandSection(savedHash.slice(1))}}function onHashChange(ev){hideSidebar();handleHashes(ev)}function openParentDetails(elem){while(elem){if(elem.tagName==="DETAILS"){elem.open=true}elem=elem.parentNode}}function expandSection(id){openParentDetails(document.getElementById(id))}function getHelpElement(build){if(build){buildHelperPopup()}return document.getElementById("help")}function displayHelp(display,ev,help){if(display){help=help?help:getHelpElement(true);if(hasClass(help,"hidden")){ev.preventDefault();removeClass(help,"hidden");addClass(document.body,"blur")}}else{help=help?help:getHelpElement(false);if(help&&!hasClass(help,"hidden")){ev.preventDefault();addClass(help,"hidden");removeClass(document.body,"blur")}}}function handleEscape(ev){var help=getHelpElement(false);var search=searchState.outputElement();if(help&&!hasClass(help,"hidden")){displayHelp(false,ev,help)}else if(search&&!hasClass(search,"hidden")){searchState.clearInputTimeout();ev.preventDefault();searchState.hideResults(search)}searchState.defocus();hideThemeButtonState()}var disableShortcuts=getSettingValue("disable-shortcuts")==="true";function handleShortcut(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts){return}if(document.activeElement.tagName==="INPUT"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":displayHelp(false,ev);ev.preventDefault();searchState.focus();break;case"+":case"-":ev.preventDefault();toggleAllDocs();break;case"?":displayHelp(true,ev);break;case"t":case"T":displayHelp(false,ev);ev.preventDefault();var themePicker=getThemePickerElement();themePicker.click();themePicker.focus();break;default:if(getThemePickerElement().parentNode.contains(ev.target)){handleThemeKeyDown(ev)}}}}function handleThemeKeyDown(ev){var active=document.activeElement;var themes=getThemesElement();switch(getVirtualKey(ev)){case"ArrowUp":ev.preventDefault();if(active.previousElementSibling&&ev.target.id!==THEME_PICKER_ELEMENT_ID){active.previousElementSibling.focus()}else{showThemeButtonState();themes.lastElementChild.focus()}break;case"ArrowDown":ev.preventDefault();if(active.nextElementSibling&&ev.target.id!==THEME_PICKER_ELEMENT_ID){active.nextElementSibling.focus()}else{showThemeButtonState();themes.firstElementChild.focus()}break;case"Enter":case"Return":case"Space":if(ev.target.id===THEME_PICKER_ELEMENT_ID&&themes.style.display==="none"){ev.preventDefault();showThemeButtonState();themes.firstElementChild.focus()}break;case"Home":ev.preventDefault();themes.firstElementChild.focus();break;case"End":ev.preventDefault();themes.lastElementChild.focus();break}}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);(function(){var x=document.getElementsByClassName("version-selector");if(x.length>0){x[0].onchange=function(){var i,match,url=document.location.href,stripped="",len=window.rootPath.match(/\.\.\//g).length+1;for(i=0;i .in-band > .trait").textContent;var baseIdName="impl-"+traitName+"-";var libs=Object.getOwnPropertyNames(imp);for(var i=0,llength=libs.length;ithe rustdoc book.";var container=document.createElement("div");var shortcuts=[["?","Show this help dialog"],["S","Focus the search field"],["T","Focus the theme picker menu"],["↑","Move up in search results"],["↓","Move down in search results"],["← / →","Switch result tab (when results focused)"],["⏎","Go to active search result"],["+","Expand all sections"],["-","Collapse all sections"],].map(function(x){return"
"+x[0].split(" ").map(function(y,index){return(index&1)===0?""+y+"":" "+y+" "}).join("")+"
"+x[1]+"
"}).join("");var div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

Keyboard Shortcuts

"+shortcuts+"
";var infos=["Prefix searches with a type followed by a colon (e.g., fn:) to \ + restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \ + enum, trait, type, macro, \ + and const.","Search functions by type signature (e.g., vec -> usize or \ + * -> vec)","Search multiple things at once by splitting your query with comma (e.g., \ + str,u8 or String,struct:Vec,test)","You can look for items with an exact name by putting double quotes around \ + your request: \"string\"","Look for items inside another one by searching for a path: vec::Vec",].map(function(x){return"

"+x+"

"}).join("");var div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

Search Tricks

"+infos;container.appendChild(book_info);container.appendChild(div_shortcuts);container.appendChild(div_infos);var rustdoc_version=document.createElement("span");rustdoc_version.className="bottom";var rustdoc_version_code=document.createElement("code");rustdoc_version_code.innerText="rustdoc 1.57.0-nightly (05044c2e6 2021-09-26)";rustdoc_version.appendChild(rustdoc_version_code);container.appendChild(rustdoc_version);popup.appendChild(container);insertAfter(popup,searchState.outputElement());buildHelperPopup=function(){}};onHashChange(null);window.addEventListener("hashchange",onHashChange);searchState.setup()}());(function(){var reset_button_timeout=null;window.copy_path=function(but){var parent=but.parentElement;var path=[];onEach(parent.childNodes,function(child){if(child.tagName==='A'){path.push(child.textContent)}});var el=document.createElement('textarea');el.value=path.join('::');el.setAttribute('readonly','');el.style.position='absolute';el.style.left='-9999px';document.body.appendChild(el);el.select();document.execCommand('copy');document.body.removeChild(el);but.children[0].style.display='none';var tmp;if(but.childNodes.length<2){tmp=document.createTextNode('✓');but.appendChild(tmp)}else{onEachLazy(but.childNodes,function(e){if(e.nodeType===Node.TEXT_NODE){tmp=e;return true}});tmp.textContent='✓'}if(reset_button_timeout!==null){window.clearTimeout(reset_button_timeout)}function reset_button(){tmp.textContent='';reset_button_timeout=null;but.children[0].style.display=""}reset_button_timeout=window.setTimeout(reset_button,1000)}}()) \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/normalize.css b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/normalize.css new file mode 100644 index 0000000000..469959f137 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/normalize.css @@ -0,0 +1,2 @@ + /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ +html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type="button"],[type="reset"],[type="submit"],button{-webkit-appearance:button}[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/noscript.css b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/noscript.css new file mode 100644 index 0000000000..aea68efbc9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/noscript.css @@ -0,0 +1 @@ + #main .attributes{margin-left:0 !important;}#copy-path{display:none;} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/noto-sans-kr-v13-korean-regular-LICENSE.txt b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/noto-sans-kr-v13-korean-regular-LICENSE.txt new file mode 100644 index 0000000000..922d5fdc18 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/noto-sans-kr-v13-korean-regular-LICENSE.txt @@ -0,0 +1,93 @@ +Copyright 2014, 2015 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/noto-sans-kr-v13-korean-regular.woff b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/noto-sans-kr-v13-korean-regular.woff new file mode 100644 index 0000000000..01d6b6b546 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/noto-sans-kr-v13-korean-regular.woff differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/rust-logo.png b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/rust-logo.png new file mode 100644 index 0000000000..74b4bd6950 Binary files /dev/null and b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/rust-logo.png differ diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/rustdoc.css b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/rustdoc.css new file mode 100644 index 0000000000..79235e3d63 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/rustdoc.css @@ -0,0 +1 @@ + @font-face {font-family:'Fira Sans';font-style:normal;font-weight:400;src:local('Fira Sans'),url("FiraSans-Regular.woff2") format("woff2"),url("FiraSans-Regular.woff") format('woff');font-display:swap;}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:500;src:local('Fira Sans Medium'),url("FiraSans-Medium.woff2") format("woff2"),url("FiraSans-Medium.woff") format('woff');font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:400;src:local('Source Serif 4'),url("SourceSerif4-Regular.ttf.woff2") format("woff2"),url("SourceSerif4-Regular.ttf.woff") format("woff");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:italic;font-weight:400;src:local('Source Serif 4 Italic'),url("SourceSerif4-It.ttf.woff2") format("woff2"),url("SourceSerif4-It.ttf.woff") format("woff");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:700;src:local('Source Serif 4 Bold'),url("SourceSerif4-Bold.ttf.woff2") format("woff2"),url("SourceSerif4-Bold.ttf.woff") format("woff");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("SourceCodePro-Regular.ttf.woff2") format("woff2"),url("SourceCodePro-Regular.ttf.woff") format("woff");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:italic;font-weight:400;src:url("SourceCodePro-It.ttf.woff2") format("woff2"),url("SourceCodePro-It.ttf.woff") format("woff");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("SourceCodePro-Semibold.ttf.woff2") format("woff2"),url("SourceCodePro-Semibold.ttf.woff") format("woff");font-display:swap;}@font-face {font-family:'Noto Sans KR';src:url("noto-sans-kr-v13-korean-regular.woff") format("woff");font-display:swap;unicode-range:U+A960-A97F,U+AC00-D7AF,U+D7B0-D7FF;}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}html{content:"";}@media (prefers-color-scheme:light){html{content:"light";}}@media (prefers-color-scheme:dark){html{content:"dark";}}body{font:16px/1.4 "Source Serif 4","Noto Sans KR",serif;margin:0;position:relative;padding:10px 15px 20px 15px;-webkit-font-feature-settings:"kern","liga";-moz-font-feature-settings:"kern","liga";font-feature-settings:"kern","liga";}h1{font-size:1.5em;}h2{font-size:1.4em;}h3{font-size:1.3em;}h1,h2,h3,h4{font-weight:500;margin:20px 0 15px 0;padding-bottom:6px;}h1.fqn{display:flex;border-bottom:1px dashed;margin-top:0;padding-left:1px;}h1.fqn>.in-band>a:hover{text-decoration:underline;}h2,h3,h4{border-bottom:1px solid;}h3.code-header,h4.code-header{font-size:1em;font-weight:600;border:none;padding:0;margin:0;}.impl,.impl-items .method,.methods .method,.impl-items .type,.methods .type,.impl-items .associatedconstant,.methods .associatedconstant,.impl-items .associatedtype,.methods .associatedtype{flex-basis:100%;font-weight:600;margin-top:16px;margin-bottom:10px;position:relative;}.impl,.method.trait-impl,.type.trait-impl,.associatedconstant.trait-impl,.associatedtype.trait-impl{padding-left:15px;}div.impl-items>div{padding-left:0;}h1,h2,h3,h4,.sidebar,a.source,.search-input,.search-results .result-name,.content table td:first-child>a,.item-left>a,div.item-list .out-of-band,span.since,#source-sidebar,#sidebar-toggle,details.rustdoc-toggle>summary::before,details.undocumented>summary::before,div.impl-items>div:not(.docblock):not(.item-info),.content ul.crate a.crate,a.srclink,#main>ul.docblock>li>a{font-family:"Fira Sans",Arial,sans-serif;}.content ul.crate a.crate{font-size:16px/1.6;}ol,ul{padding-left:25px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:.6em;}p{margin:0 0 .6em 0;}summary{outline:none;}td,th{padding:0;}table{border-collapse:collapse;}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0;}details:not(.rustdoc-toggle) summary{margin-bottom:.6em;}code,pre,a.test-arrow,.code-header{font-family:"Source Code Pro",monospace;}.docblock code,.docblock-short code{border-radius:3px;padding:0 0.1em;}.docblock pre code,.docblock-short pre code{padding:0;}pre{padding:14px;}.type-decl pre{overflow-x:auto;}.source .content pre{padding:20px;}img{max-width:100%;}li{position:relative;}.source .content{margin-top:50px;max-width:none;overflow:visible;margin-left:0px;}nav.sub{font-size:16px;text-transform:uppercase;}.sidebar{width:200px;position:fixed;left:0;top:0;bottom:0;overflow:auto;}*{scrollbar-width:initial;}.sidebar{scrollbar-width:thin;}::-webkit-scrollbar{width:12px;}.sidebar::-webkit-scrollbar{width:8px;}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0;}.sidebar .block>ul>li{margin-right:-10px;}.content,nav{max-width:960px;}.hidden{display:none !important;}.logo-container{height:100px;width:100px;position:relative;margin:20px auto;display:block;margin-top:10px;}.logo-container>img{max-width:100px;max-height:100px;height:100%;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);display:block;}.sidebar .location{border:1px solid;font-size:17px;margin:30px 10px 20px 10px;text-align:center;word-wrap:break-word;font-weight:inherit;padding:0;}.sidebar .version{font-size:15px;text-align:center;border-bottom:1px solid;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;}.location:empty{border:none;}.location a:first-of-type{font-weight:500;}.location a:hover{text-decoration:underline;}.block{padding:0;margin-bottom:14px;}.block h2,.block h3{text-align:center;}.block ul,.block li{margin:0 10px;padding:0;list-style:none;}.block a{display:block;text-overflow:ellipsis;overflow:hidden;line-height:15px;padding:7px 5px;font-size:14px;font-weight:300;transition:border 500ms ease-out;}.sidebar-title{border-top:1px solid;border-bottom:1px solid;text-align:center;font-size:17px;margin-bottom:5px;font-weight:inherit;padding:0;}.sidebar-links{margin-bottom:15px;}.sidebar-links>a{padding-left:10px;width:100%;}.sidebar-menu{display:none;}.content{padding:15px 0;}.source .content pre.rust{white-space:pre;overflow:auto;padding-left:0;}.rustdoc .example-wrap{display:inline-flex;margin-bottom:10px;}.example-wrap{position:relative;width:100%;}.example-wrap>pre.line-number{overflow:initial;border:1px solid;padding:13px 8px;text-align:right;border-top-left-radius:5px;border-bottom-left-radius:5px;}.example-wrap>pre.rust a:hover{text-decoration:underline;}.rustdoc:not(.source) .example-wrap>pre:not(.line-number){width:100%;overflow-x:auto;}.rustdoc .example-wrap>pre{margin:0;}#search{margin-left:230px;position:relative;}#results>table{width:100%;table-layout:fixed;}.content>.example-wrap pre.line-numbers{position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}.line-numbers span{cursor:pointer;}.docblock-short{overflow-wrap:anywhere;}.docblock-short p{display:inline;}.docblock-short p{overflow:hidden;text-overflow:ellipsis;margin:0;}.docblock>:not(pre)>code,.docblock-short>:not(pre)>code{white-space:pre-wrap;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom:1px solid;}.top-doc .docblock h1{font-size:1.3em;}.top-doc .docblock h2{font-size:1.15em;}.top-doc .docblock h3,.top-doc .docblock h4,.top-doc .docblock h5{font-size:1em;}.docblock h1{font-size:1em;}.docblock h2{font-size:0.95em;}.docblock h3,.docblock h4,.docblock h5{font-size:0.9em;}.docblock{margin-left:24px;position:relative;}.docblock>*{max-width:100%;overflow-x:auto;}.content .out-of-band{flex-grow:0;text-align:right;font-size:23px;margin:0px;padding:0 0 0 12px;font-weight:normal;}.method>.code-header,.trait-impl>.code-header,.invisible>.code-header{max-width:calc(100% - 41px);display:block;}.invisible{width:100%;display:inline-block;}.content .in-band{flex-grow:1;margin:0px;padding:0px;}.in-band>code,.in-band>.code-header{display:inline-block;}#main{position:relative;}#main>.since{top:inherit;font-family:"Fira Sans",Arial,sans-serif;}.content table:not(.table-display){border-spacing:0 5px;}.content td{vertical-align:top;}.content td:first-child{padding-right:20px;}.content td p:first-child{margin-top:0;}.content td h1,.content td h2{margin-left:0;font-size:1.1em;}.content tr:first-child td{border-top:0;}.docblock table{margin:.5em 0;width:calc(100% - 2px);overflow-x:auto;display:block;}.docblock table td{padding:.5em;border:1px dashed;}.docblock table th{padding:.5em;text-align:left;border:1px solid;}.fields+table{margin-bottom:1em;}.content .item-list{list-style-type:none;padding:0;}.content .multi-column{-moz-column-count:5;-moz-column-gap:2.5em;-webkit-column-count:5;-webkit-column-gap:2.5em;column-count:5;column-gap:2.5em;}.content .multi-column li{width:100%;display:inline-block;}.content>.methods>.method{font-size:1em;position:relative;}.content .method .where,.content .fn .where,.content .where.fmt-newline{display:block;font-size:0.8em;}.content .methods>div:not(.notable-traits):not(.method){margin-left:40px;margin-bottom:15px;}.content .docblock>.impl-items{margin-left:20px;margin-top:-34px;}.content .docblock>.impl-items .table-display{margin:0;}.content .docblock>.impl-items table td{padding:0;}.content .docblock>.impl-items .table-display,.impl-items table td{border:none;}.content .item-info code{font-size:90%;}.content .item-info{position:relative;margin-left:33px;}.sub-variant>div>.item-info{margin-top:initial;}.content .item-info::before{content:'⬑';font-size:25px;position:absolute;top:-6px;left:-19px;}.content .impl-items .method,.content .impl-items>.type,.impl-items>.associatedconstant,.impl-items>.associatedtype,.content .impl-items details>summary>.type,.impl-items details>summary>.associatedconstant,.impl-items details>summary>.associatedtype{margin-left:20px;}.content .impl-items .docblock,.content .impl-items .item-info{margin-bottom:.6em;}.content .impl-items>.item-info{margin-left:40px;}.methods>.item-info,.content .impl-items>.item-info{margin-top:-8px;}.impl-items{flex-basis:100%;}#main>.item-info{margin-top:0;}nav:not(.sidebar){border-bottom:1px solid;padding-bottom:10px;margin-bottom:10px;}nav.main{padding:20px 0;text-align:center;}nav.main .current{border-top:1px solid;border-bottom:1px solid;}nav.main .separator{border:1px solid;display:inline-block;height:23px;margin:0 20px;}nav.sum{text-align:right;}nav.sub form{display:inline;}nav.sub,.content{margin-left:230px;}a{text-decoration:none;background:transparent;}.small-section-header{display:flex;justify-content:space-between;position:relative;}.small-section-header:hover>.anchor{display:initial;}.in-band:hover>.anchor,.impl:hover>.anchor,.method.trait-impl:hover>.anchor,.type.trait-impl:hover>.anchor,.associatedconstant.trait-impl:hover>.anchor,.associatedtype.trait-impl:hover>.anchor{display:inline-block;position:absolute;}.anchor{display:none;position:absolute;left:0;background:none !important;}.anchor.field{left:-5px;}.small-section-header>.anchor{left:-15px;padding-right:8px;}h2.small-section-header>.anchor{padding-right:6px;}.anchor::before{content:'§';}.docblock a:not(.srclink):not(.test-arrow):hover,.docblock-short a:not(.srclink):not(.test-arrow):hover,.item-info a{text-decoration:underline;}.invisible>.srclink,.method>.code-header+.srclink{position:absolute;top:0;right:0;font-size:17px;font-weight:normal;}.block a.current.crate{font-weight:500;}.item-table{display:grid;column-gap:1.2rem;row-gap:0.0rem;grid-template-columns:auto 1fr;justify-items:start;}.item-left,.item-right{display:block;}.item-left{grid-column:1;}.item-right{grid-column:2;}.search-container{position:relative;}.search-container>div{display:inline-flex;width:calc(100% - 63px);}#crate-search{min-width:115px;margin-top:5px;padding:6px;padding-right:19px;flex:none;border:0;border-right:0;border-radius:4px 0 0 4px;outline:none;cursor:pointer;border-right:1px solid;-moz-appearance:none;-webkit-appearance:none;text-indent:0.01px;text-overflow:"";background-repeat:no-repeat;background-color:transparent;background-size:20px;background-position:calc(100% - 1px) 56%;}.search-container>.top-button{position:absolute;right:0;top:10px;}.search-input{-moz-box-sizing:border-box !important;box-sizing:border-box !important;outline:none;border:none;border-radius:1px;margin-top:5px;padding:10px 16px;font-size:17px;transition:border-color 300ms ease;transition:border-radius 300ms ease-in-out;transition:box-shadow 300ms ease-in-out;width:100%;}#crate-search+.search-input{border-radius:0 1px 1px 0;width:calc(100% - 32px);}.search-input:focus{border-radius:2px;border:0;outline:0;}.search-results{display:none;padding-bottom:2em;}.search-results.active{display:block;clear:both;}.search-results .desc>span{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;display:block;}.search-results>a{display:block;width:100%;margin-left:2px;margin-right:2px;border-bottom:1px solid #aaa3;}.search-results>a>div{display:flex;flex-flow:row wrap;}.search-results .result-name,.search-results div.desc,.search-results .result-description{width:50%;}.search-results .result-name{padding-right:1em;}.search-results .result-name>span{display:inline-block;margin:0;font-weight:normal;}body.blur>:not(#help){filter:blur(8px);-webkit-filter:blur(8px);opacity:.7;}#help{width:100%;height:100vh;position:fixed;top:0;left:0;display:flex;justify-content:center;align-items:center;}#help>div{flex:0 0 auto;box-shadow:0 0 6px rgba(0,0,0,.2);width:550px;height:auto;border:1px solid;}#help dt{float:left;clear:left;display:block;margin-right:0.5rem;}#help span.top,#help span.bottom{text-align:center;display:block;font-size:18px;}#help span.top{text-align:center;display:block;margin:10px 0;border-bottom:1px solid;padding-bottom:4px;margin-bottom:6px;}#help span.bottom{clear:both;border-top:1px solid;}#help dd{margin:5px 35px;}#help .infos{padding-left:0;}#help h1,#help h2{margin-top:0;}#help>div div{width:50%;float:left;padding:0 20px 20px 17px;;}.item-info .stab{display:table;}.stab{border-width:1px;border-style:solid;padding:3px;margin-bottom:5px;font-size:90%;font-weight:normal;}.stab p{display:inline;}.stab .emoji{font-size:1.5em;}.emoji{text-shadow:1px 0 0 black,-1px 0 0 black,0 1px 0 black,0 -1px 0 black;}.module-item .stab,.import-item .stab{border-radius:3px;display:inline-block;font-size:80%;line-height:1.2;margin-bottom:0;margin-left:.3em;padding:2px;vertical-align:text-bottom;}.module-item.unstable,.import-item.unstable{opacity:0.65;}.since{font-weight:normal;font-size:initial;}.impl-items .since,.impl .since,.methods .since{padding-left:12px;padding-right:2px;position:initial;}.impl-items .srclink,.impl .srclink,.methods .srclink{font-size:17px;font-weight:normal;}.rightside{float:right;}.has-srclink{font-size:16px;margin-bottom:12px;justify-content:space-between;}.variants_table{width:100%;}.variants_table tbody tr td:first-child{width:1%;}td.summary-column{width:100%;}.summary{padding-right:0px;}pre.rust .question-mark{font-weight:bold;}a.test-arrow{display:inline-block;position:absolute;padding:5px 10px 5px 10px;border-radius:5px;font-size:130%;top:5px;right:5px;z-index:1;}a.test-arrow:hover{text-decoration:none;}.section-header:hover a:before{position:absolute;left:-25px;padding-right:10px;content:'\2002\00a7\2002';}.section-header:hover a{text-decoration:none;}.section-header a{color:inherit;}.code-attribute{font-weight:300;}.since+.srclink{padding-left:10px;}.item-spacer{width:100%;height:12px;}.out-of-band>span.since{position:initial;font-size:20px;margin-right:5px;}.sub-variant,.sub-variant>h3{margin-top:0px !important;padding-top:1px;}#main .sub-variant>h3{font-size:15px;margin-left:25px;margin-bottom:5px;}.sub-variant>div{margin-left:20px;margin-bottom:10px;}.sub-variant>div>span{display:block;position:relative;}.toggle-label{display:inline-block;margin-left:4px;margin-top:3px;}.docblock>.section-header:first-child{margin-left:15px;margin-top:0;}.docblock>.section-header:first-child:hover>a:before{left:-10px;}:target>code,:target>.code-header{opacity:1;}:target{padding-right:3px;}.information{position:absolute;left:-25px;margin-top:7px;z-index:1;}.tooltip{position:relative;display:inline-block;cursor:pointer;}.tooltip::after{display:none;text-align:center;padding:5px 3px 3px 3px;border-radius:6px;margin-left:5px;font-size:16px;}.tooltip.ignore::after{content:"This example is not tested";}.tooltip.compile_fail::after{content:"This example deliberately fails to compile";}.tooltip.should_panic::after{content:"This example panics";}.tooltip.edition::after{content:"This code runs with edition " attr(data-edition);}.tooltip::before{content:" ";position:absolute;top:50%;left:16px;margin-top:-5px;border-width:5px;border-style:solid;display:none;}.tooltip:hover::before,.tooltip:hover::after{display:inline;}.tooltip.compile_fail,.tooltip.should_panic,.tooltip.ignore{font-weight:bold;font-size:20px;}.notable-traits-tooltip{display:inline-block;cursor:pointer;}.notable-traits:hover .notable-traits-tooltiptext,.notable-traits .notable-traits-tooltiptext.force-tooltip{display:inline-block;}.notable-traits .notable-traits-tooltiptext{display:none;padding:5px 3px 3px 3px;border-radius:6px;margin-left:5px;z-index:10;font-size:16px;cursor:default;position:absolute;border:1px solid;}.notable-traits-tooltip::after{content:"\00a0\00a0\00a0";}.notable-traits .notable,.notable-traits .docblock{margin:0;}.notable-traits .notable{margin:0;margin-bottom:13px;font-size:19px;font-weight:600;}.notable-traits .docblock code.content{margin:0;padding:0;font-size:20px;}pre.rust.rust-example-rendered{position:relative;}pre.rust{tab-size:4;-moz-tab-size:4;}.search-failed{text-align:center;margin-top:20px;display:none;}.search-failed.active{display:block;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#titles{height:35px;}#titles>button{float:left;width:33.3%;text-align:center;font-size:18px;cursor:pointer;border:0;border-top:2px solid;}#titles>button:not(:last-child){margin-right:1px;width:calc(33.3% - 1px);}#titles>button>div.count{display:inline-block;font-size:16px;}.notable-traits{cursor:pointer;z-index:2;margin-left:5px;}#all-types{text-align:center;border:1px solid;margin:0 10px;margin-bottom:10px;display:block;border-radius:7px;}#all-types>p{margin:5px 0;}#sidebar-toggle{position:fixed;top:30px;left:300px;z-index:10;padding:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;cursor:pointer;font-weight:bold;transition:left .5s;font-size:1.2em;border:1px solid;border-left:0;}#source-sidebar{position:fixed;top:0;bottom:0;left:0;width:300px;z-index:1;overflow:auto;transition:left .5s;border-right:1px solid;}#source-sidebar>.title{font-size:1.5em;text-align:center;border-bottom:1px solid;margin-bottom:6px;}.theme-picker{position:absolute;left:211px;top:19px;}.theme-picker button{outline:none;}#settings-menu,#help-button{position:absolute;top:10px;}#settings-menu{right:0;outline:none;}#theme-picker,#settings-menu,#help-button,#copy-path{padding:4px;width:27px;height:29px;border:1px solid;border-radius:3px;cursor:pointer;}#help-button{right:30px;font-family:"Fira Sans",Arial,sans-serif;text-align:center;font-size:17px;padding-top:2px;}#copy-path{background:initial;margin-left:10px;padding:0;padding-left:2px;border:0;}#theme-choices{display:none;position:absolute;left:0;top:28px;border:1px solid;border-radius:3px;z-index:1;cursor:pointer;}#theme-choices>button{border:none;width:100%;padding:4px 8px;text-align:center;background:rgba(0,0,0,0);}#theme-choices>button:not(:first-child){border-top:1px solid;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px;border-radius:3px;box-shadow:inset 0 -1px 0;cursor:default;}.hidden-by-impl-hider,.hidden-by-usual-hider{display:none !important;}#implementations-list>h3>span.in-band{width:100%;}.table-display{width:100%;border:0;border-collapse:collapse;border-spacing:0;font-size:16px;}.table-display tr td:first-child{padding-right:0;}.table-display tr td:last-child{float:right;}.table-display .out-of-band{position:relative;font-size:19px;display:block;}#implementors-list>.impl-items .table-display .out-of-band{font-size:17px;}.table-display td:hover .anchor{display:block;top:2px;left:-5px;}#main>ul{padding-left:10px;}#main>ul>li{list-style:none;}.non-exhaustive{margin-bottom:1em;}div.children{padding-left:27px;display:none;}div.name{cursor:pointer;position:relative;margin-left:16px;}div.files>a{display:block;padding:0 3px;}div.files>a:hover,div.name:hover{background-color:#a14b4b;}div.name.expand+.children{display:block;}div.name::before{content:"\25B6";padding-left:4px;font-size:0.7em;position:absolute;left:-16px;top:4px;}div.name.expand::before{transform:rotate(90deg);left:-15px;top:2px;}details.rustdoc-toggle>summary.hideme{cursor:pointer;}details.rustdoc-toggle>summary,details.undocumented>summary{list-style:none;}details.rustdoc-toggle>summary::-webkit-details-marker,details.rustdoc-toggle>summary::marker,details.undocumented>summary::-webkit-details-marker,details.undocumented>summary::marker{display:none;}details.rustdoc-toggle>summary.hideme>span{margin-left:9px;}details.rustdoc-toggle>summary::before{content:"";cursor:pointer;width:17px;height:max(17px,1.1em);background-repeat:no-repeat;background-position:top left;display:inline-block;vertical-align:middle;opacity:.5;}details.rustdoc-toggle>summary::after{content:"Expand";overflow:hidden;width:0;height:0;position:absolute;}details.rustdoc-toggle>summary.hideme::after{content:"";}details.rustdoc-toggle>summary:focus::before,details.rustdoc-toggle>summary:hover::before{opacity:1;}details.rustdoc-toggle.top-doc>summary,details.rustdoc-toggle.top-doc>summary::before,details.rustdoc-toggle.non-exhaustive>summary,details.rustdoc-toggle.non-exhaustive>summary::before{font-family:'Fira Sans';font-size:16px;}details.non-exhaustive{margin-bottom:8px;}details.rustdoc-toggle>summary.hideme::before{position:relative;}details.rustdoc-toggle>summary:not(.hideme)::before{position:absolute;left:-23px;top:3px;}.impl-items>details.rustdoc-toggle>summary:not(.hideme)::before,.undocumented>details.rustdoc-toggle>summary:not(.hideme)::before{position:absolute;left:-2px;}details.rustdoc-toggle[open] >summary.hideme{position:absolute;}details.rustdoc-toggle,details.undocumented{position:relative;}details.rustdoc-toggle[open] >summary.hideme>span{display:none;}details.rustdoc-toggle[open] >summary::before,details.rustdoc-toggle[open] >summary.hideme::before{width:17px;height:max(17px,1.1em);background-repeat:no-repeat;background-position:top left;display:inline-block;content:"";}details.rustdoc-toggle[open] >summary::after,details.rustdoc-toggle[open] >summary.hideme::after{content:"Collapse";}details.undocumented>summary::before{padding-left:17px;height:max(17px,1.1em);background-repeat:no-repeat;background-position:top left;content:"Show hidden undocumented items";cursor:pointer;font-size:16px;font-weight:300;opacity:.5;}details.undocumented>summary:focus::before,details.undocumented>summary:hover::before{opacity:1;}details.undocumented[open] >summary::before{padding-left:17px;height:max(17px,1.1em);background-repeat:no-repeat background-position:top left;content:"Hide undocumented items";}@media (min-width:701px){.docblock>.information:first-child>.tooltip{margin-top:16px;}}@media (max-width:700px){body{padding-top:0px;}.rustdoc>.sidebar{height:45px;min-height:40px;margin:0;margin-left:-15px;padding:0 15px;position:static;z-index:11;}.sidebar>.location{float:right;margin:0px;margin-top:2px;padding:3px 10px 1px 10px;min-height:39px;background:inherit;text-align:left;font-size:24px;}.sidebar .location:empty{padding:0;}.sidebar .logo-container{width:35px;height:35px;margin-top:5px;margin-bottom:5px;float:left;margin-left:50px;}.sidebar .logo-container>img{max-width:35px;max-height:35px;}.sidebar-menu{position:fixed;z-index:10;font-size:2rem;cursor:pointer;width:45px;left:0;text-align:center;display:block;border-bottom:1px solid;border-right:1px solid;height:45px;}.rustdoc.source>.sidebar>.sidebar-menu{display:none;}.sidebar-elems{position:fixed;z-index:1;top:45px;bottom:0;width:246px;left:-246px;overflow-y:auto;border-right:1px solid;}.sidebar>.block.version{overflow:hidden;border-bottom:none;margin-bottom:0;height:100%;padding-left:12px;}.sidebar>.block.version>div.narrow-helper{float:left;width:1px;height:100%;}.sidebar>.block.version>p{margin:0;min-width:55px;display:flex;align-items:center;height:100%;}nav.sub{width:calc(100% - 32px);float:right;}.content{margin-left:0px;}#main,#search{margin-top:45px;padding:0;}#search{margin-left:0;}.anchor{display:none !important;}.theme-picker{left:10px;top:54px;z-index:1;}.notable-traits{position:absolute;left:-22px;top:24px;}#titles>button>div.count{float:left;width:100%;}#titles{height:50px;}.sidebar.mobile{position:fixed;width:100%;margin-left:0;background-color:rgba(0,0,0,0);height:100%;}.sidebar.mobile>div.version{overflow:hidden;max-height:33px;}.sidebar{width:calc(100% + 30px);}.show-it,.sidebar-elems:focus-within{z-index:2;left:0;}.show-it>.block.items{margin:8px 0;}.show-it>.block.items>ul{margin:0;}.show-it>.block.items>ul>li{text-align:center;margin:2px 0;}.show-it>.block.items>ul>li>a{font-size:21px;}#sidebar-filler{position:fixed;left:45px;width:calc(100% - 45px);top:0;height:45px;z-index:-1;border-bottom:1px solid;}#main>details.rustdoc-toggle>summary::before,#main>div>details.rustdoc-toggle>summary::before{left:-11px;}#all-types{margin:10px;}#sidebar-toggle{top:100px;width:30px;font-size:1.5rem;text-align:center;padding:0;}#source-sidebar{z-index:11;}#main>.line-numbers{margin-top:0;}.notable-traits .notable-traits-tooltiptext{left:0;top:100%;}#help-button{display:none;}.item-table{display:flex;flex-flow:column wrap;}.item-left,.item-right{width:100%;}.search-container>div{width:calc(100% - 32px);}.search-results>a{border-bottom:1px solid #aaa9;padding:5px 0px;}.search-results .result-name,.search-results div.desc,.search-results .result-description{width:100%;}.search-results div.desc,.search-results .result-description,.item-right{padding-left:2em;}}@media print{nav.sub,.content .out-of-band{display:none;}}@media (max-width:464px){#titles,#titles>button{height:73px;}#main,#search{margin-top:100px;}#main>table:not(.table-display) td{word-break:break-word;width:50%;}.search-container>div{display:block;width:calc(100% - 37px);}#crate-search{width:100%;border-radius:4px;border:0;}#crate-search+.search-input{width:calc(100% + 71px);margin-left:-36px;}#theme-picker,#settings-menu{padding:5px;width:31px;height:31px;}#theme-picker{margin-top:-2px;}#settings-menu{top:7px;}.docblock{margin-left:12px;}}details.undocumented[open] >summary::before,details.rustdoc-toggle[open] >summary::before,details.rustdoc-toggle[open] >summary.hideme::before{background-image:url(toggle-minus.svg);}details.undocumented>summary::before,details.rustdoc-toggle>summary::before{background-image:url(toggle-plus.svg);} \ 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 new file mode 100644 index 0000000000..48240e03f9 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/search-index.js @@ -0,0 +1,4 @@ +var searchIndex = JSON.parse('{\ +"bdk":{"doc":"A modern, lightweight, descriptor-based wallet library …","t":[13,13,13,13,13,13,3,13,13,13,4,13,13,3,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,4,13,3,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,3,13,13,4,8,3,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,14,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,14,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,0,11,11,11,11,11,11,11,11,12,11,12,12,12,11,11,11,11,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,12,11,12,11,11,11,11,11,11,11,11,12,10,12,5,11,11,11,11,11,11,11,11,0,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,12,12,12,12,12,12,12,12,12,12,13,8,4,16,8,3,13,13,3,3,8,6,0,11,11,11,11,11,11,10,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,0,11,0,10,11,11,11,11,10,10,11,10,10,11,11,11,11,11,11,11,5,5,5,10,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,4,4,13,13,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,13,3,3,3,4,13,13,13,13,13,13,13,13,3,13,13,13,3,13,13,13,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,12,11,11,11,11,11,12,12,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,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,12,11,11,12,12,12,11,11,11,11,11,11,11,12,11,11,13,3,3,4,3,13,13,13,13,13,13,13,13,13,13,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,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,12,12,12,12,16,8,8,16,8,8,3,0,10,11,11,11,10,11,10,11,12,10,11,10,11,10,11,10,11,10,11,10,11,11,11,11,10,11,11,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,11,11,10,11,10,11,10,11,10,11,0,11,12,10,11,10,11,10,11,10,11,10,11,11,11,11,11,4,4,4,13,13,13,13,13,13,3,13,13,13,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,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,12,12,12,12,12,12,12,12,12,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,13,6,3,4,6,8,6,8,6,4,3,13,8,4,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,10,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,12,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,10,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,11,11,11,11,11,11,11,11,11,0,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,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,12,12,5,13,13,13,4,13,13,13,13,13,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,13,13,13,4,13,3,6,6,13,13,13,13,13,13,13,13,13,13,13,3,3,4,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,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,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,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,3,3,3,3,3,3,8,6,3,3,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,8,4,4,4,3,3,16,16,8,4,8,8,3,8,13,13,13,4,6,13,13,13,16,13,3,13,8,4,13,13,13,3,6,13,13,5,10,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,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,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,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,10,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,12,12,12,11,5,11,10,11,11,5,11,11,11,11,12,12,11,11,11,11,11,11,12,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,11,11,11,11,11,11,11,11,11,11,11,11,11,11,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,13,13,13,13,13,13,13,4,3,4,6,3,13,13,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,4,3,8,13,13,13,13,3,11,11,12,0,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,5,11,11,12,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,0,11,0,11,11,11,11,11,11,11,0,11,11,11,11,11,11,12,12,8,4,13,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,12,3,8,3,6,3,11,11,11,11,11,11,11,11,10,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,11,11,11,11,11,11,11,3,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,12,13,13,13,13,13,13,13,13,13,13,13,13,3,8,4,4,3,3,13,11,12,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,10,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,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,5,13,3,13,13,4,3,13,13,3,8,4,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11],"n":["AddressValidator","Bip32","BnBNoExactMatch","BnBTotalTriesExceeded","ChecksumMismatch","CompactFilters","ConfirmationTime","Descriptor","Electrum","Encode","Error","Esplora","External","FeeRate","FeeRateTooLow","FeeRateUnavailable","FeeTooLow","Foreign","Generic","Hex","InsufficientFunds","Internal","InvalidNetwork","InvalidOutpoint","InvalidPolicyPathError","InvalidProgressValue","InvalidU32Bytes","IrreplaceableTransaction","Json","Key","KeychainKind","Local","LocalUtxo","Miniscript","MissingKeyOrigin","NoRecipients","NoUtxosSelected","OutputBelowDustLimit","ProgressUpdateError","Psbt","PsbtParse","Rusqlite","ScriptDoesntHaveAddressForm","Secp256k1","Signer","Sled","SpendingPolicyRequired","TransactionConfirmed","TransactionDetails","TransactionNotFound","UnknownUtxo","Utxo","Vbytes","WeightedUtxo","as_byte","as_fail","as_ref","as_sat_vb","base32_len","blockchain","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","check_base32","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","confirmation_time","database","default","default","default","default_min_relay_fee","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","descriptor","descriptor","deserialize","deserialize","deserialize","deserialize","drop","drop","drop","drop","drop","drop","drop","drop","eq","eq","eq","eq","eq","eq","eq","fee","fee_vb","fee_wu","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fragment","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_btc_per_kvb","from_sat_per_vb","from_vb","from_wu","get_hash","get_hash","hash","hash","height","init","init","init","init","init","init","init","init","into","into","into","into","into","into","into","into","into_descriptor_key","into_extended_key","into_wallet_descriptor","into_wallet_descriptor","keychain","keys","ne","ne","ne","ne","ne","ne","new","outpoint","outpoint","partial_cmp","received","satisfaction_weight","sent","serialize","serialize","serialize","serialize","sub","timestamp","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","transaction","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","txid","txout","txout","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","utxo","vbytes","verified","version","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","wallet","write_base32","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","available","found","needed","requested","required","required","0","outpoint","psbt_input","AccurateFees","Blockchain","Capability","Config","ConfigurableBlockchain","EsploraBlockchain","FullHistory","GetAnyTx","LogProgress","NoopProgress","Progress","ProgressData","any","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","broadcast","clone","clone","clone","clone_into","clone_into","clone_into","compact_filters","deref","deref","deref","deref_mut","deref_mut","deref_mut","drop","drop","drop","electrum","eq","esplora","estimate_fee","fmt","from","from","from","from_config","get_capabilities","get_hash","get_height","get_tx","hash","init","init","init","into","into","into","log_progress","noop_progress","progress","setup","sync","to_owned","to_owned","to_owned","try_from","try_from","try_from","try_into","try_into","try_into","type_id","type_id","type_id","update","update","update","vzip","vzip","vzip","AnyBlockchain","AnyBlockchainConfig","CompactFilters","CompactFilters","Electrum","Electrum","Esplora","Esplora","borrow","borrow","borrow_mut","borrow_mut","broadcast","clone","clone_into","deref","deref","deref_mut","deref_mut","deserialize","drop","drop","eq","estimate_fee","fmt","from","from","from","from","from","from","from","from","from_config","get_capabilities","get_height","get_tx","init","init","into","into","ne","serialize","setup","sync","to_owned","try_from","try_from","try_into","try_into","type_id","type_id","vzip","vzip","0","0","0","0","0","0","Bip158","BitcoinPeerConfig","CompactFiltersBlockchain","CompactFiltersBlockchainConfig","CompactFiltersError","DataCorruption","Db","Global","InvalidFilter","InvalidFilterHeader","InvalidHeaders","InvalidResponse","Io","Mempool","MissingBlock","NoPeers","NotConnected","Peer","PeerBloomDisabled","Time","Timeout","add_tx","address","as_fail","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","broadcast","clone","clone","clone_into","clone_into","connect","connect_proxy","default","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","deserialize","drop","drop","drop","drop","drop","drop","eq","eq","estimate_fee","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from_config","get_capabilities","get_height","get_mempool","get_network","get_tx","get_tx","get_version","has_tx","init","init","init","init","init","init","into","into","into","into","into","into","is_connected","iter_txs","ne","ne","network","new","new","peers","recv","send","serialize","serialize","setup","skip_blocks","socks5","socks5_credentials","storage_dir","to_owned","to_owned","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","0","0","0","0","0","ElectrumBlockchain","ElectrumBlockchainConfig","borrow","borrow","borrow_mut","borrow_mut","broadcast","clone","clone_into","deref","deref","deref_mut","deref_mut","deserialize","drop","drop","eq","estimate_fee","fmt","from","from","from","from_config","get_capabilities","get_height","get_tx","init","init","into","into","ne","retry","serialize","setup","socks5","stop_gap","timeout","to_owned","try_from","try_from","try_into","try_into","type_id","type_id","url","vzip","vzip","BitcoinEncoding","EsploraBlockchain","EsploraBlockchainConfig","EsploraError","EsploraGetHistory","HeaderHashNotFound","HeaderHeightNotFound","Hex","HttpResponse","Io","NoHeader","Parsing","TransactionNotFound","Ureq","UreqTransport","as_fail","base_url","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","broadcast","clone","clone_into","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","deserialize","drop","drop","drop","drop","eq","estimate_fee","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from_config","get_capabilities","get_height","get_tx","init","init","init","init","into","into","into","into","ne","new","proxy","serialize","setup","stop_gap","timeout_read","timeout_write","to_owned","to_string","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","with_agent","0","0","0","0","0","0","0","0","0","0","Batch","BatchDatabase","BatchOperations","Config","ConfigurableDatabase","Database","SqliteDatabase","any","begin_batch","begin_batch","borrow","borrow_mut","check_descriptor_checksum","check_descriptor_checksum","commit_batch","commit_batch","connection","del_last_index","del_last_index","del_path_from_script_pubkey","del_path_from_script_pubkey","del_raw_tx","del_raw_tx","del_script_pubkey_from_path","del_script_pubkey_from_path","del_tx","del_tx","del_utxo","del_utxo","deref","deref_mut","drop","flush","flush","fmt","from","from_config","from_config","get_last_index","get_last_index","get_path_from_script_pubkey","get_path_from_script_pubkey","get_raw_tx","get_raw_tx","get_script_pubkey_from_path","get_script_pubkey_from_path","get_tx","get_tx","get_utxo","get_utxo","increment_last_index","increment_last_index","init","into","iter_raw_txs","iter_raw_txs","iter_script_pubkeys","iter_script_pubkeys","iter_txs","iter_txs","iter_utxos","iter_utxos","memory","new","path","set_last_index","set_last_index","set_raw_tx","set_raw_tx","set_script_pubkey","set_script_pubkey","set_tx","set_tx","set_utxo","set_utxo","try_from","try_into","type_id","vzip","AnyBatch","AnyDatabase","AnyDatabaseConfig","Memory","Memory","Memory","Sled","Sled","Sled","SledDbConfiguration","Sqlite","Sqlite","Sqlite","SqliteDbConfiguration","begin_batch","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","check_descriptor_checksum","commit_batch","del_last_index","del_last_index","del_path_from_script_pubkey","del_path_from_script_pubkey","del_raw_tx","del_raw_tx","del_script_pubkey_from_path","del_script_pubkey_from_path","del_tx","del_tx","del_utxo","del_utxo","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","deserialize","deserialize","drop","drop","drop","drop","drop","flush","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_config","get_last_index","get_path_from_script_pubkey","get_raw_tx","get_script_pubkey_from_path","get_tx","get_utxo","increment_last_index","init","init","init","init","init","into","into","into","into","into","iter_raw_txs","iter_script_pubkeys","iter_txs","iter_utxos","path","path","serialize","serialize","serialize","set_last_index","set_last_index","set_raw_tx","set_raw_tx","set_script_pubkey","set_script_pubkey","set_tx","set_tx","set_utxo","set_utxo","tree_name","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","0","0","0","0","0","0","0","0","0","MemoryDatabase","begin_batch","borrow","borrow_mut","check_descriptor_checksum","commit_batch","default","del_last_index","del_path_from_script_pubkey","del_raw_tx","del_script_pubkey_from_path","del_tx","del_utxo","deref","deref_mut","drop","flush","fmt","from","from_config","get_last_index","get_path_from_script_pubkey","get_raw_tx","get_script_pubkey_from_path","get_tx","get_utxo","increment_last_index","init","into","iter_raw_txs","iter_script_pubkeys","iter_txs","iter_utxos","new","set_last_index","set_raw_tx","set_script_pubkey","set_tx","set_utxo","try_from","try_into","type_id","vzip","Bare","DerivedDescriptor","DerivedDescriptorKey","Descriptor","ExtendedDescriptor","ExtractPolicy","HdKeyPaths","IntoWalletDescriptor","KeyMap","Legacy","Miniscript","Pkh","ScriptContext","Segwitv0","Sh","Wpkh","Wsh","address","as_enum","as_enum","as_inner","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","branches","check_global_consensus_validity","check_global_consensus_validity","check_global_consensus_validity","check_global_policy_validity","check_global_policy_validity","check_global_validity","check_local_consensus_validity","check_local_consensus_validity","check_local_consensus_validity","check_local_policy_validity","check_local_policy_validity","check_local_policy_validity","check_local_validity","check_terminal_non_malleable","check_terminal_non_malleable","check_terminal_non_malleable","check_witness","check_witness","check_witness","checksum","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","cmp","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","derive","desc_type","deserialize","deserialize","drop","drop","drop","drop","drop","encode","eq","eq","eq","eq","eq","error","explicit_script","ext","extract_policy","extract_policy","extract_policy","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","for_each_key","for_each_key","from","from","from","from","from","from_ast","from_str","from_str","from_str_insane","from_tree","from_tree","get_hash","get_hash","get_hash","get_hash","get_hash","get_leaf_pk","get_leaf_pk_pkh","get_leaf_pkh","get_nth_child","get_nth_pk","get_nth_pk_pkh","get_nth_pkh","get_satisfaction","has_mixed_timelocks","has_repeated_keys","hash","hash","hash","hash","hash","hash_to_hash160","init","init","init","init","init","into","into","into","into","into","into_inner","into_wallet_descriptor","is_deriveable","is_non_malleable","is_uncompressed","iter","iter_pk","iter_pk_pkh","iter_pkh","lift","lift","lift_check","max_satisfaction_size","max_satisfaction_size","max_satisfaction_size","max_satisfaction_size","max_satisfaction_weight","max_satisfaction_witness_elements","ne","new","new_bare","new_pk","new_pkh","new_sh","new_sh_sortedmulti","new_sh_wpkh","new_sh_wsh","new_sh_wsh_sortedmulti","new_wpkh","new_wsh","new_wsh_sortedmulti","node","other_top_level_checks","parse","parse_descriptor","parse_insane","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","policy","requires_sig","sanity_check","sanity_check","satisfy","satisfy_malleable","script_code","script_pubkey","script_size","serialize","serialize","serialized_len","template","to_owned","to_owned","to_owned","to_owned","to_owned","to_pubkeyhash","to_public_key","to_string","to_string","to_string","to_string_with_secret","top_level_checks","top_level_type_check","translate_pk","translate_pk","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","ty","type_id","type_id","type_id","type_id","type_id","unsigned_script_sig","vzip","vzip","vzip","vzip","vzip","within_resource_limits","0","0","0","0","0","get_checksum","Base58","Bip32","DuplicatedKeys","Error","HardenedDerivationXpub","Hex","InvalidDescriptorCharacter","InvalidDescriptorChecksum","InvalidHdKeyPath","Key","Miniscript","Pk","Policy","as_fail","borrow","borrow_mut","deref","deref_mut","drop","fmt","fmt","from","from","from","from","from","from","from","from","init","into","to_string","try_from","try_into","type_id","vzip","0","0","0","0","0","0","0","0","AbsoluteTimelock","AddOnLeaf","AddOnPartialComplete","BuildSatisfaction","Complete","Condition","ConditionMap","FoldedConditionMap","Hash160Preimage","Hash256Preimage","IncompatibleConditions","IndexOutOfRange","MixedTimelockUnits","Multisig","None","None","NotEnoughItemsSelected","Partial","PartialComplete","PkOrF","Policy","PolicyError","Psbt","PsbtTimelocks","RelativeTimelock","Ripemd160Preimage","Satisfaction","SatisfiableItem","Sha256Preimage","Signature","SignatureKey","Thresh","as_fail","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","cmp","contribution","csv","default","default","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","drop","drop","drop","drop","drop","drop","drop","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","get_condition","get_hash","hash","id","id","init","init","init","init","init","init","init","into","into","into","into","into","into","into","is_leaf","is_leaf","is_null","item","ne","ne","partial_cmp","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","0","current_height","input_max_height","psbt","0","0","condition","conditions","conditions","items","items","m","m","n","n","sorted","sorted","0","0","hash","hash","hash","hash","items","keys","threshold","threshold","value","value","0","0","0","0","0","0","0","0","0","1","1","1","1","1","1","2","2","2","Bip44","Bip44Public","Bip49","Bip49Public","Bip84","Bip84Public","DescriptorTemplate","DescriptorTemplateOut","P2Pkh","P2Wpkh","P2Wpkh_P2Sh","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build","build","build","build","build","build","build","build","build","build","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","drop","drop","drop","drop","drop","drop","drop","drop","drop","from","from","from","from","from","from","from","from","from","init","init","init","init","init","init","init","init","init","into","into","into","into","into","into","into","into","into","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","Bip32","DerivableKey","DescriptorKey","DescriptorPublicKey","DescriptorSecretKey","DescriptorSinglePriv","DescriptorSinglePub","Entropy","Error","ExtScriptContext","ExtendedKey","GeneratableDefaultOptions","GeneratableKey","GeneratedKey","IntoDescriptorKey","InvalidChecksum","InvalidNetwork","InvalidScriptContext","KeyError","KeyMap","Legacy","Message","Miniscript","Options","Private","PrivateKeyGenerateOptions","Public","ScriptContext","ScriptContextEnum","Segwitv0","SinglePriv","SinglePub","SortedMultiVec","ValidNetworks","XPrv","XPub","any_network","as_enum","as_fail","as_public","bip39","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","check_global_consensus_validity","check_global_consensus_validity","check_global_policy_validity","check_global_policy_validity","check_global_validity","check_global_validity","check_local_consensus_validity","check_local_consensus_validity","check_local_policy_validity","check_local_policy_validity","check_local_validity","check_local_validity","check_terminal_non_malleable","check_witness","check_witness","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","compressed","default","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","derive","derive_public_key","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","encode","eq","eq","eq","eq","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_public","from_secret","from_str","from_str","from_tree","full_derivation_path","generate","generate_default","generate_with_entropy","generate_with_entropy_default","get_hash","get_hash","get_hash","has_secret","hash","hash","hash","init","init","init","init","init","init","init","init","init","init","init","into","into","into","into","into","into","into","into","into","into","into","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_extended_key","into_extended_key","into_extended_key","into_key","into_xprv","into_xpub","is_deriveable","is_legacy","is_legacy","is_segwit_v0","is_segwit_v0","is_uncompressed","k","key","key","lift","mainnet_network","master_fingerprint","max_satisfaction_size","max_satisfaction_size","max_satisfaction_witness_elements","merge_networks","ne","ne","ne","new","origin","origin","other_top_level_checks","other_top_level_checks","override_valid_networks","partial_cmp","partial_cmp","partial_cmp","pks","sanity_check","satisfy","script_size","sorted_node","test_networks","to_owned","to_owned","to_owned","to_owned","to_owned","to_pubkeyhash","to_string","to_string","to_string","to_string","top_level_checks","top_level_checks","top_level_type_check","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_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","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","0","0","0","0","0","0","0","0","0","ChineseSimplified","ChineseTraditional","English","French","Italian","Japanese","Korean","Language","Mnemonic","MnemonicType","MnemonicWithPassphrase","Seed","Spanish","Words12","Words15","Words18","Words21","Words24","as_bytes","as_ref","as_ref","base32_len","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","check_base32","checksum_bits","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","default","default","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","drop","drop","drop","drop","entropy","entropy_bits","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","for_key_size","for_phrase","for_word_count","from","from","from","from","from_entropy","from_language_code","from_phrase","generate_with_entropy","init","init","init","init","into","into","into","into","into_descriptor_key","into_descriptor_key","into_extended_key","into_extended_key","into_phrase","language","new","new","phrase","to_hex","to_hex","to_owned","to_owned","to_owned","to_owned","to_string","to_string","total_bits","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","validate","vzip","vzip","vzip","vzip","word_count","wordlist","wordmap","write_base32","AddressIndex","AddressInfo","IsDust","LastUnused","New","Peek","Reset","Wallet","add_address_validator","add_signer","address","address_validator","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","broadcast","build_fee_bump","build_tx","client","coin_selection","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","drop","drop","drop","eq","export","finalize_psbt","fmt","fmt","fmt","fmt","from","from","from","get_address","get_balance","get_descriptor_for_keychain","get_funded_wallet","get_psbt_input","get_utxo","index","init","init","init","into","into","into","is_dust","is_mine","list_transactions","list_unspent","ne","network","new","new_offline","policies","public_descriptor","secp_ctx","sign","signer","sync","time","to_string","try_from","try_from","try_from","try_into","try_into","try_into","tx_builder","type_id","type_id","type_id","vzip","vzip","vzip","0","0","AddressValidator","AddressValidatorError","ConnectionError","InvalidScript","Message","TimeoutError","UserRejected","as_fail","borrow","borrow_mut","clone","clone_into","deref","deref_mut","drop","eq","fmt","fmt","from","init","into","ne","to_owned","to_string","try_from","try_into","type_id","validate","vzip","0","BranchAndBoundCoinSelection","CoinSelectionAlgorithm","CoinSelectionResult","DefaultCoinSelectionAlgorithm","LargestFirstCoinSelection","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","clone","clone_into","coin_select","coin_select","coin_select","default","default","deref","deref","deref","deref_mut","deref_mut","deref_mut","drop","drop","drop","fee_amount","fmt","fmt","fmt","from","from","from","init","init","init","into","into","into","local_selected_amount","new","selected","selected_amount","to_owned","try_from","try_from","try_from","try_into","try_into","try_into","type_id","type_id","type_id","vzip","vzip","vzip","WalletExport","blockheight","borrow","borrow_mut","change_descriptor","deref","deref_mut","descriptor","deserialize","drop","export_wallet","fmt","from","from_str","init","into","label","serialize","to_string","try_from","try_into","type_id","vzip","0","Dummy","Fingerprint","InputIndexOutOfRange","InvalidKey","InvalidNonWitnessUtxo","MissingHdKeypath","MissingKey","MissingNonWitnessUtxo","MissingWitnessScript","MissingWitnessUtxo","NonStandardSighash","PkHash","SignOptions","Signer","SignerError","SignerId","SignerOrdering","SignersContainer","UserCanceled","add_external","allow_all_sighashes","as_fail","as_key_map","assume_height","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","default","default","default","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","descriptor_secret_key","drop","drop","drop","drop","drop","eq","eq","eq","find","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","get_hash","hash","id","ids","init","init","init","init","init","into","into","into","into","into","ne","ne","new","partial_cmp","partial_cmp","remove","sign","sign_whole_tx","signers","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","trust_witness_utxo","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","0","0","0","get_timestamp","Bip69Lexicographic","BumpFee","ChangeAllowed","ChangeForbidden","ChangeSpendPolicy","CreateTx","OnlyChange","Shuffle","TxBuilder","TxBuilderContext","TxOrdering","Untouched","add_foreign_utxo","add_global_xpubs","add_recipient","add_unspendable","add_utxo","add_utxos","allow_shrinking","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","change_policy","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","coin_selection","default","default","default","default","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","do_not_spend_change","drain_to","drain_wallet","drop","drop","drop","drop","drop","enable_rbf","enable_rbf_with_sequence","eq","eq","fee_absolute","fee_rate","finish","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","get_hash","get_hash","hash","hash","include_output_redeem_witness_script","init","init","init","init","init","into","into","into","into","into","manually_selected_only","nlocktime","only_spend_change","only_witness_utxo","ordering","partial_cmp","partial_cmp","policy_path","set_recipients","sighash","sort_tx","to_owned","to_owned","to_owned","to_owned","to_owned","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","unspendable","version","vzip","vzip","vzip","vzip","vzip"],"q":["bdk","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::Error","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::Utxo","","","bdk::blockchain","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::blockchain::any","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::blockchain::any::AnyBlockchain","","","bdk::blockchain::any::AnyBlockchainConfig","","","bdk::blockchain::compact_filters","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::blockchain::compact_filters::CompactFiltersError","","","","","bdk::blockchain::electrum","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::blockchain::esplora","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::blockchain::esplora::EsploraError","","","","","","","","","","bdk::database","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::database::any","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::database::any::AnyBatch","","","bdk::database::any::AnyDatabase","","","bdk::database::any::AnyDatabaseConfig","","","bdk::database::memory","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::Descriptor","","","","","bdk::descriptor::checksum","bdk::descriptor::error","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::error::Error","","","","","","","","bdk::descriptor::policy","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::policy::BuildSatisfaction","","","","bdk::descriptor::policy::PolicyError","","bdk::descriptor::policy::Satisfaction","","","","","","","","","","","bdk::descriptor::policy::SatisfiableItem","","","","","","","","","","","","bdk::descriptor::template","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::keys","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::keys::DescriptorPublicKey","","bdk::keys::DescriptorSecretKey","","bdk::keys::ExtendedKey","","bdk::keys::KeyError","","","bdk::keys::bip39","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::AddressIndex","","bdk::wallet::address_validator","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::address_validator::AddressValidatorError","bdk::wallet::coin_selection","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::export","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::signer","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::signer::SignerId","","","bdk::wallet::time","bdk::wallet::tx_builder","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"d":["Error that can be returned to fail the validation of an …","BIP32 error","Branch and bound coin selection tries to avoid needing a …","Branch and bound coin selection possible attempts with …","Descriptor checksum mismatch","Compact filters client error)","Block height and timestamp of the block containing the …","Error related to the parsing and usage of descriptors","Electrum client error","Encoding error","Errors that can be thrown by the Wallet","Esplora client error","External","Fee rate","When bumping a tx the fee rate requested is lower than …","Node doesn’t have data to estimate a fee rate","When bumping a tx the absolute fee requested is lower than …","A UTXO owned by another wallet.","Generic error","Hex decoding error","Wallet’s UTXO set is not enough to cover recipient’s …","Internal, usually used for change outputs","Invalid network","Requested outpoint doesn’t exist in the tx (vout greater …","Error while extracting and manipulating policies","Progress value must be between 0.0 (included) and 100.0 …","Wrong number of bytes found when trying to convert to u32","Trying to replace a tx that has a sequence >= 0xFFFFFFFE","Error serializing or deserializing JSON data","Error while working with keys","Types of keychains","A UTXO owned by the local wallet.","An unspent output owned by a Wallet.","Miniscript error","In order to use the TxBuilder::add_global_xpubs option …","Cannot build a tx without recipients","manually_selected_only option is selected but no utxo has …","Output created is under the dust limit, 546 satoshis","Progress update error (maybe the channel has been closed)","Partially signed bitcoin transaction error","Partially signed bitcoin transaction parseerror","Rusqlite client error","This error is thrown when trying to convert Bare and …","An ECDSA error","Signing error","Sled database error","Spending policy is not compatible with this KeychainKind","Happens when trying to bump a transaction that is already …","A wallet transaction","Thrown when a tx is not found in the internal database","Happens when trying to spend an UTXO that is not in the …","An unspent transaction output (UTXO).","Trait implemented by types that can be used to measure …","A Utxo with its satisfaction_weight.","Return KeychainKind as a byte","","","Return the value as satoshi/vbyte","","Blockchain backends","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","If the transaction is confirmed, contains height and …","Database types","","","","Create a new FeeRate with the default min relay fee value","","","","","","","","","","","","","","","","","Descriptors","Macro to write full descriptors with code","","","","","","","","","","","","","","","","","","","","Fee value (sats) if available. The availability of the fee …","Calculate absolute fee in Satoshis using size in virtual …","Calculate absolute fee in Satoshis using size in weight …","","","","","","","","","","Macro to write descriptor fragments with code","","","","","","","","","","","","","","","","","","","","","","","","","","","Create a new instance of FeeRate given a float fee rate in …","Create a new instance of FeeRate given a float fee rate in …","Calculate fee rate from fee and vbytes.","Calculate fee rate from fee and weight units (wu).","","","","","confirmation block height","","","","","","","","","","","","","","","","","","","","","Type of keychain","Key formats","","","","","","","Returns Some ConfirmationTime if both height and timestamp …","Get the location of the UTXO","Reference to a transaction output","","Received value (sats)","The weight of the witness data and scriptSig expressed in …","Sent value (sats)","","","","","","confirmation block timestamp","","","","","","","","","Optional transaction","","","","","","","","","","","","","","","","","Transaction id","Get the TxOut of the UTXO","Transaction output","","","","","","","","","The UTXO","Convert weight units to virtual bytes.","Whether the tx has been verified against the consensus …","Get the version of BDK at runtime","","","","","","","","","Wallet","","","","","","","","","","","","","","","","","","","","","","","","","","","Sats available for spending","found network, for example the network of the bitcoin node","Sats needed for some transaction","requested network, for example what is given as bdk-cli …","Required fee rate (satoshi/vbyte)","Required fee absolute value (satoshi)","","The location of the output.","The information about the input we require to add it to a …","Can compute accurate fees for the transactions found …","Trait that defines the actions that must be supported by a …","Capabilities that can be supported by a Blockchain backend","Type that contains the configuration","Trait for Blockchain types that can be created given a …","Structure that implements the logic to sync with Esplora","Can recover the full history of a wallet and not only the …","Can fetch any historical transaction given its txid","Type that implements Progress and logs at level INFO every …","Type that implements Progress and drops every update …","Trait for types that can receive and process progress …","Data sent with a progress update over a channel","Runtime-checked blockchain types","","","","","","","Broadcast a transaction","","","","","","","Compact Filters","","","","","","","","","","Electrum","","Esplora","Estimate the fee rate required to confirm a transaction in …","","","","","Create a new instance given a configuration","Return the set of Capability supported by this backend","","Return the current height","Fetch a transaction from the blockchain given its txid","","","","","","","","Create a new instance of LogProgress","Create a new instance of NoopProgress","Shortcut to create a channel (pair of Sender and Receiver) …","Setup the backend and populate the internal database for …","Populate the internal database with transactions and UTXOs","","","","","","","","","","","","","Send a new progress update","","","","","","Type that can contain any of the Blockchain types defined …","Type that can contain any of the blockchain configurations …","Compact filters client","Compact filters client","Electrum client","Electrum client","Esplora client","Esplora client","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Invalid BIP158 filter","Data to connect to a Bitcoin P2P peer","Structure implementing the required blockchain traits","Configuration for a CompactFiltersBlockchain","An error that can occur during sync with a …","The data stored in the block filters storage are corrupted","Internal database error","Wrapper for crate::error::Error","The compact filter returned is invalid","The compact filter headers returned are invalid","The headers returned are invalid","A peer sent an invalid or unexpected response","Internal I/O error","Container for unconfirmed, but valid Bitcoin transactions","The peer is missing a block in the valid chain","No peers have been specified","A peer is not connected","A Bitcoin peer","The peer doesn’t advertise the BLOOM service flag","Internal system time error","A peer took too long to reply to one of our messages","Add a transaction to the mempool","Peer address such as 127.0.0.1:18333","","","","","","","","","","","","","","","","","","","Connect to a peer over a plaintext TCP connection","Connect to a peer through a SOCKS5 proxy, optionally by …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Return the mempool used by this peer","Return the Bitcoin Network in use","Look-up a transaction in the mempool given an Inventory …","","Return the VersionMessage sent by the peer","Return whether or not the mempool contains a transaction …","","","","","","","","","","","","","Return whether or not the peer is still connected","Return the list of transactions contained in the mempool","","","Network used","Create a new empty mempool","Construct a new instance given a list of peers, a path to …","List of peers to try to connect to for asking headers and …","Waits for a specific incoming Bitcoin message, optionally …","Send a raw Bitcoin message to the peer","","","","Optionally skip initial skip_blocks blocks (default: 0)","Optional socks5 proxy","Optional socks5 proxy credentials","Storage dir to save partially downloaded headers and full …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Wrapper over an Electrum Client that implements the …","Configuration for an ElectrumBlockchain","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Request retry count","","","URL of the socks5 proxy server or a Tor service","Stop searching addresses for transactions after finding an …","Request timeout (seconds)","","","","","","","","URL of the Electrum server (such as ElectrumX, Esplora, …","","","Invalid Bitcoin data returned","Structure that implements the logic to sync with Esplora","Configuration for an EsploraBlockchain","Errors that can happen during a sync with EsploraBlockchain","Data type used when fetching transaction history from …","Header hash not found","Header height not found","Invalid Hex data returned","HTTP response error","IO error during ureq response read","No header found in ureq response","Invalid number returned","Transaction not found","Error during ureq HTTP request","Transport error during the ureq HTTP call","","Base URL of the esplora service eg. …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Create a new instance of the client from a base URL and …","Optional URL of the proxy to use to make requests to the …","","","Stop searching addresses for transactions after finding an …","Socket read timeout.","Socket write timeout.","","","","","","","","","","","","","","","","","","","Set the inner ureq agent.","","","","","","","","","","","Container for the operations","Trait for a database that supports batch operations","Trait for operations that can be batched","Type that contains the configuration","Trait for Database types that can be created given a …","Trait for reading data from a database","Sqlite database stored on filesystem","Runtime-checked database types","Create a new batch container","","","","Read and checks the descriptor checksum for a given …","","Consume and apply a batch of operations","","A rusqlite connection object to the sqlite database","Delete the last derivation index for a keychain.","","Delete the data related to a specific script_pubkey, …","","Delete a raw transaction given its Txid","","Delete a script_pubkey given the keychain and its child …","","Delete the metadata of a transaction and optionally the …","","Delete a LocalUtxo given its OutPoint","","","","","Force changes to be written to disk","","","","Create a new instance given a configuration","","Return the last defivation index for a keychain.","","Fetch the keychain and child number of a given …","","Fetch a raw transaction given its Txid","","Fetch a script_pubkey given the child number of a keychain.","","Fetch the transaction metadata and optionally also the raw …","","Fetch a LocalUtxo given its OutPoint","","Increment the last derivation index for a keychain and …","","","","Return the list of raw transactions","","Return the list of script_pubkeys","","Return the list of transactions metadata","","Return the list of LocalUtxos","","In-memory ephemeral database","Instantiate a new SqliteDatabase instance by creating a …","Path on the local filesystem to store the sqlite file","Store the last derivation index for a given keychain.","","Store a raw transaction","","Store a script_pubkey along with its keychain and child …","","Store the metadata of a transaction","","Store a LocalUtxo","","","","","","Type that contains any of the BatchDatabase::Batch types …","Type that can contain any of the Database types defined by …","Type that can contain any of the database configurations …","In-memory ephemeral database","In-memory ephemeral database","Memory database has no config","Simple key-value embedded database based on sled","Simple key-value embedded database based on sled","Simple key-value embedded database based on sled","Configuration type for a sled::Tree database","Sqlite embedded database using rusqlite","Sqlite embedded database using rusqlite","Sqlite embedded database using rusqlite","Configuration type for a sqlite::SqliteDatabase database","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Main directory of the db","Main directory of the db","","","","","","","","","","","","","","Name of the database tree, a separated namespace for the …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","In-memory ephemeral database","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Create a new empty database","","","","","","","","","","A raw scriptpubkey (including pay-to-pubkey) under Legacy …","Alias for a Descriptor that contains extended derived keys","Extended DescriptorPublicKey that has been derived","Script descriptor","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 …","Alias type for a map of public key to secret key","Legacy ScriptContext To be used as P2SH scripts For …","Top-level script AST type","Pay-to-PubKey-Hash","The ScriptContext for Miniscript. Additional type …","Segwitv0 ScriptContext","Pay-to-ScriptHash(includes nested wsh/wpkh/sorted multi)","Pay-to-Witness-PubKey-Hash","Pay-to-Witness-ScriptHash with Segwitv0 context","Computes the Bitcoin address of the descriptor, if one …","","","Get a reference to the inner AstElem representing the root …","","","","","","","","","","","Enumerates all child nodes of the current AST node (self) …","Depending on script Context, some of the Terminals might …","","","Depending on script Context, some of the script resource …","","Check the consensus + policy(if not disabled) rules that …","Consensus rules at the Miniscript satisfaction time. It is …","","","Policy rules at the Miniscript satisfaction time. It is …","","","Check the consensus + policy(if not disabled) rules …","Depending on ScriptContext, fragments can be malleable. …","","","Check whether the given satisfaction is valid under the …","","","Descriptor checksum","","","","","","","","","","","","","","","","","","","","","","","","","","","Derives all wildcard keys in the descriptor using the …","Get the DescriptorType of Descriptor","","","","","","","","Encode as a Bitcoin script","","","","","","Descriptor errors","Computes the “witness script” of the descriptor, i.e. …","Additional information helpful for extra analysis.","Extract the spending policy","","","","","","","","","","","","","","","","","","Add type information(Type and Extdata) to Miniscript based …","","","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 Vec with cloned version of all public keys from …","Returns Vec of PkPkh entries, representing either public …","Returns Vec with hashes of all public keys from the …","Returns child node with given index, if any","Returns Option::Some with cloned n’th public key from …","Returns Option::Some with hash of n’th public key or …","Returns Option::Some with hash of n’th public key from …","Returns satisfying witness and scriptSig to spend an …","Whether the miniscript contains a combination of timelocks","Whether the miniscript has repeated Pk or Pkh","","","","","","","","","","","","","","","","","Extracts the AstElem representing the root of the …","Convert to wallet descriptor","Whether or not the descriptor has any wildcards","Whether the miniscript is malleable","","Creates a new Iter iterator that will iterate over all …","Creates a new PkIter iterator that will iterate over all …","Creates a new PkPkhIter iterator that will iterate over …","Creates a new PkhIter iterator that will iterate over all …","","","Lifting corresponds conversion of miniscript into Policy […","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 …","","Construct a new derived key","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 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 a new Wpkh descriptor Will return Err if …","Create a new wsh descriptor from witness script Errors …","Create a new wsh sorted multi descriptor Errors when …","A node in the Abstract Syntax Tree(","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 …","","","","","","Descriptor policy","Whether all spend paths of miniscript require a signature","Whether the descriptor is safe Checks whether all the …","Check whether the underlying Miniscript is safe under the …","Attempt to produce non-malleable satisfying witness for the","Attempt to produce a malleable satisfying witness for the …","Get the scriptCode of a transaction output.","Computes the scriptpubkey of the descriptor","Size, in bytes of the script-pubkey. If this Miniscript is …","","","","Descriptor templates","","","","","","","","","","","Serialize a descriptor to string with its secret keys","Check top level consensus rules.","Check whether the top-level is type B","Convert a descriptor using abstract keys to one using …","This will panic if translatefpk returns an uncompressed …","","","","","","","","","","","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","Error during base58 decoding","BIP32 error","The descriptor contains multiple keys with the same BIP32 …","Errors related to the parsing and usage of descriptors","The descriptor contains hardened derivation steps on …","Hex decoding error","Invalid character found in the descriptor checksum","The provided descriptor doesn’t match its checksum","Invalid HD Key path, such as having a wildcard but a …","Error thrown while working with keys","Miniscript error","Key-related error","Error while extracting and manipulating policies","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","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…","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","Raw public key or extended key fingerprint","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","Relative timelock locktime","RIPEMD160 preimage hash","Represent if and how much a policy item is satisfied by …","An item that needs to be satisfied","SHA256 preimage hash","Signature for a raw public key","Signature for an extended key fingerprint","Threshold items with threshold count","","","","","","","","","","","","","","","","","","","","","","","","","","","","","How the wallet’s descriptor can satisfy this policy node","Optional CheckSequenceVerify condition","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Return the conditions that are set by the spending policy …","","","Returns a unique id for the SatisfiableItem","Identifier for this policy node","","","","","","","","","","","","","","","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 timestamp value","The locktime value","","","","","","","","","","","","","","","","","","","BIP44 template. Expands to pkh(key/44'/0'/0'/{0,1}/*)","BIP44 public template. Expands to pkh(key/{0,1}/*)","BIP49 template. Expands to sh(wpkh(key/49'/0'/0'/{0,1}/*))","BIP49 public template. Expands to sh(wpkh(key/{0,1}/*))","BIP84 template. Expands to wpkh(key/84'/0'/0'/{0,1}/*)","BIP84 public template. Expands to wpkh(key/{0,1}/*)","Trait for descriptor templates that can be built into a …","Type alias for the return type of DescriptorTemplate, …","P2PKH template. Expands to a descriptor pkh(key)","P2WPKH template. Expands to a descriptor wpkh(key)","P2WPKH-P2SH template. Expands to a descriptor sh(wpkh(key))","","","","","","","","","","","","","","","","","","","Build the complete descriptor","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","BIP32 error","Trait for keys that can be derived.","Container for public or secret keys","The MiniscriptKey corresponding to Descriptors. This can …","A Secret Key that can be either a single key or an Xprv","A Single Descriptor Secret Key with optional origin …","A Single Descriptor Key with optional origin information","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","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","Errors thrown while working with keys","Alias type for a map of public key to secret key","Legacy scripts","Custom error message","Miniscript error","Extra options required by the generate_with_entropy","A private extended key, aka an xprv","Options for generating a PrivateKey","A public extended key, aka an xpub","The ScriptContext for Miniscript. Additional type …","Enum representation of the known valid ScriptContexts","Segwitv0 scripts","Single Secret Key","Single Public Key","Contents of a “sortedmulti” descriptor","Set of valid networks for a key","Xprv","Xpub","Create a set containing mainnet, testnet and regtest","Returns the ScriptContext as a ScriptContextEnum","","Return the public version of this key, by applying either …","BIP-0039","","","","","","","","","","","","","","","","","","","","","","","Depending on script Context, some of the Terminals might …","Depending on script Context, some of the Terminals might …","Depending on script Context, some of the script resource …","Depending on script Context, some of the script resource …","Check the consensus + policy(if not disabled) rules that …","Check the consensus + policy(if not disabled) rules that …","Consensus rules at the Miniscript satisfaction time. It is …","Consensus rules at the Miniscript satisfaction time. It is …","Policy 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 …","Check the consensus + policy(if not disabled) rules …","Depending on ScriptContext, fragments can be malleable. …","Check whether the given satisfaction is valid under the …","Check whether the given satisfaction is valid under the …","","","","","","","","","","","","","","Whether the generated key should be “compressed” or not","","","","","","","","","","","","","","","","","","","","","","","","","If this public key has a wildcard, replace it by the given …","Computes the public key corresponding to this descriptor …","","","","","","","","","","","","Encode as a Bitcoin script","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Create an instance given a public key and a set of valid …","Create an instance given a secret key and a set of valid …","","","Parse an expression tree into a SortedMultiVec","Full path, from the master key","Generate a key given the options with a random entropy","Generate a key with the default options and a random …","Generate a key given the extra options and the entropy","Generate a key with the default options and a given entropy","","","","Return whether or not the key contains the private data","","","","","","","","","","","","","","","","","","","","","","","","","","Turn the key into a DescriptorKey within the requested …","Consume self and turn it into a DescriptorKey by adding …","","","","","","Consume self and turn it into an ExtendedKey","","","Consumes self and returns the key","Transform the ExtendedKey into an ExtendedPrivKey for the …","Transform the ExtendedKey into an ExtendedPubKey for the …","Whether or not the key has a wildcards","Returns whether the script context is Legacy","Returns whether the script context is …","Returns whether the script context is Segwitv0","Returns whether the script context is …","","signatures required","The key","The key","","Create a set only containing mainnet","The fingerprint of the master key associated with this key","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","","","","Create a new instance of SortedMultiVec given a list of …","Origin information","Origin information","Other top level checks that are context specific","Other top level checks that are context specific","Override the computed set of valid networks","","","","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 …","Create Terminal::Multi containing sorted pubkeys","Create a set containing testnet and regtest","","","","","","","","","","","Check top level consensus rules.","Check top level consensus rules.","Check whether the top-level is type B","Check whether the top-level is type B","This will panic if translatefpk returns an uncompressed …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","The language determines which words will be used in a …","The primary type in this crate, most tasks require …","Determines the number of words that will be present in a …","Type for a BIP39 mnemonic with an optional passphrase","The secret value used to derive HD wallet addresses from a …","","","","","","","Get the seed value as a byte slice","","","","","","","","","","","","","Return the number of checksum bits","","","","","","","","","","","","","","","","","","","","","","","Get the original entropy value of the mnemonic phrase as a …","Return the number of entropy bits","","","","","","","","","","","","Get a MnemonicType for a mnemonic phrase representing the …","Get a MnemonicType for an existing mnemonic phrase","Get a MnemonicType for a mnemonic phrase with a specific …","","","","","Create a Mnemonic from pre-generated entropy","Construct a word list from its language code. Returns None …","Create a Mnemonic from an existing mnemonic phrase","","","","","","","","","","","","","","Consume the Mnemonic and return the phrase as a String.","Get the Language","Generates a new Mnemonic","Generates the seed from the Mnemonic and the password.","Get the mnemonic phrase as a string reference.","Outputs the hash in hexadecimal form","Outputs the hash in hexadecimal form","","","","","","","Return the number of entropy+checksum bits","","","","","","","","","","","","","Validate a mnemonic phrase","","","","","Return the number of words","Get the word list for this language","Get a WordMap that allows word -> index lookups in the …","","The address index selection strategy to use to derived an …","A derived address and the index it was found at For …","Trait to check if a value is below the dust limit","Return the address for the current descriptor index if it …","Return a new address after incrementing the current …","Return the address for a specific descriptor index. Does …","Return the address for a specific descriptor index and …","A Bitcoin wallet","Add an address validator","Add an external signer","Address","Address validation callbacks","","","","","","","Broadcast a transaction to the network","Bump the fee of a transaction previously created with this …","Start building a transaction.","Return a reference to the internal blockchain client","Coin selection","","","","","","","","","","","","Wallet export","Try to finalize a PSBT","","","","","","","","Return a derived address using the external descriptor, …","Return the balance, meaning the sum of this wallet’s …","Returns the descriptor used to create adddresses for a …","Return a fake wallet that appears to be funded for testing.","get the corresponding PSBT Input for a LocalUtxo","Returns the UTXO owned by this wallet corresponding to …","Child index of this address","","","","","","","Check whether or not a value is below dust limit","Return whether or not a script is part of this wallet …","Return the list of transactions made and received by the …","Return the list of unspent outputs of this wallet","","Get the Bitcoin network the wallet is using.","Create a new “online” wallet","Create a new “offline” wallet","Return the spending policies for the wallet’s descriptor","Return the “public” version of the wallet’s …","Return the secp256k1 context used for all signing …","Sign a transaction with all the wallet’s signers, in the …","Generalized signers","Sync the internal database with the blockchain","Cross-platform time","","","","","","","","Transaction builder","","","","","","","","","Trait to build address validators","Errors that can be returned to fail the validation of an …","Network connection error","Invalid script","A custom error message","Network request timeout error","User rejected the address","","","","","","","","","","","","","","","","","","","","","Validate or inspect an address","","","Branch and bound coin selection","Trait for generalized coin selection algorithms","Result of a successful coin selection","Default coin selection algorithm used by TxBuilder if not …","Simple and dumb coin selection","","","","","","","","","Perform the coin selection","","","","","","","","","","","","","","Total fee amount in satoshi","","","","","","","","","","","","","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.","","","","","","","","","","","","","","Structure that contains the export of a wallet","Earliest block to rescan when looking for the wallet’s …","","","Return the internal descriptor, if present","","","Return the external descriptor","","","Export a wallet","","","","","","Arbitrary label for the wallet","","","","","","","","Dummy identifier","The fingerprint of a BIP32 extended key","Input index is out of range","The private key in use has the right fingerprint but …","The non_witness_utxo specified is invalid","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 requied to …","The witness_utxo field of the transaction is required to …","The psbt contains a non-SIGHASH_ALL sighash in one of its …","Bitcoin HASH160 (RIPEMD160 after SHA256) hash of an ECDSA …","Options for a software signer","Trait for signers","Signing error","Identifier of a signer in the SignersContainers. Used as a …","Defines the order in which signers are called","Container for multiple signers","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 …","","Create a map of public keys to secret keys","Whether the wallet should assume a specific height has …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Return the secret key for the signer","","","","","","","","","Finds the signer with lowest ordering for a given id in …","","","","","","","","","","","","","","","","","Return the SignerId for this signer","Returns the list of identifiers of all the signers in the …","","","","","","","","","","","","","Default constructor","","","Removes a signer from the container and returns it","Sign a PSBT","Return whether or not the signer signs the whole …","Returns the list of signers in the container, sorted by …","","","","","","","Whether the signer should trust the witness_utxo, if the …","","","","","","","","","","","","","","","","","","","","","","","","Return the current timestamp in seconds","BIP69 / Lexicographic","Marker type to indicate the TxBuilder is being used to …","Use both change and non-change outputs (default)","Only use non-change outputs (see …","Policy regarding the use of change outputs when creating a …","Marker type to indicate the TxBuilder is being used to …","Only use change outputs (see TxBuilder::only_spend_change)","Randomized (default)","A transaction builder","Context in which the TxBuilder is valid","Ordering of the transaction’s inputs and outputs","Unchanged","Add a foreign UTXO i.e. a UTXO not owned by this wallet.","Fill-in the PSBT_GLOBAL_XPUB field with the extended keys …","Add a recipient to the internal list","Add a utxo to the internal list of unspendable utxos","Add a utxo to the internal list of utxos that must be spent","Add the list of outpoints to the internal list of UTXOs …","Explicitly tells the wallet that it is allowed to reduce …","","","","","","","","","","","Set a specific ChangeSpendPolicy. See …","","","","","","","","","","","","","Choose the coin selection algorithm","","","","","","","","","","","","","","","Do not spend change outputs","Sets the address to drain excess coins to.","Spend all the available inputs. This respects filters like …","","","","","","Enable signaling RBF","Enable signaling RBF with a specific nSequence value","","","Set an absolute fee","Set a custom fee rate","Finish the building the transaction.","","","","","","","","","","","","","","","Fill-in the psbt::Output::redeem_script and …","","","","","","","","","","","Only spend utxos added by add_utxo.","Use a specific nLockTime while creating the transaction","Only spend change outputs","Only Fill-in the psbt::Input::witness_utxo field when …","Choose the ordering for inputs and outputs of the …","","","Set the policy path to use while creating the transaction …","Replace the recipients already added with a new list","Sign with a specific sig hash","Sort transaction inputs and outputs by TxOrdering variant","","","","","","","","","","","","","","","","","","","","","Replace the internal list of unspendable utxos with a new …","Build a transaction with a specific version","","","","",""],"i":[1,1,1,1,1,1,0,1,1,1,0,1,2,0,1,1,1,3,1,1,1,2,1,1,1,1,1,1,1,1,0,3,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,2,1,2,4,2,0,1,2,4,5,6,3,7,8,1,2,4,5,6,3,7,8,2,2,4,5,6,3,7,8,2,4,5,6,3,7,8,7,0,4,7,8,4,1,2,4,5,6,3,7,8,1,2,4,5,6,3,7,8,0,0,2,5,7,8,1,2,4,5,6,3,7,8,2,4,5,6,3,7,8,7,4,4,1,1,2,4,5,6,3,7,8,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,4,5,6,3,7,8,4,4,4,4,2,5,2,5,8,1,2,4,5,6,3,7,8,1,2,4,5,6,3,7,8,9,9,10,11,5,0,4,5,6,3,7,8,8,3,5,4,7,6,7,2,5,7,8,4,8,2,4,5,6,3,7,8,1,7,1,2,4,5,6,3,7,8,1,2,4,5,6,3,7,8,7,3,5,1,2,4,5,6,3,7,8,6,12,7,0,1,2,4,5,6,3,7,8,0,2,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,38,39,40,41,42,43,43,44,0,0,45,0,0,44,44,0,0,0,0,0,44,46,47,44,46,47,48,44,46,47,44,46,47,0,44,46,47,44,46,47,44,46,47,0,44,0,48,44,44,46,47,45,48,44,48,48,44,44,46,47,44,46,47,0,0,0,48,48,44,46,47,44,46,47,44,46,47,44,46,47,49,46,47,44,46,47,0,0,50,51,50,51,50,51,50,51,50,51,50,51,51,50,51,50,51,51,50,51,51,50,51,50,50,50,50,51,51,51,51,50,50,50,50,50,51,50,51,51,51,50,50,51,50,51,50,51,50,51,50,51,52,53,54,55,56,57,58,0,0,0,0,58,58,58,58,58,58,58,58,0,58,58,58,0,58,58,58,59,60,58,59,61,62,60,63,58,59,61,62,60,63,58,62,60,63,60,63,61,61,59,59,61,62,60,63,58,59,61,62,60,63,58,60,63,59,61,62,60,63,58,60,63,62,59,61,62,60,63,58,58,59,61,62,60,63,58,58,58,58,58,58,62,62,62,61,61,59,62,61,59,59,61,62,60,63,58,59,61,62,60,63,58,61,59,60,63,63,59,62,63,61,61,60,63,62,63,60,60,63,60,63,58,59,61,62,60,63,58,59,61,62,60,63,58,59,61,62,60,63,58,59,61,62,60,63,58,64,65,66,67,68,0,0,69,70,69,70,69,70,70,69,70,69,70,70,69,70,70,69,70,69,69,70,69,69,69,69,69,70,69,70,70,70,70,69,70,70,70,70,69,70,69,70,69,70,70,69,70,71,0,0,0,0,71,71,71,71,71,71,71,71,71,71,71,72,73,72,74,71,73,72,74,71,73,72,72,73,72,74,71,73,72,74,71,72,74,73,72,74,71,72,73,73,72,71,71,73,72,74,71,71,71,71,71,71,71,73,73,73,73,73,72,74,71,73,72,74,71,72,73,72,72,73,72,72,72,72,71,73,72,74,71,73,72,74,71,73,72,74,71,73,72,74,71,73,75,76,77,78,79,80,81,82,83,84,85,0,0,86,0,0,0,0,85,87,87,87,88,87,85,87,87,89,87,89,87,89,87,89,87,89,87,89,87,87,87,87,88,87,87,87,86,87,88,87,88,87,88,87,88,87,88,87,88,87,88,87,87,87,88,87,88,87,88,87,88,87,0,87,87,89,87,89,87,89,87,89,87,89,87,87,87,87,87,0,0,0,90,91,92,90,91,92,0,90,91,92,0,91,90,91,93,94,92,90,91,93,94,92,91,91,90,91,90,91,90,91,90,91,90,91,90,91,90,91,93,94,92,90,91,93,94,92,93,94,92,90,91,93,94,92,91,91,93,94,92,90,90,90,90,91,91,91,91,93,94,92,92,92,92,91,91,91,91,91,91,91,91,90,91,93,94,92,90,91,93,94,92,91,91,91,91,93,94,93,94,92,90,91,90,91,90,91,90,91,90,91,93,90,91,93,94,92,90,91,93,94,92,90,91,93,94,92,90,91,93,94,92,95,96,97,98,99,100,101,102,103,0,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,105,0,0,0,0,0,0,0,0,0,0,105,0,0,105,105,105,105,106,107,108,109,105,106,107,108,109,105,106,107,108,108,110,106,107,110,107,110,110,106,107,110,106,107,110,110,106,107,110,106,107,0,109,105,106,107,108,109,105,106,107,108,109,105,106,107,108,109,109,105,106,107,108,109,105,106,107,108,105,105,105,108,109,105,106,107,108,108,109,105,106,107,108,0,105,108,111,105,108,109,109,105,105,106,107,108,108,105,108,109,105,106,107,108,108,105,108,108,105,108,109,105,106,107,108,108,108,108,108,108,108,108,105,108,108,109,105,106,107,108,109,109,105,106,107,108,109,105,106,107,108,108,112,105,108,109,108,108,108,108,105,108,108,110,106,107,108,105,108,105,109,105,105,105,105,105,105,105,105,105,105,105,108,110,108,105,108,109,105,106,107,108,0,108,105,108,108,108,105,105,108,105,108,109,0,109,105,106,107,108,109,109,109,105,108,105,110,110,105,108,109,105,106,107,108,109,105,106,107,108,108,109,105,106,107,108,105,109,105,106,107,108,108,113,114,115,116,117,0,118,118,118,0,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,119,120,121,122,123,124,125,126,127,128,128,0,129,0,0,0,127,127,128,128,128,127,129,130,128,129,129,0,0,0,130,130,127,127,0,0,127,127,127,127,128,131,127,129,132,133,128,130,131,127,129,132,133,128,130,131,127,129,132,133,130,131,127,129,132,133,130,133,132,133,131,133,131,127,129,132,133,128,130,131,127,129,132,133,128,130,131,127,129,132,133,128,130,133,128,131,127,129,132,133,128,128,130,131,127,129,129,132,132,133,128,130,132,133,133,127,132,131,127,129,132,133,128,130,131,127,129,132,133,128,130,127,129,133,132,133,128,133,132,132,131,127,129,132,133,133,131,127,129,132,133,130,128,131,127,129,132,133,128,130,131,127,129,132,133,128,130,131,127,129,132,133,128,130,131,127,129,132,133,128,130,134,135,135,135,136,137,138,139,140,139,140,139,140,139,140,139,140,141,142,143,144,145,146,147,148,148,147,149,150,151,152,153,154,155,156,157,158,159,154,155,156,157,158,159,155,157,159,0,0,0,0,0,0,0,0,0,0,0,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,160,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,161,0,0,0,0,0,0,162,162,0,0,0,0,0,0,161,161,161,0,0,163,161,161,162,164,0,164,0,0,163,165,166,0,0,165,166,0,167,161,165,0,164,168,169,163,170,161,171,166,172,173,165,164,168,169,163,170,161,171,166,172,173,165,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,163,170,171,166,172,163,170,171,166,172,171,166,172,170,170,164,168,168,169,163,170,161,171,166,172,173,165,164,168,169,163,170,161,171,166,172,173,165,166,166,164,168,169,163,170,161,171,166,172,173,165,171,163,171,166,172,169,163,170,161,161,171,171,166,166,172,173,165,165,171,164,164,164,168,169,163,170,161,161,161,171,166,172,173,165,169,169,166,165,171,166,162,174,162,174,171,166,172,164,171,166,172,164,168,169,163,170,161,171,166,172,173,165,164,168,169,163,170,161,171,166,172,173,165,175,176,168,168,169,166,165,176,164,168,168,164,164,166,167,163,167,163,166,171,172,173,171,0,166,110,171,171,0,171,166,172,171,172,173,110,110,169,171,166,172,171,171,171,171,171,0,163,170,171,166,172,166,161,171,166,165,110,110,110,110,171,164,168,169,163,170,161,171,166,172,173,165,164,168,169,163,170,161,171,166,172,173,165,164,168,169,163,170,161,171,166,172,173,165,164,168,169,163,170,161,171,166,172,173,165,177,178,179,180,181,182,183,184,185,186,186,186,186,186,186,186,0,0,0,0,0,186,187,187,187,187,187,188,189,188,188,186,189,187,188,186,189,187,188,188,187,186,189,187,188,186,189,187,188,186,187,186,189,187,188,186,189,187,188,186,189,187,188,189,187,186,186,189,189,189,189,187,187,188,188,188,187,187,187,186,189,187,188,189,186,189,189,186,189,187,188,186,189,187,188,189,188,189,188,189,189,189,188,189,189,188,186,189,187,188,189,187,187,186,189,187,188,186,189,187,188,186,189,187,188,189,186,189,187,188,187,186,186,188,0,0,0,190,190,190,190,0,191,191,192,0,191,190,192,191,190,192,191,191,191,191,0,191,190,192,192,191,190,192,191,190,192,192,0,191,191,190,192,192,191,190,192,191,191,191,0,191,191,192,191,190,192,191,190,192,193,191,191,191,192,191,191,191,191,191,191,191,0,191,0,192,191,190,192,191,190,192,0,191,190,192,191,190,192,194,195,0,0,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,197,196,198,0,0,0,0,0,199,200,201,199,200,201,200,200,202,200,201,200,201,199,200,201,199,200,201,199,200,201,199,199,200,201,199,200,201,199,200,201,199,200,201,199,201,199,199,200,199,200,201,199,200,201,199,200,201,199,200,201,0,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,204,205,205,206,206,206,206,206,206,206,206,206,205,0,0,0,0,0,0,206,207,208,206,207,208,205,206,204,207,208,205,206,204,207,208,205,206,204,207,208,205,206,204,207,208,205,204,204,207,208,205,206,204,207,208,205,206,204,207,208,209,205,206,204,207,208,205,206,204,207,205,206,206,204,207,208,205,205,205,206,204,207,207,208,205,205,209,207,205,206,204,207,208,205,206,204,207,208,205,204,207,205,204,207,209,209,207,205,206,204,207,208,206,208,205,206,204,207,208,205,206,204,207,208,205,206,204,207,208,205,206,204,207,208,210,211,212,0,213,0,214,214,0,0,214,213,0,0,0,213,215,215,215,215,215,215,215,216,217,215,213,214,216,217,215,213,214,215,216,217,215,213,214,216,217,215,213,214,213,214,215,216,217,213,214,216,217,215,213,214,216,217,215,213,214,215,215,215,216,217,215,213,214,215,215,213,214,215,215,215,216,217,215,213,214,216,217,215,213,214,213,214,213,214,215,216,217,215,213,214,216,217,215,213,214,215,215,215,215,215,213,214,215,215,215,213,216,217,215,213,214,216,217,215,213,214,216,217,215,213,214,216,217,215,213,214,215,215,216,217,215,213,214],"f":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[],["u8",15]],[[],["fail",8]],[[]],[[],["f32",15]],[[],["usize",15]],null,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],[["result",4,["vec"]],["vec",3,["u5","global"]]]],[[],["keychainkind",4]],[[],["feerate",3]],[[],["localutxo",3]],[[],["weightedutxo",3]],[[],["utxo",4]],[[],["transactiondetails",3]],[[],["confirmationtime",3]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],null,null,[[]],[[],["transactiondetails",3]],[[],["confirmationtime",3]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],null,null,[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["keychainkind",4]],["bool",15]],[[["feerate",3]],["bool",15]],[[["localutxo",3]],["bool",15]],[[["weightedutxo",3]],["bool",15]],[[["utxo",4]],["bool",15]],[[["transactiondetails",3]],["bool",15]],[[["confirmationtime",3]],["bool",15]],null,[[["usize",15]],["u64",15]],[[["usize",15]],["u64",15]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],null,[[]],[[["error",3]]],[[["error",4]]],[[["error",4]]],[[["error",4]]],[[["psbtparseerror",4]]],[[["error",4]]],[[["error",4]]],[[["esploraerror",4]]],[[["compactfilterserror",4]]],[[["error",4]]],[[["error",4]]],[[["error",4]]],[[["error",4]]],[[["keyerror",4]],["error",4]],[[["signererror",4]]],[[["error",4]]],[[["addressvalidatorerror",4]]],[[["policyerror",4]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["f32",15]]],[[["f32",15]]],[[["u64",15],["usize",15]],["feerate",3]],[[["u64",15],["usize",15]],["feerate",3]],[[],["u64",15]],[[],["u64",15]],[[]],[[]],null,[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["keysource",6],["option",4,["keysource"]],["derivationpath",3]],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[],[["keyerror",4],["result",4,["extendedkey","keyerror"]],["extendedkey",4]]],[[["network",4],["secp256k1",3]],[["descriptorerror",4],["result",4,["descriptorerror"]]]],[[["network",4],["secp256k1",3]],[["descriptorerror",4],["result",4,["descriptorerror"]]]],null,null,[[["feerate",3]],["bool",15]],[[["localutxo",3]],["bool",15]],[[["weightedutxo",3]],["bool",15]],[[["utxo",4]],["bool",15]],[[["transactiondetails",3]],["bool",15]],[[["confirmationtime",3]],["bool",15]],[[["u64",15],["u32",15],["option",4,["u64"]],["option",4,["u32"]]],["option",4]],[[],["outpoint",3]],null,[[["feerate",3]],[["ordering",4],["option",4,["ordering"]]]],null,null,null,[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[["feerate",3]]],null,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],["string",3]],null,[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],null,[[],["txout",3]],null,[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],null,[[],["usize",15]],null,[[],["str",15]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],null,[[],["result",4]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[]],[[]],[[]],[[]],[[]],[[]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[],["capability",4]],[[],["noopprogress",3]],[[],["logprogress",3]],[[]],[[]],[[]],null,[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],null,[[["capability",4]],["bool",15]],null,[[["usize",15]],[["feerate",3],["error",4],["result",4,["feerate","error"]]]],[[["formatter",3]],["result",6]],[[]],[[]],[[]],[[],[["result",4,["error"]],["error",4]]],[[],[["hashset",3,["capability"]],["capability",4]]],[[],["u64",15]],[[],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[],["logprogress",3]],[[],["noopprogress",3]],[[]],[[["progress",8]],[["result",4,["error"]],["error",4]]],[[["progress",8]],[["result",4,["error"]],["error",4]]],[[]],[[]],[[]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[["f32",15],["option",4,["string"]],["string",3]],[["result",4,["error"]],["error",4]]],[[["f32",15],["option",4,["string"]],["string",3]],[["result",4,["error"]],["error",4]]],[[["f32",15],["option",4,["string"]],["string",3]],[["result",4,["error"]],["error",4]]],[[]],[[]],[[]],null,null,null,null,null,null,null,null,[[]],[[]],[[]],[[]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[],["anyblockchainconfig",4]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],["result",4]],[[["usize",15]]],[[["usize",15]]],[[["anyblockchainconfig",4]],["bool",15]],[[["usize",15]],[["feerate",3],["error",4],["result",4,["feerate","error"]]]],[[["formatter",3]],["result",6]],[[["compactfiltersblockchain",3]]],[[]],[[["electrumblockchain",3]]],[[["esplorablockchain",3]]],[[]],[[["compactfiltersblockchainconfig",3]]],[[["esplorablockchainconfig",3]]],[[["electrumblockchainconfig",3]]],[[],[["result",4,["error"]],["error",4]]],[[],[["hashset",3,["capability"]],["capability",4]]],[[],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[["anyblockchainconfig",4]],["bool",15]],[[],["result",4]],[[["progress",8]],[["result",4,["error"]],["error",4]]],[[["progress",8]],[["result",4,["error"]],["error",4]]],[[]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[["transaction",3]]],null,[[],["fail",8]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[],["bitcoinpeerconfig",3]],[[],["compactfiltersblockchainconfig",3]],[[]],[[]],[[["network",4],["tosocketaddrs",8],["arc",3,["mempool"]],["mempool",3]],[["result",4,["compactfilterserror"]],["compactfilterserror",4]]],[[["totargetaddr",8],["tosocketaddrs",8],["arc",3,["mempool"]],["mempool",3],["network",4],["option",4]],[["result",4,["compactfilterserror"]],["compactfilterserror",4]]],[[],["mempool",3]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],["result",4]],[[],["result",4]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["bitcoinpeerconfig",3]],["bool",15]],[[["compactfiltersblockchainconfig",3]],["bool",15]],[[["usize",15]],[["feerate",3],["error",4],["result",4,["feerate","error"]]]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[]],[[]],[[]],[[]],[[]],[[["error",4]]],[[["error",3]]],[[]],[[["error",4]]],[[["error",3]]],[[["systemtimeerror",3]]],[[],[["result",4,["error"]],["error",4]]],[[],[["hashset",3,["capability"]],["capability",4]]],[[],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[],[["arc",3,["mempool"]],["mempool",3]]],[[],["network",4]],[[["inventory",4]],[["option",4,["transaction"]],["transaction",3]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[],["versionmessage",3]],[[["txid",3]],["bool",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[]],[[],["bool",15]],[[],[["transaction",3],["vec",3,["transaction"]]]],[[["bitcoinpeerconfig",3]],["bool",15]],[[["compactfiltersblockchainconfig",3]],["bool",15]],null,[[]],[[["peer",3],["vec",3,["peer"]],["option",4,["usize"]],["usize",15],["path",3],["asref",8,["path"]]],[["result",4,["compactfilterserror"]],["compactfilterserror",4]]],null,[[["duration",3],["option",4,["duration"]],["str",15]],[["compactfilterserror",4],["result",4,["option","compactfilterserror"]],["option",4,["networkmessage"]]]],[[["networkmessage",4]],[["result",4,["compactfilterserror"]],["compactfilterserror",4]]],[[],["result",4]],[[],["result",4]],[[["progress",8]],[["result",4,["error"]],["error",4]]],null,null,null,null,[[]],[[]],[[],["string",3]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],[[]],[[]],[[]],null,null,null,null,null,null,null,[[]],[[]],[[]],[[]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[],["electrumblockchainconfig",3]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],["result",4]],[[["usize",15]]],[[["usize",15]]],[[["electrumblockchainconfig",3]],["bool",15]],[[["usize",15]],[["feerate",3],["error",4],["result",4,["feerate","error"]]]],[[["formatter",3]],["result",6]],[[["client",3]]],[[]],[[]],[[],[["result",4,["error"]],["error",4]]],[[],[["hashset",3,["capability"]],["capability",4]]],[[],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[["electrumblockchainconfig",3]],["bool",15]],null,[[],["result",4]],[[["progress",8]],[["result",4,["error"]],["error",4]]],null,null,null,[[]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],null,[[]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[],["fail",8]],null,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[],["esplorablockchainconfig",3]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],["result",4]],[[],["result",4]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["esplorablockchainconfig",3]],["bool",15]],[[["usize",15]],[["feerate",3],["error",4],["result",4,["feerate","error"]]]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[]],[[]],[[]],[[["parseinterror",3]]],[[["transport",3]]],[[["error",4]]],[[["error",4]]],[[["error",4]]],[[]],[[["error",3]]],[[],[["result",4,["error"]],["error",4]]],[[],[["hashset",3,["capability"]],["capability",4]]],[[],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[["esplorablockchainconfig",3]],["bool",15]],[[["usize",15],["str",15]]],null,[[],["result",4]],[[["progress",8]],[["result",4,["error"]],["error",4]]],null,null,null,[[]],[[],["string",3]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],[[]],[[["agent",3]]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[]],[[]],[[]],[[]],[[["keychainkind",4],["asref",8]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4],["asref",8]],[["result",4,["error"]],["error",4]]],[[],[["result",4,["error"]],["error",4]]],[[],[["result",4,["error"]],["error",4]]],null,[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],[["result",4,["error"]],["error",4]]],[[],[["result",4,["error"]],["error",4]]],[[["formatter",3]],["result",6]],[[]],[[],[["result",4,["error"]],["error",4]]],[[],[["result",4,["error"]],["error",4]]],[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["keychainkind",4]],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[["keychainkind",4]],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[],["usize",15]],[[]],[[],[["vec",3,["transaction"]],["error",4],["result",4,["vec","error"]]]],[[],[["vec",3,["transaction"]],["error",4],["result",4,["vec","error"]]]],[[["keychainkind",4],["option",4,["keychainkind"]]],[["error",4],["result",4,["vec","error"]],["vec",3,["script"]]]],[[["keychainkind",4],["option",4,["keychainkind"]]],[["error",4],["result",4,["vec","error"]],["vec",3,["script"]]]],[[["bool",15]],[["vec",3,["transactiondetails"]],["error",4],["result",4,["vec","error"]]]],[[["bool",15]],[["vec",3,["transactiondetails"]],["error",4],["result",4,["vec","error"]]]],[[],[["vec",3,["localutxo"]],["error",4],["result",4,["vec","error"]]]],[[],[["vec",3,["localutxo"]],["error",4],["result",4,["vec","error"]]]],null,[[["string",3]]],null,[[["keychainkind",4],["u32",15]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4],["u32",15]],[["result",4,["error"]],["error",4]]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4],["script",3],["u32",15]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4],["script",3],["u32",15]],[["result",4,["error"]],["error",4]]],[[["transactiondetails",3]],[["result",4,["error"]],["error",4]]],[[["transactiondetails",3]],[["result",4,["error"]],["error",4]]],[[["localutxo",3]],[["result",4,["error"]],["error",4]]],[[["localutxo",3]],[["result",4,["error"]],["error",4]]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["keychainkind",4],["asref",8]],[["result",4,["error"]],["error",4]]],[[],[["result",4,["error"]],["error",4]]],[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],[["result",4,["error"]],["error",4]]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[]],[[]],[[]],[[]],[[["sqlitedatabase",3]]],[[["tree",3]]],[[["memorydatabase",3]]],[[]],[[]],[[]],[[["sleddbconfiguration",3]]],[[]],[[["sqlitedbconfiguration",3]]],[[]],[[],[["result",4,["error"]],["error",4]]],[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["keychainkind",4]],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[],[["vec",3,["transaction"]],["error",4],["result",4,["vec","error"]]]],[[["keychainkind",4],["option",4,["keychainkind"]]],[["error",4],["result",4,["vec","error"]],["vec",3,["script"]]]],[[["bool",15]],[["vec",3,["transactiondetails"]],["error",4],["result",4,["vec","error"]]]],[[],[["vec",3,["localutxo"]],["error",4],["result",4,["vec","error"]]]],null,null,[[],["result",4]],[[],["result",4]],[[],["result",4]],[[["keychainkind",4],["u32",15]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4],["u32",15]],[["result",4,["error"]],["error",4]]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4],["script",3],["u32",15]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4],["script",3],["u32",15]],[["result",4,["error"]],["error",4]]],[[["transactiondetails",3]],[["result",4,["error"]],["error",4]]],[[["transactiondetails",3]],[["result",4,["error"]],["error",4]]],[[["localutxo",3]],[["result",4,["error"]],["error",4]]],[[["localutxo",3]],[["result",4,["error"]],["error",4]]],null,[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],[[]],[[]],null,null,null,null,null,null,null,null,null,null,[[]],[[]],[[]],[[["keychainkind",4],["asref",8]],[["result",4,["error"]],["error",4]]],[[],[["result",4,["error"]],["error",4]]],[[],["memorydatabase",3]],[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],[["result",4,["error"]],["error",4]]],[[["formatter",3]],["result",6]],[[]],[[],[["result",4,["error"]],["error",4]]],[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["keychainkind",4]],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[],["usize",15]],[[]],[[],[["vec",3,["transaction"]],["error",4],["result",4,["vec","error"]]]],[[["keychainkind",4],["option",4,["keychainkind"]]],[["error",4],["result",4,["vec","error"]],["vec",3,["script"]]]],[[["bool",15]],[["vec",3,["transactiondetails"]],["error",4],["result",4,["vec","error"]]]],[[],[["vec",3,["localutxo"]],["error",4],["result",4,["vec","error"]]]],[[]],[[["keychainkind",4],["u32",15]],[["result",4,["error"]],["error",4]]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4],["script",3],["u32",15]],[["result",4,["error"]],["error",4]]],[[["transactiondetails",3]],[["result",4,["error"]],["error",4]]],[[["localutxo",3]],[["result",4,["error"]],["error",4]]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[["network",4]],[["result",4,["address","error"]],["address",3],["error",4]]],[[],["scriptcontextenum",4]],[[],["scriptcontextenum",4]],[[],["terminal",4]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],[["global",3],["miniscript",3],["vec",3,["miniscript","global"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["terminal",4]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["terminal",4]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["terminal",4]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],null,[[],["deriveddescriptorkey",3]],[[],["descriptor",4]],[[],["legacy",4]],[[],["segwitv0",4]],[[],["miniscript",3]],[[]],[[]],[[]],[[]],[[]],[[],["ordering",4]],[[["descriptor",4]],["ordering",4]],[[["legacy",4]],["ordering",4]],[[["segwitv0",4]],["ordering",4]],[[["miniscript",3]],["ordering",4]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["u32",15]],[["descriptorpublickey",4],["descriptor",4,["descriptorpublickey"]]]],[[],["descriptortype",4]],[[],[["result",4,["descriptor"]],["descriptor",4]]],[[],[["result",4,["miniscript"]],["miniscript",3]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],["script",3]],[[],["bool",15]],[[["descriptor",4]],["bool",15]],[[["legacy",4]],["bool",15]],[[["segwitv0",4]],["bool",15]],[[["miniscript",3]],["bool",15]],null,[[],["script",3]],null,[[["secp256k1",3],["buildsatisfaction",4],["signerscontainer",3]],[["option",4,["policy"]],["descriptorerror",4],["result",4,["option","descriptorerror"]]]],[[["secp256k1",3],["buildsatisfaction",4],["signerscontainer",3]],[["result",4,["option","error"]],["option",4,["policy"]],["error",4]]],[[["secp256k1",3],["buildsatisfaction",4],["signerscontainer",3]],[["result",4,["option","error"]],["option",4,["policy"]],["error",4]]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[],["bool",15]],[[],["bool",15]],[[]],[[]],[[]],[[]],[[]],[[["terminal",4]],[["result",4,["miniscript","error"]],["miniscript",3],["error",4]]],[[["str",15]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[["str",15]],[["result",4,["miniscript","error"]],["miniscript",3],["error",4]]],[[["str",15]],[["result",4,["miniscript","error"]],["miniscript",3],["error",4]]],[[["tree",3]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[["tree",3]],[["result",4,["miniscript","error"]],["miniscript",3],["error",4]]],[[],["u64",15]],[[],["u64",15]],[[],["u64",15]],[[],["u64",15]],[[],["u64",15]],[[],[["global",3],["vec",3,["global"]]]],[[],[["vec",3,["pkpkh","global"]],["pkpkh",4],["global",3]]],[[],[["vec",3,["global"]],["global",3]]],[[["usize",15]],[["option",4,["miniscript"]],["miniscript",3]]],[[["usize",15]],["option",4]],[[["usize",15]],[["option",4,["pkpkh"]],["pkpkh",4]]],[[["usize",15]],["option",4]],[[],[["result",4,["error"]],["error",4]]],[[],["bool",15]],[[],["bool",15]],[[]],[[]],[[]],[[]],[[]],[[],["hash",3]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[],["terminal",4]],[[["network",4],["secp256k1",3]],[["descriptorerror",4],["result",4,["descriptorerror"]]]],[[],["bool",15]],[[],["bool",15]],[[],["bool",15]],[[],["iter",3]],[[],["pkiter",3]],[[],["pkpkhiter",3]],[[],["pkhiter",3]],[[],[["error",4],["result",4,["policy","error"]],["policy",4]]],[[],[["error",4],["result",4,["policy","error"]],["policy",4]]],[[],[["result",4,["lifterror"]],["lifterror",4]]],[[["miniscript",3]],[["option",4,["usize"]],["usize",15]]],[[["miniscript",3]],[["option",4,["usize"]],["usize",15]]],[[["miniscript",3]],[["option",4,["usize"]],["usize",15]]],[[],[["usize",15],["result",4,["usize","error"]],["error",4]]],[[],[["usize",15],["result",4,["usize","error"]],["error",4]]],[[],[["usize",15],["result",4,["usize","error"]],["error",4]]],[[["descriptor",4]],["bool",15]],[[["descriptorpublickey",4],["secp256k1",3]],["deriveddescriptorkey",3]],[[["barectx",4],["miniscript",3,["barectx"]]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[],["descriptor",4]],[[],["descriptor",4]],[[["miniscript",3,["legacy"]],["legacy",4]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[["usize",15],["vec",3,["global"]],["global",3]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[["miniscript",3,["segwitv0"]],["segwitv0",4]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[["usize",15],["vec",3,["global"]],["global",3]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[["miniscript",3,["segwitv0"]],["segwitv0",4]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[["usize",15],["vec",3,["global"]],["global",3]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],null,[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[["script",3]],[["miniscript",3,["publickey"]],["result",4,["miniscript","error"]],["error",4]]],[[["secp256k1",3],["str",15]],[["error",4],["result",4,["error"]]]],[[["script",3]],[["miniscript",3,["publickey"]],["result",4,["miniscript","error"]],["error",4]]],[[],[["option",4,["ordering"]],["ordering",4]]],[[["descriptor",4]],[["option",4,["ordering"]],["ordering",4]]],[[["legacy",4]],[["option",4,["ordering"]],["ordering",4]]],[[["segwitv0",4]],[["option",4,["ordering"]],["ordering",4]]],[[["miniscript",3]],[["option",4,["ordering"]],["ordering",4]]],null,[[],["bool",15]],[[],[["error",4],["result",4,["error"]]]],[[],[["analysiserror",4],["result",4,["analysiserror"]]]],[[],[["error",4],["vec",3,["vec","global"]],["result",4,["vec","error"]]]],[[],[["error",4],["vec",3,["vec","global"]],["result",4,["vec","error"]]]],[[],["script",3]],[[],["script",3]],[[],["usize",15]],[[],["result",4]],[[],["result",4]],[[],["usize",15]],null,[[]],[[]],[[]],[[]],[[]],[[]],[[],["publickey",3]],[[],["string",3]],[[],["string",3]],[[],["string",3]],[[["hashmap",3]],["string",3]],[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[],[["result",4,["descriptor"]],["descriptor",4]]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],null,[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["script",3]],[[]],[[]],[[]],[[]],[[]],[[],["bool",15]],null,null,null,null,null,[[["str",15]],[["descriptorerror",4],["string",3],["result",4,["string","descriptorerror"]]]],null,null,null,null,null,null,null,null,null,null,null,null,null,[[],["fail",8]],[[]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["keyerror",4]],["error",4]],[[["error",4]]],[[["error",4]]],[[["error",4]]],[[["error",4]]],[[["error",4]]],[[["policyerror",4]]],[[]],[[],["usize",15]],[[]],[[],["string",3]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[],["fail",8]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],["pkorf",3]],[[],["satisfiableitem",4]],[[],["satisfaction",4]],[[],["policy",3]],[[],["condition",3]],[[],["buildsatisfaction",4]],[[]],[[]],[[]],[[]],[[]],[[]],[[["condition",3]],["ordering",4]],null,null,[[],["pkorf",3]],[[],["condition",3]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["condition",3]],["bool",15]],[[["policyerror",4]],["bool",15]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[]],[[]],[[["bool",15]]],[[]],[[["satisfiableitem",4]]],[[]],[[]],[[]],[[]],[[["btreemap",3]],[["policyerror",4],["condition",3],["result",4,["condition","policyerror"]]]],[[],["u64",15]],[[]],[[],["string",3]],null,[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],["bool",15]],[[],["bool",15]],[[],["bool",15]],null,[[["condition",3]],["bool",15]],[[["policyerror",4]],["bool",15]],[[["condition",3]],[["ordering",4],["option",4,["ordering"]]]],[[],["bool",15]],null,[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],null,[[]],[[]],[[]],[[]],[[]],[[]],[[],["string",3]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[],["validnetworks",6]],[[],["scriptcontextenum",4]],[[],["fail",8]],[[["secp256k1",3]],[["descriptorpublickey",4],["descriptorkeyparseerror",3],["result",4,["descriptorpublickey","descriptorkeyparseerror"]]]],null,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["terminal",4]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[],["scriptcontextenum",4]],[[],["privatekeygenerateoptions",3]],[[],["sortedmultivec",3]],[[],["descriptorpublickey",4]],[[],["descriptorsinglepub",3]],[[]],[[]],[[]],[[]],[[]],[[["sortedmultivec",3]],["ordering",4]],[[["descriptorpublickey",4]],["ordering",4]],[[["descriptorsinglepub",3]],["ordering",4]],null,[[]],[[["usize",15]]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["u32",15]],["descriptorpublickey",4]],[[["secp256k1",3]],[["publickey",3],["result",4,["publickey","conversionerror"]],["conversionerror",4]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],["script",3]],[[["scriptcontextenum",4]],["bool",15]],[[["sortedmultivec",3]],["bool",15]],[[["descriptorpublickey",4]],["bool",15]],[[["descriptorsinglepub",3]],["bool",15]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[],["bool",15]],[[["extendedpubkey",3]]],[[["extendedprivkey",3]]],[[]],[[]],[[]],[[]],[[]],[[["error",4]]],[[]],[[["error",4]]],[[]],[[]],[[]],[[]],[[]],[[["descriptorpublickey",4],["validnetworks",6]]],[[["validnetworks",6],["descriptorsecretkey",4]]],[[["str",15]],[["descriptorpublickey",4],["result",4,["descriptorpublickey"]]]],[[["str",15]],[["result",4,["descriptorsecretkey"]],["descriptorsecretkey",4]]],[[["tree",3]],[["sortedmultivec",3],["result",4,["sortedmultivec","error"]],["error",4]]],[[],["derivationpath",3]],[[],[["generatedkey",3],["result",4,["generatedkey"]]]],[[],[["generatedkey",3],["result",4,["generatedkey"]]]],[[],[["generatedkey",3],["result",4,["generatedkey"]]]],[[],[["generatedkey",3],["result",4,["generatedkey"]]]],[[],["u64",15]],[[],["u64",15]],[[],["u64",15]],[[],["bool",15]],[[]],[[]],[[]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[["keysource",6],["option",4,["keysource"]],["derivationpath",3]],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[["keysource",6],["option",4,["keysource"]],["derivationpath",3]],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[],[["keyerror",4],["result",4,["extendedkey","keyerror"]],["extendedkey",4]]],[[],[["keyerror",4],["result",4,["extendedkey","keyerror"]],["extendedkey",4]]],[[],[["keyerror",4],["result",4,["extendedkey","keyerror"]],["extendedkey",4]]],[[]],[[["network",4]],[["option",4,["extendedprivkey"]],["extendedprivkey",3]]],[[["network",4],["secp256k1",3]],["extendedpubkey",3]],[[],["bool",15]],[[],["bool",15]],[[],["bool",15]],[[],["bool",15]],[[],["bool",15]],[[],["bool",15]],null,null,null,[[],[["error",4],["result",4,["policy","error"]],["policy",4]]],[[],["validnetworks",6]],[[],["fingerprint",3]],[[["miniscript",3]],[["option",4,["usize"]],["usize",15]]],[[],["usize",15]],[[],["usize",15]],[[["validnetworks",6]],["validnetworks",6]],[[["sortedmultivec",3]],["bool",15]],[[["descriptorpublickey",4]],["bool",15]],[[["descriptorsinglepub",3]],["bool",15]],[[["usize",15],["vec",3,["global"]],["global",3]],[["sortedmultivec",3],["result",4,["sortedmultivec","error"]],["error",4]]],null,null,[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[["validnetworks",6]]],[[["sortedmultivec",3]],[["option",4,["ordering"]],["ordering",4]]],[[["descriptorpublickey",4]],[["option",4,["ordering"]],["ordering",4]]],[[["descriptorsinglepub",3]],[["option",4,["ordering"]],["ordering",4]]],null,[[],[["error",4],["result",4,["error"]]]],[[],[["error",4],["vec",3,["vec","global"]],["result",4,["vec","error"]]]],[[],["usize",15]],[[],["terminal",4]],[[],["validnetworks",6]],[[]],[[]],[[]],[[]],[[]],[[],["descriptorpublickey",4]],[[],["string",3]],[[],["string",3]],[[],["string",3]],[[],["string",3]],[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[],[["result",4,["sortedmultivec"]],["sortedmultivec",3]]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[]],[[],["str",15]],[[]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],[["result",4,["vec"]],["vec",3,["u5","global"]]]],[[],["u8",15]],[[],["language",4]],[[],["mnemonic",3]],[[],["mnemonictype",4]],[[],["seed",3]],[[]],[[]],[[]],[[]],[[],["language",4]],[[],["mnemonictype",4]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[]],[[],["usize",15]],[[["language",4]],["bool",15]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["usize",15]],[["error",3],["result",4,["mnemonictype","error"]],["mnemonictype",4]]],[[["str",15]],[["error",3],["result",4,["mnemonictype","error"]],["mnemonictype",4]]],[[["usize",15]],[["error",3],["result",4,["mnemonictype","error"]],["mnemonictype",4]]],[[]],[[]],[[]],[[]],[[["language",4]],[["result",4,["mnemonic","error"]],["error",3],["mnemonic",3]]],[[["str",15]],[["option",4,["language"]],["language",4]]],[[["str",15],["language",4]],[["result",4,["mnemonic","error"]],["error",3],["mnemonic",3]]],[[],[["generatedkey",3],["result",4,["generatedkey"]]]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[["keysource",6],["option",4,["keysource"]],["derivationpath",3]],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[["keysource",6],["option",4,["keysource"]],["derivationpath",3]],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[],[["keyerror",4],["result",4,["extendedkey","keyerror"]],["extendedkey",4]]],[[],[["keyerror",4],["result",4,["extendedkey","keyerror"]],["extendedkey",4]]],[[],["string",3]],[[],["language",4]],[[["language",4],["mnemonictype",4]],["mnemonic",3]],[[["str",15],["mnemonic",3]],["seed",3]],[[],["str",15]],[[],["string",3]],[[],["string",3]],[[]],[[]],[[]],[[]],[[],["string",3]],[[],["string",3]],[[],["usize",15]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[["str",15],["language",4]],[["error",3],["result",4,["error"]]]],[[]],[[]],[[]],[[]],[[],["usize",15]],[[],["wordlist",3]],[[],["wordmap",3]],[[],["result",4]],null,null,null,null,null,null,null,null,[[["addressvalidator",8],["arc",3,["addressvalidator"]]]],[[["arc",3,["signer"]],["signer",8],["keychainkind",4],["signerordering",3]]],null,null,[[]],[[]],[[]],[[]],[[]],[[]],[[["transaction",3]],[["result",4,["txid","error"]],["txid",3],["error",4]]],[[["txid",3]],[["result",4,["txbuilder","error"]],["txbuilder",3,["defaultcoinselectionalgorithm","bumpfee"]],["error",4]]],[[],[["defaultcoinselectionalgorithm",6],["txbuilder",3,["defaultcoinselectionalgorithm","createtx"]],["createtx",3]]],[[]],null,[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["addressinfo",3]],["bool",15]],null,[[["psbt",3],["signoptions",3]],[["error",4],["result",4,["bool","error"]],["bool",15]]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[]],[[]],[[]],[[["addressindex",4]],[["result",4,["addressinfo","error"]],["addressinfo",3],["error",4]]],[[],[["u64",15],["error",4],["result",4,["u64","error"]]]],[[["keychainkind",4]],["extendeddescriptor",6]],[[["str",15]]],[[["sighashtype",4],["bool",15],["option",4,["sighashtype"]],["localutxo",3]],[["input",3],["error",4],["result",4,["input","error"]]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],null,[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[],["bool",15]],[[["script",3]],[["error",4],["result",4,["bool","error"]],["bool",15]]],[[["bool",15]],[["vec",3,["transactiondetails"]],["error",4],["result",4,["vec","error"]]]],[[],[["vec",3,["localutxo"]],["error",4],["result",4,["vec","error"]]]],[[["addressinfo",3]],["bool",15]],[[],["network",4]],[[["option",4],["intowalletdescriptor",8],["network",4]],[["result",4,["error"]],["error",4]]],[[["option",4],["intowalletdescriptor",8],["network",4]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4]],[["result",4,["option","error"]],["option",4,["policy"]],["error",4]]],[[["keychainkind",4]],[["option",4,["extendeddescriptor"]],["result",4,["option","error"]],["error",4]]],[[],["secp256k1",3]],[[["psbt",3],["signoptions",3]],[["error",4],["result",4,["bool","error"]],["bool",15]]],null,[[["progress",8],["option",4,["u32"]],["u32",15]],[["result",4,["error"]],["error",4]]],null,[[],["string",3]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],null,[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],null,null,null,null,null,null,null,null,null,[[],["fail",8]],[[]],[[]],[[],["addressvalidatorerror",4]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["addressvalidatorerror",4]],["bool",15]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[]],[[],["usize",15]],[[]],[[["addressvalidatorerror",4]],["bool",15]],[[]],[[],["string",3]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[["keychainkind",4],["hdkeypaths",6],["script",3]],[["result",4,["addressvalidatorerror"]],["addressvalidatorerror",4]]],[[]],null,null,null,null,null,null,[[]],[[]],[[]],[[]],[[]],[[]],[[],["largestfirstcoinselection",3]],[[]],[[["u64",15],["feerate",3],["weightedutxo",3],["vec",3,["weightedutxo"]]],[["result",4,["coinselectionresult","error"]],["error",4],["coinselectionresult",3]]],[[["u64",15],["feerate",3],["weightedutxo",3],["vec",3,["weightedutxo"]]],[["result",4,["coinselectionresult","error"]],["error",4],["coinselectionresult",3]]],[[["u64",15],["feerate",3],["weightedutxo",3],["vec",3,["weightedutxo"]]],[["result",4,["coinselectionresult","error"]],["error",4],["coinselectionresult",3]]],[[],["largestfirstcoinselection",3]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],null,[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[]],[[]],[[]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[],["u64",15]],[[["u64",15]]],null,[[],["u64",15]],[[]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],null,null,[[]],[[]],[[],[["option",4,["string"]],["string",3]]],[[["usize",15]]],[[["usize",15]]],[[],["string",3]],[[],["result",4]],[[["usize",15]]],[[["bool",15],["str",15],["wallet",3]],[["result",4,["str"]],["str",15]]],[[["formatter",3]],["result",6]],[[]],[[["str",15]],["result",4]],[[],["usize",15]],[[]],null,[[],["result",4]],[[],["string",3]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[["signerid",4],["arc",3,["signer"]],["signer",8],["signerordering",3]],[["arc",3,["signer"]],["option",4,["arc"]]]],null,[[],["fail",8]],[[["secp256k1",3]],["keymap",6]],null,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],["signerid",4]],[[],["signererror",4]],[[],["signerordering",3]],[[],["signerscontainer",3]],[[],["signoptions",3]],[[]],[[]],[[]],[[]],[[]],[[["signerid",4]],["ordering",4]],[[["signerordering",3]],["ordering",4]],[[]],[[],["signerscontainer",3]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],[["descriptorsecretkey",4],["option",4,["descriptorsecretkey"]]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["signerid",4]],["bool",15]],[[["signererror",4]],["bool",15]],[[["signerordering",3]],["bool",15]],[[["signerid",4]],[["option",4,["arc"]],["arc",3]]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["hash",3]],["signerid",4]],[[["fingerprint",3]],["signerid",4]],[[]],[[]],[[]],[[]],[[["keymap",6]],["signerscontainer",3]],[[]],[[],["u64",15]],[[]],[[["secp256k1",3]],["signerid",4]],[[],[["signerid",4],["vec",3,["signerid"]]]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[["signerid",4]],["bool",15]],[[["signerordering",3]],["bool",15]],[[]],[[["signerid",4]],[["ordering",4],["option",4,["ordering"]]]],[[["signerordering",3]],[["ordering",4],["option",4,["ordering"]]]],[[["signerordering",3],["signerid",4]],[["arc",3,["signer"]],["option",4,["arc"]]]],[[["option",4,["usize"]],["usize",15],["partiallysignedtransaction",3],["secp256k1",3]],[["result",4,["signererror"]],["signererror",4]]],[[],["bool",15]],[[],[["arc",3],["vec",3,["arc"]]]],[[]],[[]],[[]],[[]],[[]],[[],["string",3]],null,[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],[[]],[[]],null,null,null,[[],["u64",15]],null,null,null,null,null,null,null,null,null,null,null,null,[[["usize",15],["outpoint",3],["input",3]],[["error",4],["result",4,["error"]]]],[[]],[[["u64",15],["script",3]]],[[["outpoint",3]]],[[["outpoint",3]],[["error",4],["result",4,["error"]]]],[[],[["error",4],["result",4,["error"]]]],[[["script",3]],[["error",4],["result",4,["error"]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["changespendpolicy",4]]],[[],["createtx",3]],[[],["bumpfee",3]],[[]],[[],["txordering",4]],[[],["changespendpolicy",4]],[[]],[[]],[[]],[[]],[[]],[[["txordering",4]],["ordering",4]],[[["changespendpolicy",4]],["ordering",4]],[[["coinselectionalgorithm",8]],[["txbuilder",3],["coinselectionalgorithm",8]]],[[],["createtx",3]],[[],["bumpfee",3]],[[]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[]],[[["script",3]]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[]],[[["u32",15]]],[[["txordering",4]],["bool",15]],[[["changespendpolicy",4]],["bool",15]],[[["u64",15]]],[[["feerate",3]]],[[],[["error",4],["result",4,["error"]]]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[]],[[]],[[]],[[]],[[]],[[],["u64",15]],[[],["u64",15]],[[]],[[]],[[]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[]],[[["u32",15]]],[[]],[[]],[[["txordering",4]]],[[["txordering",4]],[["ordering",4],["option",4,["ordering"]]]],[[["changespendpolicy",4]],[["ordering",4],["option",4,["ordering"]]]],[[["vec",3,["usize"]],["string",3],["keychainkind",4],["btreemap",3,["string","vec"]]]],[[["vec",3]]],[[["sighashtype",4]]],[[["transaction",3]]],[[]],[[]],[[]],[[]],[[]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[["vec",3,["outpoint"]],["outpoint",3]]],[[["i32",15]]],[[]],[[]],[[]],[[]],[[]]],"p":[[4,"Error"],[4,"KeychainKind"],[4,"Utxo"],[3,"FeeRate"],[3,"LocalUtxo"],[3,"WeightedUtxo"],[3,"TransactionDetails"],[3,"ConfirmationTime"],[6,"MnemonicWithPassphrase"],[6,"DescriptorTemplateOut"],[6,"ExtendedDescriptor"],[8,"Vbytes"],[13,"InvalidU32Bytes"],[13,"Generic"],[13,"OutputBelowDustLimit"],[13,"MissingKeyOrigin"],[13,"Key"],[13,"SpendingPolicyRequired"],[13,"InvalidPolicyPathError"],[13,"Signer"],[13,"InvalidProgressValue"],[13,"InvalidOutpoint"],[13,"Descriptor"],[13,"AddressValidator"],[13,"Encode"],[13,"Miniscript"],[13,"Bip32"],[13,"Secp256k1"],[13,"Json"],[13,"Hex"],[13,"Psbt"],[13,"PsbtParse"],[13,"Electrum"],[13,"Esplora"],[13,"CompactFilters"],[13,"Sled"],[13,"Rusqlite"],[13,"InsufficientFunds"],[13,"InvalidNetwork"],[13,"FeeRateTooLow"],[13,"FeeTooLow"],[13,"Local"],[13,"Foreign"],[4,"Capability"],[8,"ConfigurableBlockchain"],[3,"NoopProgress"],[3,"LogProgress"],[8,"Blockchain"],[8,"Progress"],[4,"AnyBlockchain"],[4,"AnyBlockchainConfig"],[13,"Electrum"],[13,"Esplora"],[13,"CompactFilters"],[13,"Electrum"],[13,"Esplora"],[13,"CompactFilters"],[4,"CompactFiltersError"],[3,"Mempool"],[3,"BitcoinPeerConfig"],[3,"Peer"],[3,"CompactFiltersBlockchain"],[3,"CompactFiltersBlockchainConfig"],[13,"Db"],[13,"Io"],[13,"Bip158"],[13,"Time"],[13,"Global"],[3,"ElectrumBlockchain"],[3,"ElectrumBlockchainConfig"],[4,"EsploraError"],[3,"EsploraBlockchainConfig"],[3,"EsploraBlockchain"],[3,"EsploraGetHistory"],[13,"Ureq"],[13,"UreqTransport"],[13,"HttpResponse"],[13,"Io"],[13,"Parsing"],[13,"BitcoinEncoding"],[13,"Hex"],[13,"TransactionNotFound"],[13,"HeaderHeightNotFound"],[13,"HeaderHashNotFound"],[8,"BatchDatabase"],[8,"ConfigurableDatabase"],[3,"SqliteDatabase"],[8,"Database"],[8,"BatchOperations"],[4,"AnyBatch"],[4,"AnyDatabase"],[4,"AnyDatabaseConfig"],[3,"SledDbConfiguration"],[3,"SqliteDbConfiguration"],[13,"Memory"],[13,"Sled"],[13,"Sqlite"],[13,"Memory"],[13,"Sled"],[13,"Sqlite"],[13,"Memory"],[13,"Sled"],[13,"Sqlite"],[3,"MemoryDatabase"],[4,"Descriptor"],[4,"Legacy"],[4,"Segwitv0"],[3,"Miniscript"],[3,"DerivedDescriptorKey"],[8,"ScriptContext"],[8,"ExtractPolicy"],[8,"IntoWalletDescriptor"],[13,"Bare"],[13,"Pkh"],[13,"Wpkh"],[13,"Sh"],[13,"Wsh"],[4,"Error"],[13,"Key"],[13,"Policy"],[13,"InvalidDescriptorCharacter"],[13,"Bip32"],[13,"Base58"],[13,"Pk"],[13,"Miniscript"],[13,"Hex"],[4,"SatisfiableItem"],[4,"PolicyError"],[4,"Satisfaction"],[4,"BuildSatisfaction"],[3,"PkOrF"],[3,"Policy"],[3,"Condition"],[13,"Psbt"],[13,"PsbtTimelocks"],[13,"NotEnoughItemsSelected"],[13,"IndexOutOfRange"],[13,"Complete"],[13,"Partial"],[13,"PartialComplete"],[13,"Signature"],[13,"SignatureKey"],[13,"Sha256Preimage"],[13,"Hash256Preimage"],[13,"Ripemd160Preimage"],[13,"Hash160Preimage"],[13,"Thresh"],[13,"Multisig"],[13,"AbsoluteTimelock"],[13,"RelativeTimelock"],[3,"P2Pkh"],[3,"P2Wpkh_P2Sh"],[3,"P2Wpkh"],[3,"Bip44"],[3,"Bip44Public"],[3,"Bip49"],[3,"Bip49Public"],[3,"Bip84"],[3,"Bip84Public"],[8,"DescriptorTemplate"],[4,"KeyError"],[8,"GeneratableKey"],[4,"ScriptContextEnum"],[4,"ExtendedKey"],[4,"DescriptorSecretKey"],[4,"DescriptorPublicKey"],[8,"ExtScriptContext"],[3,"GeneratedKey"],[4,"DescriptorKey"],[3,"PrivateKeyGenerateOptions"],[3,"SortedMultiVec"],[3,"DescriptorSinglePub"],[3,"DescriptorSinglePriv"],[8,"GeneratableDefaultOptions"],[8,"IntoDescriptorKey"],[8,"DerivableKey"],[13,"SinglePub"],[13,"XPub"],[13,"SinglePriv"],[13,"XPrv"],[13,"Private"],[13,"Public"],[13,"Message"],[13,"Bip32"],[13,"Miniscript"],[4,"Language"],[4,"MnemonicType"],[3,"Seed"],[3,"Mnemonic"],[4,"AddressIndex"],[3,"Wallet"],[3,"AddressInfo"],[8,"IsDust"],[13,"Peek"],[13,"Reset"],[4,"AddressValidatorError"],[8,"AddressValidator"],[13,"Message"],[3,"CoinSelectionResult"],[3,"LargestFirstCoinSelection"],[3,"BranchAndBoundCoinSelection"],[8,"CoinSelectionAlgorithm"],[3,"WalletExport"],[3,"SignerOrdering"],[4,"SignerId"],[4,"SignerError"],[3,"SignersContainer"],[3,"SignOptions"],[8,"Signer"],[13,"PkHash"],[13,"Fingerprint"],[13,"Dummy"],[4,"TxOrdering"],[4,"ChangeSpendPolicy"],[3,"TxBuilder"],[3,"CreateTx"],[3,"BumpFee"]]}\ +}'); +if (window.initSearch) {window.initSearch(searchIndex)}; \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/search.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/search.js new file mode 100644 index 0000000000..91de2a155a --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/search.js @@ -0,0 +1 @@ +(function(){var itemTypes=["mod","externcrate","import","struct","enum","fn","type","static","trait","impl","tymethod","method","structfield","variant","macro","primitive","associatedtype","constant","associatedconstant","union","foreigntype","keyword","existential","attr","derive","traitalias"];var TY_PRIMITIVE=itemTypes.indexOf("primitive");var TY_KEYWORD=itemTypes.indexOf("keyword");function printTab(nb){if(nb===0||nb===1||nb===2){searchState.currentTab=nb}var nb_copy=nb;onEachLazy(document.getElementById("titles").childNodes,function(elem){if(nb_copy===0){addClass(elem,"selected")}else{removeClass(elem,"selected")}nb_copy-=1});onEachLazy(document.getElementById("results").childNodes,function(elem){if(nb===0){addClass(elem,"active")}else{removeClass(elem,"active")}nb-=1})}function removeEmptyStringsFromArray(x){for(var i=0,len=x.length;i-1){var obj=searchIndex[results[i].id];obj.lev=results[i].lev;var res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=obj.displayPath+obj.name;obj.fullPath+="|"+obj.ty;obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}return out}function sortResults(results,isType){var ar=[];for(var entry in results){if(hasOwnPropertyRustdoc(results,entry)){ar.push(results[entry])}}results=ar;var i,len,result;for(i=0,len=results.length;ib?+1:-1)}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}if((aaa.item.ty===TY_PRIMITIVE&&bbb.item.ty!==TY_KEYWORD)||(aaa.item.ty===TY_KEYWORD&&bbb.item.ty!==TY_PRIMITIVE)){return-1}if((bbb.item.ty===TY_PRIMITIVE&&aaa.item.ty!==TY_PRIMITIVE)||(bbb.item.ty===TY_KEYWORD&&aaa.item.ty!==TY_KEYWORD)){return 1}a=(aaa.item.desc==="");b=(bbb.item.desc==="");if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});for(i=0,len=results.length;i"));return{name:val.substring(0,val.indexOf("<")),generics:values.split(/\s*,\s*/),}}return{name:val,generics:[],}}function checkGenerics(obj,val){var tmp_lev,elem_name;if(val.generics.length>0){if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>=val.generics.length){var elems=Object.create(null);var elength=obj[GENERICS_DATA].length;for(var x=0;xGENERICS_DATA&&obj[GENERICS_DATA].length>0){var elems=Object.create(null);len=obj[GENERICS_DATA].length;for(x=0;xGENERICS_DATA&&obj[GENERICS_DATA].length!==0){var tmp_lev=checkGenerics(obj,val);if(tmp_lev<=MAX_LEV_DISTANCE){return tmp_lev}}}}else if(literalSearch){if((!val.generics||val.generics.length===0)&&obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>0){return obj[GENERICS_DATA].some(function(name){return name===val.name})}return false}lev_distance=Math.min(levenshtein(obj[NAME],val.name),lev_distance);if(lev_distance<=MAX_LEV_DISTANCE){lev_distance=Math.ceil((checkGenerics(obj,val)+lev_distance)/2)}else if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>0){var olength=obj[GENERICS_DATA].length;for(x=0;x0){var length=obj.type[INPUTS_DATA].length;for(var i=0;iOUTPUT_DATA){var ret=obj.type[OUTPUT_DATA];if(typeof ret[0]==="string"){ret=[ret]}for(var x=0,len=ret.length;xlength){return MAX_LEV_DISTANCE+1}for(var i=0;ilength){break}var lev_total=0;var aborted=false;for(var x=0;xMAX_LEV_DISTANCE){aborted=true;break}lev_total+=lev}if(!aborted){ret_lev=Math.min(ret_lev,Math.round(lev_total/clength))}}return ret_lev}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER)return true;if(filter===type)return true;var name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,desc:item.desc,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,}}function handleAliases(ret,query,filterCrates){var aliases=[];var crateAliases=[];if(filterCrates!==undefined){if(ALIASES[filterCrates]&&ALIASES[filterCrates][query.search]){var query_aliases=ALIASES[filterCrates][query.search];var len=query_aliases.length;for(var i=0;iMAX_RESULTS){ret.others.pop()}};onEach(aliases,pushFunc);onEach(crateAliases,pushFunc)}var nSearchWords=searchWords.length;var i,it;var ty;var fullId;var returned;var in_args;var len;if((val.charAt(0)==="\""||val.charAt(0)==="'")&&val.charAt(val.length-1)===val.charAt(0)){val=extractGenerics(val.substr(1,val.length-2));for(i=0;i")>-1){var trimmer=function(s){return s.trim()};var parts=val.split("->").map(trimmer);var input=parts[0];var inputs=input.split(",").map(trimmer).sort();for(i=0,len=inputs.length;i1?paths.length-1:1);var lev,j;for(j=0;j1){lev=checkPath(contains,paths[paths.length-1],ty);if(lev>MAX_LEV_DISTANCE){continue}else if(lev>0){lev_add=lev/10}}returned=MAX_LEV_DISTANCE+1;in_args=MAX_LEV_DISTANCE+1;var index=-1;lev=MAX_LEV_DISTANCE+1;fullId=ty.id;if(searchWords[j].indexOf(split[i])>-1||searchWords[j].indexOf(val)>-1||ty.normalizedName.indexOf(val)>-1){if(typePassesFilter(typeFilter,ty.ty)&&results[fullId]===undefined){index=ty.normalizedName.indexOf(val)}}if((lev=levenshtein(searchWords[j],val))<=MAX_LEV_DISTANCE){if(typePassesFilter(typeFilter,ty.ty)){lev+=1}else{lev=MAX_LEV_DISTANCE+1}}in_args=findArg(ty,valGenerics,false,typeFilter);returned=checkReturned(ty,valGenerics,false,typeFilter);lev+=lev_add;if(lev>0&&val.length>3&&searchWords[j].indexOf(val)>-1){if(val.length<6){lev-=1}else{lev=0}}if(in_args<=MAX_LEV_DISTANCE){if(results_in_args[fullId]===undefined){results_in_args[fullId]={id:j,index:index,lev:in_args,}}results_in_args[fullId].lev=Math.min(results_in_args[fullId].lev,in_args)}if(returned<=MAX_LEV_DISTANCE){if(results_returned[fullId]===undefined){results_returned[fullId]={id:j,index:index,lev:returned,}}results_returned[fullId].lev=Math.min(results_returned[fullId].lev,returned)}if(typePassesFilter(typeFilter,ty.ty)&&(index!==-1||lev<=MAX_LEV_DISTANCE)){if(index!==-1&&paths.length<2){lev=0}if(results[fullId]===undefined){results[fullId]={id:j,index:index,lev:lev,}}results[fullId].lev=Math.min(results[fullId].lev,lev)}}}var ret={"in_args":sortResults(results_in_args,true),"returned":sortResults(results_returned,true),"others":sortResults(results,false),};handleAliases(ret,query,filterCrates);return ret}function validateResult(name,path,keys,parent){for(var i=0,len=keys.length;i-1||path.indexOf(keys[i])>-1||(parent!==undefined&&parent.name!==undefined&&parent.name.toLowerCase().indexOf(keys[i])>-1)||levenshtein(name,keys[i])<=MAX_LEV_DISTANCE)){return false}}return true}function getQuery(raw){var matches,type,query;query=raw;matches=query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);if(matches){type=matches[1].replace(/^const$/,"constant");query=query.substring(matches[0].length)}return{raw:raw,query:query,type:type,id:query+type}}function nextTab(direction){var next=(searchState.currentTab+direction+3)%searchState.focusedByTab.length;searchState.focusedByTab[searchState.currentTab]=document.activeElement;printTab(next);focusSearchResult()}function focusSearchResult(){var target=searchState.focusedByTab[searchState.currentTab]||document.querySelectorAll(".search-results.active a").item(0)||document.querySelectorAll("#titles > button").item(searchState.currentTab);if(target){target.focus()}}function buildHrefAndPath(item){var displayPath;var href;var type=itemTypes[item.ty];var name=item.name;var path=item.path;if(type==="mod"){displayPath=path+"::";href=window.rootPath+path.replace(/::/g,"/")+"/"+name+"/index.html"}else if(type==="primitive"||type==="keyword"){displayPath="";href=window.rootPath+path.replace(/::/g,"/")+"/"+type+"."+name+".html"}else if(type==="externcrate"){displayPath="";href=window.rootPath+name+"/index.html"}else if(item.parent!==undefined){var myparent=item.parent;var anchor="#"+type+"."+name;var parentType=itemTypes[myparent.ty];var pageType=parentType;var pageName=myparent.name;if(parentType==="primitive"){displayPath=myparent.name+"::"}else if(type==="structfield"&&parentType==="variant"){var enumNameIdx=item.path.lastIndexOf("::");var enumName=item.path.substr(enumNameIdx+2);path=item.path.substr(0,enumNameIdx);displayPath=path+"::"+enumName+"::"+myparent.name+"::";anchor="#variant."+myparent.name+".field."+name;pageType="enum";pageName=enumName}else{displayPath=path+"::"+myparent.name+"::"}href=window.rootPath+path.replace(/::/g,"/")+"/"+pageType+"."+pageName+".html"+anchor}else{displayPath=item.path+"::";href=window.rootPath+item.path.replace(/::/g,"/")+"/"+type+"."+name+".html"}return[displayPath,href]}function escape(content){var h1=document.createElement("h1");h1.textContent=content;return h1.innerHTML}function pathSplitter(path){var tmp=""+path.replace(/::/g,"::");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}function addTab(array,query,display){var extraClass="";if(display===true){extraClass=" active"}var output=document.createElement("div");var duplicates={};var length=0;if(array.length>0){output.className="search-results "+extraClass;array.forEach(function(item){if(item.is_alias!==true){if(duplicates[item.fullPath]){return}duplicates[item.fullPath]=true}var name=item.name;var type=itemTypes[item.ty];length+=1;var extra="";if(type==="primitive"){extra=" (primitive type)"}else if(type==="keyword"){extra=" (keyword)"}var link=document.createElement("a");link.className="result-"+type;link.href=item.href;var wrapper=document.createElement("div");var resultName=document.createElement("div");resultName.className="result-name";if(item.is_alias){var alias=document.createElement("span");alias.className="alias";var bold=document.createElement("b");bold.innerText=item.alias;alias.appendChild(bold);alias.insertAdjacentHTML("beforeend"," - see ");resultName.appendChild(alias)}resultName.insertAdjacentHTML("beforeend",item.displayPath+""+name+extra+"");wrapper.appendChild(resultName);var description=document.createElement("div");description.className="desc";var spanDesc=document.createElement("span");spanDesc.insertAdjacentHTML("beforeend",item.desc);description.appendChild(spanDesc);wrapper.appendChild(description);link.appendChild(wrapper);output.appendChild(link)})}else{output.className="search-failed"+extraClass;output.innerHTML="No results :(
"+"Try on DuckDuckGo?

"+"Or try looking in one of these:"}return[output,length]}function makeTabHeader(tabNb,text,nbElems){if(searchState.currentTab===tabNb){return""}return""}function showResults(results,go_to_first){var search=searchState.outputElement();if(go_to_first||(results.others.length===1&&getSettingValue("go-to-only-result")==="true"&&(!search.firstChild||search.firstChild.innerText!==searchState.loadingText))){var elem=document.createElement("a");elem.href=results.others[0].href;removeClass(elem,"active");document.body.appendChild(elem);elem.click();return}var query=getQuery(searchState.input.value);currentResults=query.id;var ret_others=addTab(results.others,query);var ret_in_args=addTab(results.in_args,query,false);var ret_returned=addTab(results.returned,query,false);var currentTab=searchState.currentTab;if((currentTab===0&&ret_others[1]===0)||(currentTab===1&&ret_in_args[1]===0)||(currentTab===2&&ret_returned[1]===0)){if(ret_others[1]!==0){currentTab=0}else if(ret_in_args[1]!==0){currentTab=1}else if(ret_returned[1]!==0){currentTab=2}}var output="

Results for "+escape(query.query)+(query.type?" (type: "+escape(query.type)+")":"")+"

"+"
"+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
";var resultsElem=document.createElement("div");resultsElem.id="results";resultsElem.appendChild(ret_others[0]);resultsElem.appendChild(ret_in_args[0]);resultsElem.appendChild(ret_returned[0]);search.innerHTML=output;search.appendChild(resultsElem);searchState.focusedByTab=[null,null,null];searchState.showResults(search);var elems=document.getElementById("titles").childNodes;elems[0].onclick=function(){printTab(0)};elems[1].onclick=function(){printTab(1)};elems[2].onclick=function(){printTab(2)};printTab(currentTab)}function execSearch(query,searchWords,filterCrates){function getSmallest(arrays,positions,notDuplicates){var start=null;for(var it=0,len=positions.length;itpositions[it]&&(start===null||start>arrays[it][positions[it]].lev)&&!notDuplicates[arrays[it][positions[it]].fullPath]){start=arrays[it][positions[it]].lev}}return start}function mergeArrays(arrays){var ret=[];var positions=[];var notDuplicates={};for(var x=0,arrays_len=arrays.length;xpositions[x]&&arrays[x][positions[x]].lev===smallest&&!notDuplicates[arrays[x][positions[x]].fullPath]){ret.push(arrays[x][positions[x]]);notDuplicates[arrays[x][positions[x]].fullPath]=true;positions[x]+=1}}}return ret}function tokenizeQuery(raw){var i,matched;var l=raw.length;var depth=0;var nextAngle=/(<|>)/g;var ret=[];var start=0;for(i=0;i'){depth+=1}break;case">":if(depth>0){depth-=1}break;case",":if(depth===0){ret.push(raw.substring(start,i));start=i+1}break}}if(start!==i){ret.push(raw.substring(start,i))}return ret}var queries=tokenizeQuery(query.raw);var results={"in_args":[],"returned":[],"others":[],};for(var i=0,len=queries.length;i1){return{"in_args":mergeArrays(results.in_args),"returned":mergeArrays(results.returned),"others":mergeArrays(results.others),}}return{"in_args":results.in_args[0],"returned":results.returned[0],"others":results.others[0],}}function getFilterCrates(){var elem=document.getElementById("crate-search");if(elem&&elem.value!=="All crates"&&hasOwnPropertyRustdoc(rawSearchIndex,elem.value)){return elem.value}return undefined}function search(e,forced){var params=searchState.getQueryStringParams();var query=getQuery(searchState.input.value.trim());if(e){e.preventDefault()}if(query.query.length===0){return}if(!forced&&query.id===currentResults){if(query.query.length>0){searchState.putBackSearch(searchState.input)}return}searchState.title="Results for "+query.query+" - Rust";if(searchState.browserSupportsHistoryApi()){var newURL=getNakedUrl()+"?search="+encodeURIComponent(query.raw)+window.location.hash;if(!history.state&&!params.search){history.pushState(query,"",newURL)}else{history.replaceState(query,"",newURL)}}var filterCrates=getFilterCrates();showResults(execSearch(query,index,filterCrates),params.go_to_first)}function buildIndex(rawSearchIndex){searchIndex=[];var searchWords=[];var i,word;var currentIndex=0;var id=0;for(var crate in rawSearchIndex){if(!hasOwnPropertyRustdoc(rawSearchIndex,crate)){continue}var crateSize=0;searchWords.push(crate);var crateRow={crate:crate,ty:1,name:crate,path:"",desc:rawSearchIndex[crate].doc,parent:undefined,type:null,id:id,normalizedName:crate.indexOf("_")===-1?crate:crate.replace(/_/g,""),};id+=1;searchIndex.push(crateRow);currentIndex+=1;var itemTypes=rawSearchIndex[crate].t;var itemNames=rawSearchIndex[crate].n;var itemPaths=rawSearchIndex[crate].q;var itemDescs=rawSearchIndex[crate].d;var itemParentIdxs=rawSearchIndex[crate].i;var itemFunctionSearchTypes=rawSearchIndex[crate].f;var paths=rawSearchIndex[crate].p;var aliases=rawSearchIndex[crate].a;var len=paths.length;for(i=0;i0?paths[itemParentIdxs[i]-1]:undefined,type:itemFunctionSearchTypes[i],id:id,normalizedName:word.indexOf("_")===-1?word:word.replace(/_/g,""),};id+=1;searchIndex.push(row);lastPath=row.path;crateSize+=1}if(aliases){ALIASES[crate]={};var j,local_aliases;for(var alias_name in aliases){if(!hasOwnPropertyRustdoc(aliases,alias_name)){continue}if(!hasOwnPropertyRustdoc(ALIASES[crate],alias_name)){ALIASES[crate][alias_name]=[]}local_aliases=aliases[alias_name];for(j=0,len=local_aliases.length;j0){searchState.input.value=params.search;search(e)}else{searchState.input.value="";searchState.hideResults()}})}window.onpageshow=function(){var qSearch=searchState.getQueryStringParams().search;if(searchState.input.value===""&&qSearch){searchState.input.value=qSearch}search()}}index=buildIndex(rawSearchIndex);registerSearchEvents();if(searchState.getQueryStringParams().search){search()}};if(window.searchIndex!==undefined){initSearch(window.searchIndex)}})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/settings.css b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/settings.css new file mode 100644 index 0000000000..670986588e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/settings.css @@ -0,0 +1 @@ +.setting-line{padding:5px;position:relative;}.setting-line>div{display:inline-block;vertical-align:top;font-size:17px;padding-top:2px;}.setting-line>.title{font-size:19px;width:100%;max-width:none;border-bottom:1px solid;}.toggle{position:relative;display:inline-block;width:45px;height:27px;margin-right:20px;}.toggle input{opacity:0;position:absolute;}.select-wrapper{float:right;position:relative;height:27px;min-width:25%;}.select-wrapper select{appearance:none;-moz-appearance:none;-webkit-appearance:none;background:none;border:2px solid #ccc;padding-right:28px;width:100%;}.select-wrapper img{pointer-events:none;position:absolute;right:0;bottom:0;background:#ccc;height:100%;width:28px;padding:0px 4px;}.select-wrapper select option{color:initial;}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.3s;transition:.3s;}.slider:before{position:absolute;content:"";height:19px;width:19px;left:4px;bottom:4px;background-color:white;-webkit-transition:.3s;transition:.3s;}input:checked+.slider{background-color:#2196F3;}input:focus+.slider{box-shadow:0 0 0 2px #0a84ff,0 0 0 6px rgba(10,132,255,0.3);}input:checked+.slider:before{-webkit-transform:translateX(19px);-ms-transform:translateX(19px);transform:translateX(19px);}.setting-line>.sub-settings{padding-left:42px;width:100%;display:block;} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/settings.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/settings.html new file mode 100644 index 0000000000..e04d80ec2e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/settings.html @@ -0,0 +1,4 @@ +Rustdoc settings

Rustdoc settings

Theme preferences
Use system theme
Preferred dark theme
Preferred light theme
+
Auto-hide item contents for large items.
Auto-hide item methods' documentation
Auto-hide trait implementation documentation
Directly go to item in search if there is only one result
Show line numbers on code examples
Disable keyboard shortcuts
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/settings.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/settings.js new file mode 100644 index 0000000000..b4d6fdcd78 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/settings.js @@ -0,0 +1 @@ +(function(){function changeSetting(settingName,value){updateLocalStorage("rustdoc-"+settingName,value);switch(settingName){case"preferred-dark-theme":case"preferred-light-theme":case"use-system-theme":updateSystemTheme();break}}function handleKey(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey){return}switch(getVirtualKey(ev)){case"Enter":case"Return":case"Space":ev.target.checked=!ev.target.checked;ev.preventDefault();break}}function setEvents(){onEachLazy(document.getElementsByClassName("slider"),function(elem){var toggle=elem.previousElementSibling;var settingId=toggle.id;var settingValue=getSettingValue(settingId);if(settingValue!==null){toggle.checked=settingValue==="true"}toggle.onchange=function(){changeSetting(this.id,this.checked)};toggle.onkeyup=handleKey;toggle.onkeyrelease=handleKey});onEachLazy(document.getElementsByClassName("select-wrapper"),function(elem){var select=elem.getElementsByTagName("select")[0];var settingId=select.id;var settingValue=getSettingValue(settingId);if(settingValue!==null){select.value=settingValue}select.onchange=function(){changeSetting(this.id,this.value)}})}window.addEventListener("DOMContentLoaded",setEvents)})() \ 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 new file mode 100644 index 0000000000..34aad7c3a4 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/source-files.js @@ -0,0 +1,3 @@ +var N = null;var sourcesIndex = {}; +sourcesIndex["bdk"] = {"name":"","dirs":[{"name":"blockchain","dirs":[{"name":"compact_filters","files":["mod.rs","peer.rs","store.rs","sync.rs"]},{"name":"esplora","files":["mod.rs","ureq.rs"]}],"files":["any.rs","electrum.rs","mod.rs","utils.rs"]},{"name":"database","files":["any.rs","keyvalue.rs","memory.rs","mod.rs","sqlite.rs"]},{"name":"descriptor","files":["checksum.rs","derived.rs","dsl.rs","error.rs","mod.rs","policy.rs","template.rs"]},{"name":"keys","files":["bip39.rs","mod.rs"]},{"name":"psbt","files":["mod.rs"]},{"name":"testutils","files":["mod.rs"]},{"name":"wallet","files":["address_validator.rs","coin_selection.rs","export.rs","mod.rs","signer.rs","time.rs","tx_builder.rs","utils.rs"]}],"files":["error.rs","lib.rs","types.rs"]}; +createSourceSidebar(); diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/source-script.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/source-script.js new file mode 100644 index 0000000000..5dc8fee0f2 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/source-script.js @@ -0,0 +1 @@ +(function(){function getCurrentFilePath(){var parts=window.location.pathname.split("/");var rootPathParts=window.rootPath.split("/");for(var i=0,len=rootPathParts.length;i"){sidebar.style.left="";this.style.left="";child.innerText="<";updateLocalStorage("rustdoc-source-sidebar-show","true")}else{sidebar.style.left="-300px";this.style.left="0";child.innerText=">";updateLocalStorage("rustdoc-source-sidebar-show","false")}}function createSidebarToggle(){var sidebarToggle=document.createElement("div");sidebarToggle.id="sidebar-toggle";sidebarToggle.onclick=toggleSidebar;var inner1=document.createElement("div");inner1.style.position="relative";var inner2=document.createElement("div");inner2.style.paddingTop="3px";if(getCurrentValue("rustdoc-source-sidebar-show")==="true"){inner2.innerText="<"}else{inner2.innerText=">";sidebarToggle.style.left="0"}inner1.appendChild(inner2);sidebarToggle.appendChild(inner1);return sidebarToggle}function createSourceSidebar(){if(!window.rootPath.endsWith("/")){window.rootPath+="/"}var main=document.getElementById("main");var sidebarToggle=createSidebarToggle();main.insertBefore(sidebarToggle,main.firstChild);var sidebar=document.createElement("div");sidebar.id="source-sidebar";if(getCurrentValue("rustdoc-source-sidebar-show")!=="true"){sidebar.style.left="-300px"}var currentFile=getCurrentFilePath();var hasFoundFile=false;var title=document.createElement("div");title.className="title";title.innerText="Files";sidebar.appendChild(title);Object.keys(sourcesIndex).forEach(function(key){sourcesIndex[key].name=key;hasFoundFile=createDirEntry(sourcesIndex[key],sidebar,"",currentFile,hasFoundFile)});main.insertBefore(sidebar,main.firstChild);var selected_elem=sidebar.getElementsByClassName("selected")[0];if(typeof selected_elem!=="undefined"){selected_elem.focus()}}var lineNumbersRegex=/^#?(\d+)(?:-(\d+))?$/;function highlightSourceLines(scrollTo,match){if(typeof match==="undefined"){match=window.location.hash.match(lineNumbersRegex)}if(!match){return}var from=parseInt(match[1],10);var to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(tocur_line_id){var tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());window.addEventListener("hashchange",function(){var match=window.location.hash.match(lineNumbersRegex);if(match){return highlightSourceLines(false,match)}});onEachLazy(document.getElementsByClassName("line-numbers"),function(el){el.addEventListener("click",handleSourceHighlight)});highlightSourceLines(true);window.createSourceSidebar=createSourceSidebar})() \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/any.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/any.rs.html new file mode 100644 index 0000000000..977b1afcca --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/any.rs.html @@ -0,0 +1,510 @@ +any.rs - source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+//! Runtime-checked blockchain types
+//!
+//! This module provides the implementation of [`AnyBlockchain`] which allows switching the
+//! inner [`Blockchain`] type at runtime.
+//!
+//! ## Example
+//!
+//! In this example both `wallet_electrum` and `wallet_esplora` have the same type of
+//! `Wallet<AnyBlockchain, MemoryDatabase>`. This means that they could both, for instance, be
+//! assigned to a struct member.
+//!
+//! ```no_run
+//! # use bitcoin::Network;
+//! # use bdk::blockchain::*;
+//! # use bdk::database::MemoryDatabase;
+//! # use bdk::Wallet;
+//! # #[cfg(feature = "electrum")]
+//! # {
+//! let electrum_blockchain = ElectrumBlockchain::from(electrum_client::Client::new("...")?);
+//! let wallet_electrum: Wallet<AnyBlockchain, _> = Wallet::new(
+//!     "...",
+//!     None,
+//!     Network::Testnet,
+//!     MemoryDatabase::default(),
+//!     electrum_blockchain.into(),
+//! )?;
+//! # }
+//!
+//! # #[cfg(all(feature = "esplora", feature = "ureq"))]
+//! # {
+//! let esplora_blockchain = EsploraBlockchain::new("...", 20);
+//! let wallet_esplora: Wallet<AnyBlockchain, _> = Wallet::new(
+//!     "...",
+//!     None,
+//!     Network::Testnet,
+//!     MemoryDatabase::default(),
+//!     esplora_blockchain.into(),
+//! )?;
+//! # }
+//!
+//! # Ok::<(), bdk::Error>(())
+//! ```
+//!
+//! When paired with the use of [`ConfigurableBlockchain`], it allows creating wallets with any
+//! blockchain type supported using a single line of code:
+//!
+//! ```no_run
+//! # use bitcoin::Network;
+//! # use bdk::blockchain::*;
+//! # use bdk::database::MemoryDatabase;
+//! # use bdk::Wallet;
+//! # #[cfg(all(feature = "esplora", feature = "ureq"))]
+//! # {
+//! let config = serde_json::from_str("...")?;
+//! let blockchain = AnyBlockchain::from_config(&config)?;
+//! let wallet = Wallet::new(
+//!     "...",
+//!     None,
+//!     Network::Testnet,
+//!     MemoryDatabase::default(),
+//!     blockchain,
+//! )?;
+//! # }
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use super::*;
+
+macro_rules! impl_from {
+    ( $from:ty, $to:ty, $variant:ident, $( $cfg:tt )* ) => {
+        $( $cfg )*
+        impl From<$from> for $to {
+            fn from(inner: $from) -> Self {
+                <$to>::$variant(inner)
+            }
+        }
+    };
+}
+
+macro_rules! impl_inner_method {
+    ( $self:expr, $name:ident $(, $args:expr)* ) => {
+        match $self {
+            #[cfg(feature = "electrum")]
+            AnyBlockchain::Electrum(inner) => inner.$name( $($args, )* ),
+            #[cfg(feature = "esplora")]
+            AnyBlockchain::Esplora(inner) => inner.$name( $($args, )* ),
+            #[cfg(feature = "compact_filters")]
+            AnyBlockchain::CompactFilters(inner) => inner.$name( $($args, )* ),
+            #[cfg(feature = "rpc")]
+            AnyBlockchain::Rpc(inner) => inner.$name( $($args, )* ),
+        }
+    }
+}
+
+/// Type that can contain any of the [`Blockchain`] types defined by the library
+///
+/// It allows switching backend at runtime
+///
+/// See [this module](crate::blockchain::any)'s documentation for a usage example.
+pub enum AnyBlockchain {
+    #[cfg(feature = "electrum")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
+    /// Electrum client
+    Electrum(electrum::ElectrumBlockchain),
+    #[cfg(feature = "esplora")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
+    /// Esplora client
+    Esplora(esplora::EsploraBlockchain),
+    #[cfg(feature = "compact_filters")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
+    /// Compact filters client
+    CompactFilters(compact_filters::CompactFiltersBlockchain),
+    #[cfg(feature = "rpc")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "rpc")))]
+    /// RPC client
+    Rpc(rpc::RpcBlockchain),
+}
+
+#[maybe_async]
+impl Blockchain for AnyBlockchain {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        maybe_await!(impl_inner_method!(self, get_capabilities))
+    }
+
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(impl_inner_method!(self, setup, database, progress_update))
+    }
+    fn sync<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(impl_inner_method!(self, sync, database, progress_update))
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        maybe_await!(impl_inner_method!(self, get_tx, txid))
+    }
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        maybe_await!(impl_inner_method!(self, broadcast, tx))
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        maybe_await!(impl_inner_method!(self, get_height))
+    }
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
+        maybe_await!(impl_inner_method!(self, estimate_fee, target))
+    }
+}
+
+impl_from!(electrum::ElectrumBlockchain, AnyBlockchain, Electrum, #[cfg(feature = "electrum")]);
+impl_from!(esplora::EsploraBlockchain, AnyBlockchain, Esplora, #[cfg(feature = "esplora")]);
+impl_from!(compact_filters::CompactFiltersBlockchain, AnyBlockchain, CompactFilters, #[cfg(feature = "compact_filters")]);
+impl_from!(rpc::RpcBlockchain, AnyBlockchain, Rpc, #[cfg(feature = "rpc")]);
+
+/// Type that can contain any of the blockchain configurations defined by the library
+///
+/// This allows storing a single configuration that can be loaded into an [`AnyBlockchain`]
+/// instance. Wallets that plan to offer users the ability to switch blockchain backend at runtime
+/// will find this particularly useful.
+///
+/// This type can be serialized from a JSON object like:
+///
+/// ```
+/// # #[cfg(feature = "electrum")]
+/// # {
+/// use bdk::blockchain::{electrum::ElectrumBlockchainConfig, AnyBlockchainConfig};
+/// let config: AnyBlockchainConfig = serde_json::from_str(
+///     r#"{
+///    "type" : "electrum",
+///    "url" : "ssl://electrum.blockstream.info:50002",
+///    "retry": 2,
+///    "stop_gap": 20
+/// }"#,
+/// )
+/// .unwrap();
+/// assert_eq!(
+///     config,
+///     AnyBlockchainConfig::Electrum(ElectrumBlockchainConfig {
+///         url: "ssl://electrum.blockstream.info:50002".into(),
+///         retry: 2,
+///         socks5: None,
+///         timeout: None,
+///         stop_gap: 20,
+///     })
+/// );
+/// # }
+/// ```
+#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq)]
+#[serde(tag = "type", rename_all = "snake_case")]
+pub enum AnyBlockchainConfig {
+    #[cfg(feature = "electrum")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
+    /// Electrum client
+    Electrum(electrum::ElectrumBlockchainConfig),
+    #[cfg(feature = "esplora")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
+    /// Esplora client
+    Esplora(esplora::EsploraBlockchainConfig),
+    #[cfg(feature = "compact_filters")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
+    /// Compact filters client
+    CompactFilters(compact_filters::CompactFiltersBlockchainConfig),
+    #[cfg(feature = "rpc")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "rpc")))]
+    /// RPC client configuration
+    Rpc(rpc::RpcConfig),
+}
+
+impl ConfigurableBlockchain for AnyBlockchain {
+    type Config = AnyBlockchainConfig;
+
+    fn from_config(config: &Self::Config) -> Result<Self, Error> {
+        Ok(match config {
+            #[cfg(feature = "electrum")]
+            AnyBlockchainConfig::Electrum(inner) => {
+                AnyBlockchain::Electrum(electrum::ElectrumBlockchain::from_config(inner)?)
+            }
+            #[cfg(feature = "esplora")]
+            AnyBlockchainConfig::Esplora(inner) => {
+                AnyBlockchain::Esplora(esplora::EsploraBlockchain::from_config(inner)?)
+            }
+            #[cfg(feature = "compact_filters")]
+            AnyBlockchainConfig::CompactFilters(inner) => AnyBlockchain::CompactFilters(
+                compact_filters::CompactFiltersBlockchain::from_config(inner)?,
+            ),
+            #[cfg(feature = "rpc")]
+            AnyBlockchainConfig::Rpc(inner) => {
+                AnyBlockchain::Rpc(rpc::RpcBlockchain::from_config(inner)?)
+            }
+        })
+    }
+}
+
+impl_from!(electrum::ElectrumBlockchainConfig, AnyBlockchainConfig, Electrum, #[cfg(feature = "electrum")]);
+impl_from!(esplora::EsploraBlockchainConfig, AnyBlockchainConfig, Esplora, #[cfg(feature = "esplora")]);
+impl_from!(compact_filters::CompactFiltersBlockchainConfig, AnyBlockchainConfig, CompactFilters, #[cfg(feature = "compact_filters")]);
+impl_from!(rpc::RpcConfig, AnyBlockchainConfig, Rpc, #[cfg(feature = "rpc")]);
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/mod.rs.html new file mode 100644 index 0000000000..4927399c69 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/mod.rs.html @@ -0,0 +1,1140 @@ +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
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+//! Compact Filters
+//!
+//! This module contains a multithreaded implementation of an [`Blockchain`] backend that
+//! uses BIP157 (aka "Neutrino") to populate the wallet's [database](crate::database::Database)
+//! by downloading compact filters from the P2P network.
+//!
+//! Since there are currently very few peers "in the wild" that advertise the required service
+//! flag, this implementation requires that one or more known peers are provided by the user.
+//! No dns or other kinds of peer discovery are done internally.
+//!
+//! Moreover, this module doesn't currently support detecting and resolving conflicts between
+//! messages received by different peers. Thus, it's recommended to use this module by only
+//! connecting to a single peer at a time, optionally by opening multiple connections if it's
+//! desirable to use multiple threads at once to sync in parallel.
+//!
+//! This is an **EXPERIMENTAL** feature, API and other major changes are expected.
+//!
+//! ## Example
+//!
+//! ```no_run
+//! # use std::sync::Arc;
+//! # use bitcoin::*;
+//! # use bdk::*;
+//! # use bdk::blockchain::compact_filters::*;
+//! let num_threads = 4;
+//!
+//! let mempool = Arc::new(Mempool::default());
+//! let peers = (0..num_threads)
+//!     .map(|_| {
+//!         Peer::connect(
+//!             "btcd-mainnet.lightning.computer:8333",
+//!             Arc::clone(&mempool),
+//!             Network::Bitcoin,
+//!         )
+//!     })
+//!     .collect::<Result<_, _>>()?;
+//! let blockchain = CompactFiltersBlockchain::new(peers, "./wallet-filters", Some(500_000))?;
+//! # Ok::<(), CompactFiltersError>(())
+//! ```
+
+use std::collections::HashSet;
+use std::fmt;
+use std::path::Path;
+use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::{Arc, Mutex};
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use bitcoin::network::message_blockdata::Inventory;
+use bitcoin::{Network, OutPoint, Transaction, Txid};
+
+use rocksdb::{Options, SliceTransform, DB};
+
+mod peer;
+mod store;
+mod sync;
+
+use super::{Blockchain, Capability, ConfigurableBlockchain, Progress};
+use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
+use crate::error::Error;
+use crate::types::{KeychainKind, LocalUtxo, TransactionDetails};
+use crate::{ConfirmationTime, FeeRate};
+
+use peer::*;
+use store::*;
+use sync::*;
+
+pub use peer::{Mempool, Peer};
+
+const SYNC_HEADERS_COST: f32 = 1.0;
+const SYNC_FILTERS_COST: f32 = 11.6 * 1_000.0;
+const PROCESS_BLOCKS_COST: f32 = 20_000.0;
+
+/// Structure implementing the required blockchain traits
+///
+/// ## Example
+/// See the [`blockchain::compact_filters`](crate::blockchain::compact_filters) module for a usage example.
+#[derive(Debug)]
+pub struct CompactFiltersBlockchain {
+    peers: Vec<Arc<Peer>>,
+    headers: Arc<ChainStore<Full>>,
+    skip_blocks: Option<usize>,
+}
+
+impl CompactFiltersBlockchain {
+    /// Construct a new instance given a list of peers, a path to store headers and block
+    /// filters downloaded during the sync and optionally a number of blocks to ignore starting
+    /// from the genesis while scanning for the wallet's outputs.
+    ///
+    /// For each [`Peer`] specified a new thread will be spawned to download and verify the filters
+    /// in parallel. It's currently recommended to only connect to a single peer to avoid
+    /// inconsistencies in the data returned, optionally with multiple connections in parallel to
+    /// speed-up the sync process.
+    pub fn new<P: AsRef<Path>>(
+        peers: Vec<Peer>,
+        storage_dir: P,
+        skip_blocks: Option<usize>,
+    ) -> Result<Self, CompactFiltersError> {
+        if peers.is_empty() {
+            return Err(CompactFiltersError::NoPeers);
+        }
+
+        let mut opts = Options::default();
+        opts.create_if_missing(true);
+        opts.set_prefix_extractor(SliceTransform::create_fixed_prefix(16));
+
+        let network = peers[0].get_network();
+
+        let cfs = DB::list_cf(&opts, &storage_dir).unwrap_or_else(|_| vec!["default".to_string()]);
+        let db = DB::open_cf(&opts, &storage_dir, &cfs)?;
+        let headers = Arc::new(ChainStore::new(db, network)?);
+
+        // try to recover partial snapshots
+        for cf_name in &cfs {
+            if !cf_name.starts_with("_headers:") {
+                continue;
+            }
+
+            info!("Trying to recover: {:?}", cf_name);
+            headers.recover_snapshot(cf_name)?;
+        }
+
+        Ok(CompactFiltersBlockchain {
+            peers: peers.into_iter().map(Arc::new).collect(),
+            headers,
+            skip_blocks,
+        })
+    }
+
+    /// Process a transaction by looking for inputs that spend from a UTXO in the database or
+    /// outputs that send funds to a know script_pubkey.
+    fn process_tx<D: BatchDatabase>(
+        &self,
+        database: &mut D,
+        tx: &Transaction,
+        height: Option<u32>,
+        timestamp: Option<u64>,
+        internal_max_deriv: &mut Option<u32>,
+        external_max_deriv: &mut Option<u32>,
+    ) -> Result<(), Error> {
+        let mut updates = database.begin_batch();
+
+        let mut incoming: u64 = 0;
+        let mut outgoing: u64 = 0;
+
+        let mut inputs_sum: u64 = 0;
+        let mut outputs_sum: u64 = 0;
+
+        // look for our own inputs
+        for (i, input) in tx.input.iter().enumerate() {
+            if let Some(previous_output) = database.get_previous_output(&input.previous_output)? {
+                inputs_sum += previous_output.value;
+
+                if database.is_mine(&previous_output.script_pubkey)? {
+                    outgoing += previous_output.value;
+
+                    debug!("{} input #{} is mine, removing from utxo", tx.txid(), i);
+                    updates.del_utxo(&input.previous_output)?;
+                }
+            }
+        }
+
+        for (i, output) in tx.output.iter().enumerate() {
+            // to compute the fees later
+            outputs_sum += output.value;
+
+            // this output is ours, we have a path to derive it
+            if let Some((keychain, child)) =
+                database.get_path_from_script_pubkey(&output.script_pubkey)?
+            {
+                debug!("{} output #{} is mine, adding utxo", tx.txid(), i);
+                updates.set_utxo(&LocalUtxo {
+                    outpoint: OutPoint::new(tx.txid(), i as u32),
+                    txout: output.clone(),
+                    keychain,
+                })?;
+                incoming += output.value;
+
+                if keychain == KeychainKind::Internal
+                    && (internal_max_deriv.is_none() || child > internal_max_deriv.unwrap_or(0))
+                {
+                    *internal_max_deriv = Some(child);
+                } else if keychain == KeychainKind::External
+                    && (external_max_deriv.is_none() || child > external_max_deriv.unwrap_or(0))
+                {
+                    *external_max_deriv = Some(child);
+                }
+            }
+        }
+
+        if incoming > 0 || outgoing > 0 {
+            let tx = TransactionDetails {
+                txid: tx.txid(),
+                transaction: Some(tx.clone()),
+                received: incoming,
+                sent: outgoing,
+                confirmation_time: ConfirmationTime::new(height, timestamp),
+                verified: height.is_some(),
+                fee: Some(inputs_sum.saturating_sub(outputs_sum)),
+            };
+
+            info!("Saving tx {}", tx.txid);
+            updates.set_tx(&tx)?;
+        }
+
+        database.commit_batch(updates)?;
+
+        Ok(())
+    }
+}
+
+impl Blockchain for CompactFiltersBlockchain {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        vec![Capability::FullHistory].into_iter().collect()
+    }
+
+    #[allow(clippy::mutex_atomic)] // Mutex is easier to understand than a CAS loop.
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        let first_peer = &self.peers[0];
+
+        let skip_blocks = self.skip_blocks.unwrap_or(0);
+
+        let cf_sync = Arc::new(CfSync::new(Arc::clone(&self.headers), skip_blocks, 0x00)?);
+
+        let initial_height = self.headers.get_height()?;
+        let total_bundles = (first_peer.get_version().start_height as usize)
+            .checked_sub(skip_blocks)
+            .map(|x| x / 1000)
+            .unwrap_or(0)
+            + 1;
+        let expected_bundles_to_sync = total_bundles.saturating_sub(cf_sync.pruned_bundles()?);
+
+        let headers_cost = (first_peer.get_version().start_height as usize)
+            .saturating_sub(initial_height) as f32
+            * SYNC_HEADERS_COST;
+        let filters_cost = expected_bundles_to_sync as f32 * SYNC_FILTERS_COST;
+
+        let total_cost = headers_cost + filters_cost + PROCESS_BLOCKS_COST;
+
+        if let Some(snapshot) = sync::sync_headers(
+            Arc::clone(&first_peer),
+            Arc::clone(&self.headers),
+            |new_height| {
+                let local_headers_cost =
+                    new_height.saturating_sub(initial_height) as f32 * SYNC_HEADERS_COST;
+                progress_update.update(
+                    local_headers_cost / total_cost * 100.0,
+                    Some(format!("Synced headers to {}", new_height)),
+                )
+            },
+        )? {
+            if snapshot.work()? > self.headers.work()? {
+                info!("Applying snapshot with work: {}", snapshot.work()?);
+                self.headers.apply_snapshot(snapshot)?;
+            }
+        }
+
+        let synced_height = self.headers.get_height()?;
+        let buried_height = synced_height.saturating_sub(sync::BURIED_CONFIRMATIONS);
+        info!("Synced headers to height: {}", synced_height);
+
+        cf_sync.prepare_sync(Arc::clone(&first_peer))?;
+
+        let all_scripts = Arc::new(
+            database
+                .iter_script_pubkeys(None)?
+                .into_iter()
+                .map(|s| s.to_bytes())
+                .collect::<Vec<_>>(),
+        );
+
+        #[allow(clippy::mutex_atomic)]
+        let last_synced_block = Arc::new(Mutex::new(synced_height));
+
+        let synced_bundles = Arc::new(AtomicUsize::new(0));
+        let progress_update = Arc::new(Mutex::new(progress_update));
+
+        let mut threads = Vec::with_capacity(self.peers.len());
+        for peer in &self.peers {
+            let cf_sync = Arc::clone(&cf_sync);
+            let peer = Arc::clone(&peer);
+            let headers = Arc::clone(&self.headers);
+            let all_scripts = Arc::clone(&all_scripts);
+            let last_synced_block = Arc::clone(&last_synced_block);
+            let progress_update = Arc::clone(&progress_update);
+            let synced_bundles = Arc::clone(&synced_bundles);
+
+            let thread = std::thread::spawn(move || {
+                cf_sync.capture_thread_for_sync(
+                    peer,
+                    |block_hash, filter| {
+                        if !filter
+                            .match_any(block_hash, &mut all_scripts.iter().map(AsRef::as_ref))?
+                        {
+                            return Ok(false);
+                        }
+
+                        let block_height = headers.get_height_for(block_hash)?.unwrap_or(0);
+                        let saved_correct_block = matches!(headers.get_full_block(block_height)?, Some(block) if &block.block_hash() == block_hash);
+
+                        if saved_correct_block {
+                            Ok(false)
+                        } else {
+                            let mut last_synced_block = last_synced_block.lock().unwrap();
+
+                            // If we download a block older than `last_synced_block`, we update it so that
+                            // we know to delete and re-process all txs starting from that height
+                            if block_height < *last_synced_block {
+                                *last_synced_block = block_height;
+                            }
+
+                            Ok(true)
+                        }
+                    },
+                    |index| {
+                        let synced_bundles = synced_bundles.fetch_add(1, Ordering::SeqCst);
+                        let local_filters_cost = synced_bundles as f32 * SYNC_FILTERS_COST;
+                        progress_update.lock().unwrap().update(
+                            (headers_cost + local_filters_cost) / total_cost * 100.0,
+                            Some(format!(
+                                "Synced filters {} - {}",
+                                index * 1000 + 1,
+                                (index + 1) * 1000
+                            )),
+                        )
+                    },
+                )
+            });
+
+            threads.push(thread);
+        }
+
+        for t in threads {
+            t.join().unwrap()?;
+        }
+
+        progress_update.lock().unwrap().update(
+            (headers_cost + filters_cost) / total_cost * 100.0,
+            Some("Processing downloaded blocks and mempool".into()),
+        )?;
+
+        // delete all txs newer than last_synced_block
+        let last_synced_block = *last_synced_block.lock().unwrap();
+        log::debug!(
+            "Dropping transactions newer than `last_synced_block` = {}",
+            last_synced_block
+        );
+        let mut updates = database.begin_batch();
+        for details in database.iter_txs(false)? {
+            match details.confirmation_time {
+                Some(c) if (c.height as usize) < last_synced_block => continue,
+                _ => updates.del_tx(&details.txid, false)?,
+            };
+        }
+        database.commit_batch(updates)?;
+
+        match first_peer.ask_for_mempool() {
+            Err(CompactFiltersError::PeerBloomDisabled) => {
+                log::warn!("Peer has BLOOM disabled, we can't ask for the mempool")
+            }
+            e => e?,
+        };
+
+        let mut internal_max_deriv = None;
+        let mut external_max_deriv = None;
+
+        for (height, block) in self.headers.iter_full_blocks()? {
+            for tx in &block.txdata {
+                self.process_tx(
+                    database,
+                    tx,
+                    Some(height as u32),
+                    None,
+                    &mut internal_max_deriv,
+                    &mut external_max_deriv,
+                )?;
+            }
+        }
+        for tx in first_peer.get_mempool().iter_txs().iter() {
+            self.process_tx(
+                database,
+                tx,
+                None,
+                None,
+                &mut internal_max_deriv,
+                &mut external_max_deriv,
+            )?;
+        }
+
+        let current_ext = database
+            .get_last_index(KeychainKind::External)?
+            .unwrap_or(0);
+        let first_ext_new = external_max_deriv.map(|x| x + 1).unwrap_or(0);
+        if first_ext_new > current_ext {
+            info!("Setting external index to {}", first_ext_new);
+            database.set_last_index(KeychainKind::External, first_ext_new)?;
+        }
+
+        let current_int = database
+            .get_last_index(KeychainKind::Internal)?
+            .unwrap_or(0);
+        let first_int_new = internal_max_deriv.map(|x| x + 1).unwrap_or(0);
+        if first_int_new > current_int {
+            info!("Setting internal index to {}", first_int_new);
+            database.set_last_index(KeychainKind::Internal, first_int_new)?;
+        }
+
+        info!("Dropping blocks until {}", buried_height);
+        self.headers.delete_blocks_until(buried_height)?;
+
+        progress_update
+            .lock()
+            .unwrap()
+            .update(100.0, Some("Done".into()))?;
+
+        Ok(())
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        Ok(self.peers[0]
+            .get_mempool()
+            .get_tx(&Inventory::Transaction(*txid)))
+    }
+
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        self.peers[0].broadcast_tx(tx.clone())?;
+
+        Ok(())
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        Ok(self.headers.get_height()? as u32)
+    }
+
+    fn estimate_fee(&self, _target: usize) -> Result<FeeRate, Error> {
+        // TODO
+        Ok(FeeRate::default())
+    }
+}
+
+/// Data to connect to a Bitcoin P2P peer
+#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq)]
+pub struct BitcoinPeerConfig {
+    /// Peer address such as 127.0.0.1:18333
+    pub address: String,
+    /// Optional socks5 proxy
+    pub socks5: Option<String>,
+    /// Optional socks5 proxy credentials
+    pub socks5_credentials: Option<(String, String)>,
+}
+
+/// Configuration for a [`CompactFiltersBlockchain`]
+#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq)]
+pub struct CompactFiltersBlockchainConfig {
+    /// List of peers to try to connect to for asking headers and filters
+    pub peers: Vec<BitcoinPeerConfig>,
+    /// Network used
+    pub network: Network,
+    /// Storage dir to save partially downloaded headers and full blocks
+    pub storage_dir: String,
+    /// Optionally skip initial `skip_blocks` blocks (default: 0)
+    pub skip_blocks: Option<usize>,
+}
+
+impl ConfigurableBlockchain for CompactFiltersBlockchain {
+    type Config = CompactFiltersBlockchainConfig;
+
+    fn from_config(config: &Self::Config) -> Result<Self, Error> {
+        let mempool = Arc::new(Mempool::default());
+        let peers = config
+            .peers
+            .iter()
+            .map(|peer_conf| match &peer_conf.socks5 {
+                None => Peer::connect(&peer_conf.address, Arc::clone(&mempool), config.network),
+                Some(proxy) => Peer::connect_proxy(
+                    peer_conf.address.as_str(),
+                    proxy,
+                    peer_conf
+                        .socks5_credentials
+                        .as_ref()
+                        .map(|(a, b)| (a.as_str(), b.as_str())),
+                    Arc::clone(&mempool),
+                    config.network,
+                ),
+            })
+            .collect::<Result<_, _>>()?;
+
+        Ok(CompactFiltersBlockchain::new(
+            peers,
+            &config.storage_dir,
+            config.skip_blocks,
+        )?)
+    }
+}
+
+/// An error that can occur during sync with a [`CompactFiltersBlockchain`]
+#[derive(Debug)]
+pub enum CompactFiltersError {
+    /// A peer sent an invalid or unexpected response
+    InvalidResponse,
+    /// The headers returned are invalid
+    InvalidHeaders,
+    /// The compact filter headers returned are invalid
+    InvalidFilterHeader,
+    /// The compact filter returned is invalid
+    InvalidFilter,
+    /// The peer is missing a block in the valid chain
+    MissingBlock,
+    /// The data stored in the block filters storage are corrupted
+    DataCorruption,
+
+    /// A peer is not connected
+    NotConnected,
+    /// A peer took too long to reply to one of our messages
+    Timeout,
+    /// The peer doesn't advertise the [`BLOOM`](bitcoin::network::constants::ServiceFlags::BLOOM) service flag
+    PeerBloomDisabled,
+
+    /// No peers have been specified
+    NoPeers,
+
+    /// Internal database error
+    Db(rocksdb::Error),
+    /// Internal I/O error
+    Io(std::io::Error),
+    /// Invalid BIP158 filter
+    Bip158(bitcoin::util::bip158::Error),
+    /// Internal system time error
+    Time(std::time::SystemTimeError),
+
+    /// Wrapper for [`crate::error::Error`]
+    Global(Box<crate::error::Error>),
+}
+
+impl fmt::Display for CompactFiltersError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for CompactFiltersError {}
+
+impl_error!(rocksdb::Error, Db, CompactFiltersError);
+impl_error!(std::io::Error, Io, CompactFiltersError);
+impl_error!(bitcoin::util::bip158::Error, Bip158, CompactFiltersError);
+impl_error!(std::time::SystemTimeError, Time, CompactFiltersError);
+
+impl From<crate::error::Error> for CompactFiltersError {
+    fn from(err: crate::error::Error) -> Self {
+        CompactFiltersError::Global(Box::new(err))
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/peer.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/peer.rs.html new file mode 100644 index 0000000000..c9f3b00e9c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/peer.rs.html @@ -0,0 +1,1148 @@ +peer.rs - source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+use std::collections::HashMap;
+use std::net::{TcpStream, ToSocketAddrs};
+use std::sync::{Arc, Condvar, Mutex, RwLock};
+use std::thread;
+use std::time::{Duration, SystemTime, UNIX_EPOCH};
+
+use socks::{Socks5Stream, ToTargetAddr};
+
+use rand::{thread_rng, Rng};
+
+use bitcoin::consensus::Encodable;
+use bitcoin::hash_types::BlockHash;
+use bitcoin::network::constants::ServiceFlags;
+use bitcoin::network::message::{NetworkMessage, RawNetworkMessage};
+use bitcoin::network::message_blockdata::*;
+use bitcoin::network::message_filter::*;
+use bitcoin::network::message_network::VersionMessage;
+use bitcoin::network::stream_reader::StreamReader;
+use bitcoin::network::Address;
+use bitcoin::{Block, Network, Transaction, Txid, Wtxid};
+
+use super::CompactFiltersError;
+
+type ResponsesMap = HashMap<&'static str, Arc<(Mutex<Vec<NetworkMessage>>, Condvar)>>;
+
+pub(crate) const TIMEOUT_SECS: u64 = 30;
+
+/// Container for unconfirmed, but valid Bitcoin transactions
+///
+/// It is normally shared between [`Peer`]s with the use of [`Arc`], so that transactions are not
+/// duplicated in memory.
+#[derive(Debug, Default)]
+pub struct Mempool(RwLock<InnerMempool>);
+
+#[derive(Debug, Default)]
+struct InnerMempool {
+    txs: HashMap<Txid, Transaction>,
+    wtxids: HashMap<Wtxid, Txid>,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+enum TxIdentifier {
+    Wtxid(Wtxid),
+    Txid(Txid),
+}
+
+impl Mempool {
+    /// Create a new empty mempool
+    pub fn new() -> Self {
+        Self::default()
+    }
+
+    /// Add a transaction to the mempool
+    ///
+    /// Note that this doesn't propagate the transaction to other
+    /// peers. To do that, [`broadcast`](crate::blockchain::Blockchain::broadcast) should be used.
+    pub fn add_tx(&self, tx: Transaction) {
+        let mut guard = self.0.write().unwrap();
+
+        guard.wtxids.insert(tx.wtxid(), tx.txid());
+        guard.txs.insert(tx.txid(), tx);
+    }
+
+    /// Look-up a transaction in the mempool given an [`Inventory`] request
+    pub fn get_tx(&self, inventory: &Inventory) -> Option<Transaction> {
+        let identifer = match inventory {
+            Inventory::Error | Inventory::Block(_) | Inventory::WitnessBlock(_) => return None,
+            Inventory::Transaction(txid) => TxIdentifier::Txid(*txid),
+            Inventory::WitnessTransaction(txid) => TxIdentifier::Txid(*txid),
+            Inventory::WTx(wtxid) => TxIdentifier::Wtxid(*wtxid),
+            Inventory::Unknown { inv_type, hash } => {
+                log::warn!(
+                    "Unknown inventory request type `{}`, hash `{:?}`",
+                    inv_type,
+                    hash
+                );
+                return None;
+            }
+        };
+
+        let txid = match identifer {
+            TxIdentifier::Txid(txid) => Some(txid),
+            TxIdentifier::Wtxid(wtxid) => self.0.read().unwrap().wtxids.get(&wtxid).cloned(),
+        };
+
+        txid.map(|txid| self.0.read().unwrap().txs.get(&txid).cloned())
+            .flatten()
+    }
+
+    /// Return whether or not the mempool contains a transaction with a given txid
+    pub fn has_tx(&self, txid: &Txid) -> bool {
+        self.0.read().unwrap().txs.contains_key(txid)
+    }
+
+    /// Return the list of transactions contained in the mempool
+    pub fn iter_txs(&self) -> Vec<Transaction> {
+        self.0.read().unwrap().txs.values().cloned().collect()
+    }
+}
+
+/// A Bitcoin peer
+#[derive(Debug)]
+pub struct Peer {
+    writer: Arc<Mutex<TcpStream>>,
+    responses: Arc<RwLock<ResponsesMap>>,
+
+    reader_thread: thread::JoinHandle<()>,
+    connected: Arc<RwLock<bool>>,
+
+    mempool: Arc<Mempool>,
+
+    version: VersionMessage,
+    network: Network,
+}
+
+impl Peer {
+    /// Connect to a peer over a plaintext TCP connection
+    ///
+    /// This function internally spawns a new thread that will monitor incoming messages from the
+    /// peer, and optionally reply to some of them transparently, like [pings](bitcoin::network::message::NetworkMessage::Ping)
+    pub fn connect<A: ToSocketAddrs>(
+        address: A,
+        mempool: Arc<Mempool>,
+        network: Network,
+    ) -> Result<Self, CompactFiltersError> {
+        let stream = TcpStream::connect(address)?;
+
+        Peer::from_stream(stream, mempool, network)
+    }
+
+    /// Connect to a peer through a SOCKS5 proxy, optionally by using some credentials, specified
+    /// as a tuple of `(username, password)`
+    ///
+    /// This function internally spawns a new thread that will monitor incoming messages from the
+    /// peer, and optionally reply to some of them transparently, like [pings](NetworkMessage::Ping)
+    pub fn connect_proxy<T: ToTargetAddr, P: ToSocketAddrs>(
+        target: T,
+        proxy: P,
+        credentials: Option<(&str, &str)>,
+        mempool: Arc<Mempool>,
+        network: Network,
+    ) -> Result<Self, CompactFiltersError> {
+        let socks_stream = if let Some((username, password)) = credentials {
+            Socks5Stream::connect_with_password(proxy, target, username, password)?
+        } else {
+            Socks5Stream::connect(proxy, target)?
+        };
+
+        Peer::from_stream(socks_stream.into_inner(), mempool, network)
+    }
+
+    /// Create a [`Peer`] from an already connected TcpStream
+    fn from_stream(
+        stream: TcpStream,
+        mempool: Arc<Mempool>,
+        network: Network,
+    ) -> Result<Self, CompactFiltersError> {
+        let writer = Arc::new(Mutex::new(stream.try_clone()?));
+        let responses: Arc<RwLock<ResponsesMap>> = Arc::new(RwLock::new(HashMap::new()));
+        let connected = Arc::new(RwLock::new(true));
+
+        let mut locked_writer = writer.lock().unwrap();
+
+        let reader_thread_responses = Arc::clone(&responses);
+        let reader_thread_writer = Arc::clone(&writer);
+        let reader_thread_mempool = Arc::clone(&mempool);
+        let reader_thread_connected = Arc::clone(&connected);
+        let reader_thread = thread::spawn(move || {
+            Self::reader_thread(
+                network,
+                stream,
+                reader_thread_responses,
+                reader_thread_writer,
+                reader_thread_mempool,
+                reader_thread_connected,
+            )
+        });
+
+        let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() as i64;
+        let nonce = thread_rng().gen();
+        let receiver = Address::new(&locked_writer.peer_addr()?, ServiceFlags::NONE);
+        let sender = Address {
+            services: ServiceFlags::NONE,
+            address: [0u16; 8],
+            port: 0,
+        };
+
+        Self::_send(
+            &mut locked_writer,
+            network.magic(),
+            NetworkMessage::Version(VersionMessage::new(
+                ServiceFlags::WITNESS,
+                timestamp,
+                receiver,
+                sender,
+                nonce,
+                "MagicalBitcoinWallet".into(),
+                0,
+            )),
+        )?;
+        let version = if let NetworkMessage::Version(version) =
+            Self::_recv(&responses, "version", None).unwrap()
+        {
+            version
+        } else {
+            return Err(CompactFiltersError::InvalidResponse);
+        };
+
+        if let NetworkMessage::Verack = Self::_recv(&responses, "verack", None).unwrap() {
+            Self::_send(&mut locked_writer, network.magic(), NetworkMessage::Verack)?;
+        } else {
+            return Err(CompactFiltersError::InvalidResponse);
+        }
+
+        std::mem::drop(locked_writer);
+
+        Ok(Peer {
+            writer,
+            responses,
+            reader_thread,
+            connected,
+            mempool,
+            version,
+            network,
+        })
+    }
+
+    /// Send a Bitcoin network message
+    fn _send(
+        writer: &mut TcpStream,
+        magic: u32,
+        payload: NetworkMessage,
+    ) -> Result<(), CompactFiltersError> {
+        log::trace!("==> {:?}", payload);
+
+        let raw_message = RawNetworkMessage { magic, payload };
+
+        raw_message
+            .consensus_encode(writer)
+            .map_err(|_| CompactFiltersError::DataCorruption)?;
+
+        Ok(())
+    }
+
+    /// Wait for a specific incoming Bitcoin message, optionally with a timeout
+    fn _recv(
+        responses: &Arc<RwLock<ResponsesMap>>,
+        wait_for: &'static str,
+        timeout: Option<Duration>,
+    ) -> Option<NetworkMessage> {
+        let message_resp = {
+            let mut lock = responses.write().unwrap();
+            let message_resp = lock.entry(wait_for).or_default();
+            Arc::clone(&message_resp)
+        };
+
+        let (lock, cvar) = &*message_resp;
+
+        let mut messages = lock.lock().unwrap();
+        while messages.is_empty() {
+            match timeout {
+                None => messages = cvar.wait(messages).unwrap(),
+                Some(t) => {
+                    let result = cvar.wait_timeout(messages, t).unwrap();
+                    if result.1.timed_out() {
+                        return None;
+                    }
+                    messages = result.0;
+                }
+            }
+        }
+
+        messages.pop()
+    }
+
+    /// Return the [`VersionMessage`] sent by the peer
+    pub fn get_version(&self) -> &VersionMessage {
+        &self.version
+    }
+
+    /// Return the Bitcoin [`Network`] in use
+    pub fn get_network(&self) -> Network {
+        self.network
+    }
+
+    /// Return the mempool used by this peer
+    pub fn get_mempool(&self) -> Arc<Mempool> {
+        Arc::clone(&self.mempool)
+    }
+
+    /// Return whether or not the peer is still connected
+    pub fn is_connected(&self) -> bool {
+        *self.connected.read().unwrap()
+    }
+
+    /// Internal function called once the `reader_thread` is spawned
+    fn reader_thread(
+        network: Network,
+        connection: TcpStream,
+        reader_thread_responses: Arc<RwLock<ResponsesMap>>,
+        reader_thread_writer: Arc<Mutex<TcpStream>>,
+        reader_thread_mempool: Arc<Mempool>,
+        reader_thread_connected: Arc<RwLock<bool>>,
+    ) {
+        macro_rules! check_disconnect {
+            ($call:expr) => {
+                match $call {
+                    Ok(good) => good,
+                    Err(e) => {
+                        log::debug!("Error {:?}", e);
+                        *reader_thread_connected.write().unwrap() = false;
+
+                        break;
+                    }
+                }
+            };
+        }
+
+        let mut reader = StreamReader::new(connection, None);
+        loop {
+            let raw_message: RawNetworkMessage = check_disconnect!(reader.read_next());
+
+            let in_message = if raw_message.magic != network.magic() {
+                continue;
+            } else {
+                raw_message.payload
+            };
+
+            log::trace!("<== {:?}", in_message);
+
+            match in_message {
+                NetworkMessage::Ping(nonce) => {
+                    check_disconnect!(Self::_send(
+                        &mut reader_thread_writer.lock().unwrap(),
+                        network.magic(),
+                        NetworkMessage::Pong(nonce),
+                    ));
+
+                    continue;
+                }
+                NetworkMessage::Alert(_) => continue,
+                NetworkMessage::GetData(ref inv) => {
+                    let (found, not_found): (Vec<_>, Vec<_>) = inv
+                        .iter()
+                        .map(|item| (*item, reader_thread_mempool.get_tx(item)))
+                        .partition(|(_, d)| d.is_some());
+                    for (_, found_tx) in found {
+                        check_disconnect!(Self::_send(
+                            &mut reader_thread_writer.lock().unwrap(),
+                            network.magic(),
+                            NetworkMessage::Tx(found_tx.unwrap()),
+                        ));
+                    }
+
+                    if !not_found.is_empty() {
+                        check_disconnect!(Self::_send(
+                            &mut reader_thread_writer.lock().unwrap(),
+                            network.magic(),
+                            NetworkMessage::NotFound(
+                                not_found.into_iter().map(|(i, _)| i).collect(),
+                            ),
+                        ));
+                    }
+                }
+                _ => {}
+            }
+
+            let message_resp = {
+                let mut lock = reader_thread_responses.write().unwrap();
+                let message_resp = lock.entry(in_message.cmd()).or_default();
+                Arc::clone(&message_resp)
+            };
+
+            let (lock, cvar) = &*message_resp;
+            let mut messages = lock.lock().unwrap();
+            messages.push(in_message);
+            cvar.notify_all();
+        }
+    }
+
+    /// Send a raw Bitcoin message to the peer
+    pub fn send(&self, payload: NetworkMessage) -> Result<(), CompactFiltersError> {
+        let mut writer = self.writer.lock().unwrap();
+        Self::_send(&mut writer, self.network.magic(), payload)
+    }
+
+    /// Waits for a specific incoming Bitcoin message, optionally with a timeout
+    pub fn recv(
+        &self,
+        wait_for: &'static str,
+        timeout: Option<Duration>,
+    ) -> Result<Option<NetworkMessage>, CompactFiltersError> {
+        Ok(Self::_recv(&self.responses, wait_for, timeout))
+    }
+}
+
+pub trait CompactFiltersPeer {
+    fn get_cf_checkpt(
+        &self,
+        filter_type: u8,
+        stop_hash: BlockHash,
+    ) -> Result<CFCheckpt, CompactFiltersError>;
+    fn get_cf_headers(
+        &self,
+        filter_type: u8,
+        start_height: u32,
+        stop_hash: BlockHash,
+    ) -> Result<CFHeaders, CompactFiltersError>;
+    fn get_cf_filters(
+        &self,
+        filter_type: u8,
+        start_height: u32,
+        stop_hash: BlockHash,
+    ) -> Result<(), CompactFiltersError>;
+    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError>;
+}
+
+impl CompactFiltersPeer for Peer {
+    fn get_cf_checkpt(
+        &self,
+        filter_type: u8,
+        stop_hash: BlockHash,
+    ) -> Result<CFCheckpt, CompactFiltersError> {
+        self.send(NetworkMessage::GetCFCheckpt(GetCFCheckpt {
+            filter_type,
+            stop_hash,
+        }))?;
+
+        let response = self
+            .recv("cfcheckpt", Some(Duration::from_secs(TIMEOUT_SECS)))?
+            .ok_or(CompactFiltersError::Timeout)?;
+        let response = match response {
+            NetworkMessage::CFCheckpt(response) => response,
+            _ => return Err(CompactFiltersError::InvalidResponse),
+        };
+
+        if response.filter_type != filter_type {
+            return Err(CompactFiltersError::InvalidResponse);
+        }
+
+        Ok(response)
+    }
+
+    fn get_cf_headers(
+        &self,
+        filter_type: u8,
+        start_height: u32,
+        stop_hash: BlockHash,
+    ) -> Result<CFHeaders, CompactFiltersError> {
+        self.send(NetworkMessage::GetCFHeaders(GetCFHeaders {
+            filter_type,
+            start_height,
+            stop_hash,
+        }))?;
+
+        let response = self
+            .recv("cfheaders", Some(Duration::from_secs(TIMEOUT_SECS)))?
+            .ok_or(CompactFiltersError::Timeout)?;
+        let response = match response {
+            NetworkMessage::CFHeaders(response) => response,
+            _ => return Err(CompactFiltersError::InvalidResponse),
+        };
+
+        if response.filter_type != filter_type {
+            return Err(CompactFiltersError::InvalidResponse);
+        }
+
+        Ok(response)
+    }
+
+    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError> {
+        let response = self
+            .recv("cfilter", Some(Duration::from_secs(TIMEOUT_SECS)))?
+            .ok_or(CompactFiltersError::Timeout)?;
+        let response = match response {
+            NetworkMessage::CFilter(response) => response,
+            _ => return Err(CompactFiltersError::InvalidResponse),
+        };
+
+        Ok(response)
+    }
+
+    fn get_cf_filters(
+        &self,
+        filter_type: u8,
+        start_height: u32,
+        stop_hash: BlockHash,
+    ) -> Result<(), CompactFiltersError> {
+        self.send(NetworkMessage::GetCFilters(GetCFilters {
+            filter_type,
+            start_height,
+            stop_hash,
+        }))?;
+
+        Ok(())
+    }
+}
+
+pub trait InvPeer {
+    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError>;
+    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError>;
+    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError>;
+}
+
+impl InvPeer for Peer {
+    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError> {
+        self.send(NetworkMessage::GetData(vec![Inventory::WitnessBlock(
+            block_hash,
+        )]))?;
+
+        match self.recv("block", Some(Duration::from_secs(TIMEOUT_SECS)))? {
+            None => Ok(None),
+            Some(NetworkMessage::Block(response)) => Ok(Some(response)),
+            _ => Err(CompactFiltersError::InvalidResponse),
+        }
+    }
+
+    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError> {
+        if !self.version.services.has(ServiceFlags::BLOOM) {
+            return Err(CompactFiltersError::PeerBloomDisabled);
+        }
+
+        self.send(NetworkMessage::MemPool)?;
+        let inv = match self.recv("inv", Some(Duration::from_secs(5)))? {
+            None => return Ok(()), // empty mempool
+            Some(NetworkMessage::Inv(inv)) => inv,
+            _ => return Err(CompactFiltersError::InvalidResponse),
+        };
+
+        let getdata = inv
+            .iter()
+            .cloned()
+            .filter(
+                |item| matches!(item, Inventory::Transaction(txid) if !self.mempool.has_tx(txid)),
+            )
+            .collect::<Vec<_>>();
+        let num_txs = getdata.len();
+        self.send(NetworkMessage::GetData(getdata))?;
+
+        for _ in 0..num_txs {
+            let tx = self
+                .recv("tx", Some(Duration::from_secs(TIMEOUT_SECS)))?
+                .ok_or(CompactFiltersError::Timeout)?;
+            let tx = match tx {
+                NetworkMessage::Tx(tx) => tx,
+                _ => return Err(CompactFiltersError::InvalidResponse),
+            };
+
+            self.mempool.add_tx(tx);
+        }
+
+        Ok(())
+    }
+
+    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError> {
+        self.mempool.add_tx(tx.clone());
+        self.send(NetworkMessage::Tx(tx))?;
+
+        Ok(())
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/store.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/store.rs.html new file mode 100644 index 0000000000..e7ee810018 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/store.rs.html @@ -0,0 +1,1704 @@ +store.rs - source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+use std::convert::TryInto;
+use std::fmt;
+use std::io::{Read, Write};
+use std::marker::PhantomData;
+use std::ops::Deref;
+use std::sync::Arc;
+use std::sync::RwLock;
+
+use rand::distributions::Alphanumeric;
+use rand::{thread_rng, Rng};
+
+use rocksdb::{Direction, IteratorMode, ReadOptions, WriteBatch, DB};
+
+use bitcoin::consensus::{deserialize, encode::VarInt, serialize, Decodable, Encodable};
+use bitcoin::hash_types::{FilterHash, FilterHeader};
+use bitcoin::hashes::hex::FromHex;
+use bitcoin::hashes::Hash;
+use bitcoin::util::bip158::BlockFilter;
+use bitcoin::util::uint::Uint256;
+use bitcoin::Block;
+use bitcoin::BlockHash;
+use bitcoin::BlockHeader;
+use bitcoin::Network;
+
+use lazy_static::lazy_static;
+
+use super::CompactFiltersError;
+
+lazy_static! {
+    static ref MAINNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A29AB5F49FFFF001D1DAC2B7C0101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
+    static ref TESTNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4ADAE5494DFFFF001D1AA4AE180101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
+    static ref REGTEST_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4ADAE5494DFFFF7F20020000000101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
+    static ref SIGNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A008F4D5FAE77031E8AD222030101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
+}
+
+pub trait StoreType: Default + fmt::Debug {}
+
+#[derive(Default, Debug)]
+pub struct Full;
+impl StoreType for Full {}
+#[derive(Default, Debug)]
+pub struct Snapshot;
+impl StoreType for Snapshot {}
+
+pub enum StoreEntry {
+    BlockHeader(Option<usize>),
+    Block(Option<usize>),
+    BlockHeaderIndex(Option<BlockHash>),
+    CFilterTable((u8, Option<usize>)),
+}
+
+impl StoreEntry {
+    pub fn get_prefix(&self) -> Vec<u8> {
+        match self {
+            StoreEntry::BlockHeader(_) => b"z",
+            StoreEntry::Block(_) => b"x",
+            StoreEntry::BlockHeaderIndex(_) => b"i",
+            StoreEntry::CFilterTable(_) => b"t",
+        }
+        .to_vec()
+    }
+
+    pub fn get_key(&self) -> Vec<u8> {
+        let mut prefix = self.get_prefix();
+        match self {
+            StoreEntry::BlockHeader(Some(height)) => {
+                prefix.extend_from_slice(&height.to_be_bytes())
+            }
+            StoreEntry::Block(Some(height)) => prefix.extend_from_slice(&height.to_be_bytes()),
+            StoreEntry::BlockHeaderIndex(Some(hash)) => {
+                prefix.extend_from_slice(&hash.into_inner())
+            }
+            StoreEntry::CFilterTable((filter_type, bundle_index)) => {
+                prefix.push(*filter_type);
+                if let Some(bundle_index) = bundle_index {
+                    prefix.extend_from_slice(&bundle_index.to_be_bytes());
+                }
+            }
+            _ => {}
+        }
+
+        prefix
+    }
+}
+
+pub trait SerializeDb: Sized {
+    fn serialize(&self) -> Vec<u8>;
+    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError>;
+}
+
+impl<T> SerializeDb for T
+where
+    T: Encodable + Decodable,
+{
+    fn serialize(&self) -> Vec<u8> {
+        serialize(self)
+    }
+
+    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError> {
+        deserialize(data).map_err(|_| CompactFiltersError::DataCorruption)
+    }
+}
+
+impl Encodable for BundleStatus {
+    fn consensus_encode<W: Write>(&self, mut e: W) -> Result<usize, std::io::Error> {
+        let mut written = 0;
+
+        match self {
+            BundleStatus::Init => {
+                written += 0x00u8.consensus_encode(&mut e)?;
+            }
+            BundleStatus::CfHeaders { cf_headers } => {
+                written += 0x01u8.consensus_encode(&mut e)?;
+                written += VarInt(cf_headers.len() as u64).consensus_encode(&mut e)?;
+                for header in cf_headers {
+                    written += header.consensus_encode(&mut e)?;
+                }
+            }
+            BundleStatus::CFilters { cf_filters } => {
+                written += 0x02u8.consensus_encode(&mut e)?;
+                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
+                for filter in cf_filters {
+                    written += filter.consensus_encode(&mut e)?;
+                }
+            }
+            BundleStatus::Processed { cf_filters } => {
+                written += 0x03u8.consensus_encode(&mut e)?;
+                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
+                for filter in cf_filters {
+                    written += filter.consensus_encode(&mut e)?;
+                }
+            }
+            BundleStatus::Pruned => {
+                written += 0x04u8.consensus_encode(&mut e)?;
+            }
+            BundleStatus::Tip { cf_filters } => {
+                written += 0x05u8.consensus_encode(&mut e)?;
+                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
+                for filter in cf_filters {
+                    written += filter.consensus_encode(&mut e)?;
+                }
+            }
+        }
+
+        Ok(written)
+    }
+}
+
+impl Decodable for BundleStatus {
+    fn consensus_decode<D: Read>(mut d: D) -> Result<Self, bitcoin::consensus::encode::Error> {
+        let byte_type = u8::consensus_decode(&mut d)?;
+        match byte_type {
+            0x00 => Ok(BundleStatus::Init),
+            0x01 => {
+                let num = VarInt::consensus_decode(&mut d)?;
+                let num = num.0 as usize;
+
+                let mut cf_headers = Vec::with_capacity(num);
+                for _ in 0..num {
+                    cf_headers.push(FilterHeader::consensus_decode(&mut d)?);
+                }
+
+                Ok(BundleStatus::CfHeaders { cf_headers })
+            }
+            0x02 => {
+                let num = VarInt::consensus_decode(&mut d)?;
+                let num = num.0 as usize;
+
+                let mut cf_filters = Vec::with_capacity(num);
+                for _ in 0..num {
+                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
+                }
+
+                Ok(BundleStatus::CFilters { cf_filters })
+            }
+            0x03 => {
+                let num = VarInt::consensus_decode(&mut d)?;
+                let num = num.0 as usize;
+
+                let mut cf_filters = Vec::with_capacity(num);
+                for _ in 0..num {
+                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
+                }
+
+                Ok(BundleStatus::Processed { cf_filters })
+            }
+            0x04 => Ok(BundleStatus::Pruned),
+            0x05 => {
+                let num = VarInt::consensus_decode(&mut d)?;
+                let num = num.0 as usize;
+
+                let mut cf_filters = Vec::with_capacity(num);
+                for _ in 0..num {
+                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
+                }
+
+                Ok(BundleStatus::Tip { cf_filters })
+            }
+            _ => Err(bitcoin::consensus::encode::Error::ParseFailed(
+                "Invalid byte type",
+            )),
+        }
+    }
+}
+
+pub struct ChainStore<T: StoreType> {
+    store: Arc<RwLock<DB>>,
+    cf_name: String,
+    min_height: usize,
+    network: Network,
+    phantom: PhantomData<T>,
+}
+
+impl ChainStore<Full> {
+    pub fn new(store: DB, network: Network) -> Result<Self, CompactFiltersError> {
+        let genesis = match network {
+            Network::Bitcoin => MAINNET_GENESIS.deref(),
+            Network::Testnet => TESTNET_GENESIS.deref(),
+            Network::Regtest => REGTEST_GENESIS.deref(),
+            Network::Signet => SIGNET_GENESIS.deref(),
+        };
+
+        let cf_name = "default".to_string();
+        let cf_handle = store.cf_handle(&cf_name).unwrap();
+
+        let genesis_key = StoreEntry::BlockHeader(Some(0)).get_key();
+
+        if store.get_pinned_cf(cf_handle, &genesis_key)?.is_none() {
+            let mut batch = WriteBatch::default();
+            batch.put_cf(
+                cf_handle,
+                genesis_key,
+                (genesis.header, genesis.header.work()).serialize(),
+            );
+            batch.put_cf(
+                cf_handle,
+                StoreEntry::BlockHeaderIndex(Some(genesis.block_hash())).get_key(),
+                &0usize.to_be_bytes(),
+            );
+            store.write(batch)?;
+        }
+
+        Ok(ChainStore {
+            store: Arc::new(RwLock::new(store)),
+            cf_name,
+            min_height: 0,
+            network,
+            phantom: PhantomData,
+        })
+    }
+
+    pub fn get_locators(&self) -> Result<Vec<(BlockHash, usize)>, CompactFiltersError> {
+        let mut step = 1;
+        let mut index = self.get_height()?;
+        let mut answer = Vec::new();
+
+        let store_read = self.store.read().unwrap();
+        let cf_handle = store_read.cf_handle(&self.cf_name).unwrap();
+
+        loop {
+            if answer.len() > 10 {
+                step *= 2;
+            }
+
+            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(
+                &store_read
+                    .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(index)).get_key())?
+                    .unwrap(),
+            )?;
+            answer.push((header.block_hash(), index));
+
+            if let Some(new_index) = index.checked_sub(step) {
+                index = new_index;
+            } else {
+                break;
+            }
+        }
+
+        Ok(answer)
+    }
+
+    pub fn start_snapshot(&self, from: usize) -> Result<ChainStore<Snapshot>, CompactFiltersError> {
+        let new_cf_name: String = thread_rng().sample_iter(&Alphanumeric).take(16).collect();
+        let new_cf_name = format!("_headers:{}", new_cf_name);
+
+        let mut write_store = self.store.write().unwrap();
+
+        write_store.create_cf(&new_cf_name, &Default::default())?;
+
+        let cf_handle = write_store.cf_handle(&self.cf_name).unwrap();
+        let new_cf_handle = write_store.cf_handle(&new_cf_name).unwrap();
+
+        let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(
+            &write_store
+                .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
+                .ok_or(CompactFiltersError::DataCorruption)?,
+        )?;
+
+        let mut batch = WriteBatch::default();
+        batch.put_cf(
+            new_cf_handle,
+            StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
+            &from.to_be_bytes(),
+        );
+        batch.put_cf(
+            new_cf_handle,
+            StoreEntry::BlockHeader(Some(from)).get_key(),
+            (header, work).serialize(),
+        );
+        write_store.write(batch)?;
+
+        let store = Arc::clone(&self.store);
+        Ok(ChainStore {
+            store,
+            cf_name: new_cf_name,
+            min_height: from,
+            network: self.network,
+            phantom: PhantomData,
+        })
+    }
+
+    pub fn recover_snapshot(&self, cf_name: &str) -> Result<(), CompactFiltersError> {
+        let mut write_store = self.store.write().unwrap();
+        let snapshot_cf_handle = write_store.cf_handle(cf_name).unwrap();
+
+        let prefix = StoreEntry::BlockHeader(None).get_key();
+        let mut iterator = write_store.prefix_iterator_cf(snapshot_cf_handle, prefix);
+
+        let min_height = match iterator
+            .next()
+            .and_then(|(k, _)| k[1..].try_into().ok())
+            .map(usize::from_be_bytes)
+        {
+            None => {
+                std::mem::drop(iterator);
+                write_store.drop_cf(cf_name).ok();
+
+                return Ok(());
+            }
+            Some(x) => x,
+        };
+        std::mem::drop(iterator);
+        std::mem::drop(write_store);
+
+        let snapshot = ChainStore {
+            store: Arc::clone(&self.store),
+            cf_name: cf_name.into(),
+            min_height,
+            network: self.network,
+            phantom: PhantomData,
+        };
+        if snapshot.work()? > self.work()? {
+            self.apply_snapshot(snapshot)?;
+        }
+
+        Ok(())
+    }
+
+    pub fn apply_snapshot(
+        &self,
+        snaphost: ChainStore<Snapshot>,
+    ) -> Result<(), CompactFiltersError> {
+        let mut batch = WriteBatch::default();
+
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+        let snapshot_cf_handle = read_store.cf_handle(&snaphost.cf_name).unwrap();
+
+        let from_key = StoreEntry::BlockHeader(Some(snaphost.min_height)).get_key();
+        let to_key = StoreEntry::BlockHeader(Some(usize::MAX)).get_key();
+
+        let mut opts = ReadOptions::default();
+        opts.set_iterate_upper_bound(to_key.clone());
+
+        log::debug!("Removing items");
+        batch.delete_range_cf(cf_handle, &from_key, &to_key);
+        for (_, v) in read_store.iterator_cf_opt(
+            cf_handle,
+            opts,
+            IteratorMode::From(&from_key, Direction::Forward),
+        ) {
+            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
+
+            batch.delete_cf(
+                cf_handle,
+                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
+            );
+        }
+
+        // Delete full blocks overriden by snapshot
+        let from_key = StoreEntry::Block(Some(snaphost.min_height)).get_key();
+        let to_key = StoreEntry::Block(Some(usize::MAX)).get_key();
+        batch.delete_range(&from_key, &to_key);
+
+        log::debug!("Copying over new items");
+        for (k, v) in read_store.iterator_cf(snapshot_cf_handle, IteratorMode::Start) {
+            batch.put_cf(cf_handle, k, v);
+        }
+
+        read_store.write(batch)?;
+        std::mem::drop(read_store);
+
+        self.store.write().unwrap().drop_cf(&snaphost.cf_name)?;
+
+        Ok(())
+    }
+
+    pub fn get_height_for(
+        &self,
+        block_hash: &BlockHash,
+    ) -> Result<Option<usize>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let key = StoreEntry::BlockHeaderIndex(Some(*block_hash)).get_key();
+        let data = read_store.get_pinned_cf(cf_handle, key)?;
+        data.map(|data| {
+            Ok::<_, CompactFiltersError>(usize::from_be_bytes(
+                data.as_ref()
+                    .try_into()
+                    .map_err(|_| CompactFiltersError::DataCorruption)?,
+            ))
+        })
+        .transpose()
+    }
+
+    pub fn get_block_hash(&self, height: usize) -> Result<Option<BlockHash>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let key = StoreEntry::BlockHeader(Some(height)).get_key();
+        let data = read_store.get_pinned_cf(cf_handle, key)?;
+        data.map(|data| {
+            let (header, _): (BlockHeader, Uint256) =
+                deserialize(&data).map_err(|_| CompactFiltersError::DataCorruption)?;
+            Ok::<_, CompactFiltersError>(header.block_hash())
+        })
+        .transpose()
+    }
+
+    pub fn save_full_block(&self, block: &Block, height: usize) -> Result<(), CompactFiltersError> {
+        let key = StoreEntry::Block(Some(height)).get_key();
+        self.store.read().unwrap().put(key, block.serialize())?;
+
+        Ok(())
+    }
+
+    pub fn get_full_block(&self, height: usize) -> Result<Option<Block>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+
+        let key = StoreEntry::Block(Some(height)).get_key();
+        let opt_block = read_store.get_pinned(key)?;
+
+        opt_block
+            .map(|data| deserialize(&data))
+            .transpose()
+            .map_err(|_| CompactFiltersError::DataCorruption)
+    }
+
+    pub fn delete_blocks_until(&self, height: usize) -> Result<(), CompactFiltersError> {
+        let from_key = StoreEntry::Block(Some(0)).get_key();
+        let to_key = StoreEntry::Block(Some(height)).get_key();
+
+        let mut batch = WriteBatch::default();
+        batch.delete_range(&from_key, &to_key);
+
+        self.store.read().unwrap().write(batch)?;
+
+        Ok(())
+    }
+
+    pub fn iter_full_blocks(&self) -> Result<Vec<(usize, Block)>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+
+        let prefix = StoreEntry::Block(None).get_key();
+
+        let iterator = read_store.prefix_iterator(&prefix);
+        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
+        // have the right prefix
+        iterator
+            .filter(|(k, _)| k.starts_with(&prefix))
+            .map(|(k, v)| {
+                let height: usize = usize::from_be_bytes(
+                    k[1..]
+                        .try_into()
+                        .map_err(|_| CompactFiltersError::DataCorruption)?,
+                );
+                let block = SerializeDb::deserialize(&v)?;
+
+                Ok((height, block))
+            })
+            .collect::<Result<_, _>>()
+    }
+}
+
+impl<T: StoreType> ChainStore<T> {
+    pub fn work(&self) -> Result<Uint256, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let prefix = StoreEntry::BlockHeader(None).get_key();
+        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
+
+        Ok(iterator
+            .last()
+            .map(|(_, v)| -> Result<_, CompactFiltersError> {
+                let (_, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
+
+                Ok(work)
+            })
+            .transpose()?
+            .unwrap_or_default())
+    }
+
+    pub fn get_height(&self) -> Result<usize, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let prefix = StoreEntry::BlockHeader(None).get_key();
+        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
+
+        Ok(iterator
+            .last()
+            .map(|(k, _)| -> Result<_, CompactFiltersError> {
+                let height = usize::from_be_bytes(
+                    k[1..]
+                        .try_into()
+                        .map_err(|_| CompactFiltersError::DataCorruption)?,
+                );
+
+                Ok(height)
+            })
+            .transpose()?
+            .unwrap_or_default())
+    }
+
+    pub fn get_tip_hash(&self) -> Result<Option<BlockHash>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let prefix = StoreEntry::BlockHeader(None).get_key();
+        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
+
+        iterator
+            .last()
+            .map(|(_, v)| -> Result<_, CompactFiltersError> {
+                let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
+
+                Ok(header.block_hash())
+            })
+            .transpose()
+    }
+
+    pub fn apply(
+        &mut self,
+        from: usize,
+        headers: Vec<BlockHeader>,
+    ) -> Result<BlockHash, CompactFiltersError> {
+        let mut batch = WriteBatch::default();
+
+        let read_store = self.store.read().unwrap();
+        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
+
+        let (mut last_hash, mut accumulated_work) = read_store
+            .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
+            .map(|result| {
+                let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&result)?;
+                Ok::<_, CompactFiltersError>((header.block_hash(), work))
+            })
+            .transpose()?
+            .ok_or(CompactFiltersError::DataCorruption)?;
+
+        for (index, header) in headers.into_iter().enumerate() {
+            if header.prev_blockhash != last_hash {
+                return Err(CompactFiltersError::InvalidHeaders);
+            }
+
+            last_hash = header.block_hash();
+            accumulated_work = accumulated_work + header.work();
+
+            let height = from + index + 1;
+            batch.put_cf(
+                cf_handle,
+                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
+                &(height).to_be_bytes(),
+            );
+            batch.put_cf(
+                cf_handle,
+                StoreEntry::BlockHeader(Some(height)).get_key(),
+                (header, accumulated_work).serialize(),
+            );
+        }
+
+        std::mem::drop(read_store);
+
+        self.store.write().unwrap().write(batch)?;
+        Ok(last_hash)
+    }
+}
+
+impl<T: StoreType> fmt::Debug for ChainStore<T> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        f.debug_struct(&format!("ChainStore<{:?}>", T::default()))
+            .field("cf_name", &self.cf_name)
+            .field("min_height", &self.min_height)
+            .field("network", &self.network)
+            .field("headers_height", &self.get_height())
+            .field("tip_hash", &self.get_tip_hash())
+            .finish()
+    }
+}
+
+pub enum BundleStatus {
+    Init,
+    CfHeaders { cf_headers: Vec<FilterHeader> },
+    CFilters { cf_filters: Vec<Vec<u8>> },
+    Processed { cf_filters: Vec<Vec<u8>> },
+    Tip { cf_filters: Vec<Vec<u8>> },
+    Pruned,
+}
+
+pub struct CfStore {
+    store: Arc<RwLock<DB>>,
+    filter_type: u8,
+}
+
+type BundleEntry = (BundleStatus, FilterHeader);
+
+impl CfStore {
+    pub fn new(
+        headers_store: &ChainStore<Full>,
+        filter_type: u8,
+    ) -> Result<Self, CompactFiltersError> {
+        let cf_store = CfStore {
+            store: Arc::clone(&headers_store.store),
+            filter_type,
+        };
+
+        let genesis = match headers_store.network {
+            Network::Bitcoin => MAINNET_GENESIS.deref(),
+            Network::Testnet => TESTNET_GENESIS.deref(),
+            Network::Regtest => REGTEST_GENESIS.deref(),
+            Network::Signet => SIGNET_GENESIS.deref(),
+        };
+
+        let filter = BlockFilter::new_script_filter(genesis, |utxo| {
+            Err(bitcoin::util::bip158::Error::UtxoMissing(*utxo))
+        })?;
+        let first_key = StoreEntry::CFilterTable((filter_type, Some(0))).get_key();
+
+        // Add the genesis' filter
+        {
+            let read_store = cf_store.store.read().unwrap();
+            if read_store.get_pinned(&first_key)?.is_none() {
+                read_store.put(
+                    &first_key,
+                    (
+                        BundleStatus::Init,
+                        filter.filter_header(&FilterHeader::from_hash(Default::default())),
+                    )
+                        .serialize(),
+                )?;
+            }
+        }
+
+        Ok(cf_store)
+    }
+
+    pub fn get_filter_type(&self) -> u8 {
+        self.filter_type
+    }
+
+    pub fn get_bundles(&self) -> Result<Vec<BundleEntry>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+
+        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
+        let iterator = read_store.prefix_iterator(&prefix);
+
+        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
+        // have the right prefix
+        iterator
+            .filter(|(k, _)| k.starts_with(&prefix))
+            .map(|(_, data)| BundleEntry::deserialize(&data))
+            .collect::<Result<_, _>>()
+    }
+
+    pub fn get_checkpoints(&self) -> Result<Vec<FilterHeader>, CompactFiltersError> {
+        let read_store = self.store.read().unwrap();
+
+        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
+        let iterator = read_store.prefix_iterator(&prefix);
+
+        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
+        // have the right prefix
+        iterator
+            .filter(|(k, _)| k.starts_with(&prefix))
+            .skip(1)
+            .map(|(_, data)| Ok::<_, CompactFiltersError>(BundleEntry::deserialize(&data)?.1))
+            .collect::<Result<_, _>>()
+    }
+
+    pub fn replace_checkpoints(
+        &self,
+        checkpoints: Vec<FilterHeader>,
+    ) -> Result<(), CompactFiltersError> {
+        let current_checkpoints = self.get_checkpoints()?;
+
+        let mut equal_bundles = 0;
+        for (index, (our, their)) in current_checkpoints
+            .iter()
+            .zip(checkpoints.iter())
+            .enumerate()
+        {
+            equal_bundles = index;
+
+            if our != their {
+                break;
+            }
+        }
+
+        let read_store = self.store.read().unwrap();
+        let mut batch = WriteBatch::default();
+
+        for (index, filter_hash) in checkpoints.iter().enumerate().skip(equal_bundles) {
+            let key = StoreEntry::CFilterTable((self.filter_type, Some(index + 1))).get_key(); // +1 to skip the genesis' filter
+
+            if let Some((BundleStatus::Tip { .. }, _)) = read_store
+                .get_pinned(&key)?
+                .map(|data| BundleEntry::deserialize(&data))
+                .transpose()?
+            {
+                println!("Keeping bundle #{} as Tip", index);
+            } else {
+                batch.put(&key, (BundleStatus::Init, *filter_hash).serialize());
+            }
+        }
+
+        read_store.write(batch)?;
+
+        Ok(())
+    }
+
+    pub fn advance_to_cf_headers(
+        &self,
+        bundle: usize,
+        checkpoint: FilterHeader,
+        filter_hashes: Vec<FilterHash>,
+    ) -> Result<BundleStatus, CompactFiltersError> {
+        let cf_headers: Vec<FilterHeader> = filter_hashes
+            .into_iter()
+            .scan(checkpoint, |prev_header, filter_hash| {
+                let filter_header = filter_hash.filter_header(&prev_header);
+                *prev_header = filter_header;
+
+                Some(filter_header)
+            })
+            .collect();
+
+        let read_store = self.store.read().unwrap();
+
+        let next_key = StoreEntry::CFilterTable((self.filter_type, Some(bundle + 1))).get_key(); // +1 to skip the genesis' filter
+        if let Some((_, next_checkpoint)) = read_store
+            .get_pinned(&next_key)?
+            .map(|data| BundleEntry::deserialize(&data))
+            .transpose()?
+        {
+            // check connection with the next bundle if present
+            if cf_headers.iter().last() != Some(&next_checkpoint) {
+                return Err(CompactFiltersError::InvalidFilterHeader);
+            }
+        }
+
+        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
+        let value = (BundleStatus::CfHeaders { cf_headers }, checkpoint);
+
+        read_store.put(key, value.serialize())?;
+
+        Ok(value.0)
+    }
+
+    pub fn advance_to_cf_filters(
+        &self,
+        bundle: usize,
+        checkpoint: FilterHeader,
+        headers: Vec<FilterHeader>,
+        filters: Vec<(usize, Vec<u8>)>,
+    ) -> Result<BundleStatus, CompactFiltersError> {
+        let cf_filters = filters
+            .into_iter()
+            .zip(headers.into_iter())
+            .scan(checkpoint, |prev_header, ((_, filter_content), header)| {
+                let filter = BlockFilter::new(&filter_content);
+                if header != filter.filter_header(&prev_header) {
+                    return Some(Err(CompactFiltersError::InvalidFilter));
+                }
+                *prev_header = header;
+
+                Some(Ok::<_, CompactFiltersError>(filter_content))
+            })
+            .collect::<Result<_, _>>()?;
+
+        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
+        let value = (BundleStatus::CFilters { cf_filters }, checkpoint);
+
+        let read_store = self.store.read().unwrap();
+        read_store.put(key, value.serialize())?;
+
+        Ok(value.0)
+    }
+
+    pub fn prune_filters(
+        &self,
+        bundle: usize,
+        checkpoint: FilterHeader,
+    ) -> Result<BundleStatus, CompactFiltersError> {
+        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
+        let value = (BundleStatus::Pruned, checkpoint);
+
+        let read_store = self.store.read().unwrap();
+        read_store.put(key, value.serialize())?;
+
+        Ok(value.0)
+    }
+
+    pub fn mark_as_tip(
+        &self,
+        bundle: usize,
+        cf_filters: Vec<Vec<u8>>,
+        checkpoint: FilterHeader,
+    ) -> Result<BundleStatus, CompactFiltersError> {
+        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
+        let value = (BundleStatus::Tip { cf_filters }, checkpoint);
+
+        let read_store = self.store.read().unwrap();
+        read_store.put(key, value.serialize())?;
+
+        Ok(value.0)
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/sync.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/sync.rs.html new file mode 100644 index 0000000000..9e1601fadd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/sync.rs.html @@ -0,0 +1,596 @@ +sync.rs - source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+use std::collections::{BTreeMap, HashMap, VecDeque};
+use std::sync::{Arc, Mutex};
+use std::time::Duration;
+
+use bitcoin::hash_types::{BlockHash, FilterHeader};
+use bitcoin::network::message::NetworkMessage;
+use bitcoin::network::message_blockdata::GetHeadersMessage;
+use bitcoin::util::bip158::BlockFilter;
+
+use super::peer::*;
+use super::store::*;
+use super::CompactFiltersError;
+use crate::error::Error;
+
+pub(crate) const BURIED_CONFIRMATIONS: usize = 100;
+
+pub struct CfSync {
+    headers_store: Arc<ChainStore<Full>>,
+    cf_store: Arc<CfStore>,
+    skip_blocks: usize,
+    bundles: Mutex<VecDeque<(BundleStatus, FilterHeader, usize)>>,
+}
+
+impl CfSync {
+    pub fn new(
+        headers_store: Arc<ChainStore<Full>>,
+        skip_blocks: usize,
+        filter_type: u8,
+    ) -> Result<Self, CompactFiltersError> {
+        let cf_store = Arc::new(CfStore::new(&headers_store, filter_type)?);
+
+        Ok(CfSync {
+            headers_store,
+            cf_store,
+            skip_blocks,
+            bundles: Mutex::new(VecDeque::new()),
+        })
+    }
+
+    pub fn pruned_bundles(&self) -> Result<usize, CompactFiltersError> {
+        Ok(self
+            .cf_store
+            .get_bundles()?
+            .into_iter()
+            .skip(self.skip_blocks / 1000)
+            .fold(0, |acc, (status, _)| match status {
+                BundleStatus::Pruned => acc + 1,
+                _ => acc,
+            }))
+    }
+
+    pub fn prepare_sync(&self, peer: Arc<Peer>) -> Result<(), CompactFiltersError> {
+        let mut bundles_lock = self.bundles.lock().unwrap();
+
+        let resp = peer.get_cf_checkpt(
+            self.cf_store.get_filter_type(),
+            self.headers_store.get_tip_hash()?.unwrap(),
+        )?;
+        self.cf_store.replace_checkpoints(resp.filter_headers)?;
+
+        bundles_lock.clear();
+        for (index, (status, checkpoint)) in self.cf_store.get_bundles()?.into_iter().enumerate() {
+            bundles_lock.push_back((status, checkpoint, index));
+        }
+
+        Ok(())
+    }
+
+    pub fn capture_thread_for_sync<F, Q>(
+        &self,
+        peer: Arc<Peer>,
+        process: F,
+        completed_bundle: Q,
+    ) -> Result<(), CompactFiltersError>
+    where
+        F: Fn(&BlockHash, &BlockFilter) -> Result<bool, CompactFiltersError>,
+        Q: Fn(usize) -> Result<(), Error>,
+    {
+        let current_height = self.headers_store.get_height()?; // TODO: we should update it in case headers_store is also updated
+
+        loop {
+            let (mut status, checkpoint, index) = match self.bundles.lock().unwrap().pop_front() {
+                None => break,
+                Some(x) => x,
+            };
+
+            log::debug!(
+                "Processing bundle #{} - height {} to {}",
+                index,
+                index * 1000 + 1,
+                (index + 1) * 1000
+            );
+
+            let process_received_filters =
+                |expected_filters| -> Result<BTreeMap<usize, Vec<u8>>, CompactFiltersError> {
+                    let mut filters_map = BTreeMap::new();
+                    for _ in 0..expected_filters {
+                        let filter = peer.pop_cf_filter_resp()?;
+                        if filter.filter_type != self.cf_store.get_filter_type() {
+                            return Err(CompactFiltersError::InvalidResponse);
+                        }
+
+                        match self.headers_store.get_height_for(&filter.block_hash)? {
+                            Some(height) => filters_map.insert(height, filter.filter),
+                            None => return Err(CompactFiltersError::InvalidFilter),
+                        };
+                    }
+
+                    Ok(filters_map)
+                };
+
+            let start_height = index * 1000 + 1;
+            let mut already_processed = 0;
+
+            if start_height < self.skip_blocks {
+                status = self.cf_store.prune_filters(index, checkpoint)?;
+            }
+
+            let stop_height = std::cmp::min(current_height, start_height + 999);
+            let stop_hash = self.headers_store.get_block_hash(stop_height)?.unwrap();
+
+            if let BundleStatus::Init = status {
+                log::trace!("status: Init");
+
+                let resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
+
+                assert!(resp.previous_filter_header == checkpoint);
+                status =
+                    self.cf_store
+                        .advance_to_cf_headers(index, checkpoint, resp.filter_hashes)?;
+            }
+            if let BundleStatus::Tip { cf_filters } = status {
+                log::trace!("status: Tip (beginning) ");
+
+                already_processed = cf_filters.len();
+                let headers_resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
+
+                let cf_headers = match self.cf_store.advance_to_cf_headers(
+                    index,
+                    checkpoint,
+                    headers_resp.filter_hashes,
+                )? {
+                    BundleStatus::CfHeaders { cf_headers } => cf_headers,
+                    _ => return Err(CompactFiltersError::InvalidResponse),
+                };
+
+                peer.get_cf_filters(
+                    self.cf_store.get_filter_type(),
+                    (start_height + cf_filters.len()) as u32,
+                    stop_hash,
+                )?;
+                let expected_filters = stop_height - start_height + 1 - cf_filters.len();
+                let filters_map = process_received_filters(expected_filters)?;
+                let filters = cf_filters
+                    .into_iter()
+                    .enumerate()
+                    .chain(filters_map.into_iter())
+                    .collect();
+                status = self
+                    .cf_store
+                    .advance_to_cf_filters(index, checkpoint, cf_headers, filters)?;
+            }
+            if let BundleStatus::CfHeaders { cf_headers } = status {
+                log::trace!("status: CFHeaders");
+
+                peer.get_cf_filters(
+                    self.cf_store.get_filter_type(),
+                    start_height as u32,
+                    stop_hash,
+                )?;
+                let expected_filters = stop_height - start_height + 1;
+                let filters_map = process_received_filters(expected_filters)?;
+                status = self.cf_store.advance_to_cf_filters(
+                    index,
+                    checkpoint,
+                    cf_headers,
+                    filters_map.into_iter().collect(),
+                )?;
+            }
+            if let BundleStatus::CFilters { cf_filters } = status {
+                log::trace!("status: CFilters");
+
+                let last_sync_buried_height =
+                    (start_height + already_processed).saturating_sub(BURIED_CONFIRMATIONS);
+
+                for (filter_index, filter) in cf_filters.iter().enumerate() {
+                    let height = filter_index + start_height;
+
+                    // do not download blocks that were already "buried" since the last sync
+                    if height < last_sync_buried_height {
+                        continue;
+                    }
+
+                    let block_hash = self.headers_store.get_block_hash(height)?.unwrap();
+
+                    // TODO: also download random blocks?
+                    if process(&block_hash, &BlockFilter::new(&filter))? {
+                        log::debug!("Downloading block {}", block_hash);
+
+                        let block = peer
+                            .get_block(block_hash)?
+                            .ok_or(CompactFiltersError::MissingBlock)?;
+                        self.headers_store.save_full_block(&block, height)?;
+                    }
+                }
+
+                status = BundleStatus::Processed { cf_filters };
+            }
+            if let BundleStatus::Processed { cf_filters } = status {
+                log::trace!("status: Processed");
+
+                if current_height - stop_height > 1000 {
+                    status = self.cf_store.prune_filters(index, checkpoint)?;
+                } else {
+                    status = self.cf_store.mark_as_tip(index, cf_filters, checkpoint)?;
+                }
+
+                completed_bundle(index)?;
+            }
+            if let BundleStatus::Pruned = status {
+                log::trace!("status: Pruned");
+            }
+            if let BundleStatus::Tip { .. } = status {
+                log::trace!("status: Tip");
+            }
+        }
+
+        Ok(())
+    }
+}
+
+pub fn sync_headers<F>(
+    peer: Arc<Peer>,
+    store: Arc<ChainStore<Full>>,
+    sync_fn: F,
+) -> Result<Option<ChainStore<Snapshot>>, CompactFiltersError>
+where
+    F: Fn(usize) -> Result<(), Error>,
+{
+    let locators = store.get_locators()?;
+    let locators_vec = locators.iter().map(|(hash, _)| hash).cloned().collect();
+    let locators_map: HashMap<_, _> = locators.into_iter().collect();
+
+    peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
+        locators_vec,
+        Default::default(),
+    )))?;
+    let (mut snapshot, mut last_hash) = if let NetworkMessage::Headers(headers) = peer
+        .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
+        .ok_or(CompactFiltersError::Timeout)?
+    {
+        if headers.is_empty() {
+            return Ok(None);
+        }
+
+        match locators_map.get(&headers[0].prev_blockhash) {
+            None => return Err(CompactFiltersError::InvalidHeaders),
+            Some(from) => (store.start_snapshot(*from)?, headers[0].prev_blockhash),
+        }
+    } else {
+        return Err(CompactFiltersError::InvalidResponse);
+    };
+
+    let mut sync_height = store.get_height()?;
+    while sync_height < peer.get_version().start_height as usize {
+        peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
+            vec![last_hash],
+            Default::default(),
+        )))?;
+        if let NetworkMessage::Headers(headers) = peer
+            .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
+            .ok_or(CompactFiltersError::Timeout)?
+        {
+            let batch_len = headers.len();
+            last_hash = snapshot.apply(sync_height, headers)?;
+
+            sync_height += batch_len;
+            sync_fn(sync_height)?;
+        } else {
+            return Err(CompactFiltersError::InvalidResponse);
+        }
+    }
+
+    Ok(Some(snapshot))
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/electrum.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/electrum.rs.html new file mode 100644 index 0000000000..a51f2cbb78 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/electrum.rs.html @@ -0,0 +1,374 @@ +electrum.rs - source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+//! Electrum
+//!
+//! This module defines a [`Blockchain`] struct that wraps an [`electrum_client::Client`]
+//! and implements the logic required to populate the wallet's [database](crate::database::Database) by
+//! querying the inner client.
+//!
+//! ## Example
+//!
+//! ```no_run
+//! # use bdk::blockchain::electrum::ElectrumBlockchain;
+//! let client = electrum_client::Client::new("ssl://electrum.blockstream.info:50002")?;
+//! let blockchain = ElectrumBlockchain::from(client);
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use std::collections::HashSet;
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use bitcoin::{BlockHeader, Script, Transaction, Txid};
+
+use electrum_client::{Client, ConfigBuilder, ElectrumApi, Socks5Config};
+
+use self::utils::{ElectrumLikeSync, ElsGetHistoryRes};
+use super::*;
+use crate::database::BatchDatabase;
+use crate::error::Error;
+use crate::FeeRate;
+
+/// Wrapper over an Electrum Client that implements the required blockchain traits
+///
+/// ## Example
+/// See the [`blockchain::electrum`](crate::blockchain::electrum) module for a usage example.
+pub struct ElectrumBlockchain {
+    client: Client,
+    stop_gap: usize,
+}
+
+impl std::convert::From<Client> for ElectrumBlockchain {
+    fn from(client: Client) -> Self {
+        ElectrumBlockchain {
+            client,
+            stop_gap: 20,
+        }
+    }
+}
+
+impl Blockchain for ElectrumBlockchain {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        vec![
+            Capability::FullHistory,
+            Capability::GetAnyTx,
+            Capability::AccurateFees,
+        ]
+        .into_iter()
+        .collect()
+    }
+
+    fn setup<D: BatchDatabase, P: Progress>(
+        &self,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        self.client
+            .electrum_like_setup(self.stop_gap, database, progress_update)
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        Ok(self.client.transaction_get(txid).map(Option::Some)?)
+    }
+
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        Ok(self.client.transaction_broadcast(tx).map(|_| ())?)
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        // TODO: unsubscribe when added to the client, or is there a better call to use here?
+
+        Ok(self
+            .client
+            .block_headers_subscribe()
+            .map(|data| data.height as u32)?)
+    }
+
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
+        Ok(FeeRate::from_btc_per_kvb(
+            self.client.estimate_fee(target)? as f32
+        ))
+    }
+}
+
+impl ElectrumLikeSync for Client {
+    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script> + Clone>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ElsGetHistoryRes>>, Error> {
+        self.batch_script_get_history(scripts)
+            .map(|v| {
+                v.into_iter()
+                    .map(|v| {
+                        v.into_iter()
+                            .map(
+                                |electrum_client::GetHistoryRes {
+                                     height, tx_hash, ..
+                                 }| ElsGetHistoryRes {
+                                    height,
+                                    tx_hash,
+                                },
+                            )
+                            .collect()
+                    })
+                    .collect()
+            })
+            .map_err(Error::Electrum)
+    }
+
+    fn els_batch_transaction_get<'s, I: IntoIterator<Item = &'s Txid> + Clone>(
+        &self,
+        txids: I,
+    ) -> Result<Vec<Transaction>, Error> {
+        self.batch_transaction_get(txids).map_err(Error::Electrum)
+    }
+
+    fn els_batch_block_header<I: IntoIterator<Item = u32> + Clone>(
+        &self,
+        heights: I,
+    ) -> Result<Vec<BlockHeader>, Error> {
+        self.batch_block_header(heights).map_err(Error::Electrum)
+    }
+}
+
+/// Configuration for an [`ElectrumBlockchain`]
+#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq)]
+pub struct ElectrumBlockchainConfig {
+    /// URL of the Electrum server (such as ElectrumX, Esplora, BWT) may start with `ssl://` or `tcp://` and include a port
+    ///
+    /// eg. `ssl://electrum.blockstream.info:60002`
+    pub url: String,
+    /// URL of the socks5 proxy server or a Tor service
+    pub socks5: Option<String>,
+    /// Request retry count
+    pub retry: u8,
+    /// Request timeout (seconds)
+    pub timeout: Option<u8>,
+    /// Stop searching addresses for transactions after finding an unused gap of this length
+    pub stop_gap: usize,
+}
+
+impl ConfigurableBlockchain for ElectrumBlockchain {
+    type Config = ElectrumBlockchainConfig;
+
+    fn from_config(config: &Self::Config) -> Result<Self, Error> {
+        let socks5 = config.socks5.as_ref().map(Socks5Config::new);
+        let electrum_config = ConfigBuilder::new()
+            .retry(config.retry)
+            .timeout(config.timeout)?
+            .socks5(socks5)?
+            .build();
+
+        Ok(ElectrumBlockchain {
+            client: Client::from_config(config.url.as_str(), electrum_config)?,
+            stop_gap: config.stop_gap,
+        })
+    }
+}
+
+#[cfg(test)]
+#[cfg(feature = "test-electrum")]
+crate::bdk_blockchain_tests! {
+    fn test_instance(test_client: &TestClient) -> ElectrumBlockchain {
+        ElectrumBlockchain::from(Client::new(&test_client.electrsd.electrum_url).unwrap())
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/mod.rs.html new file mode 100644 index 0000000000..7d87905c9b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/mod.rs.html @@ -0,0 +1,262 @@ +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
+
//! Esplora
+//!
+//! This module defines a [`EsploraBlockchain`] struct that can query an Esplora
+//! backend populate the wallet's [database](crate::database::Database) by:
+//!
+//! ## Example
+//!
+//! ```no_run
+//! # use bdk::blockchain::esplora::EsploraBlockchain;
+//! let blockchain = EsploraBlockchain::new("https://blockstream.info/testnet/api", 20);
+//! # Ok::<(), bdk::Error>(())
+//! ```
+//!
+//! Esplora blockchain can use either `ureq` or `reqwest` for the HTTP client
+//! depending on your needs (blocking or async respectively).
+//!
+//! Please note, to configure the Esplora HTTP client correctly use one of:
+//! Blocking:  --features='esplora,ureq'
+//! Async:     --features='async-interface,esplora,reqwest' --no-default-features
+use std::collections::HashMap;
+use std::fmt;
+use std::io;
+
+use serde::Deserialize;
+
+use bitcoin::consensus;
+use bitcoin::{BlockHash, Txid};
+
+use crate::error::Error;
+use crate::FeeRate;
+
+#[cfg(feature = "reqwest")]
+mod reqwest;
+
+#[cfg(feature = "reqwest")]
+pub use self::reqwest::*;
+
+#[cfg(feature = "ureq")]
+mod ureq;
+
+#[cfg(feature = "ureq")]
+pub use self::ureq::*;
+
+fn into_fee_rate(target: usize, estimates: HashMap<String, f64>) -> Result<FeeRate, Error> {
+    let fee_val = estimates
+        .into_iter()
+        .map(|(k, v)| Ok::<_, std::num::ParseIntError>((k.parse::<usize>()?, v)))
+        .collect::<Result<Vec<_>, _>>()
+        .map_err(|e| Error::Generic(e.to_string()))?
+        .into_iter()
+        .take_while(|(k, _)| k <= &target)
+        .map(|(_, v)| v)
+        .last()
+        .unwrap_or(1.0);
+
+    Ok(FeeRate::from_sat_per_vb(fee_val as f32))
+}
+
+/// Data type used when fetching transaction history from Esplora.
+#[derive(Deserialize)]
+pub struct EsploraGetHistory {
+    txid: Txid,
+    status: EsploraGetHistoryStatus,
+}
+
+#[derive(Deserialize)]
+struct EsploraGetHistoryStatus {
+    block_height: Option<usize>,
+}
+
+/// Errors that can happen during a sync with [`EsploraBlockchain`]
+#[derive(Debug)]
+pub enum EsploraError {
+    /// Error during ureq HTTP request
+    #[cfg(feature = "ureq")]
+    Ureq(::ureq::Error),
+    /// Transport error during the ureq HTTP call
+    #[cfg(feature = "ureq")]
+    UreqTransport(::ureq::Transport),
+    /// Error during reqwest HTTP request
+    #[cfg(feature = "reqwest")]
+    Reqwest(::reqwest::Error),
+    /// HTTP response error
+    HttpResponse(u16),
+    /// IO error during ureq response read
+    Io(io::Error),
+    /// No header found in ureq response
+    NoHeader,
+    /// Invalid number returned
+    Parsing(std::num::ParseIntError),
+    /// Invalid Bitcoin data returned
+    BitcoinEncoding(bitcoin::consensus::encode::Error),
+    /// Invalid Hex data returned
+    Hex(bitcoin::hashes::hex::Error),
+
+    /// Transaction not found
+    TransactionNotFound(Txid),
+    /// Header height not found
+    HeaderHeightNotFound(u32),
+    /// Header hash not found
+    HeaderHashNotFound(BlockHash),
+}
+
+impl fmt::Display for EsploraError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for EsploraError {}
+
+#[cfg(feature = "ureq")]
+impl_error!(::ureq::Error, Ureq, EsploraError);
+#[cfg(feature = "ureq")]
+impl_error!(::ureq::Transport, UreqTransport, EsploraError);
+#[cfg(feature = "reqwest")]
+impl_error!(::reqwest::Error, Reqwest, EsploraError);
+impl_error!(io::Error, Io, EsploraError);
+impl_error!(std::num::ParseIntError, Parsing, EsploraError);
+impl_error!(consensus::encode::Error, BitcoinEncoding, EsploraError);
+impl_error!(bitcoin::hashes::hex::Error, Hex, EsploraError);
+
+#[cfg(test)]
+#[cfg(feature = "test-esplora")]
+crate::bdk_blockchain_tests! {
+    fn test_instance(test_client: &TestClient) -> EsploraBlockchain {
+        EsploraBlockchain::new(&format!("http://{}",test_client.electrsd.esplora_url.as_ref().unwrap()), 20)
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/ureq.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/ureq.rs.html new file mode 100644 index 0000000000..10f92a0fea --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/ureq.rs.html @@ -0,0 +1,800 @@ +ureq.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
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+//! Esplora by way of `ureq` HTTP client.
+
+use std::collections::{HashMap, HashSet};
+use std::io;
+use std::io::Read;
+use std::time::Duration;
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use ureq::{Agent, Proxy, Response};
+
+use bitcoin::consensus::{deserialize, serialize};
+use bitcoin::hashes::hex::{FromHex, ToHex};
+use bitcoin::hashes::{sha256, Hash};
+use bitcoin::{BlockHeader, Script, Transaction, Txid};
+
+use crate::blockchain::esplora::{EsploraError, EsploraGetHistory};
+use crate::blockchain::utils::{ElectrumLikeSync, ElsGetHistoryRes};
+use crate::blockchain::*;
+use crate::database::BatchDatabase;
+use crate::error::Error;
+use crate::FeeRate;
+
+#[derive(Debug)]
+struct UrlClient {
+    url: String,
+    agent: Agent,
+}
+
+/// Structure that implements the logic to sync with Esplora
+///
+/// ## Example
+/// See the [`blockchain::esplora`](crate::blockchain::esplora) module for a usage example.
+#[derive(Debug)]
+pub struct EsploraBlockchain {
+    url_client: UrlClient,
+    stop_gap: usize,
+}
+
+impl std::convert::From<UrlClient> for EsploraBlockchain {
+    fn from(url_client: UrlClient) -> Self {
+        EsploraBlockchain {
+            url_client,
+            stop_gap: 20,
+        }
+    }
+}
+
+impl EsploraBlockchain {
+    /// Create a new instance of the client from a base URL and the `stop_gap`.
+    pub fn new(base_url: &str, stop_gap: usize) -> Self {
+        EsploraBlockchain {
+            url_client: UrlClient {
+                url: base_url.to_string(),
+                agent: Agent::new(),
+            },
+            stop_gap,
+        }
+    }
+
+    /// Set the inner `ureq` agent.
+    pub fn with_agent(mut self, agent: Agent) -> Self {
+        self.url_client.agent = agent;
+        self
+    }
+}
+
+impl Blockchain for EsploraBlockchain {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        vec![
+            Capability::FullHistory,
+            Capability::GetAnyTx,
+            Capability::AccurateFees,
+        ]
+        .into_iter()
+        .collect()
+    }
+
+    fn setup<D: BatchDatabase, P: Progress>(
+        &self,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        self.url_client
+            .electrum_like_setup(self.stop_gap, database, progress_update)
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        Ok(self.url_client._get_tx(txid)?)
+    }
+
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        let _txid = self.url_client._broadcast(tx)?;
+        Ok(())
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        Ok(self.url_client._get_height()?)
+    }
+
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
+        let estimates = self.url_client._get_fee_estimates()?;
+        super::into_fee_rate(target, estimates)
+    }
+}
+
+impl UrlClient {
+    fn script_to_scripthash(script: &Script) -> String {
+        sha256::Hash::hash(script.as_bytes()).into_inner().to_hex()
+    }
+
+    fn _get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, EsploraError> {
+        let resp = self
+            .agent
+            .get(&format!("{}/tx/{}/raw", self.url, txid))
+            .call();
+
+        match resp {
+            Ok(resp) => Ok(Some(deserialize(&into_bytes(resp)?)?)),
+            Err(ureq::Error::Status(code, _)) => {
+                if is_status_not_found(code) {
+                    return Ok(None);
+                }
+                Err(EsploraError::HttpResponse(code))
+            }
+            Err(e) => Err(EsploraError::Ureq(e)),
+        }
+    }
+
+    fn _get_tx_no_opt(&self, txid: &Txid) -> Result<Transaction, EsploraError> {
+        match self._get_tx(txid) {
+            Ok(Some(tx)) => Ok(tx),
+            Ok(None) => Err(EsploraError::TransactionNotFound(*txid)),
+            Err(e) => Err(e),
+        }
+    }
+
+    fn _get_header(&self, block_height: u32) -> Result<BlockHeader, EsploraError> {
+        let resp = self
+            .agent
+            .get(&format!("{}/block-height/{}", self.url, block_height))
+            .call();
+
+        let bytes = match resp {
+            Ok(resp) => Ok(into_bytes(resp)?),
+            Err(ureq::Error::Status(code, _)) => Err(EsploraError::HttpResponse(code)),
+            Err(e) => Err(EsploraError::Ureq(e)),
+        }?;
+
+        let hash = std::str::from_utf8(&bytes)
+            .map_err(|_| EsploraError::HeaderHeightNotFound(block_height))?;
+
+        let resp = self
+            .agent
+            .get(&format!("{}/block/{}/header", self.url, hash))
+            .call();
+
+        match resp {
+            Ok(resp) => Ok(deserialize(&Vec::from_hex(&resp.into_string()?)?)?),
+            Err(ureq::Error::Status(code, _)) => Err(EsploraError::HttpResponse(code)),
+            Err(e) => Err(EsploraError::Ureq(e)),
+        }
+    }
+
+    fn _broadcast(&self, transaction: &Transaction) -> Result<(), EsploraError> {
+        let resp = self
+            .agent
+            .post(&format!("{}/tx", self.url))
+            .send_string(&serialize(transaction).to_hex());
+
+        match resp {
+            Ok(_) => Ok(()), // We do not return the txid?
+            Err(ureq::Error::Status(code, _)) => Err(EsploraError::HttpResponse(code)),
+            Err(e) => Err(EsploraError::Ureq(e)),
+        }
+    }
+
+    fn _get_height(&self) -> Result<u32, EsploraError> {
+        let resp = self
+            .agent
+            .get(&format!("{}/blocks/tip/height", self.url))
+            .call();
+
+        match resp {
+            Ok(resp) => Ok(resp.into_string()?.parse()?),
+            Err(ureq::Error::Status(code, _)) => Err(EsploraError::HttpResponse(code)),
+            Err(e) => Err(EsploraError::Ureq(e)),
+        }
+    }
+
+    fn _script_get_history(&self, script: &Script) -> Result<Vec<ElsGetHistoryRes>, EsploraError> {
+        let mut result = Vec::new();
+        let scripthash = Self::script_to_scripthash(script);
+
+        // Add the unconfirmed transactions first
+
+        let resp = self
+            .agent
+            .get(&format!(
+                "{}/scripthash/{}/txs/mempool",
+                self.url, scripthash
+            ))
+            .call();
+
+        let v = match resp {
+            Ok(resp) => {
+                let v: Vec<EsploraGetHistory> = resp.into_json()?;
+                Ok(v)
+            }
+            Err(ureq::Error::Status(code, _)) => Err(EsploraError::HttpResponse(code)),
+            Err(e) => Err(EsploraError::Ureq(e)),
+        }?;
+
+        result.extend(v.into_iter().map(|x| ElsGetHistoryRes {
+            tx_hash: x.txid,
+            height: x.status.block_height.unwrap_or(0) as i32,
+        }));
+
+        debug!(
+            "Found {} mempool txs for {} - {:?}",
+            result.len(),
+            scripthash,
+            script
+        );
+
+        // Then go through all the pages of confirmed transactions
+        let mut last_txid = String::new();
+        loop {
+            let resp = self
+                .agent
+                .get(&format!(
+                    "{}/scripthash/{}/txs/chain/{}",
+                    self.url, scripthash, last_txid
+                ))
+                .call();
+
+            let v = match resp {
+                Ok(resp) => {
+                    let v: Vec<EsploraGetHistory> = resp.into_json()?;
+                    Ok(v)
+                }
+                Err(ureq::Error::Status(code, _)) => Err(EsploraError::HttpResponse(code)),
+                Err(e) => Err(EsploraError::Ureq(e)),
+            }?;
+
+            let len = v.len();
+            if let Some(elem) = v.last() {
+                last_txid = elem.txid.to_hex();
+            }
+
+            debug!("... adding {} confirmed transactions", len);
+
+            result.extend(v.into_iter().map(|x| ElsGetHistoryRes {
+                tx_hash: x.txid,
+                height: x.status.block_height.unwrap_or(0) as i32,
+            }));
+
+            if len < 25 {
+                break;
+            }
+        }
+
+        Ok(result)
+    }
+
+    fn _get_fee_estimates(&self) -> Result<HashMap<String, f64>, EsploraError> {
+        let resp = self
+            .agent
+            .get(&format!("{}/fee-estimates", self.url,))
+            .call();
+
+        let map = match resp {
+            Ok(resp) => {
+                let map: HashMap<String, f64> = resp.into_json()?;
+                Ok(map)
+            }
+            Err(ureq::Error::Status(code, _)) => Err(EsploraError::HttpResponse(code)),
+            Err(e) => Err(EsploraError::Ureq(e)),
+        }?;
+
+        Ok(map)
+    }
+}
+
+fn is_status_not_found(status: u16) -> bool {
+    status == 404
+}
+
+fn into_bytes(resp: Response) -> Result<Vec<u8>, io::Error> {
+    const BYTES_LIMIT: usize = 10 * 1_024 * 1_024;
+
+    let mut buf: Vec<u8> = vec![];
+    resp.into_reader()
+        .take((BYTES_LIMIT + 1) as u64)
+        .read_to_end(&mut buf)?;
+    if buf.len() > BYTES_LIMIT {
+        return Err(io::Error::new(
+            io::ErrorKind::Other,
+            "response too big for into_bytes",
+        ));
+    }
+
+    Ok(buf)
+}
+
+impl ElectrumLikeSync for UrlClient {
+    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ElsGetHistoryRes>>, Error> {
+        let mut results = vec![];
+        for script in scripts.into_iter() {
+            let v = self._script_get_history(script)?;
+            results.push(v);
+        }
+        Ok(results)
+    }
+
+    fn els_batch_transaction_get<'s, I: IntoIterator<Item = &'s Txid>>(
+        &self,
+        txids: I,
+    ) -> Result<Vec<Transaction>, Error> {
+        let mut results = vec![];
+        for txid in txids.into_iter() {
+            let tx = self._get_tx_no_opt(txid)?;
+            results.push(tx);
+        }
+        Ok(results)
+    }
+
+    fn els_batch_block_header<I: IntoIterator<Item = u32>>(
+        &self,
+        heights: I,
+    ) -> Result<Vec<BlockHeader>, Error> {
+        let mut results = vec![];
+        for height in heights.into_iter() {
+            let header = self._get_header(height)?;
+            results.push(header);
+        }
+        Ok(results)
+    }
+}
+
+/// Configuration for an [`EsploraBlockchain`]
+#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq)]
+pub struct EsploraBlockchainConfig {
+    /// Base URL of the esplora service eg. `https://blockstream.info/api/`
+    pub base_url: String,
+    /// Optional URL of the proxy to use to make requests to the Esplora server
+    ///
+    /// The string should be formatted as: `<protocol>://<user>:<password>@host:<port>`.
+    ///
+    /// Note that the format of this value and the supported protocols change slightly between the
+    /// sync version of esplora (using `ureq`) and the async version (using `reqwest`). For more
+    /// details check with the documentation of the two crates. Both of them are compiled with
+    /// the `socks` feature enabled.
+    ///
+    /// The proxy is ignored when targeting `wasm32`.
+    pub proxy: Option<String>,
+    /// Socket read timeout.
+    pub timeout_read: u64,
+    /// Socket write timeout.
+    pub timeout_write: u64,
+    /// Stop searching addresses for transactions after finding an unused gap of this length.
+    pub stop_gap: usize,
+}
+
+impl ConfigurableBlockchain for EsploraBlockchain {
+    type Config = EsploraBlockchainConfig;
+
+    fn from_config(config: &Self::Config) -> Result<Self, Error> {
+        let mut agent_builder = ureq::AgentBuilder::new()
+            .timeout_read(Duration::from_secs(config.timeout_read))
+            .timeout_write(Duration::from_secs(config.timeout_write));
+
+        if let Some(proxy) = &config.proxy {
+            agent_builder = agent_builder
+                .proxy(Proxy::new(proxy).map_err(|e| Error::Esplora(Box::new(e.into())))?);
+        }
+
+        Ok(
+            EsploraBlockchain::new(config.base_url.as_str(), config.stop_gap)
+                .with_agent(agent_builder.build()),
+        )
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/mod.rs.html new file mode 100644 index 0000000000..6bac7fc40c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/mod.rs.html @@ -0,0 +1,516 @@ +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
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+//! Blockchain backends
+//!
+//! This module provides the implementation of a few commonly-used backends like
+//! [Electrum](crate::blockchain::electrum), [Esplora](crate::blockchain::esplora) and
+//! [Compact Filters/Neutrino](crate::blockchain::compact_filters), along with a generalized trait
+//! [`Blockchain`] that can be implemented to build customized backends.
+
+use std::collections::HashSet;
+use std::ops::Deref;
+use std::sync::mpsc::{channel, Receiver, Sender};
+use std::sync::Arc;
+
+use bitcoin::{Transaction, Txid};
+
+use crate::database::BatchDatabase;
+use crate::error::Error;
+use crate::FeeRate;
+
+#[cfg(any(feature = "electrum", feature = "esplora"))]
+pub(crate) mod utils;
+
+#[cfg(any(
+    feature = "electrum",
+    feature = "esplora",
+    feature = "compact_filters",
+    feature = "rpc"
+))]
+pub mod any;
+#[cfg(any(
+    feature = "electrum",
+    feature = "esplora",
+    feature = "compact_filters",
+    feature = "rpc"
+))]
+pub use any::{AnyBlockchain, AnyBlockchainConfig};
+
+#[cfg(feature = "electrum")]
+#[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
+pub mod electrum;
+#[cfg(feature = "electrum")]
+pub use self::electrum::ElectrumBlockchain;
+#[cfg(feature = "electrum")]
+pub use self::electrum::ElectrumBlockchainConfig;
+
+#[cfg(feature = "rpc")]
+#[cfg_attr(docsrs, doc(cfg(feature = "rpc")))]
+pub mod rpc;
+#[cfg(feature = "rpc")]
+pub use self::rpc::RpcBlockchain;
+#[cfg(feature = "rpc")]
+pub use self::rpc::RpcConfig;
+
+#[cfg(feature = "esplora")]
+#[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
+pub mod esplora;
+#[cfg(feature = "esplora")]
+pub use self::esplora::EsploraBlockchain;
+
+#[cfg(feature = "compact_filters")]
+#[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
+pub mod compact_filters;
+
+#[cfg(feature = "compact_filters")]
+pub use self::compact_filters::CompactFiltersBlockchain;
+
+/// Capabilities that can be supported by a [`Blockchain`] backend
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum Capability {
+    /// Can recover the full history of a wallet and not only the set of currently spendable UTXOs
+    FullHistory,
+    /// Can fetch any historical transaction given its txid
+    GetAnyTx,
+    /// Can compute accurate fees for the transactions found during sync
+    AccurateFees,
+}
+
+/// Trait that defines the actions that must be supported by a blockchain backend
+#[maybe_async]
+pub trait Blockchain {
+    /// Return the set of [`Capability`] supported by this backend
+    fn get_capabilities(&self) -> HashSet<Capability>;
+
+    /// Setup the backend and populate the internal database for the first time
+    ///
+    /// This method is the equivalent of [`Blockchain::sync`], but it's guaranteed to only be
+    /// called once, at the first [`Wallet::sync`](crate::wallet::Wallet::sync).
+    ///
+    /// The rationale behind the distinction between `sync` and `setup` is that some custom backends
+    /// might need to perform specific actions only the first time they are synced.
+    ///
+    /// For types that do not have that distinction, only this method can be implemented, since
+    /// [`Blockchain::sync`] defaults to calling this internally if not overridden.
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error>;
+    /// Populate the internal database with transactions and UTXOs
+    ///
+    /// If not overridden, it defaults to calling [`Blockchain::setup`] internally.
+    ///
+    /// This method should implement the logic required to iterate over the list of the wallet's
+    /// script_pubkeys using [`Database::iter_script_pubkeys`] and look for relevant transactions
+    /// in the blockchain to populate the database with [`BatchOperations::set_tx`] and
+    /// [`BatchOperations::set_utxo`].
+    ///
+    /// This method should also take care of removing UTXOs that are seen as spent in the
+    /// blockchain, using [`BatchOperations::del_utxo`].
+    ///
+    /// The `progress_update` object can be used to give the caller updates about the progress by using
+    /// [`Progress::update`].
+    ///
+    /// [`Database::iter_script_pubkeys`]: crate::database::Database::iter_script_pubkeys
+    /// [`BatchOperations::set_tx`]: crate::database::BatchOperations::set_tx
+    /// [`BatchOperations::set_utxo`]: crate::database::BatchOperations::set_utxo
+    /// [`BatchOperations::del_utxo`]: crate::database::BatchOperations::del_utxo
+    fn sync<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(self.setup(database, progress_update))
+    }
+
+    /// Fetch a transaction from the blockchain given its txid
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
+    /// Broadcast a transaction
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error>;
+
+    /// Return the current height
+    fn get_height(&self) -> Result<u32, Error>;
+    /// Estimate the fee rate required to confirm a transaction in a given `target` of blocks
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>;
+}
+
+/// Trait for [`Blockchain`] types that can be created given a configuration
+pub trait ConfigurableBlockchain: Blockchain + Sized {
+    /// Type that contains the configuration
+    type Config: std::fmt::Debug;
+
+    /// Create a new instance given a configuration
+    fn from_config(config: &Self::Config) -> Result<Self, Error>;
+}
+
+/// Data sent with a progress update over a [`channel`]
+pub type ProgressData = (f32, Option<String>);
+
+/// Trait for types that can receive and process progress updates during [`Blockchain::sync`] and
+/// [`Blockchain::setup`]
+pub trait Progress: Send {
+    /// Send a new progress update
+    ///
+    /// The `progress` value should be in the range 0.0 - 100.0, and the `message` value is an
+    /// optional text message that can be displayed to the user.
+    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error>;
+}
+
+/// Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]
+pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>) {
+    channel()
+}
+
+impl Progress for Sender<ProgressData> {
+    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
+        if !(0.0..=100.0).contains(&progress) {
+            return Err(Error::InvalidProgressValue(progress));
+        }
+
+        self.send((progress, message))
+            .map_err(|_| Error::ProgressUpdateError)
+    }
+}
+
+/// Type that implements [`Progress`] and drops every update received
+#[derive(Clone, Copy)]
+pub struct NoopProgress;
+
+/// Create a new instance of [`NoopProgress`]
+pub fn noop_progress() -> NoopProgress {
+    NoopProgress
+}
+
+impl Progress for NoopProgress {
+    fn update(&self, _progress: f32, _message: Option<String>) -> Result<(), Error> {
+        Ok(())
+    }
+}
+
+/// Type that implements [`Progress`] and logs at level `INFO` every update received
+#[derive(Clone, Copy)]
+pub struct LogProgress;
+
+/// Create a new instance of [`LogProgress`]
+pub fn log_progress() -> LogProgress {
+    LogProgress
+}
+
+impl Progress for LogProgress {
+    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
+        log::info!(
+            "Sync {:.3}%: `{}`",
+            progress,
+            message.unwrap_or_else(|| "".into())
+        );
+
+        Ok(())
+    }
+}
+
+#[maybe_async]
+impl<T: Blockchain> Blockchain for Arc<T> {
+    fn get_capabilities(&self) -> HashSet<Capability> {
+        maybe_await!(self.deref().get_capabilities())
+    }
+
+    fn setup<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(self.deref().setup(database, progress_update))
+    }
+
+    fn sync<D: BatchDatabase, P: 'static + Progress>(
+        &self,
+        database: &mut D,
+        progress_update: P,
+    ) -> Result<(), Error> {
+        maybe_await!(self.deref().sync(database, progress_update))
+    }
+
+    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        maybe_await!(self.deref().get_tx(txid))
+    }
+    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
+        maybe_await!(self.deref().broadcast(tx))
+    }
+
+    fn get_height(&self) -> Result<u32, Error> {
+        maybe_await!(self.deref().get_height())
+    }
+    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
+        maybe_await!(self.deref().estimate_fee(target))
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/utils.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/utils.rs.html new file mode 100644 index 0000000000..c5288d5967 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/blockchain/utils.rs.html @@ -0,0 +1,780 @@ +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
+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
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+use std::collections::{HashMap, HashSet};
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+use rand::seq::SliceRandom;
+use rand::thread_rng;
+
+use bitcoin::{BlockHeader, OutPoint, Script, Transaction, Txid};
+
+use super::*;
+use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
+use crate::error::Error;
+use crate::types::{ConfirmationTime, KeychainKind, LocalUtxo, TransactionDetails};
+use crate::wallet::time::Instant;
+use crate::wallet::utils::ChunksIterator;
+
+#[derive(Debug)]
+pub struct ElsGetHistoryRes {
+    pub height: i32,
+    pub tx_hash: Txid,
+}
+
+/// Implements the synchronization logic for an Electrum-like client.
+#[maybe_async]
+pub trait ElectrumLikeSync {
+    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script> + Clone>(
+        &self,
+        scripts: I,
+    ) -> Result<Vec<Vec<ElsGetHistoryRes>>, Error>;
+
+    fn els_batch_transaction_get<'s, I: IntoIterator<Item = &'s Txid> + Clone>(
+        &self,
+        txids: I,
+    ) -> Result<Vec<Transaction>, Error>;
+
+    fn els_batch_block_header<I: IntoIterator<Item = u32> + Clone>(
+        &self,
+        heights: I,
+    ) -> Result<Vec<BlockHeader>, Error>;
+
+    // Provided methods down here...
+
+    fn electrum_like_setup<D: BatchDatabase, P: Progress>(
+        &self,
+        stop_gap: usize,
+        db: &mut D,
+        _progress_update: P,
+    ) -> Result<(), Error> {
+        // TODO: progress
+        let start = Instant::new();
+        debug!("start setup");
+
+        let chunk_size = stop_gap;
+
+        let mut history_txs_id = HashSet::new();
+        let mut txid_height = HashMap::new();
+        let mut max_indexes = HashMap::new();
+
+        let mut wallet_chains = vec![KeychainKind::Internal, KeychainKind::External];
+        // shuffling improve privacy, the server doesn't know my first request is from my internal or external addresses
+        wallet_chains.shuffle(&mut thread_rng());
+        // download history of our internal and external script_pubkeys
+        for keychain in wallet_chains.iter() {
+            let script_iter = db.iter_script_pubkeys(Some(*keychain))?.into_iter();
+
+            for (i, chunk) in ChunksIterator::new(script_iter, stop_gap).enumerate() {
+                // TODO if i == last, should create another chunk of addresses in db
+                let call_result: Vec<Vec<ElsGetHistoryRes>> =
+                    maybe_await!(self.els_batch_script_get_history(chunk.iter()))?;
+                let max_index = call_result
+                    .iter()
+                    .enumerate()
+                    .filter_map(|(i, v)| v.first().map(|_| i as u32))
+                    .max();
+                if let Some(max) = max_index {
+                    max_indexes.insert(keychain, max + (i * chunk_size) as u32);
+                }
+                let flattened: Vec<ElsGetHistoryRes> = call_result.into_iter().flatten().collect();
+                debug!("#{} of {:?} results:{}", i, keychain, flattened.len());
+                if flattened.is_empty() {
+                    // Didn't find anything in the last `stop_gap` script_pubkeys, breaking
+                    break;
+                }
+
+                for el in flattened {
+                    // el.height = -1 means unconfirmed with unconfirmed parents
+                    // el.height =  0 means unconfirmed with confirmed parents
+                    // but we treat those tx the same
+                    if el.height <= 0 {
+                        txid_height.insert(el.tx_hash, None);
+                    } else {
+                        txid_height.insert(el.tx_hash, Some(el.height as u32));
+                    }
+                    history_txs_id.insert(el.tx_hash);
+                }
+            }
+        }
+
+        // saving max indexes
+        info!("max indexes are: {:?}", max_indexes);
+        for keychain in wallet_chains.iter() {
+            if let Some(index) = max_indexes.get(keychain) {
+                db.set_last_index(*keychain, *index)?;
+            }
+        }
+
+        // get db status
+        let txs_details_in_db: HashMap<Txid, TransactionDetails> = db
+            .iter_txs(false)?
+            .into_iter()
+            .map(|tx| (tx.txid, tx))
+            .collect();
+        let txs_raw_in_db: HashMap<Txid, Transaction> = db
+            .iter_raw_txs()?
+            .into_iter()
+            .map(|tx| (tx.txid(), tx))
+            .collect();
+        let utxos_deps = utxos_deps(db, &txs_raw_in_db)?;
+
+        // download new txs and headers
+        let new_txs = maybe_await!(self.download_and_save_needed_raw_txs(
+            &history_txs_id,
+            &txs_raw_in_db,
+            chunk_size,
+            db
+        ))?;
+        let new_timestamps = maybe_await!(self.download_needed_headers(
+            &txid_height,
+            &txs_details_in_db,
+            chunk_size
+        ))?;
+
+        let mut batch = db.begin_batch();
+
+        // save any tx details not in db but in history_txs_id or with different height/timestamp
+        for txid in history_txs_id.iter() {
+            let height = txid_height.get(txid).cloned().flatten();
+            let timestamp = new_timestamps.get(txid).cloned();
+            if let Some(tx_details) = txs_details_in_db.get(txid) {
+                // check if tx height matches, otherwise updates it. timestamp is not in the if clause
+                // because we are not asking headers for confirmed tx we know about
+                if tx_details.confirmation_time.as_ref().map(|c| c.height) != height {
+                    let confirmation_time = ConfirmationTime::new(height, timestamp);
+                    let mut new_tx_details = tx_details.clone();
+                    new_tx_details.confirmation_time = confirmation_time;
+                    batch.set_tx(&new_tx_details)?;
+                }
+            } else {
+                save_transaction_details_and_utxos(
+                    txid,
+                    db,
+                    timestamp,
+                    height,
+                    &mut batch,
+                    &utxos_deps,
+                )?;
+            }
+        }
+
+        // remove any tx details in db but not in history_txs_id
+        for txid in txs_details_in_db.keys() {
+            if !history_txs_id.contains(txid) {
+                batch.del_tx(txid, false)?;
+            }
+        }
+
+        // remove any spent utxo
+        for new_tx in new_txs.iter() {
+            for input in new_tx.input.iter() {
+                batch.del_utxo(&input.previous_output)?;
+            }
+        }
+
+        db.commit_batch(batch)?;
+        info!("finish setup, elapsed {:?}ms", start.elapsed().as_millis());
+
+        Ok(())
+    }
+
+    /// download txs identified by `history_txs_id` and theirs previous outputs if not already present in db
+    fn download_and_save_needed_raw_txs<D: BatchDatabase>(
+        &self,
+        history_txs_id: &HashSet<Txid>,
+        txs_raw_in_db: &HashMap<Txid, Transaction>,
+        chunk_size: usize,
+        db: &mut D,
+    ) -> Result<Vec<Transaction>, Error> {
+        let mut txs_downloaded = vec![];
+        let txids_raw_in_db: HashSet<Txid> = txs_raw_in_db.keys().cloned().collect();
+        let txids_to_download: Vec<&Txid> = history_txs_id.difference(&txids_raw_in_db).collect();
+        if !txids_to_download.is_empty() {
+            info!("got {} txs to download", txids_to_download.len());
+            txs_downloaded.extend(maybe_await!(self.download_and_save_in_chunks(
+                txids_to_download,
+                chunk_size,
+                db,
+            ))?);
+            let mut prev_txids = HashSet::new();
+            let mut txids_downloaded = HashSet::new();
+            for tx in txs_downloaded.iter() {
+                txids_downloaded.insert(tx.txid());
+                // add every previous input tx, but skip coinbase
+                for input in tx.input.iter().filter(|i| !i.previous_output.is_null()) {
+                    prev_txids.insert(input.previous_output.txid);
+                }
+            }
+            let already_present: HashSet<Txid> =
+                txids_downloaded.union(&txids_raw_in_db).cloned().collect();
+            let prev_txs_to_download: Vec<&Txid> =
+                prev_txids.difference(&already_present).collect();
+            info!("{} previous txs to download", prev_txs_to_download.len());
+            txs_downloaded.extend(maybe_await!(self.download_and_save_in_chunks(
+                prev_txs_to_download,
+                chunk_size,
+                db,
+            ))?);
+        }
+
+        Ok(txs_downloaded)
+    }
+
+    /// download headers at heights in `txid_height` if tx details not already present, returns a map Txid -> timestamp
+    fn download_needed_headers(
+        &self,
+        txid_height: &HashMap<Txid, Option<u32>>,
+        txs_details_in_db: &HashMap<Txid, TransactionDetails>,
+        chunk_size: usize,
+    ) -> Result<HashMap<Txid, u64>, Error> {
+        let mut txid_timestamp = HashMap::new();
+        let txid_in_db_with_conf: HashSet<_> = txs_details_in_db
+            .values()
+            .filter_map(|details| details.confirmation_time.as_ref().map(|_| details.txid))
+            .collect();
+        let needed_txid_height: HashMap<&Txid, u32> = txid_height
+            .iter()
+            .filter(|(t, _)| !txid_in_db_with_conf.contains(*t))
+            .filter_map(|(t, o)| o.map(|h| (t, h)))
+            .collect();
+        let needed_heights: HashSet<u32> = needed_txid_height.values().cloned().collect();
+        if !needed_heights.is_empty() {
+            info!("{} headers to download for timestamp", needed_heights.len());
+            let mut height_timestamp: HashMap<u32, u64> = HashMap::new();
+            for chunk in ChunksIterator::new(needed_heights.into_iter(), chunk_size) {
+                let call_result: Vec<BlockHeader> =
+                    maybe_await!(self.els_batch_block_header(chunk.clone()))?;
+                height_timestamp.extend(
+                    chunk
+                        .into_iter()
+                        .zip(call_result.iter().map(|h| h.time as u64)),
+                );
+            }
+            for (txid, height) in needed_txid_height {
+                let timestamp = height_timestamp
+                    .get(&height)
+                    .ok_or_else(|| Error::Generic("timestamp missing".to_string()))?;
+                txid_timestamp.insert(*txid, *timestamp);
+            }
+        }
+
+        Ok(txid_timestamp)
+    }
+
+    fn download_and_save_in_chunks<D: BatchDatabase>(
+        &self,
+        to_download: Vec<&Txid>,
+        chunk_size: usize,
+        db: &mut D,
+    ) -> Result<Vec<Transaction>, Error> {
+        let mut txs_downloaded = vec![];
+        for chunk in ChunksIterator::new(to_download.into_iter(), chunk_size) {
+            let call_result: Vec<Transaction> =
+                maybe_await!(self.els_batch_transaction_get(chunk))?;
+            let mut batch = db.begin_batch();
+            for new_tx in call_result.iter() {
+                batch.set_raw_tx(new_tx)?;
+            }
+            db.commit_batch(batch)?;
+            txs_downloaded.extend(call_result);
+        }
+
+        Ok(txs_downloaded)
+    }
+}
+
+fn save_transaction_details_and_utxos<D: BatchDatabase>(
+    txid: &Txid,
+    db: &mut D,
+    timestamp: Option<u64>,
+    height: Option<u32>,
+    updates: &mut dyn BatchOperations,
+    utxo_deps: &HashMap<OutPoint, OutPoint>,
+) -> Result<(), Error> {
+    let tx = db.get_raw_tx(txid)?.ok_or(Error::TransactionNotFound)?;
+
+    let mut incoming: u64 = 0;
+    let mut outgoing: u64 = 0;
+
+    let mut inputs_sum: u64 = 0;
+    let mut outputs_sum: u64 = 0;
+
+    // look for our own inputs
+    for input in tx.input.iter() {
+        // skip coinbase inputs
+        if input.previous_output.is_null() {
+            continue;
+        }
+
+        // We already downloaded all previous output txs in the previous step
+        if let Some(previous_output) = db.get_previous_output(&input.previous_output)? {
+            inputs_sum += previous_output.value;
+
+            if db.is_mine(&previous_output.script_pubkey)? {
+                outgoing += previous_output.value;
+            }
+        } else {
+            // The input is not ours, but we still need to count it for the fees
+            let tx = db
+                .get_raw_tx(&input.previous_output.txid)?
+                .ok_or(Error::TransactionNotFound)?;
+            inputs_sum += tx.output[input.previous_output.vout as usize].value;
+        }
+
+        // removes conflicting UTXO if any (generated from same inputs, like for example RBF)
+        if let Some(outpoint) = utxo_deps.get(&input.previous_output) {
+            updates.del_utxo(outpoint)?;
+        }
+    }
+
+    for (i, output) in tx.output.iter().enumerate() {
+        // to compute the fees later
+        outputs_sum += output.value;
+
+        // this output is ours, we have a path to derive it
+        if let Some((keychain, _child)) = db.get_path_from_script_pubkey(&output.script_pubkey)? {
+            debug!("{} output #{} is mine, adding utxo", txid, i);
+            updates.set_utxo(&LocalUtxo {
+                outpoint: OutPoint::new(tx.txid(), i as u32),
+                txout: output.clone(),
+                keychain,
+            })?;
+
+            incoming += output.value;
+        }
+    }
+
+    let tx_details = TransactionDetails {
+        txid: tx.txid(),
+        transaction: Some(tx),
+        received: incoming,
+        sent: outgoing,
+        confirmation_time: ConfirmationTime::new(height, timestamp),
+        fee: Some(inputs_sum.saturating_sub(outputs_sum)), /* if the tx is a coinbase, fees would be negative */
+        verified: height.is_some(),
+    };
+    updates.set_tx(&tx_details)?;
+
+    Ok(())
+}
+
+/// returns utxo dependency as the inputs needed for the utxo to exist
+/// `tx_raw_in_db` must contains utxo's generating txs or errors with [crate::Error::TransactionNotFound]
+fn utxos_deps<D: BatchDatabase>(
+    db: &mut D,
+    tx_raw_in_db: &HashMap<Txid, Transaction>,
+) -> Result<HashMap<OutPoint, OutPoint>, Error> {
+    let utxos = db.iter_utxos()?;
+    let mut utxos_deps = HashMap::new();
+    for utxo in utxos {
+        let from_tx = tx_raw_in_db
+            .get(&utxo.outpoint.txid)
+            .ok_or(Error::TransactionNotFound)?;
+        for input in from_tx.input.iter() {
+            utxos_deps.insert(input.previous_output, utxo.outpoint);
+        }
+    }
+    Ok(utxos_deps)
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/any.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/any.rs.html new file mode 100644 index 0000000000..a259b301c3 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/any.rs.html @@ -0,0 +1,834 @@ +any.rs - source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+//! Runtime-checked database types
+//!
+//! This module provides the implementation of [`AnyDatabase`] which allows switching the
+//! inner [`Database`] type at runtime.
+//!
+//! ## Example
+//!
+//! In this example, `wallet_memory` and `wallet_sled` have the same type of `Wallet<(), AnyDatabase>`.
+//!
+//! ```no_run
+//! # use bitcoin::Network;
+//! # use bdk::database::{AnyDatabase, MemoryDatabase};
+//! # use bdk::{Wallet};
+//! let memory = MemoryDatabase::default();
+//! let wallet_memory = Wallet::new_offline("...", None, Network::Testnet, memory)?;
+//!
+//! # #[cfg(feature = "key-value-db")]
+//! # {
+//! let sled = sled::open("my-database")?.open_tree("default_tree")?;
+//! let wallet_sled = Wallet::new_offline("...", None, Network::Testnet, sled)?;
+//! # }
+//! # Ok::<(), bdk::Error>(())
+//! ```
+//!
+//! When paired with the use of [`ConfigurableDatabase`], it allows creating wallets with any
+//! database supported using a single line of code:
+//!
+//! ```no_run
+//! # use bitcoin::Network;
+//! # use bdk::database::*;
+//! # use bdk::{Wallet};
+//! let config = serde_json::from_str("...")?;
+//! let database = AnyDatabase::from_config(&config)?;
+//! let wallet = Wallet::new_offline("...", None, Network::Testnet, database)?;
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use super::*;
+
+macro_rules! impl_from {
+    ( $from:ty, $to:ty, $variant:ident, $( $cfg:tt )* ) => {
+        $( $cfg )*
+        impl From<$from> for $to {
+            fn from(inner: $from) -> Self {
+                <$to>::$variant(inner)
+            }
+        }
+    };
+}
+
+macro_rules! impl_inner_method {
+    ( $enum_name:ident, $self:expr, $name:ident $(, $args:expr)* ) => {
+        match $self {
+            $enum_name::Memory(inner) => inner.$name( $($args, )* ),
+            #[cfg(feature = "key-value-db")]
+            $enum_name::Sled(inner) => inner.$name( $($args, )* ),
+            #[cfg(feature = "sqlite")]
+            $enum_name::Sqlite(inner) => inner.$name( $($args, )* ),
+        }
+    }
+}
+
+/// Type that can contain any of the [`Database`] types defined by the library
+///
+/// It allows switching database type at runtime.
+///
+/// See [this module](crate::database::any)'s documentation for a usage example.
+#[derive(Debug)]
+pub enum AnyDatabase {
+    /// In-memory ephemeral database
+    Memory(memory::MemoryDatabase),
+    #[cfg(feature = "key-value-db")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
+    /// Simple key-value embedded database based on [`sled`]
+    Sled(sled::Tree),
+    #[cfg(feature = "sqlite")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
+    /// Sqlite embedded database using [`rusqlite`]
+    Sqlite(sqlite::SqliteDatabase),
+}
+
+impl_from!(memory::MemoryDatabase, AnyDatabase, Memory,);
+impl_from!(sled::Tree, AnyDatabase, Sled, #[cfg(feature = "key-value-db")]);
+impl_from!(sqlite::SqliteDatabase, AnyDatabase, Sqlite, #[cfg(feature = "sqlite")]);
+
+/// Type that contains any of the [`BatchDatabase::Batch`] types defined by the library
+pub enum AnyBatch {
+    /// In-memory ephemeral database
+    Memory(<memory::MemoryDatabase as BatchDatabase>::Batch),
+    #[cfg(feature = "key-value-db")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
+    /// Simple key-value embedded database based on [`sled`]
+    Sled(<sled::Tree as BatchDatabase>::Batch),
+    #[cfg(feature = "sqlite")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
+    /// Sqlite embedded database using [`rusqlite`]
+    Sqlite(<sqlite::SqliteDatabase as BatchDatabase>::Batch),
+}
+
+impl_from!(
+    <memory::MemoryDatabase as BatchDatabase>::Batch,
+    AnyBatch,
+    Memory,
+);
+impl_from!(<sled::Tree as BatchDatabase>::Batch, AnyBatch, Sled, #[cfg(feature = "key-value-db")]);
+impl_from!(<sqlite::SqliteDatabase as BatchDatabase>::Batch, AnyBatch, Sqlite, #[cfg(feature = "sqlite")]);
+
+impl BatchOperations for AnyDatabase {
+    fn set_script_pubkey(
+        &mut self,
+        script: &Script,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<(), Error> {
+        impl_inner_method!(
+            AnyDatabase,
+            self,
+            set_script_pubkey,
+            script,
+            keychain,
+            child
+        )
+    }
+    fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
+        impl_inner_method!(AnyDatabase, self, set_utxo, utxo)
+    }
+    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
+        impl_inner_method!(AnyDatabase, self, set_raw_tx, transaction)
+    }
+    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
+        impl_inner_method!(AnyDatabase, self, set_tx, transaction)
+    }
+    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
+        impl_inner_method!(AnyDatabase, self, set_last_index, keychain, value)
+    }
+
+    fn del_script_pubkey_from_path(
+        &mut self,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<Option<Script>, Error> {
+        impl_inner_method!(
+            AnyDatabase,
+            self,
+            del_script_pubkey_from_path,
+            keychain,
+            child
+        )
+    }
+    fn del_path_from_script_pubkey(
+        &mut self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error> {
+        impl_inner_method!(AnyDatabase, self, del_path_from_script_pubkey, script)
+    }
+    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
+        impl_inner_method!(AnyDatabase, self, del_utxo, outpoint)
+    }
+    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        impl_inner_method!(AnyDatabase, self, del_raw_tx, txid)
+    }
+    fn del_tx(
+        &mut self,
+        txid: &Txid,
+        include_raw: bool,
+    ) -> Result<Option<TransactionDetails>, Error> {
+        impl_inner_method!(AnyDatabase, self, del_tx, txid, include_raw)
+    }
+    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
+        impl_inner_method!(AnyDatabase, self, del_last_index, keychain)
+    }
+}
+
+impl Database for AnyDatabase {
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
+        &mut self,
+        keychain: KeychainKind,
+        bytes: B,
+    ) -> Result<(), Error> {
+        impl_inner_method!(
+            AnyDatabase,
+            self,
+            check_descriptor_checksum,
+            keychain,
+            bytes
+        )
+    }
+
+    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
+        impl_inner_method!(AnyDatabase, self, iter_script_pubkeys, keychain)
+    }
+    fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
+        impl_inner_method!(AnyDatabase, self, iter_utxos)
+    }
+    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
+        impl_inner_method!(AnyDatabase, self, iter_raw_txs)
+    }
+    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
+        impl_inner_method!(AnyDatabase, self, iter_txs, include_raw)
+    }
+
+    fn get_script_pubkey_from_path(
+        &self,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<Option<Script>, Error> {
+        impl_inner_method!(
+            AnyDatabase,
+            self,
+            get_script_pubkey_from_path,
+            keychain,
+            child
+        )
+    }
+    fn get_path_from_script_pubkey(
+        &self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error> {
+        impl_inner_method!(AnyDatabase, self, get_path_from_script_pubkey, script)
+    }
+    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
+        impl_inner_method!(AnyDatabase, self, get_utxo, outpoint)
+    }
+    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        impl_inner_method!(AnyDatabase, self, get_raw_tx, txid)
+    }
+    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
+        impl_inner_method!(AnyDatabase, self, get_tx, txid, include_raw)
+    }
+    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
+        impl_inner_method!(AnyDatabase, self, get_last_index, keychain)
+    }
+
+    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
+        impl_inner_method!(AnyDatabase, self, increment_last_index, keychain)
+    }
+
+    fn flush(&mut self) -> Result<(), Error> {
+        impl_inner_method!(AnyDatabase, self, flush)
+    }
+}
+
+impl BatchOperations for AnyBatch {
+    fn set_script_pubkey(
+        &mut self,
+        script: &Script,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<(), Error> {
+        impl_inner_method!(AnyBatch, self, set_script_pubkey, script, keychain, child)
+    }
+    fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
+        impl_inner_method!(AnyBatch, self, set_utxo, utxo)
+    }
+    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
+        impl_inner_method!(AnyBatch, self, set_raw_tx, transaction)
+    }
+    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
+        impl_inner_method!(AnyBatch, self, set_tx, transaction)
+    }
+    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
+        impl_inner_method!(AnyBatch, self, set_last_index, keychain, value)
+    }
+
+    fn del_script_pubkey_from_path(
+        &mut self,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<Option<Script>, Error> {
+        impl_inner_method!(AnyBatch, self, del_script_pubkey_from_path, keychain, child)
+    }
+    fn del_path_from_script_pubkey(
+        &mut self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error> {
+        impl_inner_method!(AnyBatch, self, del_path_from_script_pubkey, script)
+    }
+    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
+        impl_inner_method!(AnyBatch, self, del_utxo, outpoint)
+    }
+    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        impl_inner_method!(AnyBatch, self, del_raw_tx, txid)
+    }
+    fn del_tx(
+        &mut self,
+        txid: &Txid,
+        include_raw: bool,
+    ) -> Result<Option<TransactionDetails>, Error> {
+        impl_inner_method!(AnyBatch, self, del_tx, txid, include_raw)
+    }
+    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
+        impl_inner_method!(AnyBatch, self, del_last_index, keychain)
+    }
+}
+
+impl BatchDatabase for AnyDatabase {
+    type Batch = AnyBatch;
+
+    fn begin_batch(&self) -> Self::Batch {
+        match self {
+            AnyDatabase::Memory(inner) => inner.begin_batch().into(),
+            #[cfg(feature = "key-value-db")]
+            AnyDatabase::Sled(inner) => inner.begin_batch().into(),
+            #[cfg(feature = "sqlite")]
+            AnyDatabase::Sqlite(inner) => inner.begin_batch().into(),
+        }
+    }
+    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
+        match self {
+            AnyDatabase::Memory(db) => match batch {
+                AnyBatch::Memory(batch) => db.commit_batch(batch),
+                #[cfg(any(feature = "key-value-db", feature = "sqlite"))]
+                _ => unimplemented!("Other batch shouldn't be used with Memory db."),
+            },
+            #[cfg(feature = "key-value-db")]
+            AnyDatabase::Sled(db) => match batch {
+                AnyBatch::Sled(batch) => db.commit_batch(batch),
+                _ => unimplemented!("Other batch shouldn't be used with Sled db."),
+            },
+            #[cfg(feature = "sqlite")]
+            AnyDatabase::Sqlite(db) => match batch {
+                AnyBatch::Sqlite(batch) => db.commit_batch(batch),
+                _ => unimplemented!("Other batch shouldn't be used with Sqlite db."),
+            },
+        }
+    }
+}
+
+/// Configuration type for a [`sled::Tree`] database
+#[cfg(feature = "key-value-db")]
+#[derive(Debug, serde::Serialize, serde::Deserialize)]
+pub struct SledDbConfiguration {
+    /// Main directory of the db
+    pub path: String,
+    /// Name of the database tree, a separated namespace for the data
+    pub tree_name: String,
+}
+
+#[cfg(feature = "key-value-db")]
+impl ConfigurableDatabase for sled::Tree {
+    type Config = SledDbConfiguration;
+
+    fn from_config(config: &Self::Config) -> Result<Self, Error> {
+        Ok(sled::open(&config.path)?.open_tree(&config.tree_name)?)
+    }
+}
+
+/// Configuration type for a [`sqlite::SqliteDatabase`] database
+#[cfg(feature = "sqlite")]
+#[derive(Debug, serde::Serialize, serde::Deserialize)]
+pub struct SqliteDbConfiguration {
+    /// Main directory of the db
+    pub path: String,
+}
+
+#[cfg(feature = "sqlite")]
+impl ConfigurableDatabase for sqlite::SqliteDatabase {
+    type Config = SqliteDbConfiguration;
+
+    fn from_config(config: &Self::Config) -> Result<Self, Error> {
+        Ok(sqlite::SqliteDatabase::new(config.path.clone()))
+    }
+}
+
+/// Type that can contain any of the database configurations defined by the library
+///
+/// This allows storing a single configuration that can be loaded into an [`AnyDatabase`]
+/// instance. Wallets that plan to offer users the ability to switch blockchain backend at runtime
+/// will find this particularly useful.
+#[derive(Debug, serde::Serialize, serde::Deserialize)]
+pub enum AnyDatabaseConfig {
+    /// Memory database has no config
+    Memory(()),
+    #[cfg(feature = "key-value-db")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
+    /// Simple key-value embedded database based on [`sled`]
+    Sled(SledDbConfiguration),
+    #[cfg(feature = "sqlite")]
+    #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
+    /// Sqlite embedded database using [`rusqlite`]
+    Sqlite(SqliteDbConfiguration),
+}
+
+impl ConfigurableDatabase for AnyDatabase {
+    type Config = AnyDatabaseConfig;
+
+    fn from_config(config: &Self::Config) -> Result<Self, Error> {
+        Ok(match config {
+            AnyDatabaseConfig::Memory(inner) => {
+                AnyDatabase::Memory(memory::MemoryDatabase::from_config(inner)?)
+            }
+            #[cfg(feature = "key-value-db")]
+            AnyDatabaseConfig::Sled(inner) => AnyDatabase::Sled(sled::Tree::from_config(inner)?),
+            #[cfg(feature = "sqlite")]
+            AnyDatabaseConfig::Sqlite(inner) => {
+                AnyDatabase::Sqlite(sqlite::SqliteDatabase::from_config(inner)?)
+            }
+        })
+    }
+}
+
+impl_from!((), AnyDatabaseConfig, Memory,);
+impl_from!(SledDbConfiguration, AnyDatabaseConfig, Sled, #[cfg(feature = "key-value-db")]);
+impl_from!(SqliteDbConfiguration, AnyDatabaseConfig, Sqlite, #[cfg(feature = "sqlite")]);
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/keyvalue.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/keyvalue.rs.html new file mode 100644 index 0000000000..111cc74a11 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/keyvalue.rs.html @@ -0,0 +1,950 @@ +keyvalue.rs - source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+use std::convert::TryInto;
+
+use sled::{Batch, Tree};
+
+use bitcoin::consensus::encode::{deserialize, serialize};
+use bitcoin::hash_types::Txid;
+use bitcoin::{OutPoint, Script, Transaction};
+
+use crate::database::memory::MapKey;
+use crate::database::{BatchDatabase, BatchOperations, Database};
+use crate::error::Error;
+use crate::types::*;
+
+macro_rules! impl_batch_operations {
+    ( { $($after_insert:tt)* }, $process_delete:ident ) => {
+        fn set_script_pubkey(&mut self, script: &Script, keychain: KeychainKind, path: u32) -> Result<(), Error> {
+            let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
+            self.insert(key, serialize(script))$($after_insert)*;
+
+            let key = MapKey::Script(Some(script)).as_map_key();
+            let value = json!({
+                "t": keychain,
+                "p": path,
+            });
+            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
+
+            Ok(())
+        }
+
+        fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
+            let key = MapKey::Utxo(Some(&utxo.outpoint)).as_map_key();
+            let value = json!({
+                "t": utxo.txout,
+                "i": utxo.keychain,
+            });
+            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
+
+            Ok(())
+        }
+
+        fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
+            let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
+            let value = serialize(transaction);
+            self.insert(key, value)$($after_insert)*;
+
+            Ok(())
+        }
+
+        fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
+            let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
+
+            // remove the raw tx from the serialized version
+            let mut value = serde_json::to_value(transaction)?;
+            value["transaction"] = serde_json::Value::Null;
+            let value = serde_json::to_vec(&value)?;
+
+            self.insert(key, value)$($after_insert)*;
+
+            // insert the raw_tx if present
+            if let Some(ref tx) = transaction.transaction {
+                self.set_raw_tx(tx)?;
+            }
+
+            Ok(())
+        }
+
+        fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
+            let key = MapKey::LastIndex(keychain).as_map_key();
+            self.insert(key, &value.to_be_bytes())$($after_insert)*;
+
+            Ok(())
+        }
+
+        fn del_script_pubkey_from_path(&mut self, keychain: KeychainKind, path: u32) -> Result<Option<Script>, Error> {
+            let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
+        }
+
+        fn del_path_from_script_pubkey(&mut self, script: &Script) -> Result<Option<(KeychainKind, u32)>, Error> {
+            let key = MapKey::Script(Some(script)).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            match res {
+                None => Ok(None),
+                Some(b) => {
+                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
+                    let st = serde_json::from_value(val["t"].take())?;
+                    let path = serde_json::from_value(val["p"].take())?;
+
+                    Ok(Some((st, path)))
+                }
+            }
+        }
+
+        fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
+            let key = MapKey::Utxo(Some(outpoint)).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            match res {
+                None => Ok(None),
+                Some(b) => {
+                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
+                    let txout = serde_json::from_value(val["t"].take())?;
+                    let keychain = serde_json::from_value(val["i"].take())?;
+
+                    Ok(Some(LocalUtxo { outpoint: outpoint.clone(), txout, keychain }))
+                }
+            }
+        }
+
+        fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+            let key = MapKey::RawTx(Some(txid)).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
+        }
+
+        fn del_tx(&mut self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
+            let raw_tx = if include_raw {
+                self.del_raw_tx(txid)?
+            } else {
+                None
+            };
+
+            let key = MapKey::Transaction(Some(txid)).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            match res {
+                None => Ok(None),
+                Some(b) => {
+                    let mut val: TransactionDetails = serde_json::from_slice(&b)?;
+                    val.transaction = raw_tx;
+
+                    Ok(Some(val))
+                }
+            }
+        }
+
+        fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
+            let key = MapKey::LastIndex(keychain).as_map_key();
+            let res = self.remove(key);
+            let res = $process_delete!(res);
+
+            match res {
+                None => Ok(None),
+                Some(b) => {
+                    let array: [u8; 4] = b.as_ref().try_into().map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
+                    let val = u32::from_be_bytes(array);
+                    Ok(Some(val))
+                }
+            }
+        }
+    }
+}
+
+macro_rules! process_delete_tree {
+    ($res:expr) => {
+        $res?
+    };
+}
+impl BatchOperations for Tree {
+    impl_batch_operations!({?}, process_delete_tree);
+}
+
+macro_rules! process_delete_batch {
+    ($res:expr) => {
+        None as Option<sled::IVec>
+    };
+}
+#[allow(unused_variables)]
+impl BatchOperations for Batch {
+    impl_batch_operations!({}, process_delete_batch);
+}
+
+impl Database for Tree {
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
+        &mut self,
+        keychain: KeychainKind,
+        bytes: B,
+    ) -> Result<(), Error> {
+        let key = MapKey::DescriptorChecksum(keychain).as_map_key();
+
+        let prev = self.get(&key)?.map(|x| x.to_vec());
+        if let Some(val) = prev {
+            if val == bytes.as_ref() {
+                Ok(())
+            } else {
+                Err(Error::ChecksumMismatch)
+            }
+        } else {
+            self.insert(&key, bytes.as_ref())?;
+            Ok(())
+        }
+    }
+
+    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
+        let key = MapKey::Path((keychain, None)).as_map_key();
+        self.scan_prefix(key)
+            .map(|x| -> Result<_, Error> {
+                let (_, v) = x?;
+                Ok(deserialize(&v)?)
+            })
+            .collect()
+    }
+
+    fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
+        let key = MapKey::Utxo(None).as_map_key();
+        self.scan_prefix(key)
+            .map(|x| -> Result<_, Error> {
+                let (k, v) = x?;
+                let outpoint = deserialize(&k[1..])?;
+
+                let mut val: serde_json::Value = serde_json::from_slice(&v)?;
+                let txout = serde_json::from_value(val["t"].take())?;
+                let keychain = serde_json::from_value(val["i"].take())?;
+
+                Ok(LocalUtxo {
+                    outpoint,
+                    txout,
+                    keychain,
+                })
+            })
+            .collect()
+    }
+
+    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
+        let key = MapKey::RawTx(None).as_map_key();
+        self.scan_prefix(key)
+            .map(|x| -> Result<_, Error> {
+                let (_, v) = x?;
+                Ok(deserialize(&v)?)
+            })
+            .collect()
+    }
+
+    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
+        let key = MapKey::Transaction(None).as_map_key();
+        self.scan_prefix(key)
+            .map(|x| -> Result<_, Error> {
+                let (k, v) = x?;
+                let mut txdetails: TransactionDetails = serde_json::from_slice(&v)?;
+                if include_raw {
+                    let txid = deserialize(&k[1..])?;
+                    txdetails.transaction = self.get_raw_tx(&txid)?;
+                }
+
+                Ok(txdetails)
+            })
+            .collect()
+    }
+
+    fn get_script_pubkey_from_path(
+        &self,
+        keychain: KeychainKind,
+        path: u32,
+    ) -> Result<Option<Script>, Error> {
+        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
+        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
+    }
+
+    fn get_path_from_script_pubkey(
+        &self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error> {
+        let key = MapKey::Script(Some(script)).as_map_key();
+        self.get(key)?
+            .map(|b| -> Result<_, Error> {
+                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
+                let st = serde_json::from_value(val["t"].take())?;
+                let path = serde_json::from_value(val["p"].take())?;
+
+                Ok((st, path))
+            })
+            .transpose()
+    }
+
+    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
+        let key = MapKey::Utxo(Some(outpoint)).as_map_key();
+        self.get(key)?
+            .map(|b| -> Result<_, Error> {
+                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
+                let txout = serde_json::from_value(val["t"].take())?;
+                let keychain = serde_json::from_value(val["i"].take())?;
+
+                Ok(LocalUtxo {
+                    outpoint: *outpoint,
+                    txout,
+                    keychain,
+                })
+            })
+            .transpose()
+    }
+
+    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        let key = MapKey::RawTx(Some(txid)).as_map_key();
+        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
+    }
+
+    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
+        let key = MapKey::Transaction(Some(txid)).as_map_key();
+        self.get(key)?
+            .map(|b| -> Result<_, Error> {
+                let mut txdetails: TransactionDetails = serde_json::from_slice(&b)?;
+                if include_raw {
+                    txdetails.transaction = self.get_raw_tx(txid)?;
+                }
+
+                Ok(txdetails)
+            })
+            .transpose()
+    }
+
+    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
+        let key = MapKey::LastIndex(keychain).as_map_key();
+        self.get(key)?
+            .map(|b| -> Result<_, Error> {
+                let array: [u8; 4] = b
+                    .as_ref()
+                    .try_into()
+                    .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
+                let val = u32::from_be_bytes(array);
+                Ok(val)
+            })
+            .transpose()
+    }
+
+    // inserts 0 if not present
+    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
+        let key = MapKey::LastIndex(keychain).as_map_key();
+        self.update_and_fetch(key, |prev| {
+            let new = match prev {
+                Some(b) => {
+                    let array: [u8; 4] = b.try_into().unwrap_or([0; 4]);
+                    let val = u32::from_be_bytes(array);
+
+                    val + 1
+                }
+                None => 0,
+            };
+
+            Some(new.to_be_bytes().to_vec())
+        })?
+        .map_or(Ok(0), |b| -> Result<_, Error> {
+            let array: [u8; 4] = b
+                .as_ref()
+                .try_into()
+                .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
+            let val = u32::from_be_bytes(array);
+            Ok(val)
+        })
+    }
+
+    fn flush(&mut self) -> Result<(), Error> {
+        Ok(Tree::flush(self).map(|_| ())?)
+    }
+}
+
+impl BatchDatabase for Tree {
+    type Batch = sled::Batch;
+
+    fn begin_batch(&self) -> Self::Batch {
+        sled::Batch::default()
+    }
+
+    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
+        Ok(self.apply_batch(batch)?)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use lazy_static::lazy_static;
+    use std::sync::{Arc, Condvar, Mutex, Once};
+    use std::time::{SystemTime, UNIX_EPOCH};
+
+    use sled::{Db, Tree};
+
+    static mut COUNT: usize = 0;
+
+    lazy_static! {
+        static ref DB: Arc<(Mutex<Option<Db>>, Condvar)> =
+            Arc::new((Mutex::new(None), Condvar::new()));
+        static ref INIT: Once = Once::new();
+    }
+
+    fn get_tree() -> Tree {
+        unsafe {
+            let cloned = DB.clone();
+            let (mutex, cvar) = &*cloned;
+
+            INIT.call_once(|| {
+                let mut db = mutex.lock().unwrap();
+
+                let time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
+                let mut dir = std::env::temp_dir();
+                dir.push(format!("mbw_{}", time.as_nanos()));
+
+                *db = Some(sled::open(dir).unwrap());
+                cvar.notify_all();
+            });
+
+            let mut db = mutex.lock().unwrap();
+            while !db.is_some() {
+                db = cvar.wait(db).unwrap();
+            }
+
+            COUNT += 1;
+
+            db.as_ref()
+                .unwrap()
+                .open_tree(format!("tree_{}", COUNT))
+                .unwrap()
+        }
+    }
+
+    #[test]
+    fn test_script_pubkey() {
+        crate::database::test::test_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_batch_script_pubkey() {
+        crate::database::test::test_batch_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_iter_script_pubkey() {
+        crate::database::test::test_iter_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_del_script_pubkey() {
+        crate::database::test::test_del_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_utxo() {
+        crate::database::test::test_utxo(get_tree());
+    }
+
+    #[test]
+    fn test_raw_tx() {
+        crate::database::test::test_raw_tx(get_tree());
+    }
+
+    #[test]
+    fn test_tx() {
+        crate::database::test::test_tx(get_tree());
+    }
+
+    #[test]
+    fn test_last_index() {
+        crate::database::test::test_last_index(get_tree());
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/memory.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/memory.rs.html new file mode 100644 index 0000000000..5c0d43db48 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/memory.rs.html @@ -0,0 +1,1188 @@ +memory.rs - source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+//! In-memory ephemeral database
+//!
+//! This module defines an in-memory database type called [`MemoryDatabase`] that is based on a
+//! [`BTreeMap`].
+
+use std::collections::BTreeMap;
+use std::ops::Bound::{Excluded, Included};
+
+use bitcoin::consensus::encode::{deserialize, serialize};
+use bitcoin::hash_types::Txid;
+use bitcoin::{OutPoint, Script, Transaction};
+
+use crate::database::{BatchDatabase, BatchOperations, ConfigurableDatabase, Database};
+use crate::error::Error;
+use crate::types::*;
+
+// path -> script       p{i,e}<path> -> script
+// script -> path       s<script> -> {i,e}<path>
+// outpoint             u<outpoint> -> txout
+// rawtx                r<txid> -> tx
+// transactions         t<txid> -> tx details
+// deriv indexes        c{i,e} -> u32
+// descriptor checksum  d{i,e} -> vec<u8>
+
+pub(crate) enum MapKey<'a> {
+    Path((Option<KeychainKind>, Option<u32>)),
+    Script(Option<&'a Script>),
+    Utxo(Option<&'a OutPoint>),
+    RawTx(Option<&'a Txid>),
+    Transaction(Option<&'a Txid>),
+    LastIndex(KeychainKind),
+    DescriptorChecksum(KeychainKind),
+}
+
+impl MapKey<'_> {
+    fn as_prefix(&self) -> Vec<u8> {
+        match self {
+            MapKey::Path((st, _)) => {
+                let mut v = b"p".to_vec();
+                if let Some(st) = st {
+                    v.push(st.as_byte());
+                }
+                v
+            }
+            MapKey::Script(_) => b"s".to_vec(),
+            MapKey::Utxo(_) => b"u".to_vec(),
+            MapKey::RawTx(_) => b"r".to_vec(),
+            MapKey::Transaction(_) => b"t".to_vec(),
+            MapKey::LastIndex(st) => [b"c", st.as_ref()].concat(),
+            MapKey::DescriptorChecksum(st) => [b"d", st.as_ref()].concat(),
+        }
+    }
+
+    fn serialize_content(&self) -> Vec<u8> {
+        match self {
+            MapKey::Path((_, Some(child))) => child.to_be_bytes().to_vec(),
+            MapKey::Script(Some(s)) => serialize(*s),
+            MapKey::Utxo(Some(s)) => serialize(*s),
+            MapKey::RawTx(Some(s)) => serialize(*s),
+            MapKey::Transaction(Some(s)) => serialize(*s),
+            _ => vec![],
+        }
+    }
+
+    pub fn as_map_key(&self) -> Vec<u8> {
+        let mut v = self.as_prefix();
+        v.extend_from_slice(&self.serialize_content());
+
+        v
+    }
+}
+
+fn after(key: &[u8]) -> Vec<u8> {
+    let mut key = key.to_owned();
+    let mut idx = key.len();
+    while idx > 0 {
+        if key[idx - 1] == 0xFF {
+            idx -= 1;
+            continue;
+        } else {
+            key[idx - 1] += 1;
+            break;
+        }
+    }
+
+    key
+}
+
+/// In-memory ephemeral database
+///
+/// This database can be used as a temporary storage for wallets that are not kept permanently on
+/// a device, or on platforms that don't provide a filesystem, like `wasm32`.
+///
+/// Once it's dropped its content will be lost.
+///
+/// If you are looking for a permanent storage solution, you can try with the default key-value
+/// database called [`sled`]. See the [`database`] module documentation for more defailts.
+///
+/// [`database`]: crate::database
+#[derive(Debug, Default)]
+pub struct MemoryDatabase {
+    map: BTreeMap<Vec<u8>, Box<dyn std::any::Any>>,
+    deleted_keys: Vec<Vec<u8>>,
+}
+
+impl MemoryDatabase {
+    /// Create a new empty database
+    pub fn new() -> Self {
+        MemoryDatabase {
+            map: BTreeMap::new(),
+            deleted_keys: Vec::new(),
+        }
+    }
+}
+
+impl BatchOperations for MemoryDatabase {
+    fn set_script_pubkey(
+        &mut self,
+        script: &Script,
+        keychain: KeychainKind,
+        path: u32,
+    ) -> Result<(), Error> {
+        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
+        self.map.insert(key, Box::new(script.clone()));
+
+        let key = MapKey::Script(Some(script)).as_map_key();
+        let value = json!({
+            "t": keychain,
+            "p": path,
+        });
+        self.map.insert(key, Box::new(value));
+
+        Ok(())
+    }
+
+    fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
+        let key = MapKey::Utxo(Some(&utxo.outpoint)).as_map_key();
+        self.map
+            .insert(key, Box::new((utxo.txout.clone(), utxo.keychain)));
+
+        Ok(())
+    }
+    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
+        let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
+        self.map.insert(key, Box::new(transaction.clone()));
+
+        Ok(())
+    }
+    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
+        let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
+
+        // insert the raw_tx if present
+        if let Some(ref tx) = transaction.transaction {
+            self.set_raw_tx(tx)?;
+        }
+
+        // remove the raw tx from the serialized version
+        let mut transaction = transaction.clone();
+        transaction.transaction = None;
+
+        self.map.insert(key, Box::new(transaction));
+
+        Ok(())
+    }
+    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
+        let key = MapKey::LastIndex(keychain).as_map_key();
+        self.map.insert(key, Box::new(value));
+
+        Ok(())
+    }
+
+    fn del_script_pubkey_from_path(
+        &mut self,
+        keychain: KeychainKind,
+        path: u32,
+    ) -> Result<Option<Script>, Error> {
+        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
+    }
+    fn del_path_from_script_pubkey(
+        &mut self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error> {
+        let key = MapKey::Script(Some(script)).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        match res {
+            None => Ok(None),
+            Some(b) => {
+                let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
+                let st = serde_json::from_value(val["t"].take())?;
+                let path = serde_json::from_value(val["p"].take())?;
+
+                Ok(Some((st, path)))
+            }
+        }
+    }
+    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
+        let key = MapKey::Utxo(Some(outpoint)).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        match res {
+            None => Ok(None),
+            Some(b) => {
+                let (txout, keychain) = b.downcast_ref().cloned().unwrap();
+                Ok(Some(LocalUtxo {
+                    outpoint: *outpoint,
+                    txout,
+                    keychain,
+                }))
+            }
+        }
+    }
+    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        let key = MapKey::RawTx(Some(txid)).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
+    }
+    fn del_tx(
+        &mut self,
+        txid: &Txid,
+        include_raw: bool,
+    ) -> Result<Option<TransactionDetails>, Error> {
+        let raw_tx = if include_raw {
+            self.del_raw_tx(txid)?
+        } else {
+            None
+        };
+
+        let key = MapKey::Transaction(Some(txid)).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        match res {
+            None => Ok(None),
+            Some(b) => {
+                let mut val: TransactionDetails = b.downcast_ref().cloned().unwrap();
+                val.transaction = raw_tx;
+
+                Ok(Some(val))
+            }
+        }
+    }
+    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
+        let key = MapKey::LastIndex(keychain).as_map_key();
+        let res = self.map.remove(&key);
+        self.deleted_keys.push(key);
+
+        match res {
+            None => Ok(None),
+            Some(b) => Ok(Some(*b.downcast_ref().unwrap())),
+        }
+    }
+}
+
+impl Database for MemoryDatabase {
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
+        &mut self,
+        keychain: KeychainKind,
+        bytes: B,
+    ) -> Result<(), Error> {
+        let key = MapKey::DescriptorChecksum(keychain).as_map_key();
+
+        let prev = self
+            .map
+            .get(&key)
+            .map(|x| x.downcast_ref::<Vec<u8>>().unwrap());
+        if let Some(val) = prev {
+            if val == &bytes.as_ref().to_vec() {
+                Ok(())
+            } else {
+                Err(Error::ChecksumMismatch)
+            }
+        } else {
+            self.map.insert(key, Box::new(bytes.as_ref().to_vec()));
+            Ok(())
+        }
+    }
+
+    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
+        let key = MapKey::Path((keychain, None)).as_map_key();
+        self.map
+            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
+            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
+            .collect()
+    }
+
+    fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
+        let key = MapKey::Utxo(None).as_map_key();
+        self.map
+            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
+            .map(|(k, v)| {
+                let outpoint = deserialize(&k[1..]).unwrap();
+                let (txout, keychain) = v.downcast_ref().cloned().unwrap();
+                Ok(LocalUtxo {
+                    outpoint,
+                    txout,
+                    keychain,
+                })
+            })
+            .collect()
+    }
+
+    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
+        let key = MapKey::RawTx(None).as_map_key();
+        self.map
+            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
+            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
+            .collect()
+    }
+
+    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
+        let key = MapKey::Transaction(None).as_map_key();
+        self.map
+            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
+            .map(|(k, v)| {
+                let mut txdetails: TransactionDetails = v.downcast_ref().cloned().unwrap();
+                if include_raw {
+                    let txid = deserialize(&k[1..])?;
+                    txdetails.transaction = self.get_raw_tx(&txid)?;
+                }
+
+                Ok(txdetails)
+            })
+            .collect()
+    }
+
+    fn get_script_pubkey_from_path(
+        &self,
+        keychain: KeychainKind,
+        path: u32,
+    ) -> Result<Option<Script>, Error> {
+        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
+        Ok(self
+            .map
+            .get(&key)
+            .map(|b| b.downcast_ref().cloned().unwrap()))
+    }
+
+    fn get_path_from_script_pubkey(
+        &self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error> {
+        let key = MapKey::Script(Some(script)).as_map_key();
+        Ok(self.map.get(&key).map(|b| {
+            let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
+            let st = serde_json::from_value(val["t"].take()).unwrap();
+            let path = serde_json::from_value(val["p"].take()).unwrap();
+
+            (st, path)
+        }))
+    }
+
+    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
+        let key = MapKey::Utxo(Some(outpoint)).as_map_key();
+        Ok(self.map.get(&key).map(|b| {
+            let (txout, keychain) = b.downcast_ref().cloned().unwrap();
+            LocalUtxo {
+                outpoint: *outpoint,
+                txout,
+                keychain,
+            }
+        }))
+    }
+
+    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        let key = MapKey::RawTx(Some(txid)).as_map_key();
+        Ok(self
+            .map
+            .get(&key)
+            .map(|b| b.downcast_ref().cloned().unwrap()))
+    }
+
+    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
+        let key = MapKey::Transaction(Some(txid)).as_map_key();
+        Ok(self.map.get(&key).map(|b| {
+            let mut txdetails: TransactionDetails = b.downcast_ref().cloned().unwrap();
+            if include_raw {
+                txdetails.transaction = self.get_raw_tx(txid).unwrap();
+            }
+
+            txdetails
+        }))
+    }
+
+    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
+        let key = MapKey::LastIndex(keychain).as_map_key();
+        Ok(self.map.get(&key).map(|b| *b.downcast_ref().unwrap()))
+    }
+
+    // inserts 0 if not present
+    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
+        let key = MapKey::LastIndex(keychain).as_map_key();
+        let value = self
+            .map
+            .entry(key)
+            .and_modify(|x| *x.downcast_mut::<u32>().unwrap() += 1)
+            .or_insert_with(|| Box::<u32>::new(0))
+            .downcast_mut()
+            .unwrap();
+
+        Ok(*value)
+    }
+
+    fn flush(&mut self) -> Result<(), Error> {
+        Ok(())
+    }
+}
+
+impl BatchDatabase for MemoryDatabase {
+    type Batch = Self;
+
+    fn begin_batch(&self) -> Self::Batch {
+        MemoryDatabase::new()
+    }
+
+    fn commit_batch(&mut self, mut batch: Self::Batch) -> Result<(), Error> {
+        for key in batch.deleted_keys.iter() {
+            self.map.remove(key);
+        }
+        self.map.append(&mut batch.map);
+        Ok(())
+    }
+}
+
+impl ConfigurableDatabase for MemoryDatabase {
+    type Config = ();
+
+    fn from_config(_config: &Self::Config) -> Result<Self, Error> {
+        Ok(MemoryDatabase::default())
+    }
+}
+
+#[macro_export]
+#[doc(hidden)]
+/// Artificially insert a tx in the database, as if we had found it with a `sync`. This is a hidden
+/// macro and not a `[cfg(test)]` function so it can be called within the context of doctests which
+/// don't have `test` set.
+macro_rules! populate_test_db {
+    ($db:expr, $tx_meta:expr, $current_height:expr$(,)?) => {{
+        use std::str::FromStr;
+        use $crate::database::BatchOperations;
+        let mut db = $db;
+        let tx_meta = $tx_meta;
+        let current_height: Option<u32> = $current_height;
+        let tx = $crate::bitcoin::Transaction {
+            version: 1,
+            lock_time: 0,
+            input: vec![],
+            output: tx_meta
+                .output
+                .iter()
+                .map(|out_meta| $crate::bitcoin::TxOut {
+                    value: out_meta.value,
+                    script_pubkey: $crate::bitcoin::Address::from_str(&out_meta.to_address)
+                        .unwrap()
+                        .script_pubkey(),
+                })
+                .collect(),
+        };
+
+        let txid = tx.txid();
+        let confirmation_time = tx_meta
+            .min_confirmations
+            .map(|conf| $crate::ConfirmationTime {
+                height: current_height.unwrap().checked_sub(conf as u32).unwrap(),
+                timestamp: 0,
+            });
+
+        let tx_details = $crate::TransactionDetails {
+            transaction: Some(tx.clone()),
+            txid,
+            fee: Some(0),
+            received: 0,
+            sent: 0,
+            confirmation_time,
+            verified: current_height.is_some(),
+        };
+
+        db.set_tx(&tx_details).unwrap();
+        for (vout, out) in tx.output.iter().enumerate() {
+            db.set_utxo(&$crate::LocalUtxo {
+                txout: out.clone(),
+                outpoint: $crate::bitcoin::OutPoint {
+                    txid,
+                    vout: vout as u32,
+                },
+                keychain: $crate::KeychainKind::External,
+            })
+            .unwrap();
+        }
+
+        txid
+    }};
+}
+
+#[macro_export]
+#[doc(hidden)]
+/// Macro for getting a wallet for use in a doctest
+macro_rules! doctest_wallet {
+    () => {{
+        use $crate::bitcoin::Network;
+        use $crate::database::MemoryDatabase;
+        use $crate::testutils;
+        let descriptor = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)";
+        let descriptors = testutils!(@descriptors (descriptor) (descriptor));
+
+        let mut db = MemoryDatabase::new();
+        let txid = populate_test_db!(
+            &mut db,
+            testutils! {
+                @tx ( (@external descriptors, 0) => 500_000 ) (@confirmations 1)
+            },
+            Some(100),
+        );
+
+        $crate::Wallet::new_offline(
+            &descriptors.0,
+            descriptors.1.as_ref(),
+            Network::Regtest,
+            db
+        )
+        .unwrap()
+    }}
+}
+
+#[cfg(test)]
+mod test {
+    use super::MemoryDatabase;
+
+    fn get_tree() -> MemoryDatabase {
+        MemoryDatabase::new()
+    }
+
+    #[test]
+    fn test_script_pubkey() {
+        crate::database::test::test_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_batch_script_pubkey() {
+        crate::database::test::test_batch_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_iter_script_pubkey() {
+        crate::database::test::test_iter_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_del_script_pubkey() {
+        crate::database::test::test_del_script_pubkey(get_tree());
+    }
+
+    #[test]
+    fn test_utxo() {
+        crate::database::test::test_utxo(get_tree());
+    }
+
+    #[test]
+    fn test_raw_tx() {
+        crate::database::test::test_raw_tx(get_tree());
+    }
+
+    #[test]
+    fn test_tx() {
+        crate::database::test::test_tx(get_tree());
+    }
+
+    #[test]
+    fn test_last_index() {
+        crate::database::test::test_last_index(get_tree());
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/mod.rs.html new file mode 100644 index 0000000000..8dfc8a0079 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/mod.rs.html @@ -0,0 +1,766 @@ +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
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+//! Database types
+//!
+//! This module provides the implementation of some defaults database types, along with traits that
+//! can be implemented externally to let [`Wallet`]s use customized databases.
+//!
+//! It's important to note that the databases defined here only contains "blockchain-related" data.
+//! They can be seen more as a cache than a critical piece of storage that contains secrets and
+//! keys.
+//!
+//! The currently recommended database is [`sled`], which is a pretty simple key-value embedded
+//! database written in Rust. If the `key-value-db` feature is enabled (which by default is),
+//! this library automatically implements all the required traits for [`sled::Tree`].
+//!
+//! [`Wallet`]: crate::wallet::Wallet
+
+use bitcoin::hash_types::Txid;
+use bitcoin::{OutPoint, Script, Transaction, TxOut};
+
+use crate::error::Error;
+use crate::types::*;
+
+pub mod any;
+pub use any::{AnyDatabase, AnyDatabaseConfig};
+
+#[cfg(feature = "key-value-db")]
+pub(crate) mod keyvalue;
+
+#[cfg(feature = "sqlite")]
+pub(crate) mod sqlite;
+#[cfg(feature = "sqlite")]
+pub use sqlite::SqliteDatabase;
+
+pub mod memory;
+pub use memory::MemoryDatabase;
+
+/// Trait for operations that can be batched
+///
+/// This trait defines the list of operations that must be implemented on the [`Database`] type and
+/// the [`BatchDatabase::Batch`] type.
+pub trait BatchOperations {
+    /// Store a script_pubkey along with its keychain and child number.
+    fn set_script_pubkey(
+        &mut self,
+        script: &Script,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<(), Error>;
+    /// Store a [`LocalUtxo`]
+    fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error>;
+    /// Store a raw transaction
+    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>;
+    /// Store the metadata of a transaction
+    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>;
+    /// Store the last derivation index for a given keychain.
+    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error>;
+
+    /// Delete a script_pubkey given the keychain and its child number.
+    fn del_script_pubkey_from_path(
+        &mut self,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<Option<Script>, Error>;
+    /// Delete the data related to a specific script_pubkey, meaning the keychain and the child
+    /// number.
+    fn del_path_from_script_pubkey(
+        &mut self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error>;
+    /// Delete a [`LocalUtxo`] given its [`OutPoint`]
+    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error>;
+    /// Delete a raw transaction given its [`Txid`]
+    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>;
+    /// Delete the metadata of a transaction and optionally the raw transaction itself
+    fn del_tx(
+        &mut self,
+        txid: &Txid,
+        include_raw: bool,
+    ) -> Result<Option<TransactionDetails>, Error>;
+    /// Delete the last derivation index for a keychain.
+    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error>;
+}
+
+/// Trait for reading data from a database
+///
+/// This traits defines the operations that can be used to read data out of a database
+pub trait Database: BatchOperations {
+    /// Read and checks the descriptor checksum for a given keychain.
+    ///
+    /// Should return [`Error::ChecksumMismatch`](crate::error::Error::ChecksumMismatch) if the
+    /// checksum doesn't match. If there's no checksum in the database, simply store it for the
+    /// next time.
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
+        &mut self,
+        keychain: KeychainKind,
+        bytes: B,
+    ) -> Result<(), Error>;
+
+    /// Return the list of script_pubkeys
+    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error>;
+    /// Return the list of [`LocalUtxo`]s
+    fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error>;
+    /// Return the list of raw transactions
+    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>;
+    /// Return the list of transactions metadata
+    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error>;
+
+    /// Fetch a script_pubkey given the child number of a keychain.
+    fn get_script_pubkey_from_path(
+        &self,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<Option<Script>, Error>;
+    /// Fetch the keychain and child number of a given script_pubkey
+    fn get_path_from_script_pubkey(
+        &self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error>;
+    /// Fetch a [`LocalUtxo`] given its [`OutPoint`]
+    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error>;
+    /// Fetch a raw transaction given its [`Txid`]
+    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
+    /// Fetch the transaction metadata and optionally also the raw transaction
+    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error>;
+    /// Return the last defivation index for a keychain.
+    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error>;
+
+    /// Increment the last derivation index for a keychain and return it
+    ///
+    /// It should insert and return `0` if not present in the database
+    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error>;
+
+    /// Force changes to be written to disk
+    fn flush(&mut self) -> Result<(), Error>;
+}
+
+/// Trait for a database that supports batch operations
+///
+/// This trait defines the methods to start and apply a batch of operations.
+pub trait BatchDatabase: Database {
+    /// Container for the operations
+    type Batch: BatchOperations;
+
+    /// Create a new batch container
+    fn begin_batch(&self) -> Self::Batch;
+    /// Consume and apply a batch of operations
+    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>;
+}
+
+/// Trait for [`Database`] types that can be created given a configuration
+pub trait ConfigurableDatabase: Database + Sized {
+    /// Type that contains the configuration
+    type Config: std::fmt::Debug;
+
+    /// Create a new instance given a configuration
+    fn from_config(config: &Self::Config) -> Result<Self, Error>;
+}
+
+pub(crate) trait DatabaseUtils: Database {
+    fn is_mine(&self, script: &Script) -> Result<bool, Error> {
+        self.get_path_from_script_pubkey(script)
+            .map(|o| o.is_some())
+    }
+
+    fn get_raw_tx_or<D>(&self, txid: &Txid, default: D) -> Result<Option<Transaction>, Error>
+    where
+        D: FnOnce() -> Result<Option<Transaction>, Error>,
+    {
+        self.get_tx(txid, true)?
+            .map(|t| t.transaction)
+            .flatten()
+            .map_or_else(default, |t| Ok(Some(t)))
+    }
+
+    fn get_previous_output(&self, outpoint: &OutPoint) -> Result<Option<TxOut>, Error> {
+        self.get_raw_tx(&outpoint.txid)?
+            .map(|previous_tx| {
+                if outpoint.vout as usize >= previous_tx.output.len() {
+                    Err(Error::InvalidOutpoint(*outpoint))
+                } else {
+                    Ok(previous_tx.output[outpoint.vout as usize].clone())
+                }
+            })
+            .transpose()
+    }
+}
+
+impl<T: Database> DatabaseUtils for T {}
+
+#[cfg(test)]
+pub mod test {
+    use std::str::FromStr;
+
+    use bitcoin::consensus::encode::deserialize;
+    use bitcoin::hashes::hex::*;
+    use bitcoin::*;
+
+    use super::*;
+
+    pub fn test_script_pubkey<D: Database>(mut tree: D) {
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let path = 42;
+        let keychain = KeychainKind::External;
+
+        tree.set_script_pubkey(&script, keychain, path).unwrap();
+
+        assert_eq!(
+            tree.get_script_pubkey_from_path(keychain, path).unwrap(),
+            Some(script.clone())
+        );
+        assert_eq!(
+            tree.get_path_from_script_pubkey(&script).unwrap(),
+            Some((keychain, path))
+        );
+    }
+
+    pub fn test_batch_script_pubkey<D: BatchDatabase>(mut tree: D) {
+        let mut batch = tree.begin_batch();
+
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let path = 42;
+        let keychain = KeychainKind::External;
+
+        batch.set_script_pubkey(&script, keychain, path).unwrap();
+
+        assert_eq!(
+            tree.get_script_pubkey_from_path(keychain, path).unwrap(),
+            None
+        );
+        assert_eq!(tree.get_path_from_script_pubkey(&script).unwrap(), None);
+
+        tree.commit_batch(batch).unwrap();
+
+        assert_eq!(
+            tree.get_script_pubkey_from_path(keychain, path).unwrap(),
+            Some(script.clone())
+        );
+        assert_eq!(
+            tree.get_path_from_script_pubkey(&script).unwrap(),
+            Some((keychain, path))
+        );
+    }
+
+    pub fn test_iter_script_pubkey<D: Database>(mut tree: D) {
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let path = 42;
+        let keychain = KeychainKind::External;
+
+        tree.set_script_pubkey(&script, keychain, path).unwrap();
+
+        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 1);
+    }
+
+    pub fn test_del_script_pubkey<D: Database>(mut tree: D) {
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let path = 42;
+        let keychain = KeychainKind::External;
+
+        tree.set_script_pubkey(&script, keychain, path).unwrap();
+        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 1);
+
+        tree.del_script_pubkey_from_path(keychain, path).unwrap();
+        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 0);
+    }
+
+    pub fn test_utxo<D: Database>(mut tree: D) {
+        let outpoint = OutPoint::from_str(
+            "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0",
+        )
+        .unwrap();
+        let script = Script::from(
+            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
+        );
+        let txout = TxOut {
+            value: 133742,
+            script_pubkey: script,
+        };
+        let utxo = LocalUtxo {
+            txout,
+            outpoint,
+            keychain: KeychainKind::External,
+        };
+
+        tree.set_utxo(&utxo).unwrap();
+
+        assert_eq!(tree.get_utxo(&outpoint).unwrap(), Some(utxo));
+    }
+
+    pub fn test_raw_tx<D: Database>(mut tree: D) {
+        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
+        let tx: Transaction = deserialize(&hex_tx).unwrap();
+
+        tree.set_raw_tx(&tx).unwrap();
+
+        let txid = tx.txid();
+
+        assert_eq!(tree.get_raw_tx(&txid).unwrap(), Some(tx));
+    }
+
+    pub fn test_tx<D: Database>(mut tree: D) {
+        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
+        let tx: Transaction = deserialize(&hex_tx).unwrap();
+        let txid = tx.txid();
+        let mut tx_details = TransactionDetails {
+            transaction: Some(tx),
+            txid,
+            received: 1337,
+            sent: 420420,
+            fee: Some(140),
+            confirmation_time: Some(ConfirmationTime {
+                timestamp: 123456,
+                height: 1000,
+            }),
+            verified: true,
+        };
+
+        tree.set_tx(&tx_details).unwrap();
+
+        // get with raw tx too
+        assert_eq!(
+            tree.get_tx(&tx_details.txid, true).unwrap(),
+            Some(tx_details.clone())
+        );
+        // get only raw_tx
+        assert_eq!(
+            tree.get_raw_tx(&tx_details.txid).unwrap(),
+            tx_details.transaction
+        );
+
+        // now get without raw_tx
+        tx_details.transaction = None;
+        assert_eq!(
+            tree.get_tx(&tx_details.txid, false).unwrap(),
+            Some(tx_details)
+        );
+    }
+
+    pub fn test_last_index<D: Database>(mut tree: D) {
+        tree.set_last_index(KeychainKind::External, 1337).unwrap();
+
+        assert_eq!(
+            tree.get_last_index(KeychainKind::External).unwrap(),
+            Some(1337)
+        );
+        assert_eq!(tree.get_last_index(KeychainKind::Internal).unwrap(), None);
+
+        let res = tree.increment_last_index(KeychainKind::External).unwrap();
+        assert_eq!(res, 1338);
+        let res = tree.increment_last_index(KeychainKind::Internal).unwrap();
+        assert_eq!(res, 0);
+
+        assert_eq!(
+            tree.get_last_index(KeychainKind::External).unwrap(),
+            Some(1338)
+        );
+        assert_eq!(
+            tree.get_last_index(KeychainKind::Internal).unwrap(),
+            Some(0)
+        );
+    }
+
+    // TODO: more tests...
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/sqlite.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/sqlite.rs.html new file mode 100644 index 0000000000..ff5e01c5bf --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/database/sqlite.rs.html @@ -0,0 +1,1940 @@ +sqlite.rs - source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+284
+285
+286
+287
+288
+289
+290
+291
+292
+293
+294
+295
+296
+297
+298
+299
+300
+301
+302
+303
+304
+305
+306
+307
+308
+309
+310
+311
+312
+313
+314
+315
+316
+317
+318
+319
+320
+321
+322
+323
+324
+325
+326
+327
+328
+329
+330
+331
+332
+333
+334
+335
+336
+337
+338
+339
+340
+341
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+352
+353
+354
+355
+356
+357
+358
+359
+360
+361
+362
+363
+364
+365
+366
+367
+368
+369
+370
+371
+372
+373
+374
+375
+376
+377
+378
+379
+380
+381
+382
+383
+384
+385
+386
+387
+388
+389
+390
+391
+392
+393
+394
+395
+396
+397
+398
+399
+400
+401
+402
+403
+404
+405
+406
+407
+408
+409
+410
+411
+412
+413
+414
+415
+416
+417
+418
+419
+420
+421
+422
+423
+424
+425
+426
+427
+428
+429
+430
+431
+432
+433
+434
+435
+436
+437
+438
+439
+440
+441
+442
+443
+444
+445
+446
+447
+448
+449
+450
+451
+452
+453
+454
+455
+456
+457
+458
+459
+460
+461
+462
+463
+464
+465
+466
+467
+468
+469
+470
+471
+472
+473
+474
+475
+476
+477
+478
+479
+480
+481
+482
+483
+484
+485
+486
+487
+488
+489
+490
+491
+492
+493
+494
+495
+496
+497
+498
+499
+500
+501
+502
+503
+504
+505
+506
+507
+508
+509
+510
+511
+512
+513
+514
+515
+516
+517
+518
+519
+520
+521
+522
+523
+524
+525
+526
+527
+528
+529
+530
+531
+532
+533
+534
+535
+536
+537
+538
+539
+540
+541
+542
+543
+544
+545
+546
+547
+548
+549
+550
+551
+552
+553
+554
+555
+556
+557
+558
+559
+560
+561
+562
+563
+564
+565
+566
+567
+568
+569
+570
+571
+572
+573
+574
+575
+576
+577
+578
+579
+580
+581
+582
+583
+584
+585
+586
+587
+588
+589
+590
+591
+592
+593
+594
+595
+596
+597
+598
+599
+600
+601
+602
+603
+604
+605
+606
+607
+608
+609
+610
+611
+612
+613
+614
+615
+616
+617
+618
+619
+620
+621
+622
+623
+624
+625
+626
+627
+628
+629
+630
+631
+632
+633
+634
+635
+636
+637
+638
+639
+640
+641
+642
+643
+644
+645
+646
+647
+648
+649
+650
+651
+652
+653
+654
+655
+656
+657
+658
+659
+660
+661
+662
+663
+664
+665
+666
+667
+668
+669
+670
+671
+672
+673
+674
+675
+676
+677
+678
+679
+680
+681
+682
+683
+684
+685
+686
+687
+688
+689
+690
+691
+692
+693
+694
+695
+696
+697
+698
+699
+700
+701
+702
+703
+704
+705
+706
+707
+708
+709
+710
+711
+712
+713
+714
+715
+716
+717
+718
+719
+720
+721
+722
+723
+724
+725
+726
+727
+728
+729
+730
+731
+732
+733
+734
+735
+736
+737
+738
+739
+740
+741
+742
+743
+744
+745
+746
+747
+748
+749
+750
+751
+752
+753
+754
+755
+756
+757
+758
+759
+760
+761
+762
+763
+764
+765
+766
+767
+768
+769
+770
+771
+772
+773
+774
+775
+776
+777
+778
+779
+780
+781
+782
+783
+784
+785
+786
+787
+788
+789
+790
+791
+792
+793
+794
+795
+796
+797
+798
+799
+800
+801
+802
+803
+804
+805
+806
+807
+808
+809
+810
+811
+812
+813
+814
+815
+816
+817
+818
+819
+820
+821
+822
+823
+824
+825
+826
+827
+828
+829
+830
+831
+832
+833
+834
+835
+836
+837
+838
+839
+840
+841
+842
+843
+844
+845
+846
+847
+848
+849
+850
+851
+852
+853
+854
+855
+856
+857
+858
+859
+860
+861
+862
+863
+864
+865
+866
+867
+868
+869
+870
+871
+872
+873
+874
+875
+876
+877
+878
+879
+880
+881
+882
+883
+884
+885
+886
+887
+888
+889
+890
+891
+892
+893
+894
+895
+896
+897
+898
+899
+900
+901
+902
+903
+904
+905
+906
+907
+908
+909
+910
+911
+912
+913
+914
+915
+916
+917
+918
+919
+920
+921
+922
+923
+924
+925
+926
+927
+928
+929
+930
+931
+932
+933
+934
+935
+936
+937
+938
+939
+940
+941
+942
+943
+944
+945
+946
+947
+948
+949
+950
+951
+952
+953
+954
+955
+956
+957
+958
+959
+960
+961
+962
+963
+964
+965
+966
+967
+968
+
// 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::consensus::encode::{deserialize, serialize};
+use bitcoin::hash_types::Txid;
+use bitcoin::{OutPoint, Script, Transaction, TxOut};
+
+use crate::database::{BatchDatabase, BatchOperations, Database};
+use crate::error::Error;
+use crate::types::*;
+
+use rusqlite::{named_params, Connection};
+
+static MIGRATIONS: &[&str] = &[
+    "CREATE TABLE version (version INTEGER)",
+    "INSERT INTO version VALUES (1)",
+    "CREATE TABLE script_pubkeys (keychain TEXT, child INTEGER, script BLOB);",
+    "CREATE INDEX idx_keychain_child ON script_pubkeys(keychain, child);",
+    "CREATE INDEX idx_script ON script_pubkeys(script);",
+    "CREATE TABLE utxos (value INTEGER, keychain TEXT, vout INTEGER, txid BLOB, script BLOB);",
+    "CREATE INDEX idx_txid_vout ON utxos(txid, vout);",
+    "CREATE TABLE transactions (txid BLOB, raw_tx BLOB);",
+    "CREATE INDEX idx_txid ON transactions(txid);",
+    "CREATE TABLE transaction_details (txid BLOB, timestamp INTEGER, received INTEGER, sent INTEGER, fee INTEGER, height INTEGER, verified INTEGER DEFAULT 0);",
+    "CREATE INDEX idx_txdetails_txid ON transaction_details(txid);",
+    "CREATE TABLE last_derivation_indices (keychain TEXT, value INTEGER);",
+    "CREATE UNIQUE INDEX idx_indices_keychain ON last_derivation_indices(keychain);",
+    "CREATE TABLE checksums (keychain TEXT, checksum BLOB);",
+    "CREATE INDEX idx_checksums_keychain ON checksums(keychain);",
+];
+
+/// Sqlite database stored on filesystem
+///
+/// This is a permanent storage solution for devices and platforms that provide a filesystem.
+/// [`crate::database`]
+#[derive(Debug)]
+pub struct SqliteDatabase {
+    /// Path on the local filesystem to store the sqlite file
+    pub path: String,
+    /// A rusqlite connection object to the sqlite database
+    pub connection: Connection,
+}
+
+impl SqliteDatabase {
+    /// Instantiate a new SqliteDatabase instance by creating a connection
+    /// to the database stored at path
+    pub fn new(path: String) -> Self {
+        let connection = get_connection(&path).unwrap();
+        SqliteDatabase { path, connection }
+    }
+    fn insert_script_pubkey(
+        &self,
+        keychain: String,
+        child: u32,
+        script: &[u8],
+    ) -> Result<i64, Error> {
+        let mut statement = self.connection.prepare_cached("INSERT INTO script_pubkeys (keychain, child, script) VALUES (:keychain, :child, :script)")?;
+        statement.execute(named_params! {
+            ":keychain": keychain,
+            ":child": child,
+            ":script": script
+        })?;
+
+        Ok(self.connection.last_insert_rowid())
+    }
+    fn insert_utxo(
+        &self,
+        value: u64,
+        keychain: String,
+        vout: u32,
+        txid: &[u8],
+        script: &[u8],
+    ) -> Result<i64, Error> {
+        let mut statement = self.connection.prepare_cached("INSERT INTO utxos (value, keychain, vout, txid, script) VALUES (:value, :keychain, :vout, :txid, :script)")?;
+        statement.execute(named_params! {
+            ":value": value,
+            ":keychain": keychain,
+            ":vout": vout,
+            ":txid": txid,
+            ":script": script
+        })?;
+
+        Ok(self.connection.last_insert_rowid())
+    }
+    fn insert_transaction(&self, txid: &[u8], raw_tx: &[u8]) -> Result<i64, Error> {
+        let mut statement = self
+            .connection
+            .prepare_cached("INSERT INTO transactions (txid, raw_tx) VALUES (:txid, :raw_tx)")?;
+        statement.execute(named_params! {
+            ":txid": txid,
+            ":raw_tx": raw_tx,
+        })?;
+
+        Ok(self.connection.last_insert_rowid())
+    }
+
+    fn update_transaction(&self, txid: &[u8], raw_tx: &[u8]) -> Result<(), Error> {
+        let mut statement = self
+            .connection
+            .prepare_cached("UPDATE transactions SET raw_tx=:raw_tx WHERE txid=:txid")?;
+
+        statement.execute(named_params! {
+            ":txid": txid,
+            ":raw_tx": raw_tx,
+        })?;
+
+        Ok(())
+    }
+
+    fn insert_transaction_details(&self, transaction: &TransactionDetails) -> Result<i64, Error> {
+        let (timestamp, height) = match &transaction.confirmation_time {
+            Some(confirmation_time) => (
+                Some(confirmation_time.timestamp),
+                Some(confirmation_time.height),
+            ),
+            None => (None, None),
+        };
+
+        let txid: &[u8] = &transaction.txid;
+
+        let mut statement = self.connection.prepare_cached("INSERT INTO transaction_details (txid, timestamp, received, sent, fee, height, verified) VALUES (:txid, :timestamp, :received, :sent, :fee, :height, :verified)")?;
+
+        statement.execute(named_params! {
+            ":txid": txid,
+            ":timestamp": timestamp,
+            ":received": transaction.received,
+            ":sent": transaction.sent,
+            ":fee": transaction.fee,
+            ":height": height,
+            ":verified": transaction.verified
+        })?;
+
+        Ok(self.connection.last_insert_rowid())
+    }
+
+    fn update_transaction_details(&self, transaction: &TransactionDetails) -> Result<(), Error> {
+        let (timestamp, height) = match &transaction.confirmation_time {
+            Some(confirmation_time) => (
+                Some(confirmation_time.timestamp),
+                Some(confirmation_time.height),
+            ),
+            None => (None, None),
+        };
+
+        let txid: &[u8] = &transaction.txid;
+
+        let mut statement = self.connection.prepare_cached("UPDATE transaction_details SET timestamp=:timestamp, received=:received, sent=:sent, fee=:fee, height=:height, verified=:verified WHERE txid=:txid")?;
+
+        statement.execute(named_params! {
+            ":txid": txid,
+            ":timestamp": timestamp,
+            ":received": transaction.received,
+            ":sent": transaction.sent,
+            ":fee": transaction.fee,
+            ":height": height,
+            ":verified": transaction.verified,
+        })?;
+
+        Ok(())
+    }
+
+    fn insert_last_derivation_index(&self, keychain: String, value: u32) -> Result<i64, Error> {
+        let mut statement = self.connection.prepare_cached(
+            "INSERT INTO last_derivation_indices (keychain, value) VALUES (:keychain, :value)",
+        )?;
+
+        statement.execute(named_params! {
+            ":keychain": keychain,
+            ":value": value,
+        })?;
+
+        Ok(self.connection.last_insert_rowid())
+    }
+
+    fn insert_checksum(&self, keychain: String, checksum: &[u8]) -> Result<i64, Error> {
+        let mut statement = self.connection.prepare_cached(
+            "INSERT INTO checksums (keychain, checksum) VALUES (:keychain, :checksum)",
+        )?;
+        statement.execute(named_params! {
+            ":keychain": keychain,
+            ":checksum": checksum,
+        })?;
+
+        Ok(self.connection.last_insert_rowid())
+    }
+
+    fn update_last_derivation_index(&self, keychain: String, value: u32) -> Result<(), Error> {
+        let mut statement = self.connection.prepare_cached(
+            "INSERT INTO last_derivation_indices (keychain, value) VALUES (:keychain, :value) ON CONFLICT(keychain) DO UPDATE SET value=:value WHERE keychain=:keychain",
+        )?;
+
+        statement.execute(named_params! {
+            ":keychain": keychain,
+            ":value": value,
+        })?;
+
+        Ok(())
+    }
+
+    fn select_script_pubkeys(&self) -> Result<Vec<Script>, Error> {
+        let mut statement = self
+            .connection
+            .prepare_cached("SELECT script FROM script_pubkeys")?;
+        let mut scripts: Vec<Script> = vec![];
+        let mut rows = statement.query([])?;
+        while let Some(row) = rows.next()? {
+            let raw_script: Vec<u8> = row.get(0)?;
+            scripts.push(raw_script.into());
+        }
+
+        Ok(scripts)
+    }
+
+    fn select_script_pubkeys_by_keychain(&self, keychain: String) -> Result<Vec<Script>, Error> {
+        let mut statement = self
+            .connection
+            .prepare_cached("SELECT script FROM script_pubkeys WHERE keychain=:keychain")?;
+        let mut scripts: Vec<Script> = vec![];
+        let mut rows = statement.query(named_params! {":keychain": keychain})?;
+        while let Some(row) = rows.next()? {
+            let raw_script: Vec<u8> = row.get(0)?;
+            scripts.push(raw_script.into());
+        }
+
+        Ok(scripts)
+    }
+
+    fn select_script_pubkey_by_path(
+        &self,
+        keychain: String,
+        child: u32,
+    ) -> Result<Option<Script>, Error> {
+        let mut statement = self.connection.prepare_cached(
+            "SELECT script FROM script_pubkeys WHERE keychain=:keychain AND child=:child",
+        )?;
+        let mut rows = statement.query(named_params! {":keychain": keychain,":child": child})?;
+
+        match rows.next()? {
+            Some(row) => {
+                let script: Vec<u8> = row.get(0)?;
+                let script: Script = script.into();
+                Ok(Some(script))
+            }
+            None => Ok(None),
+        }
+    }
+
+    fn select_script_pubkey_by_script(
+        &self,
+        script: &[u8],
+    ) -> Result<Option<(KeychainKind, u32)>, Error> {
+        let mut statement = self
+            .connection
+            .prepare_cached("SELECT keychain, child FROM script_pubkeys WHERE script=:script")?;
+        let mut rows = statement.query(named_params! {":script": script})?;
+        match rows.next()? {
+            Some(row) => {
+                let keychain: String = row.get(0)?;
+                let keychain: KeychainKind = serde_json::from_str(&keychain)?;
+                let child: u32 = row.get(1)?;
+                Ok(Some((keychain, child)))
+            }
+            None => Ok(None),
+        }
+    }
+
+    fn select_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
+        let mut statement = self
+            .connection
+            .prepare_cached("SELECT value, keychain, vout, txid, script FROM utxos")?;
+        let mut utxos: Vec<LocalUtxo> = vec![];
+        let mut rows = statement.query([])?;
+        while let Some(row) = rows.next()? {
+            let value = row.get(0)?;
+            let keychain: String = row.get(1)?;
+            let vout = row.get(2)?;
+            let txid: Vec<u8> = row.get(3)?;
+            let script: Vec<u8> = row.get(4)?;
+
+            let keychain: KeychainKind = serde_json::from_str(&keychain)?;
+
+            utxos.push(LocalUtxo {
+                outpoint: OutPoint::new(deserialize(&txid)?, vout),
+                txout: TxOut {
+                    value,
+                    script_pubkey: script.into(),
+                },
+                keychain,
+            })
+        }
+
+        Ok(utxos)
+    }
+
+    fn select_utxo_by_outpoint(
+        &self,
+        txid: &[u8],
+        vout: u32,
+    ) -> Result<Option<(u64, KeychainKind, Script)>, Error> {
+        let mut statement = self.connection.prepare_cached(
+            "SELECT value, keychain, script FROM utxos WHERE txid=:txid AND vout=:vout",
+        )?;
+        let mut rows = statement.query(named_params! {":txid": txid,":vout": vout})?;
+        match rows.next()? {
+            Some(row) => {
+                let value: u64 = row.get(0)?;
+                let keychain: String = row.get(1)?;
+                let keychain: KeychainKind = serde_json::from_str(&keychain)?;
+                let script: Vec<u8> = row.get(2)?;
+                let script: Script = script.into();
+
+                Ok(Some((value, keychain, script)))
+            }
+            None => Ok(None),
+        }
+    }
+
+    fn select_transactions(&self) -> Result<Vec<Transaction>, Error> {
+        let mut statement = self
+            .connection
+            .prepare_cached("SELECT raw_tx FROM transactions")?;
+        let mut txs: Vec<Transaction> = vec![];
+        let mut rows = statement.query([])?;
+        while let Some(row) = rows.next()? {
+            let raw_tx: Vec<u8> = row.get(0)?;
+            let tx: Transaction = deserialize(&raw_tx)?;
+            txs.push(tx);
+        }
+        Ok(txs)
+    }
+
+    fn select_transaction_by_txid(&self, txid: &[u8]) -> Result<Option<Transaction>, Error> {
+        let mut statement = self
+            .connection
+            .prepare_cached("SELECT raw_tx FROM transactions WHERE txid=:txid")?;
+        let mut rows = statement.query(named_params! {":txid": txid})?;
+        match rows.next()? {
+            Some(row) => {
+                let raw_tx: Vec<u8> = row.get(0)?;
+                let tx: Transaction = deserialize(&raw_tx)?;
+                Ok(Some(tx))
+            }
+            None => Ok(None),
+        }
+    }
+
+    fn select_transaction_details_with_raw(&self) -> Result<Vec<TransactionDetails>, Error> {
+        let mut statement = self.connection.prepare_cached("SELECT transaction_details.txid, transaction_details.timestamp, transaction_details.received, transaction_details.sent, transaction_details.fee, transaction_details.height, transaction_details.verified, transactions.raw_tx FROM transaction_details, transactions WHERE transaction_details.txid = transactions.txid")?;
+        let mut transaction_details: Vec<TransactionDetails> = vec![];
+        let mut rows = statement.query([])?;
+        while let Some(row) = rows.next()? {
+            let txid: Vec<u8> = row.get(0)?;
+            let txid: Txid = deserialize(&txid)?;
+            let timestamp: Option<u64> = row.get(1)?;
+            let received: u64 = row.get(2)?;
+            let sent: u64 = row.get(3)?;
+            let fee: Option<u64> = row.get(4)?;
+            let height: Option<u32> = row.get(5)?;
+            let verified: bool = row.get(6)?;
+            let raw_tx: Option<Vec<u8>> = row.get(7)?;
+            let tx: Option<Transaction> = match raw_tx {
+                Some(raw_tx) => {
+                    let tx: Transaction = deserialize(&raw_tx)?;
+                    Some(tx)
+                }
+                None => None,
+            };
+
+            let confirmation_time = match (height, timestamp) {
+                (Some(height), Some(timestamp)) => Some(ConfirmationTime { height, timestamp }),
+                _ => None,
+            };
+
+            transaction_details.push(TransactionDetails {
+                transaction: tx,
+                txid,
+                received,
+                sent,
+                fee,
+                confirmation_time,
+                verified,
+            });
+        }
+        Ok(transaction_details)
+    }
+
+    fn select_transaction_details(&self) -> Result<Vec<TransactionDetails>, Error> {
+        let mut statement = self.connection.prepare_cached(
+            "SELECT txid, timestamp, received, sent, fee, height, verified FROM transaction_details",
+        )?;
+        let mut transaction_details: Vec<TransactionDetails> = vec![];
+        let mut rows = statement.query([])?;
+        while let Some(row) = rows.next()? {
+            let txid: Vec<u8> = row.get(0)?;
+            let txid: Txid = deserialize(&txid)?;
+            let timestamp: Option<u64> = row.get(1)?;
+            let received: u64 = row.get(2)?;
+            let sent: u64 = row.get(3)?;
+            let fee: Option<u64> = row.get(4)?;
+            let height: Option<u32> = row.get(5)?;
+            let verified: bool = row.get(6)?;
+
+            let confirmation_time = match (height, timestamp) {
+                (Some(height), Some(timestamp)) => Some(ConfirmationTime { height, timestamp }),
+                _ => None,
+            };
+
+            transaction_details.push(TransactionDetails {
+                transaction: None,
+                txid,
+                received,
+                sent,
+                fee,
+                confirmation_time,
+                verified,
+            });
+        }
+        Ok(transaction_details)
+    }
+
+    fn select_transaction_details_by_txid(
+        &self,
+        txid: &[u8],
+    ) -> Result<Option<TransactionDetails>, Error> {
+        let mut statement = self.connection.prepare_cached("SELECT transaction_details.timestamp, transaction_details.received, transaction_details.sent, transaction_details.fee, transaction_details.height, transaction_details.verified, transactions.raw_tx FROM transaction_details, transactions WHERE transaction_details.txid=transactions.txid AND transaction_details.txid=:txid")?;
+        let mut rows = statement.query(named_params! { ":txid": txid })?;
+
+        match rows.next()? {
+            Some(row) => {
+                let timestamp: Option<u64> = row.get(0)?;
+                let received: u64 = row.get(1)?;
+                let sent: u64 = row.get(2)?;
+                let fee: Option<u64> = row.get(3)?;
+                let height: Option<u32> = row.get(4)?;
+                let verified: bool = row.get(5)?;
+
+                let raw_tx: Option<Vec<u8>> = row.get(6)?;
+                let tx: Option<Transaction> = match raw_tx {
+                    Some(raw_tx) => {
+                        let tx: Transaction = deserialize(&raw_tx)?;
+                        Some(tx)
+                    }
+                    None => None,
+                };
+
+                let confirmation_time = match (height, timestamp) {
+                    (Some(height), Some(timestamp)) => Some(ConfirmationTime { height, timestamp }),
+                    _ => None,
+                };
+
+                Ok(Some(TransactionDetails {
+                    transaction: tx,
+                    txid: deserialize(txid)?,
+                    received,
+                    sent,
+                    fee,
+                    confirmation_time,
+                    verified,
+                }))
+            }
+            None => Ok(None),
+        }
+    }
+
+    fn select_last_derivation_index_by_keychain(
+        &self,
+        keychain: String,
+    ) -> Result<Option<u32>, Error> {
+        let mut statement = self
+            .connection
+            .prepare_cached("SELECT value FROM last_derivation_indices WHERE keychain=:keychain")?;
+        let mut rows = statement.query(named_params! {":keychain": keychain})?;
+        match rows.next()? {
+            Some(row) => {
+                let value: u32 = row.get(0)?;
+                Ok(Some(value))
+            }
+            None => Ok(None),
+        }
+    }
+
+    fn select_checksum_by_keychain(&self, keychain: String) -> Result<Option<Vec<u8>>, Error> {
+        let mut statement = self
+            .connection
+            .prepare_cached("SELECT checksum FROM checksums WHERE keychain=:keychain")?;
+        let mut rows = statement.query(named_params! {":keychain": keychain})?;
+
+        match rows.next()? {
+            Some(row) => {
+                let checksum: Vec<u8> = row.get(0)?;
+                Ok(Some(checksum))
+            }
+            None => Ok(None),
+        }
+    }
+
+    fn delete_script_pubkey_by_path(&self, keychain: String, child: u32) -> Result<(), Error> {
+        let mut statement = self.connection.prepare_cached(
+            "DELETE FROM script_pubkeys WHERE keychain=:keychain AND child=:child",
+        )?;
+        statement.execute(named_params! {
+            ":keychain": keychain,
+            ":child": child
+        })?;
+
+        Ok(())
+    }
+
+    fn delete_script_pubkey_by_script(&self, script: &[u8]) -> Result<(), Error> {
+        let mut statement = self
+            .connection
+            .prepare_cached("DELETE FROM script_pubkeys WHERE script=:script")?;
+        statement.execute(named_params! {
+            ":script": script
+        })?;
+
+        Ok(())
+    }
+
+    fn delete_utxo_by_outpoint(&self, txid: &[u8], vout: u32) -> Result<(), Error> {
+        let mut statement = self
+            .connection
+            .prepare_cached("DELETE FROM utxos WHERE txid=:txid AND vout=:vout")?;
+        statement.execute(named_params! {
+            ":txid": txid,
+            ":vout": vout
+        })?;
+
+        Ok(())
+    }
+
+    fn delete_transaction_by_txid(&self, txid: &[u8]) -> Result<(), Error> {
+        let mut statement = self
+            .connection
+            .prepare_cached("DELETE FROM transactions WHERE txid=:txid")?;
+        statement.execute(named_params! {":txid": txid})?;
+        Ok(())
+    }
+
+    fn delete_transaction_details_by_txid(&self, txid: &[u8]) -> Result<(), Error> {
+        let mut statement = self
+            .connection
+            .prepare_cached("DELETE FROM transaction_details WHERE txid=:txid")?;
+        statement.execute(named_params! {":txid": txid})?;
+        Ok(())
+    }
+
+    fn delete_last_derivation_index_by_keychain(&self, keychain: String) -> Result<(), Error> {
+        let mut statement = self
+            .connection
+            .prepare_cached("DELETE FROM last_derivation_indices WHERE keychain=:keychain")?;
+        statement.execute(named_params! {
+            ":keychain": &keychain
+        })?;
+
+        Ok(())
+    }
+}
+
+impl BatchOperations for SqliteDatabase {
+    fn set_script_pubkey(
+        &mut self,
+        script: &Script,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<(), Error> {
+        let keychain = serde_json::to_string(&keychain)?;
+        self.insert_script_pubkey(keychain, child, script.as_bytes())?;
+        Ok(())
+    }
+
+    fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
+        self.insert_utxo(
+            utxo.txout.value,
+            serde_json::to_string(&utxo.keychain)?,
+            utxo.outpoint.vout,
+            &utxo.outpoint.txid,
+            utxo.txout.script_pubkey.as_bytes(),
+        )?;
+        Ok(())
+    }
+
+    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
+        match self.select_transaction_by_txid(&transaction.txid())? {
+            Some(_) => {
+                self.update_transaction(&transaction.txid(), &serialize(transaction))?;
+            }
+            None => {
+                self.insert_transaction(&transaction.txid(), &serialize(transaction))?;
+            }
+        }
+        Ok(())
+    }
+
+    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
+        match self.select_transaction_details_by_txid(&transaction.txid)? {
+            Some(_) => {
+                self.update_transaction_details(transaction)?;
+            }
+            None => {
+                self.insert_transaction_details(transaction)?;
+            }
+        }
+
+        if let Some(tx) = &transaction.transaction {
+            self.set_raw_tx(tx)?;
+        }
+
+        Ok(())
+    }
+
+    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
+        self.update_last_derivation_index(serde_json::to_string(&keychain)?, value)?;
+        Ok(())
+    }
+
+    fn del_script_pubkey_from_path(
+        &mut self,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<Option<Script>, Error> {
+        let keychain = serde_json::to_string(&keychain)?;
+        let script = self.select_script_pubkey_by_path(keychain.clone(), child)?;
+        match script {
+            Some(script) => {
+                self.delete_script_pubkey_by_path(keychain, child)?;
+                Ok(Some(script))
+            }
+            None => Ok(None),
+        }
+    }
+
+    fn del_path_from_script_pubkey(
+        &mut self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error> {
+        match self.select_script_pubkey_by_script(script.as_bytes())? {
+            Some((keychain, child)) => {
+                self.delete_script_pubkey_by_script(script.as_bytes())?;
+                Ok(Some((keychain, child)))
+            }
+            None => Ok(None),
+        }
+    }
+
+    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
+        match self.select_utxo_by_outpoint(&outpoint.txid, outpoint.vout)? {
+            Some((value, keychain, script_pubkey)) => {
+                self.delete_utxo_by_outpoint(&outpoint.txid, outpoint.vout)?;
+                Ok(Some(LocalUtxo {
+                    outpoint: *outpoint,
+                    txout: TxOut {
+                        value,
+                        script_pubkey,
+                    },
+                    keychain,
+                }))
+            }
+            None => Ok(None),
+        }
+    }
+
+    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        match self.select_transaction_by_txid(txid)? {
+            Some(tx) => {
+                self.delete_transaction_by_txid(txid)?;
+                Ok(Some(tx))
+            }
+            None => Ok(None),
+        }
+    }
+
+    fn del_tx(
+        &mut self,
+        txid: &Txid,
+        include_raw: bool,
+    ) -> Result<Option<TransactionDetails>, Error> {
+        match self.select_transaction_details_by_txid(txid)? {
+            Some(transaction_details) => {
+                self.delete_transaction_details_by_txid(txid)?;
+
+                if include_raw {
+                    self.delete_transaction_by_txid(txid)?;
+                }
+                Ok(Some(transaction_details))
+            }
+            None => Ok(None),
+        }
+    }
+
+    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
+        let keychain = serde_json::to_string(&keychain)?;
+        match self.select_last_derivation_index_by_keychain(keychain.clone())? {
+            Some(value) => {
+                self.delete_last_derivation_index_by_keychain(keychain)?;
+
+                Ok(Some(value))
+            }
+            None => Ok(None),
+        }
+    }
+}
+
+impl Database for SqliteDatabase {
+    fn check_descriptor_checksum<B: AsRef<[u8]>>(
+        &mut self,
+        keychain: KeychainKind,
+        bytes: B,
+    ) -> Result<(), Error> {
+        let keychain = serde_json::to_string(&keychain)?;
+
+        match self.select_checksum_by_keychain(keychain.clone())? {
+            Some(checksum) => {
+                if checksum == bytes.as_ref().to_vec() {
+                    Ok(())
+                } else {
+                    Err(Error::ChecksumMismatch)
+                }
+            }
+            None => {
+                self.insert_checksum(keychain, bytes.as_ref())?;
+                Ok(())
+            }
+        }
+    }
+
+    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
+        match keychain {
+            Some(keychain) => {
+                let keychain = serde_json::to_string(&keychain)?;
+                self.select_script_pubkeys_by_keychain(keychain)
+            }
+            None => self.select_script_pubkeys(),
+        }
+    }
+
+    fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
+        self.select_utxos()
+    }
+
+    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
+        self.select_transactions()
+    }
+
+    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
+        match include_raw {
+            true => self.select_transaction_details_with_raw(),
+            false => self.select_transaction_details(),
+        }
+    }
+
+    fn get_script_pubkey_from_path(
+        &self,
+        keychain: KeychainKind,
+        child: u32,
+    ) -> Result<Option<Script>, Error> {
+        let keychain = serde_json::to_string(&keychain)?;
+        match self.select_script_pubkey_by_path(keychain, child)? {
+            Some(script) => Ok(Some(script)),
+            None => Ok(None),
+        }
+    }
+
+    fn get_path_from_script_pubkey(
+        &self,
+        script: &Script,
+    ) -> Result<Option<(KeychainKind, u32)>, Error> {
+        match self.select_script_pubkey_by_script(script.as_bytes())? {
+            Some((keychain, child)) => Ok(Some((keychain, child))),
+            None => Ok(None),
+        }
+    }
+
+    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
+        match self.select_utxo_by_outpoint(&outpoint.txid, outpoint.vout)? {
+            Some((value, keychain, script_pubkey)) => Ok(Some(LocalUtxo {
+                outpoint: *outpoint,
+                txout: TxOut {
+                    value,
+                    script_pubkey,
+                },
+                keychain,
+            })),
+            None => Ok(None),
+        }
+    }
+
+    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
+        match self.select_transaction_by_txid(txid)? {
+            Some(tx) => Ok(Some(tx)),
+            None => Ok(None),
+        }
+    }
+
+    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
+        match self.select_transaction_details_by_txid(txid)? {
+            Some(mut transaction_details) => {
+                if !include_raw {
+                    transaction_details.transaction = None;
+                }
+                Ok(Some(transaction_details))
+            }
+            None => Ok(None),
+        }
+    }
+
+    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
+        let keychain = serde_json::to_string(&keychain)?;
+        let value = self.select_last_derivation_index_by_keychain(keychain)?;
+        Ok(value)
+    }
+
+    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
+        let keychain_string = serde_json::to_string(&keychain)?;
+        match self.get_last_index(keychain)? {
+            Some(value) => {
+                self.update_last_derivation_index(keychain_string, value + 1)?;
+                Ok(value + 1)
+            }
+            None => {
+                self.insert_last_derivation_index(keychain_string, 0)?;
+                Ok(0)
+            }
+        }
+    }
+
+    fn flush(&mut self) -> Result<(), Error> {
+        Ok(())
+    }
+}
+
+impl BatchDatabase for SqliteDatabase {
+    type Batch = SqliteDatabase;
+
+    fn begin_batch(&self) -> Self::Batch {
+        let db = SqliteDatabase::new(self.path.clone());
+        db.connection.execute("BEGIN TRANSACTION", []).unwrap();
+        db
+    }
+
+    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
+        batch.connection.execute("COMMIT TRANSACTION", [])?;
+        Ok(())
+    }
+}
+
+pub fn get_connection(path: &str) -> Result<Connection, Error> {
+    let connection = Connection::open(path)?;
+    migrate(&connection)?;
+    Ok(connection)
+}
+
+pub fn get_schema_version(conn: &Connection) -> rusqlite::Result<i32> {
+    let statement = conn.prepare_cached("SELECT version FROM version");
+    match statement {
+        Err(rusqlite::Error::SqliteFailure(e, Some(msg))) => {
+            if msg == "no such table: version" {
+                Ok(0)
+            } else {
+                Err(rusqlite::Error::SqliteFailure(e, Some(msg)))
+            }
+        }
+        Ok(mut stmt) => {
+            let mut rows = stmt.query([])?;
+            match rows.next()? {
+                Some(row) => {
+                    let version: i32 = row.get(0)?;
+                    Ok(version)
+                }
+                None => Ok(0),
+            }
+        }
+        _ => Ok(0),
+    }
+}
+
+pub fn set_schema_version(conn: &Connection, version: i32) -> rusqlite::Result<usize> {
+    conn.execute(
+        "UPDATE version SET version=:version",
+        named_params! {":version": version},
+    )
+}
+
+pub fn migrate(conn: &Connection) -> rusqlite::Result<()> {
+    let version = get_schema_version(conn)?;
+    let stmts = &MIGRATIONS[(version as usize)..];
+    let mut i: i32 = version;
+
+    if version == MIGRATIONS.len() as i32 {
+        log::info!("db up to date, no migration needed");
+        return Ok(());
+    }
+
+    for stmt in stmts {
+        let res = conn.execute(stmt, []);
+        if res.is_err() {
+            println!("migration failed on:\n{}\n{:?}", stmt, res);
+            break;
+        }
+
+        i += 1;
+    }
+
+    set_schema_version(conn, i)?;
+
+    Ok(())
+}
+
+#[cfg(test)]
+pub mod test {
+    use crate::database::SqliteDatabase;
+    use std::time::{SystemTime, UNIX_EPOCH};
+
+    fn get_database() -> SqliteDatabase {
+        let time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
+        let mut dir = std::env::temp_dir();
+        dir.push(format!("bdk_{}", time.as_nanos()));
+        SqliteDatabase::new(String::from(dir.to_str().unwrap()))
+    }
+
+    #[test]
+    fn test_script_pubkey() {
+        crate::database::test::test_script_pubkey(get_database());
+    }
+
+    #[test]
+    fn test_batch_script_pubkey() {
+        crate::database::test::test_batch_script_pubkey(get_database());
+    }
+
+    #[test]
+    fn test_iter_script_pubkey() {
+        crate::database::test::test_iter_script_pubkey(get_database());
+    }
+
+    #[test]
+    fn test_del_script_pubkey() {
+        crate::database::test::test_del_script_pubkey(get_database());
+    }
+
+    #[test]
+    fn test_utxo() {
+        crate::database::test::test_utxo(get_database());
+    }
+
+    #[test]
+    fn test_raw_tx() {
+        crate::database::test::test_raw_tx(get_database());
+    }
+
+    #[test]
+    fn test_tx() {
+        crate::database::test::test_tx(get_database());
+    }
+
+    #[test]
+    fn test_last_index() {
+        crate::database::test::test_last_index(get_database());
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/checksum.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/checksum.rs.html new file mode 100644 index 0000000000..93562a5060 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/checksum.rs.html @@ -0,0 +1,230 @@ +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
+
// 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 std::iter::FromIterator;
+
+use crate::descriptor::DescriptorError;
+
+const INPUT_CHARSET: &str =  "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
+const CHECKSUM_CHARSET: &str = "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 of a descriptor
+pub fn get_checksum(desc: &str) -> Result<String, DescriptorError> {
+    let mut c = 1;
+    let mut cls = 0;
+    let mut clscount = 0;
+    for ch in desc.chars() {
+        let pos = INPUT_CHARSET
+            .find(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 chars = Vec::with_capacity(8);
+    for j in 0..8 {
+        chars.push(
+            CHECKSUM_CHARSET
+                .chars()
+                .nth(((c >> (5 * (7 - j))) & 31) as usize)
+                .unwrap(),
+        );
+    }
+
+    Ok(String::from_iter(chars))
+}
+
+#[cfg(test)]
+mod test {
+    use super::*;
+    use crate::descriptor::get_checksum;
+
+    // test get_checksum() function; it should return the same value as Bitcoin Core
+    #[test]
+    fn test_get_checksum() {
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)";
+        assert_eq!(get_checksum(desc).unwrap(), "tqz0nc62");
+
+        let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)";
+        assert_eq!(get_checksum(desc).unwrap(), "lasegmfs");
+    }
+
+    #[test]
+    fn test_get_checksum_invalid_character() {
+        let sparkle_heart = vec![240, 159, 146, 150];
+        let sparkle_heart = std::str::from_utf8(&sparkle_heart)
+            .unwrap()
+            .chars()
+            .next()
+            .unwrap();
+        let invalid_desc = format!("wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcL{}fjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)", sparkle_heart);
+
+        assert!(matches!(
+            get_checksum(&invalid_desc).err(),
+            Some(DescriptorError::InvalidDescriptorCharacter(invalid_char)) if invalid_char == sparkle_heart
+        ));
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/derived.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/derived.rs.html new file mode 100644 index 0000000000..edd1b2714d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/derived.rs.html @@ -0,0 +1,304 @@ +derived.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
+
// 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.
+
+//! Derived descriptor keys
+
+use std::cmp::Ordering;
+use std::fmt;
+use std::hash::{Hash, Hasher};
+use std::ops::Deref;
+
+use bitcoin::hashes::hash160;
+use bitcoin::PublicKey;
+
+pub use miniscript::{
+    descriptor::KeyMap, descriptor::Wildcard, Descriptor, DescriptorPublicKey, Legacy, Miniscript,
+    ScriptContext, Segwitv0,
+};
+use miniscript::{MiniscriptKey, ToPublicKey, TranslatePk};
+
+use crate::wallet::utils::SecpCtx;
+
+/// Extended [`DescriptorPublicKey`] that has been derived
+///
+/// Derived keys are guaranteed to never contain wildcards of any kind
+#[derive(Debug, Clone)]
+pub struct DerivedDescriptorKey<'s>(DescriptorPublicKey, &'s SecpCtx);
+
+impl<'s> DerivedDescriptorKey<'s> {
+    /// Construct a new derived key
+    ///
+    /// Panics if the key is wildcard
+    pub fn new(key: DescriptorPublicKey, secp: &'s SecpCtx) -> DerivedDescriptorKey<'s> {
+        if let DescriptorPublicKey::XPub(xpub) = &key {
+            assert!(xpub.wildcard == Wildcard::None)
+        }
+
+        DerivedDescriptorKey(key, secp)
+    }
+}
+
+impl<'s> Deref for DerivedDescriptorKey<'s> {
+    type Target = DescriptorPublicKey;
+
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl<'s> PartialEq for DerivedDescriptorKey<'s> {
+    fn eq(&self, other: &Self) -> bool {
+        self.0 == other.0
+    }
+}
+
+impl<'s> Eq for DerivedDescriptorKey<'s> {}
+
+impl<'s> PartialOrd for DerivedDescriptorKey<'s> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        self.0.partial_cmp(&other.0)
+    }
+}
+
+impl<'s> Ord for DerivedDescriptorKey<'s> {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.0.cmp(&other.0)
+    }
+}
+
+impl<'s> fmt::Display for DerivedDescriptorKey<'s> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+impl<'s> Hash for DerivedDescriptorKey<'s> {
+    fn hash<H: Hasher>(&self, state: &mut H) {
+        self.0.hash(state);
+    }
+}
+
+impl<'s> MiniscriptKey for DerivedDescriptorKey<'s> {
+    type Hash = Self;
+
+    fn to_pubkeyhash(&self) -> Self::Hash {
+        DerivedDescriptorKey(self.0.to_pubkeyhash(), self.1)
+    }
+
+    fn is_uncompressed(&self) -> bool {
+        self.0.is_uncompressed()
+    }
+    fn serialized_len(&self) -> usize {
+        self.0.serialized_len()
+    }
+}
+
+impl<'s> ToPublicKey for DerivedDescriptorKey<'s> {
+    fn to_public_key(&self) -> PublicKey {
+        match &self.0 {
+            DescriptorPublicKey::SinglePub(ref spub) => spub.key.to_public_key(),
+            DescriptorPublicKey::XPub(ref xpub) => {
+                xpub.xkey
+                    .derive_pub(self.1, &xpub.derivation_path)
+                    .expect("Shouldn't fail, only normal derivations")
+                    .public_key
+            }
+        }
+    }
+
+    fn hash_to_hash160(hash: &Self::Hash) -> hash160::Hash {
+        hash.to_public_key().to_pubkeyhash()
+    }
+}
+
+pub(crate) trait AsDerived {
+    // Derive a descriptor and transform all of its keys to `DerivedDescriptorKey`
+    fn as_derived<'s>(&self, index: u32, secp: &'s SecpCtx)
+        -> Descriptor<DerivedDescriptorKey<'s>>;
+
+    // Transform the keys into `DerivedDescriptorKey`.
+    //
+    // Panics if the descriptor is not "fixed", i.e. if it's derivable
+    fn as_derived_fixed<'s>(&self, secp: &'s SecpCtx) -> Descriptor<DerivedDescriptorKey<'s>>;
+}
+
+impl AsDerived for Descriptor<DescriptorPublicKey> {
+    fn as_derived<'s>(
+        &self,
+        index: u32,
+        secp: &'s SecpCtx,
+    ) -> Descriptor<DerivedDescriptorKey<'s>> {
+        self.derive(index).translate_pk_infallible(
+            |key| DerivedDescriptorKey::new(key.clone(), secp),
+            |key| DerivedDescriptorKey::new(key.clone(), secp),
+        )
+    }
+
+    fn as_derived_fixed<'s>(&self, secp: &'s SecpCtx) -> Descriptor<DerivedDescriptorKey<'s>> {
+        assert!(!self.is_deriveable());
+
+        self.as_derived(0, secp)
+    }
+}
+
+
+ + \ 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 new file mode 100644 index 0000000000..4914cdfc1d --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/dsl.rs.html @@ -0,0 +1,2134 @@ +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
+
// 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 std::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 std::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_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_minsicript()?;
+            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_minsicript()?;
+            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_minsicript()?;
+            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(
+                    std::sync::Arc::new(a_minisc),
+                    std::sync::Arc::new(b_minisc),
+                ))?;
+
+                minisc.check_minsicript()?;
+
+                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(
+                    std::sync::Arc::new(a_minisc),
+                    std::sync::Arc::new(b_minisc),
+                    std::sync::Arc::new(c_minisc),
+                ))?;
+
+                minisc.check_minsicript()?;
+
+                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<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! 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(
+                        std::sync::Arc::new(minisc),
+                    ),
+                )?;
+
+                minisc.check_minsicript()?;
+
+                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,
+                std::sync::Arc::new(a_minisc),
+                std::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,
+                std::sync::Arc::new($crate::fragment!(false).unwrap().0),
+                std::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,
+                std::sync::Arc::new(a_minisc),
+                std::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(...),sdv: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: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: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>>(())
+/// ```
+#[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)
+            .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?, 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?, 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 )*)
+    });
+}
+
+#[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! 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 succedes, 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, $value)
+    });
+    ( older ( $value:expr ) ) => ({
+        $crate::impl_leaf_opcode_value!(Older, $value)
+    });
+    ( 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): (Vec<_>, Vec<_>) = $items.into_iter().map(|(a, b, c)| (a, (b, c))).unzip();
+        let items = items.into_iter().map(std::sync::Arc::new).collect();
+
+        let (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<Vec<_>, _>>()
+            .and_then(|items| $crate::fragment!(thresh_vec($thresh, items)))
+    });
+    ( multi_vec ( $thresh:expr, $keys:expr ) ) => ({
+        $crate::keys::make_multi($thresh, $keys)
+    });
+    ( multi ( $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<Vec<_>, _>>()
+            .map_err($crate::descriptor::DescriptorError::Key)
+            .and_then(|keys| $crate::keys::make_multi($thresh, keys, &secp))
+    });
+
+    // `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 bitcoin::hashes::hex::ToHex;
+    use bitcoin::secp256k1::Secp256k1;
+    use miniscript::descriptor::{DescriptorPublicKey, DescriptorTrait, KeyMap};
+    use miniscript::{Descriptor, Legacy, Segwitv0};
+
+    use std::str::FromStr;
+
+    use crate::descriptor::{DescriptorError, DescriptorMeta};
+    use crate::keys::{DescriptorKey, IntoDescriptorKey, ValidNetworks};
+    use bitcoin::network::constants::Network::{Bitcoin, Regtest, Signet, Testnet};
+    use bitcoin::util::bip32;
+    use bitcoin::PrivateKey;
+
+    use crate::descriptor::derived::AsDerived;
+
+    // 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 secp = Secp256k1::new();
+
+        let (desc, _key_map, _networks) = desc.unwrap();
+        assert_eq!(desc.is_witness(), is_witness);
+        assert_eq!(!desc.is_deriveable(), is_fixed);
+        for i in 0..expected.len() {
+            let index = i as u32;
+            let child_desc = if !desc.is_deriveable() {
+                desc.as_derived_fixed(&secp)
+            } else {
+                desc.as_derived(index, &secp)
+            };
+            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().as_str(), *expected.get(i).unwrap());
+            }
+        }
+    }
+
+    // - at least one of each "type" of operator; ie. 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::ExtendedPrivKey::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::ExtendedPrivKey::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::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        let path_1 = bip32::DerivationPath::from_str("m/0").unwrap();
+
+        let key_2 = bip32::ExtendedPrivKey::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::ExtendedPrivKey::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::ExtendedPrivKey::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::ExtendedPrivKey::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::ExtendedPrivKey::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::ExtendedPrivKey::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::ExtendedPrivKey::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,d:v:older(1),s:pk(private_key),s:pk(private_key)))).unwrap();
+
+        assert_eq!(descriptor.to_string(), "wsh(thresh(2,dv:older(1),s:pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),s:pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)))#cfdcqs3s")
+    }
+
+    #[test]
+    #[should_panic(expected = "Miniscript(ContextError(CompressedOnly))")]
+    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();
+    }
+}
+
+
+ + \ 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 new file mode 100644 index 0000000000..49cea1f62b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/error.rs.html @@ -0,0 +1,142 @@ +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
+
// 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
+
+/// 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 multiple keys with the same BIP32 fingerprint
+    DuplicatedKeys,
+
+    /// Error thrown while working with [`keys`](crate::keys)
+    Key(crate::keys::KeyError),
+    /// Error while extracting and manipulating policies
+    Policy(crate::descriptor::policy::PolicyError),
+
+    /// Invalid character found in the descriptor checksum
+    InvalidDescriptorCharacter(char),
+
+    /// BIP32 error
+    Bip32(bitcoin::util::bip32::Error),
+    /// Error during base58 decoding
+    Base58(bitcoin::util::base58::Error),
+    /// Key-related error
+    Pk(bitcoin::util::key::Error),
+    /// Miniscript error
+    Miniscript(miniscript::Error),
+    /// Hex decoding error
+    Hex(bitcoin::hashes::hex::Error),
+}
+
+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 std::fmt::Display for Error {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for Error {}
+
+impl_error!(bitcoin::util::bip32::Error, Bip32);
+impl_error!(bitcoin::util::base58::Error, Base58);
+impl_error!(bitcoin::util::key::Error, Pk);
+impl_error!(miniscript::Error, Miniscript);
+impl_error!(bitcoin::hashes::hex::Error, Hex);
+impl_error!(crate::descriptor::policy::PolicyError, Policy);
+
+
+ + \ 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 new file mode 100644 index 0000000000..628c70d6f8 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/mod.rs.html @@ -0,0 +1,1612 @@ +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
+
// 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 std::collections::{BTreeMap, HashMap, HashSet};
+use std::ops::Deref;
+
+use bitcoin::util::bip32::{
+    ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey, Fingerprint, KeySource,
+};
+use bitcoin::util::psbt;
+use bitcoin::{Network, PublicKey, Script, TxOut};
+
+use miniscript::descriptor::{DescriptorPublicKey, DescriptorType, DescriptorXKey, Wildcard};
+pub use miniscript::{descriptor::KeyMap, Descriptor, Legacy, Miniscript, ScriptContext, Segwitv0};
+use miniscript::{DescriptorTrait, ForEachKey, TranslatePk};
+
+use crate::descriptor::policy::BuildSatisfaction;
+
+pub mod checksum;
+pub(crate) mod derived;
+#[doc(hidden)]
+pub mod dsl;
+pub mod error;
+pub mod policy;
+pub mod template;
+
+pub use self::checksum::get_checksum;
+use self::derived::AsDerived;
+pub use self::derived::DerivedDescriptorKey;
+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<'s> = Descriptor<DerivedDescriptorKey<'s>>;
+
+/// Alias for the type of maps that represent derivation paths in a [`psbt::Input`] or
+/// [`psbt::Output`]
+///
+/// [`psbt::Input`]: bitcoin::util::psbt::Input
+/// [`psbt::Output`]: bitcoin::util::psbt::Output
+pub type HdKeyPaths = BTreeMap<PublicKey, 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 = if self.contains('#') {
+            let parts: Vec<&str> = self.splitn(2, '#').collect();
+            if !get_checksum(parts[0])
+                .ok()
+                .map(|computed| computed == parts[1])
+                .unwrap_or(false)
+            {
+                return Err(DescriptorError::InvalidDescriptorChecksum);
+            }
+
+            parts[0]
+        } else {
+            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;
+
+        let check_key = |pk: &DescriptorPublicKey| {
+            let (pk, _, networks) = if self.0.is_witness() {
+                let desciptor_key: DescriptorKey<miniscript::Segwitv0> =
+                    pk.clone().into_descriptor_key()?;
+                desciptor_key.extract(secp)?
+            } else {
+                let desciptor_key: DescriptorKey<miniscript::Legacy> =
+                    pk.clone().into_descriptor_key()?;
+                desciptor_key.extract(secp)?
+            };
+
+            if networks.contains(&network) {
+                Ok(pk)
+            } else {
+                Err(DescriptorError::Key(KeyError::InvalidNetwork))
+            }
+        };
+
+        // check the network for the keys
+        let translated = self.0.translate_pk(check_key, check_key)?;
+
+        Ok((translated, self.1))
+    }
+}
+
+impl IntoWalletDescriptor for DescriptorTemplateOut {
+    fn into_wallet_descriptor(
+        self,
+        _secp: &SecpCtx,
+        network: Network,
+    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
+        let valid_networks = &self.2;
+
+        let fix_key = |pk: &DescriptorPublicKey| {
+            if valid_networks.contains(&network) {
+                // 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 = network;
+
+                        DescriptorPublicKey::XPub(xpub)
+                    }
+                    other => other.clone(),
+                };
+
+                Ok(pk)
+            } else {
+                Err(DescriptorError::Key(KeyError::InvalidNetwork))
+            }
+        };
+
+        // fixup the network for keys that need it
+        let translated = self.0.translate_pk(fix_key, fix_key)?;
+
+        Ok((translated, self.1))
+    }
+}
+
+/// 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.as_key()
+        {
+            return *wildcard == Wildcard::Hardened
+                || derivation_path.into_iter().any(ChildNumber::is_hardened);
+        }
+
+        false
+    });
+    if descriptor_contains_hardened_steps {
+        return Err(DescriptorError::HardenedDerivationXpub);
+    }
+
+    // Ensure that there are no duplicated keys
+    let mut found_keys = HashSet::new();
+    let descriptor_contains_duplicated_keys = descriptor.for_any_key(|k| {
+        if let DescriptorPublicKey::XPub(xkey) = k.as_key() {
+            let fingerprint = xkey.root_fingerprint(secp);
+            if found_keys.contains(&fingerprint) {
+                return true;
+            }
+
+            found_keys.insert(fingerprint);
+        }
+
+        false
+    });
+    if descriptor_contains_duplicated_keys {
+        return Err(DescriptorError::DuplicatedKeys);
+    }
+
+    Ok((descriptor, keymap))
+}
+
+#[doc(hidden)]
+/// Used internally mainly by the `descriptor!()` and `fragment!()` macros
+pub trait CheckMiniscript<Ctx: miniscript::ScriptContext> {
+    fn check_minsicript(&self) -> Result<(), miniscript::Error>;
+}
+
+impl<Ctx: miniscript::ScriptContext, Pk: miniscript::MiniscriptKey> CheckMiniscript<Ctx>
+    for miniscript::Miniscript<Pk, Ctx>
+{
+    fn check_minsicript(&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 full_path(&self, append: &[ChildNumber]) -> DerivationPath;
+    fn root_fingerprint(&self, secp: &SecpCtx) -> Fingerprint;
+}
+
+// FIXME: `InnerXKey` was made private in rust-miniscript, so we have to implement this manually on
+// both `ExtendedPubKey` and `ExtendedPrivKey`.
+//
+// Revert back to using the trait once https://github.com/rust-bitcoin/rust-miniscript/pull/230 is
+// released
+impl XKeyUtils for DescriptorXKey<ExtendedPubKey> {
+    fn full_path(&self, append: &[ChildNumber]) -> DerivationPath {
+        let full_path = match self.origin {
+            Some((_, ref path)) => path
+                .into_iter()
+                .chain(self.derivation_path.into_iter())
+                .cloned()
+                .collect(),
+            None => self.derivation_path.clone(),
+        };
+
+        if self.wildcard != Wildcard::None {
+            full_path
+                .into_iter()
+                .chain(append.iter())
+                .cloned()
+                .collect()
+        } else {
+            full_path
+        }
+    }
+
+    fn root_fingerprint(&self, _: &SecpCtx) -> Fingerprint {
+        match self.origin {
+            Some((fingerprint, _)) => fingerprint,
+            None => self.xkey.fingerprint(),
+        }
+    }
+}
+impl XKeyUtils for DescriptorXKey<ExtendedPrivKey> {
+    fn full_path(&self, append: &[ChildNumber]) -> DerivationPath {
+        let full_path = match self.origin {
+            Some((_, ref path)) => path
+                .into_iter()
+                .chain(self.derivation_path.into_iter())
+                .cloned()
+                .collect(),
+            None => self.derivation_path.clone(),
+        };
+
+        if self.wildcard != Wildcard::None {
+            full_path
+                .into_iter()
+                .chain(append.iter())
+                .cloned()
+                .collect()
+        } else {
+            full_path
+        }
+    }
+
+    fn root_fingerprint(&self, secp: &SecpCtx) -> Fingerprint {
+        match self.origin {
+            Some((fingerprint, _)) => fingerprint,
+            None => self.xkey.fingerprint(secp),
+        }
+    }
+}
+
+pub(crate) trait DerivedDescriptorMeta {
+    fn get_hd_keypaths(&self, secp: &SecpCtx) -> Result<HdKeyPaths, DescriptorError>;
+}
+
+pub(crate) trait DescriptorMeta {
+    fn is_witness(&self) -> bool;
+    fn get_extended_keys(&self) -> Result<Vec<DescriptorXKey<ExtendedPubKey>>, DescriptorError>;
+    fn derive_from_hd_keypaths<'s>(
+        &self,
+        hd_keypaths: &HdKeyPaths,
+        secp: &'s SecpCtx,
+    ) -> Option<DerivedDescriptor<'s>>;
+    fn derive_from_psbt_input<'s>(
+        &self,
+        psbt_input: &psbt::Input,
+        utxo: Option<TxOut>,
+        secp: &'s SecpCtx,
+    ) -> Option<DerivedDescriptor<'s>>;
+}
+
+pub(crate) trait DescriptorScripts {
+    fn psbt_redeem_script(&self) -> Option<Script>;
+    fn psbt_witness_script(&self) -> Option<Script>;
+}
+
+impl<'s> DescriptorScripts for DerivedDescriptor<'s> {
+    fn psbt_redeem_script(&self) -> Option<Script> {
+        match self.desc_type() {
+            DescriptorType::ShWpkh => Some(self.explicit_script()),
+            DescriptorType::ShWsh => Some(self.explicit_script().to_v0_p2wsh()),
+            DescriptorType::Sh => Some(self.explicit_script()),
+            DescriptorType::Bare => Some(self.explicit_script()),
+            DescriptorType::ShSortedMulti => Some(self.explicit_script()),
+            _ => None,
+        }
+    }
+
+    fn psbt_witness_script(&self) -> Option<Script> {
+        match self.desc_type() {
+            DescriptorType::Wsh => Some(self.explicit_script()),
+            DescriptorType::ShWsh => Some(self.explicit_script()),
+            DescriptorType::WshSortedMulti | DescriptorType::ShWshSortedMulti => {
+                Some(self.explicit_script())
+            }
+            _ => None,
+        }
+    }
+}
+
+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 get_extended_keys(&self) -> Result<Vec<DescriptorXKey<ExtendedPubKey>>, DescriptorError> {
+        let mut answer = Vec::new();
+
+        self.for_each_key(|pk| {
+            if let DescriptorPublicKey::XPub(xpub) = pk.as_key() {
+                answer.push(xpub.clone());
+            }
+
+            true
+        });
+
+        Ok(answer)
+    }
+
+    fn derive_from_hd_keypaths<'s>(
+        &self,
+        hd_keypaths: &HdKeyPaths,
+        secp: &'s SecpCtx,
+    ) -> Option<DerivedDescriptor<'s>> {
+        let index: HashMap<_, _> = hd_keypaths.values().map(|(a, b)| (a, b)).collect();
+
+        let mut path_found = None;
+        self.for_each_key(|key| {
+            if path_found.is_some() {
+                // already found a matching path, we are done
+                return true;
+            }
+
+            if let DescriptorPublicKey::XPub(xpub) = key.as_key().deref() {
+                // Check if the key matches one entry in our `index`. If it does, `matches()` will
+                // return the "prefix" that matched, so we remove that prefix from the full path
+                // found in `index` 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 derivation_path: Option<Vec<ChildNumber>> = index
+                    .get_key_value(&root_fingerprint)
+                    .and_then(|(fingerprint, path)| {
+                        xpub.matches(&(**fingerprint, (*path).clone()), secp)
+                    })
+                    .map(|prefix| {
+                        index
+                            .get(&xpub.root_fingerprint(secp))
+                            .unwrap()
+                            .into_iter()
+                            .skip(prefix.into_iter().count())
+                            .cloned()
+                            .collect()
+                    });
+
+                match derivation_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)
+                        }
+                    }
+                    Some(path) if xpub.wildcard == Wildcard::None && path.is_empty() => {
+                        path_found = Some(0)
+                    }
+                    _ => {}
+                }
+            }
+
+            true
+        });
+
+        path_found.map(|path| self.as_derived(path, secp))
+    }
+
+    fn derive_from_psbt_input<'s>(
+        &self,
+        psbt_input: &psbt::Input,
+        utxo: Option<TxOut>,
+        secp: &'s SecpCtx,
+    ) -> Option<DerivedDescriptor<'s>> {
+        if let Some(derived) = self.derive_from_hd_keypaths(&psbt_input.bip32_derivation, secp) {
+            return Some(derived);
+        }
+        if self.is_deriveable() {
+            // We can't try to bruteforce the derivation index, exit here
+            return None;
+        }
+
+        let descriptor = self.as_derived_fixed(secp);
+        match descriptor.desc_type() {
+            // TODO: add pk() here
+            DescriptorType::Pkh | DescriptorType::Wpkh | DescriptorType::ShWpkh
+                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()
+                        == 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()
+                        == psbt_input.witness_script.as_ref().unwrap() =>
+            {
+                Some(descriptor)
+            }
+            _ => None,
+        }
+    }
+}
+
+impl<'s> DerivedDescriptorMeta for DerivedDescriptor<'s> {
+    fn get_hd_keypaths(&self, secp: &SecpCtx) -> Result<HdKeyPaths, DescriptorError> {
+        let mut answer = BTreeMap::new();
+        self.for_each_key(|key| {
+            if let DescriptorPublicKey::XPub(xpub) = key.as_key().deref() {
+                let derived_pubkey = xpub
+                    .xkey
+                    .derive_pub(secp, &xpub.derivation_path)
+                    .expect("Derivation can't fail");
+
+                answer.insert(
+                    derived_pubkey.public_key,
+                    (xpub.root_fingerprint(secp), xpub.full_path(&[])),
+                );
+            }
+
+            true
+        });
+
+        Ok(answer)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::str::FromStr;
+
+    use bitcoin::consensus::encode::deserialize;
+    use bitcoin::hashes::hex::FromHex;
+    use bitcoin::secp256k1::Secp256k1;
+    use bitcoin::util::{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::PartiallySignedTransaction = 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::PartiallySignedTransaction = 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::PartiallySignedTransaction = 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::PartiallySignedTransaction = 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 xpub = bip32::ExtendedPubKey::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").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 = (xpub, path).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 conver the key that supports "any_network" to the right network (testnet)
+        let (wallet_desc, _) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+
+        assert_eq!(wallet_desc.to_string(), "wpkh(tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)#y8p7e8kk");
+    }
+
+    // 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(),
+            Some(DescriptorError::InvalidDescriptorChecksum)
+        ));
+
+        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#67ju93jw"
+            .into_wallet_descriptor(&secp, Network::Testnet);
+        assert!(matches!(
+            desc.err(),
+            Some(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(),
+            Some(DescriptorError::Key(KeyError::InvalidNetwork))
+        ));
+
+        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
+            .into_wallet_descriptor(&secp, Network::Bitcoin);
+        assert!(matches!(
+            desc.err(),
+            Some(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::ExtendedPubKey::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!(result.is_err());
+        assert!(matches!(
+            result.unwrap_err(),
+            DescriptorError::HardenedDerivationXpub
+        ));
+
+        let descriptor = "wsh(multi(2,tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/0/*,tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/*))";
+        let result = into_wallet_descriptor_checked(descriptor, &secp, Network::Testnet);
+
+        assert!(result.is_err());
+        assert!(matches!(
+            result.unwrap_err(),
+            DescriptorError::DuplicatedKeys
+        ));
+    }
+}
+
+
+ + \ 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 new file mode 100644 index 0000000000..98bb3b3e19 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/policy.rs.html @@ -0,0 +1,3208 @@ +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
+
// 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::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(key_map.into());
+//! let policy = extended_desc.extract_policy(&signers, BuildSatisfaction::None, &secp)?;
+//! println!("policy: {}", serde_json::to_string(&policy)?);
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use std::cmp::max;
+use std::collections::{BTreeMap, HashSet, VecDeque};
+use std::fmt;
+
+use serde::ser::SerializeMap;
+use serde::{Serialize, Serializer};
+
+use bitcoin::hashes::*;
+use bitcoin::util::bip32::Fingerprint;
+use bitcoin::PublicKey;
+
+use miniscript::descriptor::{DescriptorPublicKey, ShInner, SortedMultiVec, WshInner};
+use miniscript::{Descriptor, Miniscript, MiniscriptKey, Satisfier, ScriptContext, Terminal};
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+use crate::descriptor::ExtractPolicy;
+use crate::wallet::signer::{SignerId, SignersContainer};
+use crate::wallet::utils::{self, After, Older, SecpCtx};
+
+use super::checksum::get_checksum;
+use super::error::Error;
+use super::XKeyUtils;
+use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
+use miniscript::psbt::PsbtInputSatisfier;
+
+/// Raw public key or extended key fingerprint
+#[derive(Debug, Clone, Default, Serialize)]
+pub struct PkOrF {
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pubkey: Option<PublicKey>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pubkey_hash: Option<hash160::Hash>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    fingerprint: Option<Fingerprint>,
+}
+
+impl PkOrF {
+    fn from_key(k: &DescriptorPublicKey, secp: &SecpCtx) -> Self {
+        match k {
+            DescriptorPublicKey::SinglePub(pubkey) => PkOrF {
+                pubkey: Some(pubkey.key),
+                ..Default::default()
+            },
+            DescriptorPublicKey::XPub(xpub) => PkOrF {
+                fingerprint: Some(xpub.root_fingerprint(secp)),
+                ..Default::default()
+            },
+        }
+    }
+}
+
+/// An item that needs to be satisfied
+#[derive(Debug, Clone, Serialize)]
+#[serde(tag = "type", rename_all = "UPPERCASE")]
+pub enum SatisfiableItem {
+    // Leaves
+    /// Signature for a raw public key
+    Signature(PkOrF),
+    /// Signature for an extended key fingerprint
+    SignatureKey(PkOrF),
+    /// SHA256 preimage hash
+    Sha256Preimage {
+        /// The digest value
+        hash: sha256::Hash,
+    },
+    /// Double SHA256 preimage hash
+    Hash256Preimage {
+        /// The digest value
+        hash: sha256d::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 timestamp value
+        value: u32,
+    },
+    /// Relative timelock locktime
+    RelativeTimelock {
+        /// The locktime value
+        value: u32,
+    },
+    /// 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 {
+        get_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, 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 ([choosen 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 possibile options and check whether or not they are compatible.
+                    .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: &Vec<(Vec<usize>, Vec<Condition>)>| println!("fetch {:?}", x))
+                    // since the previous step can turn one item of the iterator into multiple ones, we call flatten to expand them out
+                    .flatten()
+                    // .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, 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
+#[derive(Hash, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default, Serialize)]
+pub struct Condition {
+    /// Optional CheckSequenceVerify condition
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub csv: Option<u32>,
+    /// Optional timelock condition
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub timelock: Option<u32>,
+}
+
+impl Condition {
+    fn merge_nlocktime(a: u32, b: u32) -> Result<u32, PolicyError> {
+        if (a < utils::BLOCKS_TIMELOCK_THRESHOLD) != (b < utils::BLOCKS_TIMELOCK_THRESHOLD) {
+            Err(PolicyError::MixedTimelockUnits)
+        } else {
+            Ok(max(a, b))
+        }
+    }
+
+    fn merge_nsequence(a: u32, b: u32) -> Result<u32, PolicyError> {
+        let mask = utils::SEQUENCE_LOCKTIME_TYPE_FLAG | utils::SEQUENCE_LOCKTIME_MASK;
+
+        let a = a & mask;
+        let b = b & mask;
+
+        if (a < utils::SEQUENCE_LOCKTIME_TYPE_FLAG) != (b < utils::SEQUENCE_LOCKTIME_TYPE_FLAG) {
+            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 {
+        write!(f, "{:?}", self)
+    }
+}
+
+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(
+        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 signature_in_psbt(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(),
+            _ => vec![],
+        };
+        let selected = match path.get(&self.id) {
+            Some(arr) => arr,
+            _ => &default,
+        };
+
+        match &self.item {
+            SatisfiableItem::Thresh { items, threshold } => {
+                let mapped_req = items
+                    .iter()
+                    .map(|i| i.get_condition(path))
+                    .collect::<Result<Vec<_>, _>>()?;
+
+                // if all the requirements are null we don't care about `selected` because there
+                // are no requirements
+                if mapped_req.iter().all(Condition::is_null) {
+                    return Ok(Condition::default());
+                }
+
+                // 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
+                let mut requirements = Condition::default();
+                for item_index in selected {
+                    requirements = requirements.merge(
+                        mapped_req
+                            .get(*item_index)
+                            .ok_or(PolicyError::IndexOutOfRange(*item_index))?,
+                    )?;
+                }
+
+                Ok(requirements)
+            }
+            SatisfiableItem::Multisig { keys, threshold } => {
+                if selected.len() < *threshold {
+                    return Err(PolicyError::NotEnoughItemsSelected(self.id.clone()));
+                }
+                if let Some(item) = selected.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 {
+    match key {
+        DescriptorPublicKey::SinglePub(pubkey) => pubkey.key.to_pubkeyhash().into(),
+        DescriptorPublicKey::XPub(xpub) => xpub.root_fingerprint(secp).into(),
+    }
+}
+
+fn signature(
+    key: &DescriptorPublicKey,
+    signers: &SignersContainer,
+    build_sat: BuildSatisfaction,
+    secp: &SecpCtx,
+) -> Policy {
+    let mut policy: Policy = SatisfiableItem::Signature(PkOrF::from_key(key, secp)).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 signature_in_psbt(psbt, key, secp) {
+            Satisfaction::Complete {
+                condition: Default::default(),
+            }
+        } else {
+            Satisfaction::None
+        };
+    }
+
+    policy
+}
+
+fn signature_in_psbt(psbt: &Psbt, key: &DescriptorPublicKey, secp: &SecpCtx) -> bool {
+    //TODO check signature validity
+    psbt.inputs.iter().all(|input| match key {
+        DescriptorPublicKey::SinglePub(key) => input.partial_sigs.contains_key(&key.key),
+        DescriptorPublicKey::XPub(xpub) => {
+            let pubkey = input
+                .bip32_derivation
+                .iter()
+                .find(|(_, (f, _))| *f == xpub.root_fingerprint(secp))
+                .map(|(p, _)| p);
+            //TODO check actual derivation matches
+            match pubkey {
+                Some(pubkey) => input.partial_sigs.contains_key(pubkey),
+                None => false,
+            }
+        }
+    })
+}
+
+impl<Ctx: ScriptContext> 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(signature(pubkey, signers, build_sat, secp)),
+            Terminal::PkH(pubkey_hash) => Some(signature(pubkey_hash, signers, build_sat, secp)),
+            Terminal::After(value) => {
+                let mut policy: Policy = SatisfiableItem::AbsoluteTimelock { value: *value }.into();
+                policy.contribution = Satisfaction::Complete {
+                    condition: Condition {
+                        timelock: Some(*value),
+                        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);
+                    let inputs_sat = psbt_inputs_sat(psbt)
+                        .all(|sat| Satisfier::<bitcoin::PublicKey>::check_after(&sat, *value));
+                    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) => {
+                Policy::make_multisig(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)?
+            }
+        })
+    }
+}
+
+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>(
+            keys: &SortedMultiVec<DescriptorPublicKey, Ctx>,
+            signers: &SignersContainer,
+            build_sat: BuildSatisfaction,
+            secp: &SecpCtx,
+        ) -> Result<Option<Policy>, Error> {
+            Ok(Policy::make_multisig(
+                keys.pks.as_ref(),
+                signers,
+                build_sat,
+                keys.k,
+                true,
+                secp,
+            )?)
+        }
+
+        match self {
+            Descriptor::Pkh(pk) => Ok(Some(signature(pk.as_inner(), signers, build_sat, secp))),
+            Descriptor::Wpkh(pk) => Ok(Some(signature(pk.as_inner(), signers, build_sat, secp))),
+            Descriptor::Sh(sh) => match sh.as_inner() {
+                ShInner::Wpkh(pk) => Ok(Some(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)?),
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use crate::descriptor;
+    use crate::descriptor::{ExtractPolicy, IntoWalletDescriptor};
+
+    use super::*;
+    use crate::descriptor::derived::AsDerived;
+    use crate::descriptor::policy::SatisfiableItem::{Multisig, Signature, Thresh};
+    use crate::keys::{DescriptorKey, IntoDescriptorKey};
+    use crate::wallet::signer::SignersContainer;
+    use bitcoin::secp256k1::Secp256k1;
+    use bitcoin::util::bip32;
+    use bitcoin::Network;
+    use miniscript::DescriptorTrait;
+    use std::str::FromStr;
+    use std::sync::Arc;
+
+    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::ExtendedPrivKey::from_str(tprv).unwrap();
+        let tpub = bip32::ExtendedPubKey::from_private(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::from(keymap));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+
+        assert!(
+            matches!(&policy.item, Signature(pk_or_f) if pk_or_f.fingerprint.unwrap() == 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::from(keymap));
+        let policy = wallet_desc
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+
+        assert!(
+            matches!(&policy.item, Signature(pk_or_f) if pk_or_f.fingerprint.unwrap() == fingerprint)
+        );
+        assert!(
+            matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == 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::from(keymap));
+        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].fingerprint.unwrap() == fingerprint0
+            && keys[1].fingerprint.unwrap() == 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::from(keymap));
+        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].fingerprint.unwrap() == fingerprint0
+            && keys[1].fingerprint.unwrap() == 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::from(keymap));
+        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].fingerprint.unwrap() == fingerprint0
+            && keys[1].fingerprint.unwrap() == 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::from(keymap));
+        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].fingerprint.unwrap() == fingerprint0
+            && keys[1].fingerprint.unwrap() == 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 single_key = wallet_desc.derive(0);
+        let signers_container = Arc::new(SignersContainer::from(keymap));
+        let policy = single_key
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+
+        assert!(
+            matches!(&policy.item, Signature(pk_or_f) if pk_or_f.fingerprint.unwrap() == 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 single_key = wallet_desc.derive(0);
+        let signers_container = Arc::new(SignersContainer::from(keymap));
+        let policy = single_key
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+
+        assert!(
+            matches!(&policy.item, Signature(pk_or_f) if pk_or_f.fingerprint.unwrap() == fingerprint)
+        );
+        assert!(
+            matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == 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 single_key = wallet_desc.derive(0);
+        let signers_container = Arc::new(SignersContainer::from(keymap));
+        let policy = single_key
+            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
+            .unwrap()
+            .unwrap();
+
+        assert!(
+            matches!(&policy.item, Multisig { keys, threshold } if threshold == &1
+            && keys[0].fingerprint.unwrap() == fingerprint0
+            && keys[1].fingerprint.unwrap() == 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::from(keymap));
+        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)
+             && conditions.get(&vec![1,2]).unwrap().iter().next().unwrap().csv == Some(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::from(keymap));
+        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::from(keymap));
+        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::from(keymap));
+        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 = keymap.into();
+
+        let policy = wallet_desc
+            .extract_policy(&signers, 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
+            .as_derived(0, &secp)
+            .address(Network::Testnet)
+            .unwrap();
+        assert_eq!(
+            "tb1qg3cwv3xt50gdg875qvjjpfgaps86gtk4rz0ejvp6ttc5ldnlxuvqlcn0xk",
+            addr.to_string()
+        );
+
+        let signers_container = Arc::new(SignersContainer::from(keymap));
+
+        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,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::from(keymap));
+
+        let addr = wallet_desc
+            .as_derived(0, &secp)
+            .address(Network::Testnet)
+            .unwrap();
+        assert_eq!(
+            "tb1qhpemaacpeu8ajlnh8k9v55ftg0px58r8630fz8t5mypxcwdk5d8sum522g",
+            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::from(keymap));
+
+        let policy = wallet_desc.extract_policy(&signers_container, BuildSatisfaction::None, &secp);
+        assert!(policy.is_ok());
+    }
+}
+
+
+ + \ 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 new file mode 100644 index 0000000000..31d6c7edbe --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/descriptor/template.rs.html @@ -0,0 +1,1456 @@ +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
+
// 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::util::bip32;
+use bitcoin::Network;
+
+use miniscript::{Legacy, Segwitv0};
+
+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};
+///
+/// struct MyP2PKH<K: IntoDescriptorKey<Legacy>>(K);
+///
+/// impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for MyP2PKH<K> {
+///     fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
+///         Ok(bdk::descriptor!(pkh(self.0))?)
+///     }
+/// }
+/// ```
+pub trait DescriptorTemplate {
+    /// Build the complete descriptor
+    fn build(self) -> 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()?.into_wallet_descriptor(secp, network)
+    }
+}
+
+/// P2PKH template. Expands to a descriptor `pkh(key)`
+///
+/// ## Example
+///
+/// ```
+/// # use bdk::bitcoin::{PrivateKey, Network};
+/// # use bdk::{Wallet};
+/// # use bdk::database::MemoryDatabase;
+/// # use bdk::wallet::AddressIndex::New;
+/// use bdk::template::P2Pkh;
+///
+/// let key =
+///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+/// let wallet = Wallet::new_offline(
+///     P2Pkh(key),
+///     None,
+///     Network::Testnet,
+///     MemoryDatabase::default(),
+/// )?;
+///
+/// assert_eq!(
+///     wallet.get_address(New)?.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) -> 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::database::MemoryDatabase;
+/// # use bdk::wallet::AddressIndex::New;
+/// use bdk::template::P2Wpkh_P2Sh;
+///
+/// let key =
+///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+/// let wallet = Wallet::new_offline(
+///     P2Wpkh_P2Sh(key),
+///     None,
+///     Network::Testnet,
+///     MemoryDatabase::default(),
+/// )?;
+///
+/// assert_eq!(
+///     wallet.get_address(New)?.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) -> 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::database::MemoryDatabase;
+/// # use bdk::wallet::AddressIndex::New;
+/// use bdk::template::P2Wpkh;
+///
+/// let key =
+///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
+/// let wallet = Wallet::new_offline(
+///     P2Wpkh(key),
+///     None,
+///     Network::Testnet,
+///     MemoryDatabase::default(),
+/// )?;
+///
+/// assert_eq!(
+///     wallet.get_address(New)?.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) -> Result<DescriptorTemplateOut, DescriptorError> {
+        descriptor!(wpkh(self.0))
+    }
+}
+
+/// BIP44 template. Expands to `pkh(key/44'/0'/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::database::MemoryDatabase;
+/// # use bdk::wallet::AddressIndex::New;
+/// use bdk::template::Bip44;
+///
+/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+/// let wallet = Wallet::new_offline(
+///     Bip44(key.clone(), KeychainKind::External),
+///     Some(Bip44(key, KeychainKind::Internal)),
+///     Network::Testnet,
+///     MemoryDatabase::default()
+/// )?;
+///
+/// assert_eq!(wallet.get_address(New)?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
+/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#xgaaevjx");
+/// # 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) -> Result<DescriptorTemplateOut, DescriptorError> {
+        P2Pkh(legacy::make_bipxx_private(44, self.0, self.1)?).build()
+    }
+}
+
+/// BIP44 public template. Expands to `pkh(key/{0,1}/*)`
+///
+/// This assumes that the key used has already been derived with `m/44'/0'/0'`.
+///
+/// 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::database::MemoryDatabase;
+/// # use bdk::wallet::AddressIndex::New;
+/// use bdk::template::Bip44Public;
+///
+/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
+/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
+/// let wallet = Wallet::new_offline(
+///     Bip44Public(key.clone(), fingerprint, KeychainKind::External),
+///     Some(Bip44Public(key, fingerprint, KeychainKind::Internal)),
+///     Network::Testnet,
+///     MemoryDatabase::default()
+/// )?;
+///
+/// assert_eq!(wallet.get_address(New)?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
+/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#xgaaevjx");
+/// # 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) -> Result<DescriptorTemplateOut, DescriptorError> {
+        P2Pkh(legacy::make_bipxx_public(44, self.0, self.1, self.2)?).build()
+    }
+}
+
+/// BIP49 template. Expands to `sh(wpkh(key/49'/0'/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::database::MemoryDatabase;
+/// # use bdk::wallet::AddressIndex::New;
+/// use bdk::template::Bip49;
+///
+/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+/// let wallet = Wallet::new_offline(
+///     Bip49(key.clone(), KeychainKind::External),
+///     Some(Bip49(key, KeychainKind::Internal)),
+///     Network::Testnet,
+///     MemoryDatabase::default()
+/// )?;
+///
+/// assert_eq!(wallet.get_address(New)?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
+/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))#gsmdv4xr");
+/// # 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) -> Result<DescriptorTemplateOut, DescriptorError> {
+        P2Wpkh_P2Sh(segwit_v0::make_bipxx_private(49, self.0, self.1)?).build()
+    }
+}
+
+/// 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'`.
+///
+/// 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::database::MemoryDatabase;
+/// # use bdk::wallet::AddressIndex::New;
+/// use bdk::template::Bip49Public;
+///
+/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
+/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
+/// let wallet = Wallet::new_offline(
+///     Bip49Public(key.clone(), fingerprint, KeychainKind::External),
+///     Some(Bip49Public(key, fingerprint, KeychainKind::Internal)),
+///     Network::Testnet,
+///     MemoryDatabase::default()
+/// )?;
+///
+/// assert_eq!(wallet.get_address(New)?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
+/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))#gsmdv4xr");
+/// # 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) -> Result<DescriptorTemplateOut, DescriptorError> {
+        P2Wpkh_P2Sh(segwit_v0::make_bipxx_public(49, self.0, self.1, self.2)?).build()
+    }
+}
+
+/// BIP84 template. Expands to `wpkh(key/84'/0'/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::database::MemoryDatabase;
+/// # use bdk::wallet::AddressIndex::New;
+/// use bdk::template::Bip84;
+///
+/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
+/// let wallet = Wallet::new_offline(
+///     Bip84(key.clone(), KeychainKind::External),
+///     Some(Bip84(key, KeychainKind::Internal)),
+///     Network::Testnet,
+///     MemoryDatabase::default()
+/// )?;
+///
+/// assert_eq!(wallet.get_address(New)?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
+/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#nkk5dtkg");
+/// # 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) -> Result<DescriptorTemplateOut, DescriptorError> {
+        P2Wpkh(segwit_v0::make_bipxx_private(84, self.0, self.1)?).build()
+    }
+}
+
+/// BIP84 public template. Expands to `wpkh(key/{0,1}/*)`
+///
+/// This assumes that the key used has already been derived with `m/84'/0'/0'`.
+///
+/// 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::database::MemoryDatabase;
+/// # use bdk::wallet::AddressIndex::New;
+/// use bdk::template::Bip84Public;
+///
+/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
+/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
+/// let wallet = Wallet::new_offline(
+///     Bip84Public(key.clone(), fingerprint, KeychainKind::External),
+///     Some(Bip84Public(key, fingerprint, KeychainKind::Internal)),
+///     Network::Testnet,
+///     MemoryDatabase::default()
+/// )?;
+///
+/// assert_eq!(wallet.get_address(New)?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
+/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#nkk5dtkg");
+/// # 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) -> Result<DescriptorTemplateOut, DescriptorError> {
+        P2Wpkh(segwit_v0::make_bipxx_public(84, self.0, self.1, self.2)?).build()
+    }
+}
+
+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,
+            ) -> Result<impl IntoDescriptorKey<$ctx>, DescriptorError> {
+                let mut derivation_path = Vec::with_capacity(4);
+                derivation_path.push(bip32::ChildNumber::from_hardened_idx(bip)?);
+                derivation_path.push(bip32::ChildNumber::from_hardened_idx(0)?);
+                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,
+            ) -> 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)?,
+                    bip32::ChildNumber::from_hardened_idx(0)?,
+                    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);
+
+#[cfg(test)]
+mod test {
+    // test existing descriptor templates, make sure they are expanded to the right descriptors
+
+    use std::str::FromStr;
+
+    use super::*;
+    use crate::descriptor::derived::AsDerived;
+    use crate::descriptor::{DescriptorError, DescriptorMeta};
+    use crate::keys::ValidNetworks;
+    use bitcoin::network::constants::Network::Regtest;
+    use bitcoin::secp256k1::Secp256k1;
+    use miniscript::descriptor::{DescriptorPublicKey, DescriptorTrait, KeyMap};
+    use miniscript::Descriptor;
+
+    // verify template descriptor generates expected address(es)
+    fn check(
+        desc: Result<(Descriptor<DescriptorPublicKey>, KeyMap, ValidNetworks), DescriptorError>,
+        is_witness: bool,
+        is_fixed: bool,
+        expected: &[&str],
+    ) {
+        let secp = Secp256k1::new();
+
+        let (desc, _key_map, _networks) = desc.unwrap();
+        assert_eq!(desc.is_witness(), is_witness);
+        assert_eq!(!desc.is_deriveable(), is_fixed);
+        for i in 0..expected.len() {
+            let index = i as u32;
+            let child_desc = if !desc.is_deriveable() {
+                desc.as_derived_fixed(&secp)
+            } else {
+                desc.as_derived(index, &secp)
+            };
+            let address = child_desc.address(Regtest).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(),
+            false,
+            true,
+            &["mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"],
+        );
+
+        let pubkey = bitcoin::PublicKey::from_str(
+            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
+        )
+        .unwrap();
+        check(
+            P2Pkh(pubkey).build(),
+            false,
+            true,
+            &["muZpTpBYhxmRFuCjLc7C6BBDF32C8XVJUi"],
+        );
+    }
+
+    // P2WPKH-P2SH `sh(wpkh(key))`
+    #[test]
+    fn test_p2wphp2sh_template() {
+        let prvkey =
+            bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
+                .unwrap();
+        check(
+            P2Wpkh_P2Sh(prvkey).build(),
+            true,
+            true,
+            &["2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"],
+        );
+
+        let pubkey = bitcoin::PublicKey::from_str(
+            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
+        )
+        .unwrap();
+        check(
+            P2Wpkh_P2Sh(pubkey).build(),
+            true,
+            true,
+            &["2N5LiC3CqzxDamRTPG1kiNv1FpNJQ7x28sb"],
+        );
+    }
+
+    // P2WPKH `wpkh(key)`
+    #[test]
+    fn test_p2wph_template() {
+        let prvkey =
+            bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
+                .unwrap();
+        check(
+            P2Wpkh(prvkey).build(),
+            true,
+            true,
+            &["bcrt1q4525hmgw265tl3drrl8jjta7ayffu6jfcwxx9y"],
+        );
+
+        let pubkey = bitcoin::PublicKey::from_str(
+            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
+        )
+        .unwrap();
+        check(
+            P2Wpkh(pubkey).build(),
+            true,
+            true,
+            &["bcrt1qngw83fg8dz0k749cg7k3emc7v98wy0c7azaa6h"],
+        );
+    }
+
+    // BIP44 `pkh(key/44'/0'/0'/{0,1}/*)`
+    #[test]
+    fn test_bip44_template() {
+        let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        check(
+            Bip44(prvkey, KeychainKind::External).build(),
+            false,
+            false,
+            &[
+                "n453VtnjDHPyDt2fDstKSu7A3YCJoHZ5g5",
+                "mvfrrumXgTtwFPWDNUecBBgzuMXhYM7KRP",
+                "mzYvhRAuQqbdSKMVVzXNYyqihgNdRadAUQ",
+            ],
+        );
+        check(
+            Bip44(prvkey, KeychainKind::Internal).build(),
+            false,
+            false,
+            &[
+                "muHF98X9KxEzdKrnFAX85KeHv96eXopaip",
+                "n4hpyLJE5ub6B5Bymv4eqFxS5KjrewSmYR",
+                "mgvkdv1ffmsXd2B1sRKQ5dByK3SzpG42rA",
+            ],
+        );
+    }
+
+    // BIP44 public `pkh(key/{0,1}/*)`
+    #[test]
+    fn test_bip44_public_template() {
+        let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU").unwrap();
+        let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
+        check(
+            Bip44Public(pubkey, fingerprint, KeychainKind::External).build(),
+            false,
+            false,
+            &[
+                "miNG7dJTzJqNbFS19svRdTCisC65dsubtR",
+                "n2UqaDbCjWSFJvpC84m3FjUk5UaeibCzYg",
+                "muCPpS6Ue7nkzeJMWDViw7Lkwr92Yc4K8g",
+            ],
+        );
+        check(
+            Bip44Public(pubkey, fingerprint, KeychainKind::Internal).build(),
+            false,
+            false,
+            &[
+                "moDr3vJ8wpt5nNxSK55MPq797nXJb2Ru9H",
+                "ms7A1Yt4uTezT2XkefW12AvLoko8WfNJMG",
+                "mhYiyat2rtEnV77cFfQsW32y1m2ceCGHPo",
+            ],
+        );
+    }
+
+    // BIP49 `sh(wpkh(key/49'/0'/0'/{0,1}/*))`
+    #[test]
+    fn test_bip49_template() {
+        let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        check(
+            Bip49(prvkey, KeychainKind::External).build(),
+            true,
+            false,
+            &[
+                "2N9bCAJXGm168MjVwpkBdNt6ucka3PKVoUV",
+                "2NDckYkqrYyDMtttEav5hB3Bfw9EGAW5HtS",
+                "2NAFTVtksF9T4a97M7nyCjwUBD24QevZ5Z4",
+            ],
+        );
+        check(
+            Bip49(prvkey, KeychainKind::Internal).build(),
+            true,
+            false,
+            &[
+                "2NB3pA8PnzJLGV8YEKNDFpbViZv3Bm1K6CG",
+                "2NBiX2Wzxngb5rPiWpUiJQ2uLVB4HBjFD4p",
+                "2NA8ek4CdQ6aMkveYF6AYuEYNrftB47QGTn",
+            ],
+        );
+    }
+
+    // BIP49 public `sh(wpkh(key/{0,1}/*))`
+    #[test]
+    fn test_bip49_public_template() {
+        let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L").unwrap();
+        let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
+        check(
+            Bip49Public(pubkey, fingerprint, KeychainKind::External).build(),
+            true,
+            false,
+            &[
+                "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt",
+                "2NCTQfJ1sZa3wQ3pPseYRHbaNEpC3AquEfX",
+                "2MveFxAuC8BYPzTybx7FxSzW8HSd8ATT4z7",
+            ],
+        );
+        check(
+            Bip49Public(pubkey, fingerprint, KeychainKind::Internal).build(),
+            true,
+            false,
+            &[
+                "2NF2vttKibwyxigxtx95Zw8K7JhDbo5zPVJ",
+                "2Mtmyd8taksxNVWCJ4wVvaiss7QPZGcAJuH",
+                "2NBs3CTVYPr1HCzjB4YFsnWCPCtNg8uMEfp",
+            ],
+        );
+    }
+
+    // BIP84 `wpkh(key/84'/0'/0'/{0,1}/*)`
+    #[test]
+    fn test_bip84_template() {
+        let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
+        check(
+            Bip84(prvkey, KeychainKind::External).build(),
+            true,
+            false,
+            &[
+                "bcrt1qkmvk2nadgplmd57ztld8nf8v2yxkzmdvwtjf8s",
+                "bcrt1qx0v6zgfwe50m4kqc58cqzcyem7ay2sfl3gvqhp",
+                "bcrt1q4h7fq9zhxst6e69p3n882nfj649l7w9g3zccfp",
+            ],
+        );
+        check(
+            Bip84(prvkey, KeychainKind::Internal).build(),
+            true,
+            false,
+            &[
+                "bcrt1qtrwtz00wxl69e5xex7amy4xzlxkaefg3gfdkxa",
+                "bcrt1qqqasfhxpkkf7zrxqnkr2sfhn74dgsrc3e3ky45",
+                "bcrt1qpks7n0gq74hsgsz3phn5vuazjjq0f5eqhsgyce",
+            ],
+        );
+    }
+
+    // BIP84 public `wpkh(key/{0,1}/*)`
+    #[test]
+    fn test_bip84_public_template() {
+        let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q").unwrap();
+        let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
+        check(
+            Bip84Public(pubkey, fingerprint, KeychainKind::External).build(),
+            true,
+            false,
+            &[
+                "bcrt1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2prcdvd0h",
+                "bcrt1q3lncdlwq3lgcaaeyruynjnlccr0ve0kakh6ana",
+                "bcrt1qt9800y6xl3922jy3uyl0z33jh5wfpycyhcylr9",
+            ],
+        );
+        check(
+            Bip84Public(pubkey, fingerprint, KeychainKind::Internal).build(),
+            true,
+            false,
+            &[
+                "bcrt1qm6wqukenh7guu792lj2njgw9n78cmwsy8xy3z2",
+                "bcrt1q694twxtjn4nnrvnyvra769j0a23rllj5c6cgwp",
+                "bcrt1qhlac3c5ranv5w5emlnqs7wxhkxt8maelylcarp",
+            ],
+        );
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/error.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/error.rs.html new file mode 100644 index 0000000000..d6c5f36fbc --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/error.rs.html @@ -0,0 +1,460 @@ +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
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+use std::fmt;
+
+use crate::bitcoin::Network;
+use crate::{descriptor, wallet, wallet::address_validator};
+use bitcoin::OutPoint;
+
+/// Errors that can be thrown by the [`Wallet`](crate::wallet::Wallet)
+#[derive(Debug)]
+pub enum Error {
+    /// Wrong number of bytes found when trying to convert to u32
+    InvalidU32Bytes(Vec<u8>),
+    /// Generic error
+    Generic(String),
+    /// This error is thrown when trying to convert Bare and Public key script to address
+    ScriptDoesntHaveAddressForm,
+    /// Cannot build a tx without recipients
+    NoRecipients,
+    /// `manually_selected_only` option is selected but no utxo has been passed
+    NoUtxosSelected,
+    /// Output created is under the dust limit, 546 satoshis
+    OutputBelowDustLimit(usize),
+    /// 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 possible attempts with sufficiently big UTXO set could grow
+    /// exponentially, thus a limit is set, and when hit, this error is thrown
+    BnBTotalTriesExceeded,
+    /// 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,
+    /// Happens when trying to spend an UTXO that is not in the internal database
+    UnknownUtxo,
+    /// Thrown when a tx is not found in the internal database
+    TransactionNotFound,
+    /// Happens when trying to bump a transaction that is already confirmed
+    TransactionConfirmed,
+    /// Trying to replace a tx that has a sequence >= `0xFFFFFFFE`
+    IrreplaceableTransaction,
+    /// When bumping a tx the fee rate requested is lower than required
+    FeeRateTooLow {
+        /// Required fee rate (satoshi/vbyte)
+        required: crate::types::FeeRate,
+    },
+    /// When bumping a tx the absolute fee requested is lower than replaced tx absolute fee
+    FeeTooLow {
+        /// Required fee absolute value (satoshi)
+        required: u64,
+    },
+    /// Node doesn't have data to estimate a fee rate
+    FeeRateUnavailable,
+    /// 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),
+    /// Error while working with [`keys`](crate::keys)
+    Key(crate::keys::KeyError),
+    /// Descriptor checksum mismatch
+    ChecksumMismatch,
+    /// Spending policy is not compatible with this [`KeychainKind`](crate::types::KeychainKind)
+    SpendingPolicyRequired(crate::types::KeychainKind),
+    /// Error while extracting and manipulating policies
+    InvalidPolicyPathError(crate::descriptor::policy::PolicyError),
+    /// Signing error
+    Signer(crate::wallet::signer::SignerError),
+    /// Invalid network
+    InvalidNetwork {
+        /// requested network, for example what is given as bdk-cli option
+        requested: Network,
+        /// found network, for example the network of the bitcoin node
+        found: Network,
+    },
+    #[cfg(feature = "verify")]
+    /// Transaction verification error
+    Verification(crate::wallet::verify::VerifyError),
+
+    /// Progress value must be between `0.0` (included) and `100.0` (included)
+    InvalidProgressValue(f32),
+    /// Progress update error (maybe the channel has been closed)
+    ProgressUpdateError,
+    /// Requested outpoint doesn't exist in the tx (vout greater than available outputs)
+    InvalidOutpoint(OutPoint),
+
+    /// Error related to the parsing and usage of descriptors
+    Descriptor(crate::descriptor::error::Error),
+    /// Error that can be returned to fail the validation of an address
+    AddressValidator(crate::wallet::address_validator::AddressValidatorError),
+    /// Encoding error
+    Encode(bitcoin::consensus::encode::Error),
+    /// Miniscript error
+    Miniscript(miniscript::Error),
+    /// BIP32 error
+    Bip32(bitcoin::util::bip32::Error),
+    /// An ECDSA error
+    Secp256k1(bitcoin::secp256k1::Error),
+    /// Error serializing or deserializing JSON data
+    Json(serde_json::Error),
+    /// Hex decoding error
+    Hex(bitcoin::hashes::hex::Error),
+    /// Partially signed bitcoin transaction error
+    Psbt(bitcoin::util::psbt::Error),
+    /// Partially signed bitcoin transaction parseerror
+    PsbtParse(bitcoin::util::psbt::PsbtParseError),
+
+    //KeyMismatch(bitcoin::secp256k1::PublicKey, bitcoin::secp256k1::PublicKey),
+    //MissingInputUTXO(usize),
+    //InvalidAddressNetwork(Address),
+    //DifferentTransactions,
+    //DifferentDescriptorStructure,
+    //Uncapable(crate::blockchain::Capability),
+    //MissingCachedAddresses,
+    #[cfg(feature = "electrum")]
+    /// Electrum client error
+    Electrum(electrum_client::Error),
+    #[cfg(feature = "esplora")]
+    /// Esplora client error
+    Esplora(Box<crate::blockchain::esplora::EsploraError>),
+    #[cfg(feature = "compact_filters")]
+    /// Compact filters client error)
+    CompactFilters(crate::blockchain::compact_filters::CompactFiltersError),
+    #[cfg(feature = "key-value-db")]
+    /// Sled database error
+    Sled(sled::Error),
+    #[cfg(feature = "rpc")]
+    /// Rpc client error
+    Rpc(core_rpc::Error),
+    #[cfg(feature = "sqlite")]
+    /// Rusqlite client error
+    Rusqlite(rusqlite::Error),
+}
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for Error {}
+
+macro_rules! impl_error {
+    ( $from:ty, $to:ident ) => {
+        impl_error!($from, $to, Error);
+    };
+    ( $from:ty, $to:ident, $impl_for:ty ) => {
+        impl std::convert::From<$from> for $impl_for {
+            fn from(err: $from) -> Self {
+                <$impl_for>::$to(err)
+            }
+        }
+    };
+}
+
+impl_error!(descriptor::error::Error, Descriptor);
+impl_error!(address_validator::AddressValidatorError, AddressValidator);
+impl_error!(descriptor::policy::PolicyError, InvalidPolicyPathError);
+impl_error!(wallet::signer::SignerError, Signer);
+
+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),
+            crate::keys::KeyError::InvalidChecksum => Error::ChecksumMismatch,
+            e => Error::Key(e),
+        }
+    }
+}
+
+impl_error!(bitcoin::consensus::encode::Error, Encode);
+impl_error!(miniscript::Error, Miniscript);
+impl_error!(bitcoin::util::bip32::Error, Bip32);
+impl_error!(bitcoin::secp256k1::Error, Secp256k1);
+impl_error!(serde_json::Error, Json);
+impl_error!(bitcoin::hashes::hex::Error, Hex);
+impl_error!(bitcoin::util::psbt::Error, Psbt);
+impl_error!(bitcoin::util::psbt::PsbtParseError, PsbtParse);
+
+#[cfg(feature = "electrum")]
+impl_error!(electrum_client::Error, Electrum);
+#[cfg(feature = "key-value-db")]
+impl_error!(sled::Error, Sled);
+#[cfg(feature = "rpc")]
+impl_error!(core_rpc::Error, Rpc);
+#[cfg(feature = "sqlite")]
+impl_error!(rusqlite::Error, Rusqlite);
+
+#[cfg(feature = "compact_filters")]
+impl From<crate::blockchain::compact_filters::CompactFiltersError> for Error {
+    fn from(other: crate::blockchain::compact_filters::CompactFiltersError) -> Self {
+        match other {
+            crate::blockchain::compact_filters::CompactFiltersError::Global(e) => *e,
+            err => Error::CompactFilters(err),
+        }
+    }
+}
+
+#[cfg(feature = "verify")]
+impl From<crate::wallet::verify::VerifyError> for Error {
+    fn from(other: crate::wallet::verify::VerifyError) -> Self {
+        match other {
+            crate::wallet::verify::VerifyError::Global(inner) => *inner,
+            err => Error::Verification(err),
+        }
+    }
+}
+
+#[cfg(feature = "esplora")]
+impl From<crate::blockchain::esplora::EsploraError> for Error {
+    fn from(other: crate::blockchain::esplora::EsploraError) -> Self {
+        Error::Esplora(Box::new(other))
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/keys/bip39.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/keys/bip39.rs.html new file mode 100644 index 0000000000..3cf8935dbd --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/keys/bip39.rs.html @@ -0,0 +1,384 @@ +bip39.rs - source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+//! BIP-0039
+
+// TODO: maybe write our own implementation of bip39? Seems stupid to have an extra dependency for
+// something that should be fairly simple to re-implement.
+
+use bitcoin::util::bip32;
+use bitcoin::Network;
+
+use miniscript::ScriptContext;
+
+pub use bip39::{Language, Mnemonic, MnemonicType, Seed};
+
+use super::{
+    any_network, DerivableKey, DescriptorKey, ExtendedKey, GeneratableKey, GeneratedKey, KeyError,
+};
+
+fn set_valid_on_any_network<Ctx: ScriptContext>(
+    descriptor_key: DescriptorKey<Ctx>,
+) -> DescriptorKey<Ctx> {
+    // We have to pick one network to build the xprv, but since the bip39 standard doesn't
+    // encode the network, the xprv we create is actually valid everywhere. So we override the
+    // valid networks with `any_network()`.
+    descriptor_key.override_valid_networks(any_network())
+}
+
+/// Type for a BIP39 mnemonic with an optional passphrase
+pub type MnemonicWithPassphrase = (Mnemonic, Option<String>);
+
+#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed {
+    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+        Ok(bip32::ExtendedPrivKey::new_master(Network::Bitcoin, &self.as_bytes())?.into())
+    }
+
+    fn into_descriptor_key(
+        self,
+        source: Option<bip32::KeySource>,
+        derivation_path: bip32::DerivationPath,
+    ) -> Result<DescriptorKey<Ctx>, KeyError> {
+        let descriptor_key = self
+            .into_extended_key()?
+            .into_descriptor_key(source, derivation_path)?;
+
+        Ok(set_valid_on_any_network(descriptor_key))
+    }
+}
+
+#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for MnemonicWithPassphrase {
+    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+        let (mnemonic, passphrase) = self;
+        let seed = Seed::new(&mnemonic, passphrase.as_deref().unwrap_or(""));
+
+        seed.into_extended_key()
+    }
+
+    fn into_descriptor_key(
+        self,
+        source: Option<bip32::KeySource>,
+        derivation_path: bip32::DerivationPath,
+    ) -> Result<DescriptorKey<Ctx>, KeyError> {
+        let descriptor_key = self
+            .into_extended_key()?
+            .into_descriptor_key(source, derivation_path)?;
+
+        Ok(set_valid_on_any_network(descriptor_key))
+    }
+}
+
+#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for Mnemonic {
+    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+        (self, None).into_extended_key()
+    }
+
+    fn into_descriptor_key(
+        self,
+        source: Option<bip32::KeySource>,
+        derivation_path: bip32::DerivationPath,
+    ) -> Result<DescriptorKey<Ctx>, KeyError> {
+        let descriptor_key = self
+            .into_extended_key()?
+            .into_descriptor_key(source, derivation_path)?;
+
+        Ok(set_valid_on_any_network(descriptor_key))
+    }
+}
+
+#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
+impl<Ctx: ScriptContext> GeneratableKey<Ctx> for Mnemonic {
+    type Entropy = [u8; 32];
+
+    type Options = (MnemonicType, Language);
+    type Error = Option<bip39::ErrorKind>;
+
+    fn generate_with_entropy(
+        (mnemonic_type, language): Self::Options,
+        entropy: Self::Entropy,
+    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
+        let entropy = &entropy.as_ref()[..(mnemonic_type.entropy_bits() / 8)];
+        let mnemonic = Mnemonic::from_entropy(entropy, language).map_err(|e| e.downcast().ok())?;
+
+        Ok(GeneratedKey::new(mnemonic, any_network()))
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::str::FromStr;
+
+    use bitcoin::util::bip32;
+
+    use bip39::{Language, Mnemonic, MnemonicType};
+
+    use crate::keys::{any_network, GeneratableKey, GeneratedKey};
+
+    #[test]
+    fn test_keys_bip39_mnemonic() {
+        let mnemonic =
+            "aim bunker wash balance finish force paper analyst cabin spoon stable organ";
+        let mnemonic = Mnemonic::from_phrase(mnemonic, Language::English).unwrap();
+        let path = bip32::DerivationPath::from_str("m/44'/0'/0'/0").unwrap();
+
+        let key = (mnemonic, path);
+        let (desc, keys, networks) = crate::descriptor!(wpkh(key)).unwrap();
+        assert_eq!(desc.to_string(), "wpkh([be83839f/44'/0'/0']xpub6DCQ1YcqvZtSwGWMrwHELPehjWV3f2MGZ69yBADTxFEUAoLwb5Mp5GniQK6tTp3AgbngVz9zEFbBJUPVnkG7LFYt8QMTfbrNqs6FNEwAPKA/0/*)#0r8v4nkv");
+        assert_eq!(keys.len(), 1);
+        assert_eq!(networks.len(), 4);
+    }
+
+    #[test]
+    fn test_keys_bip39_mnemonic_passphrase() {
+        let mnemonic =
+            "aim bunker wash balance finish force paper analyst cabin spoon stable organ";
+        let mnemonic = Mnemonic::from_phrase(mnemonic, Language::English).unwrap();
+        let path = bip32::DerivationPath::from_str("m/44'/0'/0'/0").unwrap();
+
+        let key = ((mnemonic, Some("passphrase".into())), path);
+        let (desc, keys, networks) = crate::descriptor!(wpkh(key)).unwrap();
+        assert_eq!(desc.to_string(), "wpkh([8f6cb80c/44'/0'/0']xpub6DWYS8bbihFevy29M4cbw4ZR3P5E12jB8R88gBDWCTCNpYiDHhYWNywrCF9VZQYagzPmsZpxXpytzSoxynyeFr4ZyzheVjnpLKuse4fiwZw/0/*)#h0j0tg5m");
+        assert_eq!(keys.len(), 1);
+        assert_eq!(networks.len(), 4);
+    }
+
+    #[test]
+    fn test_keys_generate_bip39() {
+        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
+            Mnemonic::generate_with_entropy(
+                (MnemonicType::Words12, Language::English),
+                crate::keys::test::TEST_ENTROPY,
+            )
+            .unwrap();
+        assert_eq!(generated_mnemonic.valid_networks, any_network());
+        assert_eq!(
+            generated_mnemonic.to_string(),
+            "primary fetch primary fetch primary fetch primary fetch primary fetch primary fever"
+        );
+
+        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
+            Mnemonic::generate_with_entropy(
+                (MnemonicType::Words24, Language::English),
+                crate::keys::test::TEST_ENTROPY,
+            )
+            .unwrap();
+        assert_eq!(generated_mnemonic.valid_networks, any_network());
+        assert_eq!(generated_mnemonic.to_string(), "primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary foster");
+    }
+
+    #[test]
+    fn test_keys_generate_bip39_random() {
+        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
+            Mnemonic::generate((MnemonicType::Words12, Language::English)).unwrap();
+        assert_eq!(generated_mnemonic.valid_networks, any_network());
+
+        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
+            Mnemonic::generate((MnemonicType::Words24, Language::English)).unwrap();
+        assert_eq!(generated_mnemonic.valid_networks, any_network());
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/keys/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/keys/mod.rs.html new file mode 100644 index 0000000000..7dc8e48126 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/keys/mod.rs.html @@ -0,0 +1,1872 @@ +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
+
// 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 std::any::TypeId;
+use std::collections::HashSet;
+use std::marker::PhantomData;
+use std::ops::Deref;
+use std::str::FromStr;
+
+use bitcoin::secp256k1::{self, Secp256k1, Signing};
+
+use bitcoin::util::bip32;
+use bitcoin::{Network, PrivateKey, PublicKey};
+
+use miniscript::descriptor::{Descriptor, DescriptorXKey, Wildcard};
+pub use miniscript::descriptor::{
+    DescriptorPublicKey, DescriptorSecretKey, DescriptorSinglePriv, DescriptorSinglePub, KeyMap,
+    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 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::with_capacity(1);
+
+                let public = secret
+                    .as_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,
+}
+
+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
+    }
+}
+
+/// 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()
+    }
+}
+
+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,
+            _ => 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, DescriptorSinglePub,
+///     IntoDescriptorKey, KeyError, ScriptContext,
+/// };
+///
+/// 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::SinglePub(DescriptorSinglePub {
+///                 origin: None,
+///                 key: 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 std::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 [`ExtendedPrivKey`](bip32::ExtendedPrivKey)
+/// or an [`ExtendedPubKey`](bip32::ExtendedPubKey) 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::ExtendedPrivKey, PhantomData<Ctx>)),
+    /// A public extended key, aka an `xpub`
+    Public((bip32::ExtendedPubKey, 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 [`ExtendedPrivKey`](bip32::ExtendedPrivKey) for the
+    /// given [`Network`], if the key contains the private data
+    pub fn into_xprv(self, network: Network) -> Option<bip32::ExtendedPrivKey> {
+        match self {
+            ExtendedKey::Private((mut xprv, _)) => {
+                xprv.network = network;
+                Some(xprv)
+            }
+            ExtendedKey::Public(_) => None,
+        }
+    }
+
+    /// Transform the [`ExtendedKey`] into an [`ExtendedPubKey`](bip32::ExtendedPubKey) for the
+    /// given [`Network`]
+    pub fn into_xpub<C: Signing>(
+        self,
+        network: bitcoin::Network,
+        secp: &Secp256k1<C>,
+    ) -> bip32::ExtendedPubKey {
+        let mut xpub = match self {
+            ExtendedKey::Private((xprv, _)) => bip32::ExtendedPubKey::from_private(secp, &xprv),
+            ExtendedKey::Public((xpub, _)) => xpub,
+        };
+
+        xpub.network = network;
+        xpub
+    }
+}
+
+impl<Ctx: ScriptContext> From<bip32::ExtendedPubKey> for ExtendedKey<Ctx> {
+    fn from(xpub: bip32::ExtendedPubKey) -> Self {
+        ExtendedKey::Public((xpub, PhantomData))
+    }
+}
+
+impl<Ctx: ScriptContext> From<bip32::ExtendedPrivKey> for ExtendedKey<Ctx> {
+    fn from(xprv: bip32::ExtendedPrivKey) -> Self {
+        ExtendedKey::Private((xprv, PhantomData))
+    }
+}
+
+/// Trait for keys that can be derived.
+///
+/// When extra metadata are provided, a [`DerivableKey`] can be transofrmed 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 implemented 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 [`ExtendedPrivKey`] or
+/// an [`ExtendedPubKey`] can implement only the required `into_extended_key()` method.
+///
+/// ```
+/// use bdk::bitcoin;
+/// use bdk::bitcoin::util::bip32;
+/// use bdk::keys::{DerivableKey, ExtendedKey, KeyError, ScriptContext};
+///
+/// struct MyCustomKeyType {
+///     key_data: bitcoin::PrivateKey,
+///     chain_code: Vec<u8>,
+///     network: bitcoin::Network,
+/// }
+///
+/// impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
+///     fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+///         let xprv = bip32::ExtendedPrivKey {
+///             network: self.network,
+///             depth: 0,
+///             parent_fingerprint: bip32::Fingerprint::default(),
+///             private_key: self.key_data,
+///             chain_code: bip32::ChainCode::from(self.chain_code.as_ref()),
+///             child_number: bip32::ChildNumber::Normal { index: 0 },
+///         };
+///
+///         xprv.into_extended_key()
+///     }
+/// }
+/// ```
+///
+/// Types that don't internally encode the [`Network`](bitcoin::Network) in which they are valid need some extra
+/// steps to override the set of valid networks, otherwise only the network specified in the
+/// [`ExtendedPrivKey`] or [`ExtendedPubKey`] will be considered valid.
+///
+/// ```
+/// use bdk::bitcoin;
+/// use bdk::bitcoin::util::bip32;
+/// use bdk::keys::{
+///     any_network, DerivableKey, DescriptorKey, ExtendedKey, KeyError, ScriptContext,
+/// };
+///
+/// struct MyCustomKeyType {
+///     key_data: bitcoin::PrivateKey,
+///     chain_code: Vec<u8>,
+/// }
+///
+/// impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
+///     fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+///         let xprv = bip32::ExtendedPrivKey {
+///             network: bitcoin::Network::Bitcoin, // pick an arbitrary network here
+///             depth: 0,
+///             parent_fingerprint: bip32::Fingerprint::default(),
+///             private_key: self.key_data,
+///             chain_code: bip32::ChainCode::from(self.chain_code.as_ref()),
+///             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)
+/// [`ExtendedPrivKey`]: (bip32::ExtendedPrivKey)
+/// [`ExtendedPubKey`]: (bip32::ExtendedPubKey)
+pub trait DerivableKey<Ctx: ScriptContext = miniscript::Legacy>: Sized {
+    /// Consume `self` and turn it into an [`ExtendedKey`]
+    ///
+    /// This can be used to get direct access to `xprv`s and `xpub`s for types that implement this trait,
+    /// like [`Mnemonic`](bip39::Mnemonic) when the `keys-bip39` feature is enabled.
+    #[cfg_attr(
+        feature = "keys-bip39",
+        doc = r##"
+```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::from_phrase(
+        "jelly crash boy whisper mouse ecology tuna soccer memory million news short",
+        Language::English
+    )?
+    .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::ExtendedPubKey {
+    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
+        Ok(self.into())
+    }
+}
+
+impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPrivKey {
+    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
+    }
+}
+
+// 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: std::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::ExtendedPrivKey {
+    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::ExtendedPrivKey::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 key = secp256k1::SecretKey::from_slice(&entropy)?;
+        let private_key = PrivateKey {
+            compressed: options.compressed,
+            network: Network::Bitcoin,
+            key,
+        };
+
+        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.into_iter());
+            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_minsicript()?;
+
+    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_minsicript()?;
+
+    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>(
+    thresh: usize,
+    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(Terminal::Multi(thresh, pks))?;
+
+    minisc.check_minsicript()?;
+
+    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::SinglePub(_) => 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::SinglePub(DescriptorSinglePub {
+            key: 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::SinglePriv(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::SinglePriv(DescriptorSinglePriv {
+            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::util::bip32::Error),
+    /// Miniscript error
+    Miniscript(miniscript::Error),
+}
+
+impl_error!(miniscript::Error, Miniscript, KeyError);
+impl_error!(bitcoin::util::bip32::Error, Bip32, KeyError);
+
+impl std::fmt::Display for KeyError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for KeyError {}
+
+#[cfg(test)]
+pub mod test {
+    use bitcoin::util::bip32;
+
+    use super::*;
+
+    pub const TEST_ENTROPY: [u8; 32] = [0xAA; 32];
+
+    #[test]
+    fn test_keys_generate_xprv() {
+        let generated_xprv: GeneratedKey<_, miniscript::Segwitv0> =
+            bip32::ExtendedPrivKey::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"
+        );
+    }
+}
+
+
+ + \ 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 new file mode 100644 index 0000000000..5b66f7a5df --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/lib.rs.html @@ -0,0 +1,570 @@ +lib.rs - source
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+269
+270
+271
+272
+273
+274
+275
+276
+277
+278
+279
+280
+281
+282
+283
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+// rustdoc will warn if there are missing docs
+#![warn(missing_docs)]
+// only enables the `doc_cfg` feature when
+// the `docsrs` configuration attribute is defined
+#![cfg_attr(docsrs, feature(doc_cfg))]
+
+//! A modern, lightweight, descriptor-based wallet library written in Rust.
+//!
+//! # About
+//!
+//! The BDK library aims to be the core building block for Bitcoin wallets of any kind.
+//!
+//! * It uses [Miniscript](https://github.com/rust-bitcoin/rust-miniscript) to support descriptors with generalized conditions. This exact same library can be used to build
+//!   single-sig wallets, multisigs, timelocked contracts and more.
+//! * It supports multiple blockchain backends and databases, allowing developers to choose exactly what's right for their projects.
+//! * It is built to be cross-platform: the core logic works on desktop, mobile, and even WebAssembly.
+//! * It is very easy to extend: developers can implement customized logic for blockchain backends, databases, signers, coin selection, and more, without having to fork and modify this library.
+//!
+//! # A Tour of BDK
+//!
+//! BDK consists of a number of modules that provide a range of functionality
+//! essential for implementing descriptor based Bitcoin wallet applications in Rust. In this
+//! section, we will take a brief tour of BDK, summarizing the major APIs and
+//! their uses.
+//!
+//! The easiest way to get started is to add bdk to your dependencies with the default features.
+//! The default features include a simple key-value database ([`sled`](sled)) to cache
+//! blockchain data and an [electrum](https://docs.rs/electrum-client/) blockchain client to
+//! interact with the bitcoin P2P network.
+//!
+//! ```toml
+//! bdk = "0.11.0"
+//! ```
+#![cfg_attr(
+    feature = "electrum",
+    doc = r##"
+## Sync the balance of a descriptor
+
+### Example
+```no_run
+use bdk::Wallet;
+use bdk::database::MemoryDatabase;
+use bdk::blockchain::{noop_progress, ElectrumBlockchain};
+use bdk::electrum_client::Client;
+
+fn main() -> Result<(), bdk::Error> {
+    let client = Client::new("ssl://electrum.blockstream.info:60002")?;
+    let wallet = Wallet::new(
+        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
+        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
+        bitcoin::Network::Testnet,
+        MemoryDatabase::default(),
+        ElectrumBlockchain::from(client)
+    )?;
+
+    wallet.sync(noop_progress(), None)?;
+
+    println!("Descriptor balance: {} SAT", wallet.get_balance()?);
+
+    Ok(())
+}
+```
+"##
+)]
+//!
+//! ## Generate a few addresses
+//!
+//! ### Example
+//! ```
+//! use bdk::{Wallet};
+//! use bdk::database::MemoryDatabase;
+//! use bdk::wallet::AddressIndex::New;
+//!
+//! fn main() -> Result<(), bdk::Error> {
+//! let wallet = Wallet::new_offline(
+//!         "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
+//!         Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
+//!         bitcoin::Network::Testnet,
+//!         MemoryDatabase::default(),
+//!     )?;
+//!
+//!     println!("Address #0: {}", wallet.get_address(New)?);
+//!     println!("Address #1: {}", wallet.get_address(New)?);
+//!     println!("Address #2: {}", wallet.get_address(New)?);
+//!
+//!     Ok(())
+//! }
+//! ```
+#![cfg_attr(
+    feature = "electrum",
+    doc = r##"
+## Create a transaction
+
+### Example
+```no_run
+use bdk::{FeeRate, Wallet};
+use bdk::database::MemoryDatabase;
+use bdk::blockchain::{noop_progress, ElectrumBlockchain};
+use bdk::electrum_client::Client;
+
+use bitcoin::consensus::serialize;
+use bdk::wallet::AddressIndex::New;
+
+fn main() -> Result<(), bdk::Error> {
+    let client = Client::new("ssl://electrum.blockstream.info:60002")?;
+    let wallet = Wallet::new(
+        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
+        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
+        bitcoin::Network::Testnet,
+        MemoryDatabase::default(),
+        ElectrumBlockchain::from(client)
+    )?;
+
+    wallet.sync(noop_progress(), None)?;
+
+    let send_to = wallet.get_address(New)?;
+    let (psbt, details) = {
+        let mut builder =  wallet.build_tx();
+        builder
+            .add_recipient(send_to.script_pubkey(), 50_000)
+            .enable_rbf()
+            .do_not_spend_change()
+            .fee_rate(FeeRate::from_sat_per_vb(5.0));
+        builder.finish()?
+    };
+
+    println!("Transaction details: {:#?}", details);
+    println!("Unsigned PSBT: {}", &psbt);
+
+    Ok(())
+}
+```
+"##
+)]
+//!
+//! ## Sign a transaction
+//!
+//! ### Example
+//! ```no_run
+//! use std::str::FromStr;
+//!
+//! use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
+//!
+//! use bdk::{Wallet, SignOptions};
+//! use bdk::database::MemoryDatabase;
+//!
+//! fn main() -> Result<(), bdk::Error> {
+//!     let wallet = Wallet::new_offline(
+//!         "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
+//!         Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
+//!         bitcoin::Network::Testnet,
+//!         MemoryDatabase::default(),
+//!     )?;
+//!
+//!     let psbt = "...";
+//!     let mut psbt = Psbt::from_str(psbt)?;
+//!
+//!     let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
+//!
+//!     Ok(())
+//! }
+//! ```
+//!
+//! # Feature flags
+//!
+//! BDK uses a set of [feature flags](https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section)
+//! to reduce the amount of compiled code by allowing projects to only enable the features they need.
+//! By default, BDK enables two internal features, `key-value-db` and `electrum`.
+//!
+//! If you are new to BDK we recommended that you use the default features which will enable
+//! basic descriptor wallet functionality. More advanced users can disable the `default` features
+//! (`--no-default-features`) and build the BDK library with only the features you need.
+
+//! Below is a list of the available feature flags and the additional functionality they provide.
+//!
+//! * `all-keys`: all features for working with bitcoin keys
+//! * `async-interface`: async functions in bdk traits
+//! * `keys-bip39`: [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) mnemonic codes for generating deterministic keys
+//!
+//! ## Internal features
+//!
+//! These features do not expose any new API, but influence internal implementation aspects of
+//! BDK.
+//!
+//! * `compact_filters`: [`compact_filters`](crate::blockchain::compact_filters) client protocol for interacting with the bitcoin P2P network
+//! * `electrum`: [`electrum`](crate::blockchain::electrum) client protocol for interacting with electrum servers
+//! * `esplora`: [`esplora`](crate::blockchain::esplora) client protocol for interacting with blockstream [electrs](https://github.com/Blockstream/electrs) servers
+//! * `key-value-db`: key value [`database`](crate::database) based on [`sled`](crate::sled) for caching blockchain data
+
+pub extern crate bitcoin;
+extern crate log;
+pub extern crate miniscript;
+extern crate serde;
+#[macro_use]
+extern crate serde_json;
+
+#[cfg(all(feature = "reqwest", feature = "ureq"))]
+compile_error!("Features reqwest and ureq are mutually exclusive and cannot be enabled together");
+
+#[cfg(all(feature = "async-interface", feature = "electrum"))]
+compile_error!(
+    "Features async-interface and electrum are mutually exclusive and cannot be enabled together"
+);
+
+#[cfg(all(feature = "async-interface", feature = "ureq"))]
+compile_error!(
+    "Features async-interface and ureq are mutually exclusive and cannot be enabled together"
+);
+
+#[cfg(all(feature = "async-interface", feature = "compact_filters"))]
+compile_error!(
+    "Features async-interface and compact_filters are mutually exclusive and cannot be enabled together"
+);
+
+#[cfg(feature = "keys-bip39")]
+extern crate bip39;
+
+#[cfg(any(target_arch = "wasm32", feature = "async-interface"))]
+#[macro_use]
+extern crate async_trait;
+#[macro_use]
+extern crate bdk_macros;
+
+#[cfg(feature = "compact_filters")]
+extern crate lazy_static;
+
+#[cfg(feature = "rpc")]
+pub extern crate core_rpc;
+
+#[cfg(feature = "electrum")]
+pub extern crate electrum_client;
+
+#[cfg(feature = "key-value-db")]
+pub extern crate sled;
+
+#[cfg(feature = "sqlite")]
+pub extern crate rusqlite;
+
+#[allow(unused_imports)]
+#[macro_use]
+pub(crate) mod error;
+pub mod blockchain;
+pub mod database;
+pub mod descriptor;
+#[cfg(feature = "test-md-docs")]
+mod doctest;
+pub mod keys;
+pub(crate) mod psbt;
+pub(crate) mod types;
+pub mod wallet;
+
+pub use descriptor::template;
+pub use descriptor::HdKeyPaths;
+pub use error::Error;
+pub use types::*;
+pub use wallet::address_validator;
+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")
+}
+
+// We should consider putting this under a feature flag but we need the macro in doctets so we need
+// to wait until https://github.com/rust-lang/rust/issues/67295 is fixed.
+//
+// Stuff in here is too rough to document atm
+#[doc(hidden)]
+pub mod testutils;
+
+
+ + \ 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 new file mode 100644 index 0000000000..ca046b7b88 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/psbt/mod.rs.html @@ -0,0 +1,248 @@ +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
+
// 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::util::psbt::PartiallySignedTransaction as Psbt;
+use bitcoin::TxOut;
+
+pub trait PsbtUtils {
+    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut>;
+}
+
+impl PsbtUtils for Psbt {
+    #[allow(clippy::all)] // We want to allow `manual_map` but it is too new.
+    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut> {
+        let tx = &self.global.unsigned_tx;
+
+        if input_index >= tx.input.len() {
+            return None;
+        }
+
+        if let Some(input) = self.inputs.get(input_index) {
+            if let Some(wit_utxo) = &input.witness_utxo {
+                Some(wit_utxo.clone())
+            } else if let Some(in_tx) = &input.non_witness_utxo {
+                Some(in_tx.output[tx.input[input_index].previous_output.vout as usize].clone())
+            } else {
+                None
+            }
+        } else {
+            None
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use crate::bitcoin::TxIn;
+    use crate::psbt::Psbt;
+    use crate::wallet::AddressIndex;
+    use crate::wallet::{get_funded_wallet, test::get_test_wpkh};
+    use crate::SignOptions;
+    use std::str::FromStr;
+
+    // from bip 174
+    const PSBT_STR: &str = "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEHakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpIAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIAAAA";
+
+    #[test]
+    #[should_panic(expected = "InputIndexOutOfRange")]
+    fn test_psbt_malformed_psbt_input_legacy() {
+        let psbt_bip = Psbt::from_str(PSBT_STR).unwrap();
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let send_to = wallet.get_address(AddressIndex::New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(send_to.script_pubkey(), 10_000);
+        let (mut psbt, _) = builder.finish().unwrap();
+        psbt.inputs.push(psbt_bip.inputs[0].clone());
+        let options = SignOptions {
+            trust_witness_utxo: true,
+            ..Default::default()
+        };
+        let _ = wallet.sign(&mut psbt, options).unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "InputIndexOutOfRange")]
+    fn test_psbt_malformed_psbt_input_segwit() {
+        let psbt_bip = Psbt::from_str(PSBT_STR).unwrap();
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let send_to = wallet.get_address(AddressIndex::New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(send_to.script_pubkey(), 10_000);
+        let (mut psbt, _) = builder.finish().unwrap();
+        psbt.inputs.push(psbt_bip.inputs[1].clone());
+        let options = SignOptions {
+            trust_witness_utxo: true,
+            ..Default::default()
+        };
+        let _ = wallet.sign(&mut psbt, options).unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "InputIndexOutOfRange")]
+    fn test_psbt_malformed_tx_input() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let send_to = wallet.get_address(AddressIndex::New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(send_to.script_pubkey(), 10_000);
+        let (mut psbt, _) = builder.finish().unwrap();
+        psbt.global.unsigned_tx.input.push(TxIn::default());
+        let options = SignOptions {
+            trust_witness_utxo: true,
+            ..Default::default()
+        };
+        let _ = wallet.sign(&mut psbt, options).unwrap();
+    }
+
+    #[test]
+    fn test_psbt_sign_with_finalized() {
+        let psbt_bip = Psbt::from_str(PSBT_STR).unwrap();
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let send_to = wallet.get_address(AddressIndex::New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(send_to.script_pubkey(), 10_000);
+        let (mut psbt, _) = builder.finish().unwrap();
+
+        // add a finalized input
+        psbt.inputs.push(psbt_bip.inputs[0].clone());
+        psbt.global
+            .unsigned_tx
+            .input
+            .push(psbt_bip.global.unsigned_tx.input[0].clone());
+
+        let _ = wallet.sign(&mut psbt, SignOptions::default()).unwrap();
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/testutils/mod.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/testutils/mod.rs.html new file mode 100644 index 0000000000..a673857c4e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/testutils/mod.rs.html @@ -0,0 +1,466 @@ +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
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+#![allow(missing_docs)]
+
+#[cfg(test)]
+#[cfg(feature = "test-blockchains")]
+pub mod blockchain_tests;
+
+use bitcoin::secp256k1::{Secp256k1, Verification};
+use bitcoin::{Address, PublicKey};
+
+use miniscript::descriptor::DescriptorPublicKey;
+use miniscript::{Descriptor, MiniscriptKey, TranslatePk};
+
+#[derive(Clone, Debug)]
+pub struct TestIncomingOutput {
+    pub value: u64,
+    pub to_address: String,
+}
+
+impl TestIncomingOutput {
+    pub fn new(value: u64, to_address: Address) -> Self {
+        Self {
+            value,
+            to_address: to_address.to_string(),
+        }
+    }
+}
+
+#[derive(Clone, Debug)]
+pub struct TestIncomingTx {
+    pub output: Vec<TestIncomingOutput>,
+    pub min_confirmations: Option<u64>,
+    pub locktime: Option<i64>,
+    pub replaceable: Option<bool>,
+}
+
+impl TestIncomingTx {
+    pub fn new(
+        output: Vec<TestIncomingOutput>,
+        min_confirmations: Option<u64>,
+        locktime: Option<i64>,
+        replaceable: Option<bool>,
+    ) -> Self {
+        Self {
+            output,
+            min_confirmations,
+            locktime,
+            replaceable,
+        }
+    }
+
+    pub fn add_output(&mut self, output: TestIncomingOutput) {
+        self.output.push(output);
+    }
+}
+
+#[doc(hidden)]
+pub trait TranslateDescriptor {
+    // derive and translate a `Descriptor<DescriptorPublicKey>` into a `Descriptor<PublicKey>`
+    fn derive_translated<C: Verification>(
+        &self,
+        secp: &Secp256k1<C>,
+        index: u32,
+    ) -> Descriptor<PublicKey>;
+}
+
+impl TranslateDescriptor for Descriptor<DescriptorPublicKey> {
+    fn derive_translated<C: Verification>(
+        &self,
+        secp: &Secp256k1<C>,
+        index: u32,
+    ) -> Descriptor<PublicKey> {
+        let translate = |key: &DescriptorPublicKey| -> PublicKey {
+            match key {
+                DescriptorPublicKey::XPub(xpub) => {
+                    xpub.xkey
+                        .derive_pub(secp, &xpub.derivation_path)
+                        .expect("hardened derivation steps")
+                        .public_key
+                }
+                DescriptorPublicKey::SinglePub(key) => key.key,
+            }
+        };
+
+        self.derive(index)
+            .translate_pk_infallible(|pk| translate(pk), |pkh| translate(pkh).to_pubkeyhash())
+    }
+}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! testutils {
+    ( @external $descriptors:expr, $child:expr ) => ({
+        use $crate::bitcoin::secp256k1::Secp256k1;
+        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey, DescriptorTrait};
+
+        use $crate::testutils::TranslateDescriptor;
+
+        let secp = Secp256k1::new();
+
+        let parsed = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, &$descriptors.0).expect("Failed to parse descriptor in `testutils!(@external)`").0;
+        parsed.derive_translated(&secp, $child).address(bitcoin::Network::Regtest).expect("No address form")
+    });
+    ( @internal $descriptors:expr, $child:expr ) => ({
+        use $crate::bitcoin::secp256k1::Secp256k1;
+        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey, DescriptorTrait};
+
+        use $crate::testutils::TranslateDescriptor;
+
+        let secp = Secp256k1::new();
+
+        let parsed = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, &$descriptors.1.expect("Missing internal descriptor")).expect("Failed to parse descriptor in `testutils!(@internal)`").0;
+        parsed.derive_translated(&secp, $child).address($crate::bitcoin::Network::Regtest).expect("No address form")
+    });
+    ( @e $descriptors:expr, $child:expr ) => ({ testutils!(@external $descriptors, $child) });
+    ( @i $descriptors:expr, $child:expr ) => ({ testutils!(@internal $descriptors, $child) });
+
+    ( @tx ( $( ( $( $addr:tt )* ) => $amount:expr ),+ ) $( ( @locktime $locktime:expr ) )? $( ( @confirmations $confirmations:expr ) )? $( ( @replaceable $replaceable:expr ) )? ) => ({
+        let outs = vec![$( $crate::testutils::TestIncomingOutput::new($amount, testutils!( $($addr)* ))),+];
+
+        let locktime = None::<i64>$(.or(Some($locktime)))?;
+
+        let min_confirmations = None::<u64>$(.or(Some($confirmations)))?;
+        let replaceable = None::<bool>$(.or(Some($replaceable)))?;
+
+        $crate::testutils::TestIncomingTx::new(outs, min_confirmations, locktime, replaceable)
+    });
+
+    ( @literal $key:expr ) => ({
+        let key = $key.to_string();
+        (key, None::<String>, None::<String>)
+    });
+    ( @generate_xprv $( $external_path:expr )? $( ,$internal_path:expr )? ) => ({
+        use rand::Rng;
+
+        let mut seed = [0u8; 32];
+        rand::thread_rng().fill(&mut seed[..]);
+
+        let key = $crate::bitcoin::util::bip32::ExtendedPrivKey::new_master(
+            $crate::bitcoin::Network::Testnet,
+            &seed,
+        );
+
+        let external_path = None::<String>$(.or(Some($external_path.to_string())))?;
+        let internal_path = None::<String>$(.or(Some($internal_path.to_string())))?;
+
+        (key.unwrap().to_string(), external_path, internal_path)
+    });
+    ( @generate_wif ) => ({
+        use rand::Rng;
+
+        let mut key = [0u8; $crate::bitcoin::secp256k1::constants::SECRET_KEY_SIZE];
+        rand::thread_rng().fill(&mut key[..]);
+
+        ($crate::bitcoin::PrivateKey {
+            compressed: true,
+            network: $crate::bitcoin::Network::Testnet,
+            key: $crate::bitcoin::secp256k1::SecretKey::from_slice(&key).unwrap(),
+        }.to_string(), None::<String>, None::<String>)
+    });
+
+    ( @keys ( $( $alias:expr => ( $( $key_type:tt )* ) ),+ ) ) => ({
+        let mut map = std::collections::HashMap::new();
+        $(
+            let alias: &str = $alias;
+            map.insert(alias, testutils!( $($key_type)* ));
+        )+
+
+        map
+    });
+
+    ( @descriptors ( $external_descriptor:expr ) $( ( $internal_descriptor:expr ) )? $( ( @keys $( $keys:tt )* ) )* ) => ({
+        use std::str::FromStr;
+        use std::collections::HashMap;
+        use $crate::miniscript::descriptor::Descriptor;
+        use $crate::miniscript::TranslatePk;
+
+        #[allow(unused_assignments, unused_mut)]
+        let mut keys: HashMap<&'static str, (String, Option<String>, Option<String>)> = HashMap::new();
+        $(
+            keys = testutils!{ @keys $( $keys )* };
+        )*
+
+        let external: Descriptor<String> = FromStr::from_str($external_descriptor).unwrap();
+        let external: Descriptor<String> = external.translate_pk_infallible::<_, _>(|k| {
+            if let Some((key, ext_path, _)) = keys.get(&k.as_str()) {
+                format!("{}{}", key, ext_path.as_ref().unwrap_or(&"".into()))
+            } else {
+                k.clone()
+            }
+        }, |kh| {
+            if let Some((key, ext_path, _)) = keys.get(&kh.as_str()) {
+                format!("{}{}", key, ext_path.as_ref().unwrap_or(&"".into()))
+            } else {
+                kh.clone()
+            }
+
+        });
+        let external = external.to_string();
+
+        let internal = None::<String>$(.or({
+            let string_internal: Descriptor<String> = FromStr::from_str($internal_descriptor).unwrap();
+
+            let string_internal: Descriptor<String> = string_internal.translate_pk_infallible::<_, _>(|k| {
+                if let Some((key, _, int_path)) = keys.get(&k.as_str()) {
+                    format!("{}{}", key, int_path.as_ref().unwrap_or(&"".into()))
+                } else {
+                    k.clone()
+                }
+            }, |kh| {
+                if let Some((key, _, int_path)) = keys.get(&kh.as_str()) {
+                    format!("{}{}", key, int_path.as_ref().unwrap_or(&"".into()))
+                } else {
+                    kh.clone()
+                }
+            });
+            Some(string_internal.to_string())
+        }))?;
+
+        (external, internal)
+    })
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/types.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/types.rs.html new file mode 100644 index 0000000000..a5f9e76a88 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/types.rs.html @@ -0,0 +1,510 @@ +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
+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
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+use std::convert::AsRef;
+use std::ops::Sub;
+
+use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxOut};
+use bitcoin::{hash_types::Txid, util::psbt};
+
+use serde::{Deserialize, Serialize};
+
+/// Types of keychains
+#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum KeychainKind {
+    /// External
+    External = 0,
+    /// Internal, usually used for change outputs
+    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",
+        }
+    }
+}
+
+/// Fee rate
+#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
+// Internally stored as satoshi/vbyte
+pub struct FeeRate(f32);
+
+impl FeeRate {
+    /// Create a new instance of [`FeeRate`] given a float fee rate in btc/kvbytes
+    pub fn from_btc_per_kvb(btc_per_kvb: f32) -> Self {
+        FeeRate(btc_per_kvb * 1e5)
+    }
+
+    /// Create a new instance of [`FeeRate`] given a float fee rate in satoshi/vbyte
+    pub const fn from_sat_per_vb(sat_per_vb: f32) -> Self {
+        FeeRate(sat_per_vb)
+    }
+
+    /// Create a new [`FeeRate`] with the default min relay fee value
+    pub const fn default_min_relay_fee() -> Self {
+        FeeRate(1.0)
+    }
+
+    /// Calculate fee rate from `fee` and weight units (`wu`).
+    pub fn from_wu(fee: u64, wu: usize) -> FeeRate {
+        Self::from_vb(fee, wu.vbytes())
+    }
+
+    /// Calculate fee rate from `fee` and `vbytes`.
+    pub fn from_vb(fee: u64, vbytes: usize) -> FeeRate {
+        let rate = fee as f32 / vbytes as f32;
+        Self::from_sat_per_vb(rate)
+    }
+
+    /// Return the value as satoshi/vbyte
+    pub fn as_sat_vb(&self) -> f32 {
+        self.0
+    }
+
+    /// Calculate absolute fee in Satoshis using size in weight units.
+    pub fn fee_wu(&self, wu: usize) -> u64 {
+        self.fee_vb(wu.vbytes())
+    }
+
+    /// Calculate absolute fee in Satoshis using size in virtual bytes.
+    pub fn fee_vb(&self, vbytes: usize) -> u64 {
+        (self.as_sat_vb() * vbytes as f32).ceil() as u64
+    }
+}
+
+impl std::default::Default for FeeRate {
+    fn default() -> Self {
+        FeeRate::default_min_relay_fee()
+    }
+}
+
+impl Sub for FeeRate {
+    type Output = Self;
+
+    fn sub(self, other: FeeRate) -> Self::Output {
+        FeeRate(self.0 - other.0)
+    }
+}
+
+/// Trait implemented by types that can be used to measure weight units.
+pub trait Vbytes {
+    /// Convert weight units to virtual bytes.
+    fn vbytes(self) -> usize;
+}
+
+impl Vbytes for usize {
+    fn vbytes(self) -> usize {
+        // ref: https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#transaction-size-calculations
+        (self as f32 / 4.0).ceil() as usize
+    }
+}
+
+/// An unspent output owned by a [`Wallet`].
+///
+/// [`Wallet`]: crate::Wallet
+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
+pub struct LocalUtxo {
+    /// Reference to a transaction output
+    pub outpoint: OutPoint,
+    /// Transaction output
+    pub txout: TxOut,
+    /// Type of keychain
+    pub keychain: KeychainKind,
+}
+
+/// A [`Utxo`] with its `satisfaction_weight`.
+#[derive(Debug, Clone, PartialEq)]
+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)]
+/// An unspent transaction output (UTXO).
+pub enum Utxo {
+    /// A UTXO owned by the local wallet.
+    Local(LocalUtxo),
+    /// A UTXO owned by another wallet.
+    Foreign {
+        /// The location of the output.
+        outpoint: OutPoint,
+        /// 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")
+            }
+        }
+    }
+}
+
+/// A wallet transaction
+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
+pub struct TransactionDetails {
+    /// Optional transaction
+    pub transaction: Option<Transaction>,
+    /// Transaction id
+    pub txid: Txid,
+
+    /// Received value (sats)
+    pub received: u64,
+    /// Sent value (sats)
+    pub sent: u64,
+    /// Fee value (sats) if available.
+    /// The availability of the fee depends on the backend. It's never `None` with an Electrum
+    /// Server backend, but it could be `None` with a Bitcoin RPC node without txindex that receive
+    /// funds while offline.
+    pub fee: Option<u64>,
+    /// If the transaction is confirmed, contains height and timestamp of the block containing the
+    /// transaction, unconfirmed transaction contains `None`.
+    pub confirmation_time: Option<ConfirmationTime>,
+    /// Whether the tx has been verified against the consensus rules
+    ///
+    /// Confirmed txs are considered "verified" by default, while unconfirmed txs are checked to
+    /// ensure an unstrusted [`Blockchain`](crate::blockchain::Blockchain) backend can't trick the
+    /// wallet into using an invalid tx as an RBF template.
+    ///
+    /// The check is only perfomed when the `verify` feature is enabled.
+    #[serde(default = "bool::default")] // default to `false` if not specified
+    pub verified: bool,
+}
+
+/// Block height and timestamp of the block containing the confirmed transaction
+#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
+pub struct ConfirmationTime {
+    /// confirmation block height
+    pub height: u32,
+    /// confirmation block timestamp
+    pub timestamp: u64,
+}
+
+impl ConfirmationTime {
+    /// Returns `Some` `ConfirmationTime` if both `height` and `timestamp` are `Some`
+    pub fn new(height: Option<u32>, timestamp: Option<u64>) -> Option<Self> {
+        match (height, timestamp) {
+            (Some(height), Some(timestamp)) => Some(ConfirmationTime { height, timestamp }),
+            _ => None,
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn can_store_feerate_in_const() {
+        const _MY_RATE: FeeRate = FeeRate::from_sat_per_vb(10.0);
+        const _MIN_RELAY: FeeRate = FeeRate::default_min_relay_fee();
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/address_validator.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/address_validator.rs.html new file mode 100644 index 0000000000..b4b1b942ac --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/address_validator.rs.html @@ -0,0 +1,312 @@ +address_validator.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
+
// 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.
+
+//! Address validation callbacks
+//!
+//! The typical usage of those callbacks is for displaying the newly-generated address on a
+//! hardware wallet, so that the user can cross-check its correctness.
+//!
+//! More generally speaking though, these callbacks can also be used to "do something" every time
+//! an address is generated, without necessarily checking or validating it.
+//!
+//! An address validator can be attached to a [`Wallet`](super::Wallet) by using the
+//! [`Wallet::add_address_validator`](super::Wallet::add_address_validator) method, and
+//! whenever a new address is generated (either explicitly by the user with
+//! [`Wallet::get_address`](super::Wallet::get_address) or internally to create a change
+//! address) all the attached validators will be polled, in sequence. All of them must complete
+//! successfully to continue.
+//!
+//! ## Example
+//!
+//! ```
+//! # use std::sync::Arc;
+//! # use bitcoin::*;
+//! # use bdk::address_validator::*;
+//! # use bdk::database::*;
+//! # use bdk::*;
+//! # use bdk::wallet::AddressIndex::New;
+//! #[derive(Debug)]
+//! struct PrintAddressAndContinue;
+//!
+//! impl AddressValidator for PrintAddressAndContinue {
+//!     fn validate(
+//!         &self,
+//!         keychain: KeychainKind,
+//!         hd_keypaths: &HdKeyPaths,
+//!         script: &Script
+//!     ) -> Result<(), AddressValidatorError> {
+//!         let address = Address::from_script(script, Network::Testnet)
+//!             .as_ref()
+//!             .map(Address::to_string)
+//!             .unwrap_or(script.to_string());
+//!         println!("New address of type {:?}: {}", keychain, address);
+//!         println!("HD keypaths: {:#?}", hd_keypaths);
+//!
+//!         Ok(())
+//!     }
+//! }
+//!
+//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+//! let mut wallet = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+//! wallet.add_address_validator(Arc::new(PrintAddressAndContinue));
+//!
+//! let address = wallet.get_address(New)?;
+//! println!("Address: {}", address);
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use std::fmt;
+
+use bitcoin::Script;
+
+use crate::descriptor::HdKeyPaths;
+use crate::types::KeychainKind;
+
+/// Errors that can be returned to fail the validation of an address
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum AddressValidatorError {
+    /// User rejected the address
+    UserRejected,
+    /// Network connection error
+    ConnectionError,
+    /// Network request timeout error
+    TimeoutError,
+    /// Invalid script
+    InvalidScript,
+    /// A custom error message
+    Message(String),
+}
+
+impl fmt::Display for AddressValidatorError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for AddressValidatorError {}
+
+/// Trait to build address validators
+///
+/// All the address validators attached to a wallet with [`Wallet::add_address_validator`](super::Wallet::add_address_validator) will be polled
+/// every time an address (external or internal) is generated by the wallet. Errors returned in the
+/// validator will be propagated up to the original caller that triggered the address generation.
+///
+/// For a usage example see [this module](crate::address_validator)'s documentation.
+pub trait AddressValidator: Send + Sync + fmt::Debug {
+    /// Validate or inspect an address
+    fn validate(
+        &self,
+        keychain: KeychainKind,
+        hd_keypaths: &HdKeyPaths,
+        script: &Script,
+    ) -> Result<(), AddressValidatorError>;
+}
+
+#[cfg(test)]
+mod test {
+    use std::sync::Arc;
+
+    use super::*;
+    use crate::wallet::AddressIndex::New;
+    use crate::wallet::{get_funded_wallet, test::get_test_wpkh};
+
+    #[derive(Debug)]
+    struct TestValidator;
+    impl AddressValidator for TestValidator {
+        fn validate(
+            &self,
+            _keychain: KeychainKind,
+            _hd_keypaths: &HdKeyPaths,
+            _script: &bitcoin::Script,
+        ) -> Result<(), AddressValidatorError> {
+            Err(AddressValidatorError::InvalidScript)
+        }
+    }
+
+    #[test]
+    #[should_panic(expected = "InvalidScript")]
+    fn test_address_validator_external() {
+        let (mut wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        wallet.add_address_validator(Arc::new(TestValidator));
+
+        wallet.get_address(New).unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "InvalidScript")]
+    fn test_address_validator_internal() {
+        let (mut wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        wallet.add_address_validator(Arc::new(TestValidator));
+
+        let addr = crate::testutils!(@external descriptors, 10);
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        builder.finish().unwrap();
+    }
+}
+
+
+ + \ 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 new file mode 100644 index 0000000000..dc5c9f14b7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/coin_selection.rs.html @@ -0,0 +1,2122 @@ +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
+
// 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, coin_selection::*};
+//! # use bdk::database::Database;
+//! # use bdk::*;
+//! # const TXIN_BASE_WEIGHT: usize = (32 + 4 + 4 + 1) * 4;
+//! #[derive(Debug)]
+//! struct AlwaysSpendEverything;
+//!
+//! impl<D: Database> CoinSelectionAlgorithm<D> for AlwaysSpendEverything {
+//!     fn coin_select(
+//!         &self,
+//!         database: &D,
+//!         required_utxos: Vec<WeightedUtxo>,
+//!         optional_utxos: Vec<WeightedUtxo>,
+//!         fee_rate: FeeRate,
+//!         amount_needed: u64,
+//!         fee_amount: u64,
+//!     ) -> Result<CoinSelectionResult, bdk::Error> {
+//!         let mut selected_amount = 0;
+//!         let mut additional_weight = 0;
+//!         let all_utxos_selected = required_utxos
+//!             .into_iter()
+//!             .chain(optional_utxos)
+//!             .scan(
+//!                 (&mut selected_amount, &mut additional_weight),
+//!                 |(selected_amount, additional_weight), weighted_utxo| {
+//!                     **selected_amount += weighted_utxo.utxo.txout().value;
+//!                     **additional_weight += TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight;
+//!                     Some(weighted_utxo.utxo)
+//!                 },
+//!             )
+//!             .collect::<Vec<_>>();
+//!         let additional_fees = fee_rate.fee_wu(additional_weight);
+//!         let amount_needed_with_fees = (fee_amount + additional_fees) + amount_needed;
+//!         if amount_needed_with_fees > selected_amount {
+//!             return Err(bdk::Error::InsufficientFunds {
+//!                 needed: amount_needed_with_fees,
+//!                 available: selected_amount,
+//!             });
+//!         }
+//!
+//!         Ok(CoinSelectionResult {
+//!             selected: all_utxos_selected,
+//!             fee_amount: fee_amount + additional_fees,
+//!         })
+//!     }
+//! }
+//!
+//! # let wallet = doctest_wallet!();
+//! // create wallet, sync, ...
+//!
+//! let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+//! let (psbt, details) = {
+//!     let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
+//!     builder.add_recipient(to_address.script_pubkey(), 50_000);
+//!     builder.finish()?
+//! };
+//!
+//! // inspect, sign, broadcast, ...
+//!
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use crate::types::FeeRate;
+use crate::{database::Database, WeightedUtxo};
+use crate::{error::Error, Utxo};
+
+use rand::seq::SliceRandom;
+#[cfg(not(test))]
+use rand::thread_rng;
+#[cfg(test)]
+use rand::{rngs::StdRng, SeedableRng};
+use std::convert::TryInto;
+
+/// Default coin selection algorithm used by [`TxBuilder`](super::tx_builder::TxBuilder) if not
+/// overridden
+#[cfg(not(test))]
+pub type DefaultCoinSelectionAlgorithm = BranchAndBoundCoinSelection;
+#[cfg(test)]
+pub type DefaultCoinSelectionAlgorithm = LargestFirstCoinSelection; // make the tests more predictable
+
+// Base weight of a Txin, not counting the weight needed for satisfying it.
+// prev_txid (32 bytes) + prev_vout (4 bytes) + sequence (4 bytes) + script_len (1 bytes)
+pub(crate) const TXIN_BASE_WEIGHT: usize = (32 + 4 + 4 + 1) * 4;
+
+/// 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 in satoshi
+    pub fee_amount: u64,
+}
+
+impl CoinSelectionResult {
+    /// The total value of the inputs selected.
+    pub fn selected_amount(&self) -> u64 {
+        self.selected.iter().map(|u| u.txout().value).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),
+                _ => 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<D: Database>: std::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 `amount_needed` with their
+    ///                     weight cost
+    /// - `optional_utxos`: the remaining available utxos to satisfy `amount_needed` with their
+    ///                     weight cost
+    /// - `fee_rate`: fee rate to use
+    /// - `amount_needed`: the amount in satoshi to select
+    /// - `fee_amount`: the amount of fees in satoshi already accumulated from adding outputs and
+    ///                 the transaction's header
+    fn coin_select(
+        &self,
+        database: &D,
+        required_utxos: Vec<WeightedUtxo>,
+        optional_utxos: Vec<WeightedUtxo>,
+        fee_rate: FeeRate,
+        amount_needed: u64,
+        fee_amount: u64,
+    ) -> 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<D: Database> CoinSelectionAlgorithm<D> for LargestFirstCoinSelection {
+    fn coin_select(
+        &self,
+        _database: &D,
+        required_utxos: Vec<WeightedUtxo>,
+        mut optional_utxos: Vec<WeightedUtxo>,
+        fee_rate: FeeRate,
+        amount_needed: u64,
+        mut fee_amount: u64,
+    ) -> Result<CoinSelectionResult, Error> {
+        log::debug!(
+            "amount_needed = `{}`, fee_amount = `{}`, fee_rate = `{:?}`",
+            amount_needed,
+            fee_amount,
+            fee_rate
+        );
+
+        // 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)))
+        };
+
+        // Keep including inputs until we've got enough.
+        // Store the total input value in selected_amount and the total fee being paid in fee_amount
+        let mut selected_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 < amount_needed + **fee_amount {
+                        **fee_amount +=
+                            fee_rate.fee_wu(TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight);
+                        **selected_amount += weighted_utxo.utxo.txout().value;
+
+                        log::debug!(
+                            "Selected {}, updated fee_amount = `{}`",
+                            weighted_utxo.utxo.outpoint(),
+                            fee_amount
+                        );
+
+                        Some(weighted_utxo.utxo)
+                    } else {
+                        None
+                    }
+                },
+            )
+            .collect::<Vec<_>>();
+
+        let amount_needed_with_fees = amount_needed + fee_amount;
+        if selected_amount < amount_needed_with_fees {
+            return Err(Error::InsufficientFunds {
+                needed: amount_needed_with_fees,
+                available: selected_amount,
+            });
+        }
+
+        Ok(CoinSelectionResult {
+            selected,
+            fee_amount,
+        })
+    }
+}
+
+#[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.fee_wu(TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight);
+        let effective_value = weighted_utxo.utxo.txout().value 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)]
+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<D: Database> CoinSelectionAlgorithm<D> for BranchAndBoundCoinSelection {
+    fn coin_select(
+        &self,
+        _database: &D,
+        required_utxos: Vec<WeightedUtxo>,
+        optional_utxos: Vec<WeightedUtxo>,
+        fee_rate: FeeRate,
+        amount_needed: u64,
+        fee_amount: u64,
+    ) -> 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.
+        let optional_utxos: Vec<OutputGroup> = optional_utxos
+            .into_iter()
+            .map(|u| OutputGroup::new(u, fee_rate))
+            .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 actual_target = fee_amount + amount_needed;
+        let cost_of_change = self.size_of_change as f32 * fee_rate.as_sat_vb();
+
+        let expected = (curr_available_value + curr_value)
+            .try_into()
+            .map_err(|_| {
+                Error::Generic("Sum of UTXO spendable values does not fit into u64".to_string())
+            })?;
+
+        if expected < actual_target {
+            return Err(Error::InsufficientFunds {
+                needed: actual_target,
+                available: expected,
+            });
+        }
+
+        let actual_target = actual_target
+            .try_into()
+            .expect("Bitcoin amount to fit into i64");
+
+        if curr_value > actual_target {
+            return Ok(BranchAndBoundCoinSelection::calculate_cs_result(
+                vec![],
+                required_utxos,
+                fee_amount,
+            ));
+        }
+
+        Ok(self
+            .bnb(
+                required_utxos.clone(),
+                optional_utxos.clone(),
+                curr_value,
+                curr_available_value,
+                actual_target,
+                fee_amount,
+                cost_of_change,
+            )
+            .unwrap_or_else(|_| {
+                self.single_random_draw(
+                    required_utxos,
+                    optional_utxos,
+                    curr_value,
+                    actual_target,
+                    fee_amount,
+                )
+            }))
+    }
+}
+
+impl BranchAndBoundCoinSelection {
+    // TODO: make this more Rust-onic :)
+    // (And perhpaps 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,
+        actual_target: i64,
+        fee_amount: u64,
+        cost_of_change: f32,
+    ) -> 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 < actual_target
+                || curr_value > actual_target + cost_of_change as i64
+            {
+                backtrack = true;
+            } else if curr_value >= actual_target {
+                // 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 = current_selection.clone();
+                    best_selection_value = Some(curr_value);
+                }
+
+                // If we found a perfect match, break here
+                if curr_value == actual_target {
+                    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();
+
+        Ok(BranchAndBoundCoinSelection::calculate_cs_result(
+            selected_utxos,
+            required_utxos,
+            fee_amount,
+        ))
+    }
+
+    fn single_random_draw(
+        &self,
+        required_utxos: Vec<OutputGroup>,
+        mut optional_utxos: Vec<OutputGroup>,
+        curr_value: i64,
+        actual_target: i64,
+        fee_amount: u64,
+    ) -> CoinSelectionResult {
+        #[cfg(not(test))]
+        optional_utxos.shuffle(&mut thread_rng());
+        #[cfg(test)]
+        {
+            let seed = [0; 32];
+            let mut rng: StdRng = SeedableRng::from_seed(seed);
+            optional_utxos.shuffle(&mut rng);
+        }
+
+        let selected_utxos = optional_utxos
+            .into_iter()
+            .scan(curr_value, |curr_value, utxo| {
+                if *curr_value >= actual_target {
+                    None
+                } else {
+                    *curr_value += utxo.effective_value;
+                    Some(utxo)
+                }
+            })
+            .collect::<Vec<_>>();
+
+        BranchAndBoundCoinSelection::calculate_cs_result(selected_utxos, required_utxos, fee_amount)
+    }
+
+    fn calculate_cs_result(
+        mut selected_utxos: Vec<OutputGroup>,
+        mut required_utxos: Vec<OutputGroup>,
+        mut fee_amount: u64,
+    ) -> CoinSelectionResult {
+        selected_utxos.append(&mut required_utxos);
+        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,
+        }
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::str::FromStr;
+
+    use bitcoin::{OutPoint, Script, TxOut};
+
+    use super::*;
+    use crate::database::MemoryDatabase;
+    use crate::types::*;
+    use crate::wallet::Vbytes;
+
+    use rand::rngs::StdRng;
+    use rand::seq::SliceRandom;
+    use rand::{Rng, SeedableRng};
+
+    const P2WPKH_WITNESS_SIZE: usize = 73 + 33 + 2;
+
+    const FEE_AMOUNT: u64 = 50;
+
+    fn utxo(value: u64, index: u32) -> WeightedUtxo {
+        assert!(index < 10);
+        let outpoint = OutPoint::from_str(&format!(
+            "000000000000000000000000000000000000000000000000000000000000000{}:0",
+            index
+        ))
+        .unwrap();
+        WeightedUtxo {
+            satisfaction_weight: P2WPKH_WITNESS_SIZE,
+            utxo: Utxo::Local(LocalUtxo {
+                outpoint,
+                txout: TxOut {
+                    value,
+                    script_pubkey: Script::new(),
+                },
+                keychain: KeychainKind::External,
+            }),
+        }
+    }
+
+    fn get_test_utxos() -> Vec<WeightedUtxo> {
+        vec![
+            utxo(100_000, 0),
+            utxo(FEE_AMOUNT as u64 - 40, 1),
+            utxo(200_000, 2),
+        ]
+    }
+
+    fn generate_random_utxos(rng: &mut StdRng, utxos_number: usize) -> Vec<WeightedUtxo> {
+        let mut res = Vec::new();
+        for _ in 0..utxos_number {
+            res.push(WeightedUtxo {
+                satisfaction_weight: P2WPKH_WITNESS_SIZE,
+                utxo: Utxo::Local(LocalUtxo {
+                    outpoint: OutPoint::from_str(
+                        "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:0",
+                    )
+                    .unwrap(),
+                    txout: TxOut {
+                        value: rng.gen_range(0, 200000000),
+                        script_pubkey: Script::new(),
+                    },
+                    keychain: KeychainKind::External,
+                }),
+            });
+        }
+        res
+    }
+
+    fn generate_same_value_utxos(utxos_value: u64, utxos_number: usize) -> Vec<WeightedUtxo> {
+        let utxo = WeightedUtxo {
+            satisfaction_weight: P2WPKH_WITNESS_SIZE,
+            utxo: Utxo::Local(LocalUtxo {
+                outpoint: OutPoint::from_str(
+                    "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:0",
+                )
+                .unwrap(),
+                txout: TxOut {
+                    value: utxos_value,
+                    script_pubkey: Script::new(),
+                },
+                keychain: KeychainKind::External,
+            }),
+        };
+        vec![utxo; utxos_number]
+    }
+
+    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)
+            .sum()
+    }
+
+    #[test]
+    fn test_largest_first_coin_selection_success() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        let result = LargestFirstCoinSelection::default()
+            .coin_select(
+                &database,
+                utxos,
+                vec![],
+                FeeRate::from_sat_per_vb(1.0),
+                250_000,
+                FEE_AMOUNT,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 3);
+        assert_eq!(result.selected_amount(), 300_010);
+        assert_eq!(result.fee_amount, 254)
+    }
+
+    #[test]
+    fn test_largest_first_coin_selection_use_all() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        let result = LargestFirstCoinSelection::default()
+            .coin_select(
+                &database,
+                utxos,
+                vec![],
+                FeeRate::from_sat_per_vb(1.0),
+                20_000,
+                FEE_AMOUNT,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 3);
+        assert_eq!(result.selected_amount(), 300_010);
+        assert_eq!(result.fee_amount, 254);
+    }
+
+    #[test]
+    fn test_largest_first_coin_selection_use_only_necessary() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        let result = LargestFirstCoinSelection::default()
+            .coin_select(
+                &database,
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb(1.0),
+                20_000,
+                FEE_AMOUNT,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 1);
+        assert_eq!(result.selected_amount(), 200_000);
+        assert_eq!(result.fee_amount, 118);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_largest_first_coin_selection_insufficient_funds() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        LargestFirstCoinSelection::default()
+            .coin_select(
+                &database,
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb(1.0),
+                500_000,
+                FEE_AMOUNT,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_largest_first_coin_selection_insufficient_funds_high_fees() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        LargestFirstCoinSelection::default()
+            .coin_select(
+                &database,
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb(1000.0),
+                250_000,
+                FEE_AMOUNT,
+            )
+            .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 database = MemoryDatabase::default();
+
+        let result = BranchAndBoundCoinSelection::default()
+            .coin_select(
+                &database,
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb(1.0),
+                250_000,
+                FEE_AMOUNT,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 3);
+        assert_eq!(result.selected_amount(), 300_000);
+        assert_eq!(result.fee_amount, 254);
+    }
+
+    #[test]
+    fn test_bnb_coin_selection_required_are_enough() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        let result = BranchAndBoundCoinSelection::default()
+            .coin_select(
+                &database,
+                utxos.clone(),
+                utxos,
+                FeeRate::from_sat_per_vb(1.0),
+                20_000,
+                FEE_AMOUNT,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 3);
+        assert_eq!(result.selected_amount(), 300_010);
+        assert_eq!(result.fee_amount, 254);
+    }
+
+    #[test]
+    fn test_bnb_coin_selection_optional_are_enough() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        let result = BranchAndBoundCoinSelection::default()
+            .coin_select(
+                &database,
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb(1.0),
+                299756,
+                FEE_AMOUNT,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 3);
+        assert_eq!(result.selected_amount(), 300010);
+        assert_eq!(result.fee_amount, 254);
+    }
+
+    #[test]
+    fn test_bnb_coin_selection_required_not_enough() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        let required = vec![utxos[0].clone()];
+        let mut optional = utxos[1..].to_vec();
+        optional.push(utxo(500_000, 3));
+
+        // Defensive assertions, for sanity and in case someone changes the test utxos vector.
+        let amount: u64 = required.iter().map(|u| u.utxo.txout().value).sum();
+        assert_eq!(amount, 100_000);
+        let amount: u64 = optional.iter().map(|u| u.utxo.txout().value).sum();
+        assert!(amount > 150_000);
+
+        let result = BranchAndBoundCoinSelection::default()
+            .coin_select(
+                &database,
+                required,
+                optional,
+                FeeRate::from_sat_per_vb(1.0),
+                150_000,
+                FEE_AMOUNT,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 3);
+        assert_eq!(result.selected_amount(), 300_010);
+        assert!((result.fee_amount as f32 - 254.0).abs() < f32::EPSILON);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_bnb_coin_selection_insufficient_funds() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        BranchAndBoundCoinSelection::default()
+            .coin_select(
+                &database,
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb(1.0),
+                500_000,
+                FEE_AMOUNT,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_bnb_coin_selection_insufficient_funds_high_fees() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        BranchAndBoundCoinSelection::default()
+            .coin_select(
+                &database,
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb(1000.0),
+                250_000,
+                FEE_AMOUNT,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    fn test_bnb_coin_selection_check_fee_rate() {
+        let utxos = get_test_utxos();
+        let database = MemoryDatabase::default();
+
+        let result = BranchAndBoundCoinSelection::new(0)
+            .coin_select(
+                &database,
+                vec![],
+                utxos,
+                FeeRate::from_sat_per_vb(1.0),
+                99932, // first utxo's effective value
+                0,
+            )
+            .unwrap();
+
+        assert_eq!(result.selected.len(), 1);
+        assert_eq!(result.selected_amount(), 100_000);
+        let input_size = (TXIN_BASE_WEIGHT + P2WPKH_WITNESS_SIZE).vbytes();
+        let epsilon = 0.5;
+        assert!((1.0 - (result.fee_amount as f32 / input_size as f32)).abs() < epsilon);
+    }
+
+    #[test]
+    fn test_bnb_coin_selection_exact_match() {
+        let seed = [0; 32];
+        let mut rng: StdRng = SeedableRng::from_seed(seed);
+        let database = MemoryDatabase::default();
+
+        for _i in 0..200 {
+            let mut optional_utxos = generate_random_utxos(&mut rng, 16);
+            let target_amount = sum_random_utxos(&mut rng, &mut optional_utxos);
+            let result = BranchAndBoundCoinSelection::new(0)
+                .coin_select(
+                    &database,
+                    vec![],
+                    optional_utxos,
+                    FeeRate::from_sat_per_vb(0.0),
+                    target_amount,
+                    0,
+                )
+                .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(10.0);
+        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 = size_of_change as f32 * fee_rate.as_sat_vb();
+        BranchAndBoundCoinSelection::new(size_of_change)
+            .bnb(
+                vec![],
+                utxos,
+                0,
+                curr_available_value,
+                20_000,
+                FEE_AMOUNT,
+                cost_of_change,
+            )
+            .unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "BnBTotalTriesExceeded")]
+    fn test_bnb_function_tries_exceeded() {
+        let fee_rate = FeeRate::from_sat_per_vb(10.0);
+        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 = size_of_change as f32 * fee_rate.as_sat_vb();
+
+        BranchAndBoundCoinSelection::new(size_of_change)
+            .bnb(
+                vec![],
+                utxos,
+                0,
+                curr_available_value,
+                20_000,
+                FEE_AMOUNT,
+                cost_of_change,
+            )
+            .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(1.0);
+        let size_of_change = 31;
+        let cost_of_change = size_of_change as f32 * fee_rate.as_sat_vb();
+
+        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.ceil() as i64 + 5;
+
+        let result = BranchAndBoundCoinSelection::new(size_of_change)
+            .bnb(
+                vec![],
+                utxos,
+                curr_value,
+                curr_available_value,
+                target_amount,
+                FEE_AMOUNT,
+                cost_of_change,
+            )
+            .unwrap();
+        assert_eq!(result.selected_amount(), 100_000);
+        assert_eq!(result.fee_amount, 186);
+    }
+
+    // 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::from_sat_per_vb(0.0);
+
+        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 result = BranchAndBoundCoinSelection::new(0)
+                .bnb(
+                    vec![],
+                    optional_utxos,
+                    curr_value,
+                    curr_available_value,
+                    target_amount,
+                    0,
+                    0.0,
+                )
+                .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);
+
+        let fee_rate = FeeRate::from_sat_per_vb(1.0);
+        let utxos: Vec<OutputGroup> = utxos
+            .into_iter()
+            .map(|u| OutputGroup::new(u, fee_rate))
+            .collect();
+
+        let result = BranchAndBoundCoinSelection::default().single_random_draw(
+            vec![],
+            utxos,
+            0,
+            target_amount as i64,
+            FEE_AMOUNT,
+        );
+
+        assert!(result.selected_amount() > target_amount);
+        assert_eq!(result.fee_amount, (50 + result.selected.len() * 68) as u64);
+    }
+}
+
+
+ + \ 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 new file mode 100644 index 0000000000..a78d0d922f --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/export.rs.html @@ -0,0 +1,706 @@ +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
+342
+343
+344
+345
+346
+347
+348
+349
+350
+351
+
// 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::database::*;
+//! # use bdk::wallet::export::*;
+//! # use bdk::*;
+//! let import = r#"{
+//!     "descriptor": "wpkh([c258d2e4\/84h\/1h\/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe\/0\/*)",
+//!     "blockheight":1782088,
+//!     "label":"testnet"
+//! }"#;
+//!
+//! let import = WalletExport::from_str(import)?;
+//! let wallet = Wallet::new_offline(
+//!     &import.descriptor(),
+//!     import.change_descriptor().as_ref(),
+//!     Network::Testnet,
+//!     MemoryDatabase::default(),
+//! )?;
+//! # Ok::<_, bdk::Error>(())
+//! ```
+//!
+//! ### Export a `Wallet`
+//! ```
+//! # use bitcoin::*;
+//! # use bdk::database::*;
+//! # use bdk::wallet::export::*;
+//! # use bdk::*;
+//! let wallet = Wallet::new_offline(
+//!     "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
+//!     Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
+//!     Network::Testnet,
+//!     MemoryDatabase::default()
+//! )?;
+//! let export = WalletExport::export_wallet(&wallet, "exported wallet", true)
+//!     .map_err(ToString::to_string)
+//!     .map_err(bdk::Error::Generic)?;
+//!
+//! println!("Exported: {}", export.to_string());
+//! # Ok::<_, bdk::Error>(())
+//! ```
+
+use std::str::FromStr;
+
+use serde::{Deserialize, Serialize};
+
+use miniscript::descriptor::{ShInner, WshInner};
+use miniscript::{Descriptor, DescriptorPublicKey, ScriptContext, Terminal};
+
+use crate::database::BatchDatabase;
+use crate::wallet::Wallet;
+
+/// 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 WalletExport {
+    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 ToString for WalletExport {
+    fn to_string(&self) -> String {
+        serde_json::to_string(self).unwrap()
+    }
+}
+
+impl FromStr for WalletExport {
+    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.splitn(2, '#').next().map(String::from).unwrap()
+}
+
+impl WalletExport {
+    /// 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<B, D: BatchDatabase>(
+        wallet: &Wallet<B, D>,
+        label: &str,
+        include_blockheight: bool,
+    ) -> Result<Self, &'static str> {
+        let descriptor = wallet
+            .descriptor
+            .to_string_with_secret(&wallet.signers.as_key_map(wallet.secp_ctx()));
+        let descriptor = remove_checksum(descriptor);
+        Self::is_compatible_with_core(&descriptor)?;
+
+        let blockheight = match wallet.database.borrow().iter_txs(false) {
+            _ if !include_blockheight => 0,
+            Err(_) => 0,
+            Ok(txs) => {
+                let mut heights = txs
+                    .into_iter()
+                    .map(|tx| tx.confirmation_time.map(|c| c.height).unwrap_or(0))
+                    .collect::<Vec<_>>();
+                heights.sort_unstable();
+
+                *heights.last().unwrap_or(&0)
+            }
+        };
+
+        let export = WalletExport {
+            descriptor,
+            label: label.into(),
+            blockheight,
+        };
+
+        let desc_to_string = |d: &Descriptor<DescriptorPublicKey>| {
+            let descriptor =
+                d.to_string_with_secret(&wallet.change_signers.as_key_map(wallet.secp_ctx()));
+            remove_checksum(descriptor)
+        };
+        if export.change_descriptor() != wallet.change_descriptor.as_ref().map(desc_to_string) {
+            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 std::str::FromStr;
+
+    use bitcoin::{Network, Txid};
+
+    use super::*;
+    use crate::database::{memory::MemoryDatabase, BatchOperations};
+    use crate::types::TransactionDetails;
+    use crate::wallet::Wallet;
+    use crate::ConfirmationTime;
+
+    fn get_test_db() -> MemoryDatabase {
+        let mut db = MemoryDatabase::new();
+        db.set_tx(&TransactionDetails {
+            transaction: None,
+            txid: Txid::from_str(
+                "4ddff1fa33af17f377f62b72357b43107c19110a8009b36fb832af505efed98a",
+            )
+            .unwrap(),
+
+            received: 100_000,
+            sent: 0,
+            fee: Some(500),
+            confirmation_time: Some(ConfirmationTime {
+                timestamp: 12345678,
+                height: 5000,
+            }),
+            verified: true,
+        })
+        .unwrap();
+
+        db
+    }
+
+    #[test]
+    fn test_export_bip44() {
+        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
+        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
+
+        let wallet = Wallet::new_offline(
+            descriptor,
+            Some(change_descriptor),
+            Network::Bitcoin,
+            get_test_db(),
+        )
+        .unwrap();
+        let export = WalletExport::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 =
+            Wallet::new_offline(descriptor, None, Network::Bitcoin, get_test_db()).unwrap();
+        WalletExport::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 = Wallet::new_offline(
+            descriptor,
+            Some(change_descriptor),
+            Network::Bitcoin,
+            get_test_db(),
+        )
+        .unwrap();
+        WalletExport::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 = Wallet::new_offline(
+            descriptor,
+            Some(change_descriptor),
+            Network::Testnet,
+            get_test_db(),
+        )
+        .unwrap();
+        let export = WalletExport::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 = Wallet::new_offline(
+            descriptor,
+            Some(change_descriptor),
+            Network::Bitcoin,
+            get_test_db(),
+        )
+        .unwrap();
+        let export = WalletExport::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 = WalletExport::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 new file mode 100644 index 0000000000..e4602b959b --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/mod.rs.html @@ -0,0 +1,7940 @@ +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
+2709
+2710
+2711
+2712
+2713
+2714
+2715
+2716
+2717
+2718
+2719
+2720
+2721
+2722
+2723
+2724
+2725
+2726
+2727
+2728
+2729
+2730
+2731
+2732
+2733
+2734
+2735
+2736
+2737
+2738
+2739
+2740
+2741
+2742
+2743
+2744
+2745
+2746
+2747
+2748
+2749
+2750
+2751
+2752
+2753
+2754
+2755
+2756
+2757
+2758
+2759
+2760
+2761
+2762
+2763
+2764
+2765
+2766
+2767
+2768
+2769
+2770
+2771
+2772
+2773
+2774
+2775
+2776
+2777
+2778
+2779
+2780
+2781
+2782
+2783
+2784
+2785
+2786
+2787
+2788
+2789
+2790
+2791
+2792
+2793
+2794
+2795
+2796
+2797
+2798
+2799
+2800
+2801
+2802
+2803
+2804
+2805
+2806
+2807
+2808
+2809
+2810
+2811
+2812
+2813
+2814
+2815
+2816
+2817
+2818
+2819
+2820
+2821
+2822
+2823
+2824
+2825
+2826
+2827
+2828
+2829
+2830
+2831
+2832
+2833
+2834
+2835
+2836
+2837
+2838
+2839
+2840
+2841
+2842
+2843
+2844
+2845
+2846
+2847
+2848
+2849
+2850
+2851
+2852
+2853
+2854
+2855
+2856
+2857
+2858
+2859
+2860
+2861
+2862
+2863
+2864
+2865
+2866
+2867
+2868
+2869
+2870
+2871
+2872
+2873
+2874
+2875
+2876
+2877
+2878
+2879
+2880
+2881
+2882
+2883
+2884
+2885
+2886
+2887
+2888
+2889
+2890
+2891
+2892
+2893
+2894
+2895
+2896
+2897
+2898
+2899
+2900
+2901
+2902
+2903
+2904
+2905
+2906
+2907
+2908
+2909
+2910
+2911
+2912
+2913
+2914
+2915
+2916
+2917
+2918
+2919
+2920
+2921
+2922
+2923
+2924
+2925
+2926
+2927
+2928
+2929
+2930
+2931
+2932
+2933
+2934
+2935
+2936
+2937
+2938
+2939
+2940
+2941
+2942
+2943
+2944
+2945
+2946
+2947
+2948
+2949
+2950
+2951
+2952
+2953
+2954
+2955
+2956
+2957
+2958
+2959
+2960
+2961
+2962
+2963
+2964
+2965
+2966
+2967
+2968
+2969
+2970
+2971
+2972
+2973
+2974
+2975
+2976
+2977
+2978
+2979
+2980
+2981
+2982
+2983
+2984
+2985
+2986
+2987
+2988
+2989
+2990
+2991
+2992
+2993
+2994
+2995
+2996
+2997
+2998
+2999
+3000
+3001
+3002
+3003
+3004
+3005
+3006
+3007
+3008
+3009
+3010
+3011
+3012
+3013
+3014
+3015
+3016
+3017
+3018
+3019
+3020
+3021
+3022
+3023
+3024
+3025
+3026
+3027
+3028
+3029
+3030
+3031
+3032
+3033
+3034
+3035
+3036
+3037
+3038
+3039
+3040
+3041
+3042
+3043
+3044
+3045
+3046
+3047
+3048
+3049
+3050
+3051
+3052
+3053
+3054
+3055
+3056
+3057
+3058
+3059
+3060
+3061
+3062
+3063
+3064
+3065
+3066
+3067
+3068
+3069
+3070
+3071
+3072
+3073
+3074
+3075
+3076
+3077
+3078
+3079
+3080
+3081
+3082
+3083
+3084
+3085
+3086
+3087
+3088
+3089
+3090
+3091
+3092
+3093
+3094
+3095
+3096
+3097
+3098
+3099
+3100
+3101
+3102
+3103
+3104
+3105
+3106
+3107
+3108
+3109
+3110
+3111
+3112
+3113
+3114
+3115
+3116
+3117
+3118
+3119
+3120
+3121
+3122
+3123
+3124
+3125
+3126
+3127
+3128
+3129
+3130
+3131
+3132
+3133
+3134
+3135
+3136
+3137
+3138
+3139
+3140
+3141
+3142
+3143
+3144
+3145
+3146
+3147
+3148
+3149
+3150
+3151
+3152
+3153
+3154
+3155
+3156
+3157
+3158
+3159
+3160
+3161
+3162
+3163
+3164
+3165
+3166
+3167
+3168
+3169
+3170
+3171
+3172
+3173
+3174
+3175
+3176
+3177
+3178
+3179
+3180
+3181
+3182
+3183
+3184
+3185
+3186
+3187
+3188
+3189
+3190
+3191
+3192
+3193
+3194
+3195
+3196
+3197
+3198
+3199
+3200
+3201
+3202
+3203
+3204
+3205
+3206
+3207
+3208
+3209
+3210
+3211
+3212
+3213
+3214
+3215
+3216
+3217
+3218
+3219
+3220
+3221
+3222
+3223
+3224
+3225
+3226
+3227
+3228
+3229
+3230
+3231
+3232
+3233
+3234
+3235
+3236
+3237
+3238
+3239
+3240
+3241
+3242
+3243
+3244
+3245
+3246
+3247
+3248
+3249
+3250
+3251
+3252
+3253
+3254
+3255
+3256
+3257
+3258
+3259
+3260
+3261
+3262
+3263
+3264
+3265
+3266
+3267
+3268
+3269
+3270
+3271
+3272
+3273
+3274
+3275
+3276
+3277
+3278
+3279
+3280
+3281
+3282
+3283
+3284
+3285
+3286
+3287
+3288
+3289
+3290
+3291
+3292
+3293
+3294
+3295
+3296
+3297
+3298
+3299
+3300
+3301
+3302
+3303
+3304
+3305
+3306
+3307
+3308
+3309
+3310
+3311
+3312
+3313
+3314
+3315
+3316
+3317
+3318
+3319
+3320
+3321
+3322
+3323
+3324
+3325
+3326
+3327
+3328
+3329
+3330
+3331
+3332
+3333
+3334
+3335
+3336
+3337
+3338
+3339
+3340
+3341
+3342
+3343
+3344
+3345
+3346
+3347
+3348
+3349
+3350
+3351
+3352
+3353
+3354
+3355
+3356
+3357
+3358
+3359
+3360
+3361
+3362
+3363
+3364
+3365
+3366
+3367
+3368
+3369
+3370
+3371
+3372
+3373
+3374
+3375
+3376
+3377
+3378
+3379
+3380
+3381
+3382
+3383
+3384
+3385
+3386
+3387
+3388
+3389
+3390
+3391
+3392
+3393
+3394
+3395
+3396
+3397
+3398
+3399
+3400
+3401
+3402
+3403
+3404
+3405
+3406
+3407
+3408
+3409
+3410
+3411
+3412
+3413
+3414
+3415
+3416
+3417
+3418
+3419
+3420
+3421
+3422
+3423
+3424
+3425
+3426
+3427
+3428
+3429
+3430
+3431
+3432
+3433
+3434
+3435
+3436
+3437
+3438
+3439
+3440
+3441
+3442
+3443
+3444
+3445
+3446
+3447
+3448
+3449
+3450
+3451
+3452
+3453
+3454
+3455
+3456
+3457
+3458
+3459
+3460
+3461
+3462
+3463
+3464
+3465
+3466
+3467
+3468
+3469
+3470
+3471
+3472
+3473
+3474
+3475
+3476
+3477
+3478
+3479
+3480
+3481
+3482
+3483
+3484
+3485
+3486
+3487
+3488
+3489
+3490
+3491
+3492
+3493
+3494
+3495
+3496
+3497
+3498
+3499
+3500
+3501
+3502
+3503
+3504
+3505
+3506
+3507
+3508
+3509
+3510
+3511
+3512
+3513
+3514
+3515
+3516
+3517
+3518
+3519
+3520
+3521
+3522
+3523
+3524
+3525
+3526
+3527
+3528
+3529
+3530
+3531
+3532
+3533
+3534
+3535
+3536
+3537
+3538
+3539
+3540
+3541
+3542
+3543
+3544
+3545
+3546
+3547
+3548
+3549
+3550
+3551
+3552
+3553
+3554
+3555
+3556
+3557
+3558
+3559
+3560
+3561
+3562
+3563
+3564
+3565
+3566
+3567
+3568
+3569
+3570
+3571
+3572
+3573
+3574
+3575
+3576
+3577
+3578
+3579
+3580
+3581
+3582
+3583
+3584
+3585
+3586
+3587
+3588
+3589
+3590
+3591
+3592
+3593
+3594
+3595
+3596
+3597
+3598
+3599
+3600
+3601
+3602
+3603
+3604
+3605
+3606
+3607
+3608
+3609
+3610
+3611
+3612
+3613
+3614
+3615
+3616
+3617
+3618
+3619
+3620
+3621
+3622
+3623
+3624
+3625
+3626
+3627
+3628
+3629
+3630
+3631
+3632
+3633
+3634
+3635
+3636
+3637
+3638
+3639
+3640
+3641
+3642
+3643
+3644
+3645
+3646
+3647
+3648
+3649
+3650
+3651
+3652
+3653
+3654
+3655
+3656
+3657
+3658
+3659
+3660
+3661
+3662
+3663
+3664
+3665
+3666
+3667
+3668
+3669
+3670
+3671
+3672
+3673
+3674
+3675
+3676
+3677
+3678
+3679
+3680
+3681
+3682
+3683
+3684
+3685
+3686
+3687
+3688
+3689
+3690
+3691
+3692
+3693
+3694
+3695
+3696
+3697
+3698
+3699
+3700
+3701
+3702
+3703
+3704
+3705
+3706
+3707
+3708
+3709
+3710
+3711
+3712
+3713
+3714
+3715
+3716
+3717
+3718
+3719
+3720
+3721
+3722
+3723
+3724
+3725
+3726
+3727
+3728
+3729
+3730
+3731
+3732
+3733
+3734
+3735
+3736
+3737
+3738
+3739
+3740
+3741
+3742
+3743
+3744
+3745
+3746
+3747
+3748
+3749
+3750
+3751
+3752
+3753
+3754
+3755
+3756
+3757
+3758
+3759
+3760
+3761
+3762
+3763
+3764
+3765
+3766
+3767
+3768
+3769
+3770
+3771
+3772
+3773
+3774
+3775
+3776
+3777
+3778
+3779
+3780
+3781
+3782
+3783
+3784
+3785
+3786
+3787
+3788
+3789
+3790
+3791
+3792
+3793
+3794
+3795
+3796
+3797
+3798
+3799
+3800
+3801
+3802
+3803
+3804
+3805
+3806
+3807
+3808
+3809
+3810
+3811
+3812
+3813
+3814
+3815
+3816
+3817
+3818
+3819
+3820
+3821
+3822
+3823
+3824
+3825
+3826
+3827
+3828
+3829
+3830
+3831
+3832
+3833
+3834
+3835
+3836
+3837
+3838
+3839
+3840
+3841
+3842
+3843
+3844
+3845
+3846
+3847
+3848
+3849
+3850
+3851
+3852
+3853
+3854
+3855
+3856
+3857
+3858
+3859
+3860
+3861
+3862
+3863
+3864
+3865
+3866
+3867
+3868
+3869
+3870
+3871
+3872
+3873
+3874
+3875
+3876
+3877
+3878
+3879
+3880
+3881
+3882
+3883
+3884
+3885
+3886
+3887
+3888
+3889
+3890
+3891
+3892
+3893
+3894
+3895
+3896
+3897
+3898
+3899
+3900
+3901
+3902
+3903
+3904
+3905
+3906
+3907
+3908
+3909
+3910
+3911
+3912
+3913
+3914
+3915
+3916
+3917
+3918
+3919
+3920
+3921
+3922
+3923
+3924
+3925
+3926
+3927
+3928
+3929
+3930
+3931
+3932
+3933
+3934
+3935
+3936
+3937
+3938
+3939
+3940
+3941
+3942
+3943
+3944
+3945
+3946
+3947
+3948
+3949
+3950
+3951
+3952
+3953
+3954
+3955
+3956
+3957
+3958
+3959
+3960
+3961
+3962
+3963
+3964
+3965
+3966
+3967
+3968
+
// 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`] structure.
+
+use std::cell::RefCell;
+use std::collections::HashMap;
+use std::collections::{BTreeMap, HashSet};
+use std::fmt;
+use std::ops::{Deref, DerefMut};
+use std::str::FromStr;
+use std::sync::Arc;
+
+use bitcoin::secp256k1::Secp256k1;
+
+use bitcoin::consensus::encode::serialize;
+use bitcoin::util::base58;
+use bitcoin::util::psbt::raw::Key as PsbtKey;
+use bitcoin::util::psbt::Input;
+use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
+use bitcoin::{Address, Network, OutPoint, Script, SigHashType, Transaction, TxOut, Txid};
+
+use miniscript::descriptor::DescriptorTrait;
+use miniscript::psbt::PsbtInputSatisfier;
+
+#[allow(unused_imports)]
+use log::{debug, error, info, trace};
+
+pub mod address_validator;
+pub mod coin_selection;
+pub mod export;
+pub mod signer;
+pub mod time;
+pub mod tx_builder;
+pub(crate) mod utils;
+#[cfg(feature = "verify")]
+#[cfg_attr(docsrs, doc(cfg(feature = "verify")))]
+pub mod verify;
+
+pub use utils::IsDust;
+
+use address_validator::AddressValidator;
+use coin_selection::DefaultCoinSelectionAlgorithm;
+use signer::{SignOptions, Signer, SignerOrdering, SignersContainer};
+use tx_builder::{BumpFee, CreateTx, FeePolicy, TxBuilder, TxParams};
+use utils::{check_nlocktime, check_nsequence_rbf, After, Older, SecpCtx, DUST_LIMIT_SATOSHI};
+
+use crate::blockchain::{Blockchain, Progress};
+use crate::database::memory::MemoryDatabase;
+use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
+use crate::descriptor::derived::AsDerived;
+use crate::descriptor::policy::BuildSatisfaction;
+use crate::descriptor::{
+    get_checksum, into_wallet_descriptor_checked, DerivedDescriptor, DerivedDescriptorMeta,
+    DescriptorMeta, DescriptorScripts, ExtendedDescriptor, ExtractPolicy, IntoWalletDescriptor,
+    Policy, XKeyUtils,
+};
+use crate::error::Error;
+use crate::psbt::PsbtUtils;
+use crate::signer::SignerError;
+use crate::testutils;
+use crate::types::*;
+
+const CACHE_ADDR_BATCH_SIZE: u32 = 100;
+
+/// A Bitcoin wallet
+///
+/// A wallet takes descriptors, a [`database`](trait@crate::database::Database) and a
+/// [`blockchain`](trait@crate::blockchain::Blockchain) and implements the basic functions that a Bitcoin wallets
+/// needs to operate, like [generating addresses](Wallet::get_address), [returning the balance](Wallet::get_balance),
+/// [creating transactions](Wallet::build_tx), etc.
+///
+/// A wallet can be either "online" if the [`blockchain`](crate::blockchain) type provided
+/// implements [`Blockchain`], or "offline" if it is the unit type `()`. Offline wallets only expose
+/// methods that don't need any interaction with the blockchain to work.
+#[derive(Debug)]
+pub struct Wallet<B, D> {
+    descriptor: ExtendedDescriptor,
+    change_descriptor: Option<ExtendedDescriptor>,
+
+    signers: Arc<SignersContainer>,
+    change_signers: Arc<SignersContainer>,
+
+    address_validators: Vec<Arc<dyn AddressValidator>>,
+
+    network: Network,
+
+    current_height: Option<u32>,
+
+    client: B,
+    database: RefCell<D>,
+
+    secp: SecpCtx,
+}
+
+impl<D> Wallet<(), D>
+where
+    D: BatchDatabase,
+{
+    /// Create a new "offline" wallet
+    pub fn new_offline<E: IntoWalletDescriptor>(
+        descriptor: E,
+        change_descriptor: Option<E>,
+        network: Network,
+        database: D,
+    ) -> Result<Self, Error> {
+        Self::_new(descriptor, change_descriptor, network, database, (), None)
+    }
+}
+
+impl<B, D> Wallet<B, D>
+where
+    D: BatchDatabase,
+{
+    fn _new<E: IntoWalletDescriptor>(
+        descriptor: E,
+        change_descriptor: Option<E>,
+        network: Network,
+        mut database: D,
+        client: B,
+        current_height: Option<u32>,
+    ) -> Result<Self, Error> {
+        let secp = Secp256k1::new();
+
+        let (descriptor, keymap) = into_wallet_descriptor_checked(descriptor, &secp, network)?;
+        database.check_descriptor_checksum(
+            KeychainKind::External,
+            get_checksum(&descriptor.to_string())?.as_bytes(),
+        )?;
+        let signers = Arc::new(SignersContainer::from(keymap));
+        let (change_descriptor, change_signers) = match change_descriptor {
+            Some(desc) => {
+                let (change_descriptor, change_keymap) =
+                    into_wallet_descriptor_checked(desc, &secp, network)?;
+                database.check_descriptor_checksum(
+                    KeychainKind::Internal,
+                    get_checksum(&change_descriptor.to_string())?.as_bytes(),
+                )?;
+
+                let change_signers = Arc::new(SignersContainer::from(change_keymap));
+                // if !parsed.same_structure(descriptor.as_ref()) {
+                //     return Err(Error::DifferentDescriptorStructure);
+                // }
+
+                (Some(change_descriptor), change_signers)
+            }
+            None => (None, Arc::new(SignersContainer::new())),
+        };
+
+        Ok(Wallet {
+            descriptor,
+            change_descriptor,
+            signers,
+            change_signers,
+            address_validators: Vec::new(),
+            network,
+            current_height,
+            client,
+            database: RefCell::new(database),
+            secp,
+        })
+    }
+
+    /// Get the Bitcoin network the wallet is using.
+    pub fn network(&self) -> Network {
+        self.network
+    }
+}
+
+/// The address index selection strategy to use to derived an address from the wallet's external
+/// descriptor. See [`Wallet::get_address`]. If you're unsure which one to use use `WalletIndex::New`.
+#[derive(Debug)]
+pub enum AddressIndex {
+    /// Return a new address after incrementing the current descriptor index.
+    New,
+    /// Return the address for the current descriptor index if it has not been used in a received
+    /// transaction. Otherwise return a new address as with [`AddressIndex::New`].
+    ///
+    /// Use with caution, if the wallet has not yet detected an address has been used it could
+    /// return an already used address. This function is primarily meant for situations where the
+    /// caller is untrusted; for example when deriving donation addresses on-demand for a public
+    /// web page.
+    LastUnused,
+    /// Return the address for a specific descriptor index. Does not change the current descriptor
+    /// index used by `AddressIndex::New` and `AddressIndex::LastUsed`.
+    ///
+    /// Use with caution, if an index is given that is less than the current descriptor index
+    /// then the returned address may have already been used.
+    Peek(u32),
+    /// Return the address for a specific descriptor index and reset the current descriptor index
+    /// used by `AddressIndex::New` and `AddressIndex::LastUsed` to this value.
+    ///
+    /// Use with caution, if an index is given that is less than the current descriptor index
+    /// then the returned address and subsequent addresses returned by calls to `AddressIndex::New`
+    /// and `AddressIndex::LastUsed` may have already been used. Also if the index is reset to a
+    /// value earlier than the [`crate::blockchain::Blockchain`] stop_gap (default is 20) then a
+    /// larger stop_gap should be used to monitor for all possibly used addresses.
+    Reset(u32),
+}
+
+/// A derived address and the index it was found at
+/// For convenience this automatically derefs to `Address`
+#[derive(Debug, PartialEq)]
+pub struct AddressInfo {
+    /// Child index of this address
+    pub index: u32,
+    /// Address
+    pub address: Address,
+}
+
+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)
+    }
+}
+
+// offline actions, always available
+impl<B, D> Wallet<B, D>
+where
+    D: BatchDatabase,
+{
+    // Return a newly derived address using the external descriptor
+    fn get_new_address(&self) -> Result<AddressInfo, Error> {
+        let incremented_index = self.fetch_and_increment_index(KeychainKind::External)?;
+
+        let address_result = self
+            .descriptor
+            .as_derived(incremented_index, &self.secp)
+            .address(self.network);
+
+        address_result
+            .map(|address| AddressInfo {
+                address,
+                index: incremented_index,
+            })
+            .map_err(|_| Error::ScriptDoesntHaveAddressForm)
+    }
+
+    // Return the the last previously derived address if it has not been used in a received
+    // transaction. Otherwise return a new address using [`Wallet::get_new_address`].
+    fn get_unused_address(&self) -> Result<AddressInfo, Error> {
+        let current_index = self.fetch_index(KeychainKind::External)?;
+
+        let derived_key = self.descriptor.as_derived(current_index, &self.secp);
+
+        let script_pubkey = derived_key.script_pubkey();
+
+        let found_used = self
+            .list_transactions(true)?
+            .iter()
+            .flat_map(|tx_details| tx_details.transaction.as_ref())
+            .flat_map(|tx| tx.output.iter())
+            .any(|o| o.script_pubkey == script_pubkey);
+
+        if found_used {
+            self.get_new_address()
+        } else {
+            derived_key
+                .address(self.network)
+                .map(|address| AddressInfo {
+                    address,
+                    index: current_index,
+                })
+                .map_err(|_| Error::ScriptDoesntHaveAddressForm)
+        }
+    }
+
+    // Return derived address for the external descriptor at a specific index
+    fn peek_address(&self, index: u32) -> Result<AddressInfo, Error> {
+        self.descriptor
+            .as_derived(index, &self.secp)
+            .address(self.network)
+            .map(|address| AddressInfo { index, address })
+            .map_err(|_| Error::ScriptDoesntHaveAddressForm)
+    }
+
+    // Return derived address for the external descriptor at a specific index and reset current
+    // address index
+    fn reset_address(&self, index: u32) -> Result<AddressInfo, Error> {
+        self.set_index(KeychainKind::External, index)?;
+
+        self.descriptor
+            .as_derived(index, &self.secp)
+            .address(self.network)
+            .map(|address| AddressInfo { index, address })
+            .map_err(|_| Error::ScriptDoesntHaveAddressForm)
+    }
+
+    /// Return a derived address using the external descriptor, see [`AddressIndex`] for
+    /// available address index selection strategies. If none of the keys in the descriptor are derivable
+    /// (ie. does not end with /*) then the same address will always be returned for any [`AddressIndex`].
+    pub fn get_address(&self, address_index: AddressIndex) -> Result<AddressInfo, Error> {
+        match address_index {
+            AddressIndex::New => self.get_new_address(),
+            AddressIndex::LastUnused => self.get_unused_address(),
+            AddressIndex::Peek(index) => self.peek_address(index),
+            AddressIndex::Reset(index) => self.reset_address(index),
+        }
+    }
+
+    /// Return whether or not a `script` is part of this wallet (either internal or external)
+    pub fn is_mine(&self, script: &Script) -> Result<bool, Error> {
+        self.database.borrow().is_mine(script)
+    }
+
+    /// Return the list of unspent outputs of this wallet
+    ///
+    /// Note that this methods only operate on the internal database, which first needs to be
+    /// [`Wallet::sync`] manually.
+    pub fn list_unspent(&self) -> Result<Vec<LocalUtxo>, Error> {
+        self.database.borrow().iter_utxos()
+    }
+
+    /// Returns the `UTXO` owned by this wallet corresponding to `outpoint` if it exists in the
+    /// wallet's database.
+    pub fn get_utxo(&self, outpoint: OutPoint) -> Result<Option<LocalUtxo>, Error> {
+        self.database.borrow().get_utxo(&outpoint)
+    }
+
+    /// Return the list of transactions made and received by the wallet
+    ///
+    /// Optionally fill the [`TransactionDetails::transaction`] field with the raw transaction if
+    /// `include_raw` is `true`.
+    ///
+    /// Note that this methods only operate on the internal database, which first needs to be
+    /// [`Wallet::sync`] manually.
+    pub fn list_transactions(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
+        self.database.borrow().iter_txs(include_raw)
+    }
+
+    /// Return the balance, meaning the sum of this wallet's unspent outputs' values
+    ///
+    /// Note that this methods only operate on the internal database, which first needs to be
+    /// [`Wallet::sync`] manually.
+    pub fn get_balance(&self) -> Result<u64, Error> {
+        Ok(self
+            .list_unspent()?
+            .iter()
+            .fold(0, |sum, i| sum + i.txout.value))
+    }
+
+    /// 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 Signer>,
+    ) {
+        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);
+    }
+
+    /// Add an address validator
+    ///
+    /// See [the `address_validator` module](address_validator) for an example.
+    pub fn add_address_validator(&mut self, validator: Arc<dyn AddressValidator>) {
+        self.address_validators.push(validator);
+    }
+
+    /// 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::database::*;
+    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+    /// # let wallet = doctest_wallet!();
+    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+    /// let (psbt, details) = {
+    ///    let mut builder =  wallet.build_tx();
+    ///    builder
+    ///        .add_recipient(to_address.script_pubkey(), 50_000);
+    ///    builder.finish()?
+    /// };
+    ///
+    /// // sign and broadcast ...
+    /// # Ok::<(), bdk::Error>(())
+    /// ```
+    ///
+    /// [`TxBuilder`]: crate::TxBuilder
+    pub fn build_tx(&self) -> TxBuilder<'_, B, D, DefaultCoinSelectionAlgorithm, CreateTx> {
+        TxBuilder {
+            wallet: self,
+            params: TxParams::default(),
+            coin_selection: DefaultCoinSelectionAlgorithm::default(),
+            phantom: core::marker::PhantomData,
+        }
+    }
+
+    pub(crate) fn create_tx<Cs: coin_selection::CoinSelectionAlgorithm<D>>(
+        &self,
+        coin_selection: Cs,
+        params: TxParams,
+    ) -> Result<(Psbt, TransactionDetails), Error> {
+        let external_policy = self
+            .descriptor
+            .extract_policy(&self.signers, BuildSatisfaction::None, &self.secp)?
+            .unwrap();
+        let internal_policy = self
+            .change_descriptor
+            .as_ref()
+            .map(|desc| {
+                Ok::<_, Error>(
+                    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(Error::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(Error::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::<_, Error>(
+                    policy.get_condition(
+                        params
+                            .internal_policy_path
+                            .as_ref()
+                            .unwrap_or(&BTreeMap::new()),
+                    )?,
+                )
+            })
+            .transpose()?;
+
+        let requirements =
+            external_requirements.merge(&internal_requirements.unwrap_or_default())?;
+        debug!("Policy requirements: {:?}", requirements);
+
+        let version = match params.version {
+            Some(tx_builder::Version(0)) => {
+                return Err(Error::Generic("Invalid version `0`".into()))
+            }
+            Some(tx_builder::Version(1)) if requirements.csv.is_some() => {
+                return Err(Error::Generic(
+                    "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
+                        .into(),
+                ))
+            }
+            Some(tx_builder::Version(x)) => x,
+            None if requirements.csv.is_some() => 2,
+            _ => 1,
+        };
+
+        let lock_time = match params.locktime {
+            // No nLockTime, default to 0
+            None => requirements.timelock.unwrap_or(0),
+            // 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 check_nlocktime(x, requirements.timelock.unwrap()) => x,
+            // Invalid nLockTime required
+            Some(x) => return Err(Error::Generic(format!("TxBuilder requested timelock of `{}`, but at least `{}` is required to spend from this script", x, requirements.timelock.unwrap())))
+        };
+
+        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 != 0 => 0xFFFFFFFE,
+            // No RBF, CSV or nLockTime, make the transaction final
+            (None, None) => 0xFFFFFFFF,
+
+            // 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 >= 0xFFFFFFFE => {
+                return Err(Error::Generic(
+                    "Cannot enable RBF with a nSequence >= 0xFFFFFFFE".into(),
+                ))
+            }
+            // 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(Error::Generic(format!(
+                    "Cannot enable RBF with nSequence `{}` given a required OP_CSV of `{}`",
+                    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
+            .as_ref()
+            .unwrap_or(&FeePolicy::FeeRate(FeeRate::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(Error::FeeTooLow {
+                            required: previous_fee.absolute,
+                        });
+                    }
+                }
+                (FeeRate::from_sat_per_vb(0.0), *fee)
+            }
+            FeePolicy::FeeRate(rate) => {
+                if let Some(previous_fee) = params.bumping_fee {
+                    let required_feerate = FeeRate::from_sat_per_vb(previous_fee.rate + 1.0);
+                    if *rate < required_feerate {
+                        return Err(Error::FeeRateTooLow {
+                            required: required_feerate,
+                        });
+                    }
+                }
+                (*rate, 0)
+            }
+        };
+
+        let mut tx = Transaction {
+            version,
+            lock_time,
+            input: vec![],
+            output: vec![],
+        };
+
+        if params.manually_selected_only && params.utxos.is_empty() {
+            return Err(Error::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;
+
+        fee_amount += fee_rate.fee_wu(tx.get_weight());
+
+        let recipients = params.recipients.iter().map(|(r, v)| (r, *v));
+
+        for (index, (script_pubkey, value)) in recipients.enumerate() {
+            if value.is_dust() {
+                return Err(Error::OutputBelowDustLimit(index));
+            }
+
+            if self.is_mine(script_pubkey)? {
+                received += value;
+            }
+
+            let new_out = TxOut {
+                script_pubkey: script_pubkey.clone(),
+                value,
+            };
+            fee_amount += fee_rate.fee_vb(serialize(&new_out).len());
+
+            tx.output.push(new_out);
+
+            outgoing += value;
+        }
+
+        if params.change_policy != tx_builder::ChangeSpendPolicy::ChangeAllowed
+            && self.change_descriptor.is_none()
+        {
+            return Err(Error::Generic(
+                "The `change_policy` can be set only if the wallet has a change_descriptor".into(),
+            ));
+        }
+
+        let (required_utxos, optional_utxos) = self.preselect_utxos(
+            params.change_policy,
+            &params.unspendable,
+            params.utxos.clone(),
+            params.drain_wallet,
+            params.manually_selected_only,
+            params.bumping_fee.is_some(), // we mandate confirmed transactions if we're bumping the fee
+        )?;
+
+        let coin_selection = coin_selection.coin_select(
+            self.database.borrow().deref(),
+            required_utxos,
+            optional_utxos,
+            fee_rate,
+            outgoing,
+            fee_amount,
+        )?;
+        let mut fee_amount = coin_selection.fee_amount;
+
+        tx.input = coin_selection
+            .selected
+            .iter()
+            .map(|u| bitcoin::TxIn {
+                previous_output: u.outpoint(),
+                script_sig: Script::default(),
+                sequence: n_sequence,
+                witness: vec![],
+            })
+            .collect();
+
+        // prepare the drain output
+        let mut drain_output = {
+            let script_pubkey = match params.drain_to {
+                Some(ref drain_recipient) => drain_recipient.clone(),
+                None => self.get_change_address()?,
+            };
+
+            TxOut {
+                script_pubkey,
+                value: 0,
+            }
+        };
+
+        fee_amount += fee_rate.fee_vb(serialize(&drain_output).len());
+
+        let drain_val = (coin_selection.selected_amount() - outgoing).saturating_sub(fee_amount);
+
+        if tx.output.is_empty() {
+            if params.drain_to.is_some() {
+                if drain_val.is_dust() {
+                    return Err(Error::InsufficientFunds {
+                        needed: DUST_LIMIT_SATOSHI,
+                        available: drain_val,
+                    });
+                }
+            } else {
+                return Err(Error::NoRecipients);
+            }
+        }
+
+        if drain_val.is_dust() {
+            fee_amount += drain_val;
+        } else {
+            drain_output.value = drain_val;
+            if self.is_mine(&drain_output.script_pubkey)? {
+                received += drain_val;
+            }
+            tx.output.push(drain_output);
+        }
+
+        // sort input/outputs according to the chosen algorithm
+        params.ordering.sort_tx(&mut tx);
+
+        let txid = tx.txid();
+        let sent = coin_selection.local_selected_amount();
+        let psbt = self.complete_transaction(tx, coin_selection.selected, params)?;
+
+        let transaction_details = TransactionDetails {
+            transaction: None,
+            txid,
+            confirmation_time: None,
+            received,
+            sent,
+            fee: Some(fee_amount),
+            verified: true,
+        };
+
+        Ok((psbt, transaction_details))
+    }
+
+    /// 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
+    /// *repalce 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::database::*;
+    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+    /// # let wallet = doctest_wallet!();
+    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+    /// let (mut psbt, _) = {
+    ///     let mut builder = wallet.build_tx();
+    ///     builder
+    ///         .add_recipient(to_address.script_pubkey(), 50_000)
+    ///         .enable_rbf();
+    ///     builder.finish()?
+    /// };
+    /// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
+    /// let tx = psbt.extract_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.0));
+    ///     builder.finish()?
+    /// };
+    ///
+    /// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
+    /// let fee_bumped_tx = psbt.extract_tx();
+    /// // broadcast fee_bumped_tx to replace original
+    /// # Ok::<(), bdk::Error>(())
+    /// ```
+    // TODO: support for merging multiple transactions while bumping the fees
+    // TODO: option to force addition of an extra output? seems bad for privacy to update the
+    // change
+    pub fn build_fee_bump(
+        &self,
+        txid: Txid,
+    ) -> Result<TxBuilder<'_, B, D, DefaultCoinSelectionAlgorithm, BumpFee>, Error> {
+        let mut details = match self.database.borrow().get_tx(&txid, true)? {
+            None => return Err(Error::TransactionNotFound),
+            Some(tx) if tx.transaction.is_none() => return Err(Error::TransactionNotFound),
+            Some(tx) if tx.confirmation_time.is_some() => return Err(Error::TransactionConfirmed),
+            Some(tx) => tx,
+        };
+        let mut tx = details.transaction.take().unwrap();
+        if !tx.input.iter().any(|txin| txin.sequence <= 0xFFFFFFFD) {
+            return Err(Error::IrreplaceableTransaction);
+        }
+
+        let feerate = FeeRate::from_wu(
+            details.fee.ok_or(Error::FeeRateUnavailable)?,
+            tx.get_weight(),
+        );
+
+        // remove the inputs from the tx and process them
+        let original_txin = tx.input.drain(..).collect::<Vec<_>>();
+        let original_utxos = original_txin
+            .iter()
+            .map(|txin| -> Result<_, Error> {
+                let txout = self
+                    .database
+                    .borrow()
+                    .get_previous_output(&txin.previous_output)?
+                    .ok_or(Error::UnknownUtxo)?;
+
+                let (weight, keychain) = match self
+                    .database
+                    .borrow()
+                    .get_path_from_script_pubkey(&txout.script_pubkey)?
+                {
+                    Some((keychain, _)) => (
+                        self._get_descriptor_for_keychain(keychain)
+                            .0
+                            .max_satisfaction_weight()
+                            .unwrap(),
+                        keychain,
+                    ),
+                    None => {
+                        // estimate the weight based on the scriptsig/witness size present in the
+                        // original transaction
+                        let weight =
+                            serialize(&txin.script_sig).len() * 4 + serialize(&txin.witness).len();
+                        (weight, KeychainKind::External)
+                    }
+                };
+
+                let utxo = LocalUtxo {
+                    outpoint: txin.previous_output,
+                    txout,
+                    keychain,
+                };
+
+                Ok(WeightedUtxo {
+                    satisfaction_weight: weight,
+                    utxo: Utxo::Local(utxo),
+                })
+            })
+            .collect::<Result<Vec<_>, _>>()?;
+
+        if tx.output.len() > 1 {
+            let mut change_index = None;
+            for (index, txout) in tx.output.iter().enumerate() {
+                let (_, change_type) = self._get_descriptor_for_keychain(KeychainKind::Internal);
+                match self
+                    .database
+                    .borrow()
+                    .get_path_from_script_pubkey(&txout.script_pubkey)?
+                {
+                    Some((keychain, _)) if keychain == change_type => change_index = Some(index),
+                    _ => {}
+                }
+            }
+
+            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)),
+            recipients: tx
+                .output
+                .into_iter()
+                .map(|txout| (txout.script_pubkey, txout.value))
+                .collect(),
+            utxos: original_utxos,
+            bumping_fee: Some(tx_builder::PreviousFee {
+                absolute: details.fee.ok_or(Error::FeeRateUnavailable)?,
+                rate: feerate.as_sat_vb(),
+            }),
+            ..Default::default()
+        };
+
+        Ok(TxBuilder {
+            wallet: 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`]
+    ///
+    /// 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::database::*;
+    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+    /// # let wallet = doctest_wallet!();
+    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+    /// let (mut psbt, _) = {
+    ///     let mut builder = wallet.build_tx();
+    ///     builder.add_recipient(to_address.script_pubkey(), 50_000);
+    ///     builder.finish()?
+    /// };
+    /// let  finalized = wallet.sign(&mut psbt, SignOptions::default())?;
+    /// assert!(finalized, "we should have signed all the inputs");
+    /// # Ok::<(), bdk::Error>(())
+    pub fn sign(&self, psbt: &mut Psbt, sign_options: SignOptions) -> Result<bool, Error> {
+        // this helps us doing our job later
+        self.add_input_hd_keypaths(psbt)?;
+
+        // If we aren't allowed to use `witness_utxo`, ensure that every input but finalized one
+        // 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())
+                .any(|i| i.non_witness_utxo.is_none())
+        {
+            return Err(Error::Signer(signer::SignerError::MissingNonWitnessUtxo));
+        }
+
+        // If the user hasn't explicitly opted-in, refuse to sign the transaction unless every input
+        // is using `SIGHASH_ALL`
+        if !sign_options.allow_all_sighashes
+            && !psbt
+                .inputs
+                .iter()
+                .all(|i| i.sighash_type.is_none() || i.sighash_type == Some(SigHashType::All))
+        {
+            return Err(Error::Signer(signer::SignerError::NonStandardSighash));
+        }
+
+        for signer in self
+            .signers
+            .signers()
+            .iter()
+            .chain(self.change_signers.signers().iter())
+        {
+            if signer.sign_whole_tx() {
+                signer.sign(psbt, None, &self.secp)?;
+            } else {
+                for index in 0..psbt.inputs.len() {
+                    signer.sign(psbt, Some(index), &self.secp)?;
+                }
+            }
+        }
+
+        // attempt to finalize
+        self.finalize_psbt(psbt, sign_options)
+    }
+
+    /// Return the spending policies for the wallet's descriptor
+    pub fn policies(&self, keychain: KeychainKind) -> Result<Option<Policy>, Error> {
+        match (keychain, self.change_descriptor.as_ref()) {
+            (KeychainKind::External, _) => Ok(self.descriptor.extract_policy(
+                &self.signers,
+                BuildSatisfaction::None,
+                &self.secp,
+            )?),
+            (KeychainKind::Internal, None) => Ok(None),
+            (KeychainKind::Internal, Some(desc)) => Ok(desc.extract_policy(
+                &self.change_signers,
+                BuildSatisfaction::None,
+                &self.secp,
+            )?),
+        }
+    }
+
+    /// 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,
+    ) -> Result<Option<ExtendedDescriptor>, Error> {
+        match (keychain, self.change_descriptor.as_ref()) {
+            (KeychainKind::External, _) => Ok(Some(self.descriptor.clone())),
+            (KeychainKind::Internal, None) => Ok(None),
+            (KeychainKind::Internal, Some(desc)) => Ok(Some(desc.clone())),
+        }
+    }
+
+    /// Try to finalize a PSBT
+    ///
+    /// 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, Error> {
+        let tx = &psbt.global.unsigned_tx;
+        let mut finished = true;
+
+        for (n, input) in tx.input.iter().enumerate() {
+            let psbt_input = &psbt
+                .inputs
+                .get(n)
+                .ok_or(Error::Signer(SignerError::InputIndexOutOfRange))?;
+            if psbt_input.final_script_sig.is_some() || psbt_input.final_script_witness.is_some() {
+                continue;
+            }
+            // if the height is None in the database it means it's still unconfirmed, so consider
+            // that as a very high value
+            let create_height = self
+                .database
+                .borrow()
+                .get_tx(&input.previous_output.txid, false)?
+                .map(|tx| tx.confirmation_time.map(|c| c.height).unwrap_or(u32::MAX));
+            let current_height = sign_options.assume_height.or(self.current_height);
+
+            debug!(
+                "Input #{} - {}, using `create_height` = {:?}, `current_height` = {:?}",
+                n, input.previous_output, create_height, current_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)
+                .map(|txout| self.get_descriptor_for_txout(&txout))
+                .transpose()?
+                .flatten()
+                .or_else(|| {
+                    self.descriptor.derive_from_psbt_input(
+                        psbt_input,
+                        psbt.get_utxo_for(n),
+                        &self.secp,
+                    )
+                })
+                .or_else(|| {
+                    self.change_descriptor.as_ref().and_then(|desc| {
+                        desc.derive_from_psbt_input(psbt_input, psbt.get_utxo_for(n), &self.secp)
+                    })
+                });
+
+            match desc {
+                Some(desc) => {
+                    let mut tmp_input = bitcoin::TxIn::default();
+                    match desc.satisfy(
+                        &mut tmp_input,
+                        (
+                            PsbtInputSatisfier::new(psbt, n),
+                            After::new(current_height, false),
+                            Older::new(current_height, create_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);
+                        }
+                        Err(e) => {
+                            debug!("satisfy error {:?} for input {}", e, n);
+                            finished = false
+                        }
+                    }
+                }
+                None => finished = false,
+            }
+        }
+
+        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 adddresses for a particular `keychain`.
+    pub fn get_descriptor_for_keychain(&self, keychain: KeychainKind) -> &ExtendedDescriptor {
+        let (descriptor, _) = self._get_descriptor_for_keychain(keychain);
+        descriptor
+    }
+
+    // Internals
+
+    fn _get_descriptor_for_keychain(
+        &self,
+        keychain: KeychainKind,
+    ) -> (&ExtendedDescriptor, KeychainKind) {
+        match keychain {
+            KeychainKind::Internal if self.change_descriptor.is_some() => (
+                self.change_descriptor.as_ref().unwrap(),
+                KeychainKind::Internal,
+            ),
+            _ => (&self.descriptor, KeychainKind::External),
+        }
+    }
+
+    fn get_descriptor_for_txout(
+        &self,
+        txout: &TxOut,
+    ) -> Result<Option<DerivedDescriptor<'_>>, Error> {
+        Ok(self
+            .database
+            .borrow()
+            .get_path_from_script_pubkey(&txout.script_pubkey)?
+            .map(|(keychain, child)| (self.get_descriptor_for_keychain(keychain), child))
+            .map(|(desc, child)| desc.as_derived(child, &self.secp)))
+    }
+
+    fn get_change_address(&self) -> Result<Script, Error> {
+        let (desc, keychain) = self._get_descriptor_for_keychain(KeychainKind::Internal);
+        let index = self.fetch_and_increment_index(keychain)?;
+
+        Ok(desc.as_derived(index, &self.secp).script_pubkey())
+    }
+
+    fn fetch_and_increment_index(&self, keychain: KeychainKind) -> Result<u32, Error> {
+        let (descriptor, keychain) = self._get_descriptor_for_keychain(keychain);
+        let index = match descriptor.is_deriveable() {
+            false => 0,
+            true => self.database.borrow_mut().increment_last_index(keychain)?,
+        };
+
+        if self
+            .database
+            .borrow()
+            .get_script_pubkey_from_path(keychain, index)?
+            .is_none()
+        {
+            self.cache_addresses(keychain, index, CACHE_ADDR_BATCH_SIZE)?;
+        }
+
+        let derived_descriptor = descriptor.as_derived(index, &self.secp);
+
+        let hd_keypaths = derived_descriptor.get_hd_keypaths(&self.secp)?;
+        let script = derived_descriptor.script_pubkey();
+
+        for validator in &self.address_validators {
+            validator.validate(keychain, &hd_keypaths, &script)?;
+        }
+
+        Ok(index)
+    }
+
+    fn fetch_index(&self, keychain: KeychainKind) -> Result<u32, Error> {
+        let (descriptor, keychain) = self._get_descriptor_for_keychain(keychain);
+        let index = match descriptor.is_deriveable() {
+            false => Some(0),
+            true => self.database.borrow_mut().get_last_index(keychain)?,
+        };
+
+        if let Some(i) = index {
+            Ok(i)
+        } else {
+            self.fetch_and_increment_index(keychain)
+        }
+    }
+
+    fn set_index(&self, keychain: KeychainKind, index: u32) -> Result<(), Error> {
+        self.database.borrow_mut().set_last_index(keychain, index)?;
+        Ok(())
+    }
+
+    fn cache_addresses(
+        &self,
+        keychain: KeychainKind,
+        from: u32,
+        mut count: u32,
+    ) -> Result<(), Error> {
+        let (descriptor, keychain) = self._get_descriptor_for_keychain(keychain);
+        if !descriptor.is_deriveable() {
+            if from > 0 {
+                return Ok(());
+            }
+
+            count = 1;
+        }
+
+        let mut address_batch = self.database.borrow().begin_batch();
+
+        let start_time = time::Instant::new();
+        for i in from..(from + count) {
+            address_batch.set_script_pubkey(
+                &descriptor.as_derived(i, &self.secp).script_pubkey(),
+                keychain,
+                i,
+            )?;
+        }
+
+        info!(
+            "Derivation of {} addresses from {} took {} ms",
+            count,
+            from,
+            start_time.elapsed().as_millis()
+        );
+
+        self.database.borrow_mut().commit_batch(address_batch)?;
+
+        Ok(())
+    }
+
+    fn get_available_utxos(&self) -> Result<Vec<(LocalUtxo, usize)>, Error> {
+        Ok(self
+            .list_unspent()?
+            .into_iter()
+            .map(|utxo| {
+                let keychain = utxo.keychain;
+                (
+                    utxo,
+                    self.get_descriptor_for_keychain(keychain)
+                        .max_satisfaction_weight()
+                        .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.
+    #[allow(clippy::type_complexity)]
+    fn preselect_utxos(
+        &self,
+        change_policy: tx_builder::ChangeSpendPolicy,
+        unspendable: &HashSet<OutPoint>,
+        manually_selected: Vec<WeightedUtxo>,
+        must_use_all_available: bool,
+        manual_only: bool,
+        must_only_use_confirmed_tx: bool,
+    ) -> Result<(Vec<WeightedUtxo>, Vec<WeightedUtxo>), Error> {
+        //    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 manual_only {
+            return Ok((must_spend, vec![]));
+        }
+
+        let satisfies_confirmed = match must_only_use_confirmed_tx {
+            true => {
+                let database = self.database.borrow();
+                may_spend
+                    .iter()
+                    .map(|u| {
+                        database
+                            .get_tx(&u.0.outpoint.txid, true)
+                            .map(|tx| match tx {
+                                None => false,
+                                Some(tx) => tx.confirmation_time.is_some(),
+                            })
+                    })
+                    .collect::<Result<Vec<_>, _>>()?
+            }
+            false => vec![true; may_spend.len()],
+        };
+
+        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);
+        }
+
+        Ok((must_spend, may_spend))
+    }
+
+    fn complete_transaction(
+        &self,
+        tx: Transaction,
+        selected: Vec<Utxo>,
+        params: TxParams,
+    ) -> Result<Psbt, Error> {
+        use bitcoin::util::psbt::serialize::Serialize;
+
+        let mut psbt = Psbt::from_unsigned_tx(tx)?;
+
+        if params.add_global_xpubs {
+            let mut all_xpubs = self.descriptor.get_extended_keys()?;
+            if let Some(change_descriptor) = &self.change_descriptor {
+                all_xpubs.extend(change_descriptor.get_extended_keys()?);
+            }
+
+            for xpub in all_xpubs {
+                let serialized_xpub = base58::from_check(&xpub.xkey.to_string())
+                    .expect("Internal serialization error");
+                let key = PsbtKey {
+                    type_value: 0x01,
+                    key: serialized_xpub,
+                };
+
+                let origin = match xpub.origin {
+                    Some(origin) => origin,
+                    None if xpub.xkey.depth == 0 => {
+                        (xpub.root_fingerprint(&self.secp), vec![].into())
+                    }
+                    _ => return Err(Error::MissingKeyOrigin(xpub.xkey.to_string())),
+                };
+
+                psbt.global.unknown.insert(key, origin.serialize());
+            }
+        }
+
+        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.global.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 {
+                                Error::UnknownUtxo => Input {
+                                    sighash_type: params.sighash,
+                                    ..Input::default()
+                                },
+                                _ => return Err(e),
+                            },
+                        }
+                }
+                Utxo::Foreign {
+                    psbt_input: foreign_psbt_input,
+                    outpoint,
+                } => {
+                    if !params.only_witness_utxo && foreign_psbt_input.non_witness_utxo.is_none() {
+                        return Err(Error::Generic(format!(
+                            "Missing non_witness_utxo on foreign utxo {}",
+                            outpoint
+                        )));
+                    }
+                    *psbt_input = *foreign_psbt_input;
+                }
+            }
+        }
+
+        // probably redundant but it doesn't hurt...
+        self.add_input_hd_keypaths(&mut psbt)?;
+
+        // add metadata for the outputs
+        for (psbt_output, tx_output) in psbt
+            .outputs
+            .iter_mut()
+            .zip(psbt.global.unsigned_tx.output.iter())
+        {
+            if let Some((keychain, child)) = self
+                .database
+                .borrow()
+                .get_path_from_script_pubkey(&tx_output.script_pubkey)?
+            {
+                let (desc, _) = self._get_descriptor_for_keychain(keychain);
+                let derived_descriptor = desc.as_derived(child, &self.secp);
+
+                psbt_output.bip32_derivation = derived_descriptor.get_hd_keypaths(&self.secp)?;
+                if params.include_output_redeem_witness_script {
+                    psbt_output.witness_script = derived_descriptor.psbt_witness_script();
+                    psbt_output.redeem_script = derived_descriptor.psbt_redeem_script();
+                };
+            }
+        }
+
+        Ok(psbt)
+    }
+
+    /// get the corresponding PSBT Input for a LocalUtxo
+    pub fn get_psbt_input(
+        &self,
+        utxo: LocalUtxo,
+        sighash_type: Option<SigHashType>,
+        only_witness_utxo: bool,
+    ) -> Result<Input, Error> {
+        // Try to find the prev_script in our db to figure out if this is internal or external,
+        // and the derivation index
+        let (keychain, child) = self
+            .database
+            .borrow()
+            .get_path_from_script_pubkey(&utxo.txout.script_pubkey)?
+            .ok_or(Error::UnknownUtxo)?;
+
+        let mut psbt_input = Input {
+            sighash_type,
+            ..Input::default()
+        };
+
+        let desc = self.get_descriptor_for_keychain(keychain);
+        let derived_descriptor = desc.as_derived(child, &self.secp);
+        psbt_input.bip32_derivation = derived_descriptor.get_hd_keypaths(&self.secp)?;
+
+        psbt_input.redeem_script = derived_descriptor.psbt_redeem_script();
+        psbt_input.witness_script = derived_descriptor.psbt_witness_script();
+
+        let prev_output = utxo.outpoint;
+        if let Some(prev_tx) = self.database.borrow().get_raw_tx(&prev_output.txid)? {
+            if desc.is_witness() {
+                psbt_input.witness_utxo = Some(prev_tx.output[prev_output.vout as usize].clone());
+            }
+            if !desc.is_witness() || !only_witness_utxo {
+                psbt_input.non_witness_utxo = Some(prev_tx);
+            }
+        }
+        Ok(psbt_input)
+    }
+
+    fn add_input_hd_keypaths(&self, psbt: &mut Psbt) -> Result<(), Error> {
+        let mut input_utxos = Vec::with_capacity(psbt.inputs.len());
+        for n in 0..psbt.inputs.len() {
+            input_utxos.push(psbt.get_utxo_for(n).clone());
+        }
+
+        // try to add hd_keypaths if we've already seen the output
+        for (psbt_input, out) in psbt.inputs.iter_mut().zip(input_utxos.iter()) {
+            if let Some(out) = out {
+                if let Some((keychain, child)) = self
+                    .database
+                    .borrow()
+                    .get_path_from_script_pubkey(&out.script_pubkey)?
+                {
+                    debug!("Found descriptor {:?}/{}", keychain, child);
+
+                    // merge hd_keypaths
+                    let desc = self.get_descriptor_for_keychain(keychain);
+                    let mut hd_keypaths = desc
+                        .as_derived(child, &self.secp)
+                        .get_hd_keypaths(&self.secp)?;
+                    psbt_input.bip32_derivation.append(&mut hd_keypaths);
+                }
+            }
+        }
+
+        Ok(())
+    }
+}
+
+impl<B, D> Wallet<B, D>
+where
+    B: Blockchain,
+    D: BatchDatabase,
+{
+    /// Create a new "online" wallet
+    #[maybe_async]
+    pub fn new<E: IntoWalletDescriptor>(
+        descriptor: E,
+        change_descriptor: Option<E>,
+        network: Network,
+        database: D,
+        client: B,
+    ) -> Result<Self, Error> {
+        let current_height = Some(maybe_await!(client.get_height())? as u32);
+        Self::_new(
+            descriptor,
+            change_descriptor,
+            network,
+            database,
+            client,
+            current_height,
+        )
+    }
+
+    /// Sync the internal database with the blockchain
+    #[maybe_async]
+    pub fn sync<P: 'static + Progress>(
+        &self,
+        progress_update: P,
+        max_address_param: Option<u32>,
+    ) -> Result<(), Error> {
+        debug!("Begin sync...");
+
+        let mut run_setup = false;
+
+        let max_address = match self.descriptor.is_deriveable() {
+            false => 0,
+            true => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
+        };
+        debug!("max_address {}", max_address);
+        if self
+            .database
+            .borrow()
+            .get_script_pubkey_from_path(KeychainKind::External, max_address.saturating_sub(1))?
+            .is_none()
+        {
+            debug!("caching external addresses");
+            run_setup = true;
+            self.cache_addresses(KeychainKind::External, 0, max_address)?;
+        }
+
+        if let Some(change_descriptor) = &self.change_descriptor {
+            let max_address = match change_descriptor.is_deriveable() {
+                false => 0,
+                true => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
+            };
+
+            if self
+                .database
+                .borrow()
+                .get_script_pubkey_from_path(KeychainKind::Internal, max_address.saturating_sub(1))?
+                .is_none()
+            {
+                debug!("caching internal addresses");
+                run_setup = true;
+                self.cache_addresses(KeychainKind::Internal, 0, max_address)?;
+            }
+        }
+
+        debug!("run_setup: {}", run_setup);
+        // TODO: what if i generate an address first and cache some addresses?
+        // TODO: we should sync if generating an address triggers a new batch to be stored
+        if run_setup {
+            maybe_await!(self
+                .client
+                .setup(self.database.borrow_mut().deref_mut(), progress_update,))?;
+        } else {
+            maybe_await!(self
+                .client
+                .sync(self.database.borrow_mut().deref_mut(), progress_update,))?;
+        }
+
+        #[cfg(feature = "verify")]
+        {
+            debug!("Verifying transactions...");
+            for mut tx in self.database.borrow().iter_txs(true)? {
+                if !tx.verified {
+                    verify::verify_tx(
+                        tx.transaction.as_ref().ok_or(Error::TransactionNotFound)?,
+                        self.database.borrow().deref(),
+                        &self.client,
+                    )?;
+
+                    tx.verified = true;
+                    self.database.borrow_mut().set_tx(&tx)?;
+                }
+            }
+        }
+
+        Ok(())
+    }
+
+    /// Return a reference to the internal blockchain client
+    pub fn client(&self) -> &B {
+        &self.client
+    }
+
+    /// Broadcast a transaction to the network
+    #[maybe_async]
+    pub fn broadcast(&self, tx: Transaction) -> Result<Txid, Error> {
+        maybe_await!(self.client.broadcast(&tx))?;
+
+        Ok(tx.txid())
+    }
+}
+
+/// Return a fake wallet that appears to be funded for testing.
+pub fn get_funded_wallet(
+    descriptor: &str,
+) -> (
+    Wallet<(), MemoryDatabase>,
+    (String, Option<String>),
+    bitcoin::Txid,
+) {
+    let descriptors = testutils!(@descriptors (descriptor));
+    let wallet = Wallet::new_offline(
+        &descriptors.0,
+        None,
+        Network::Regtest,
+        MemoryDatabase::new(),
+    )
+    .unwrap();
+
+    let funding_address_kix = 0;
+
+    let tx_meta = testutils! {
+            @tx ( (@external descriptors, funding_address_kix) => 50_000 ) (@confirmations 1)
+    };
+
+    wallet
+        .database
+        .borrow_mut()
+        .set_script_pubkey(
+            &bitcoin::Address::from_str(&tx_meta.output.get(0).unwrap().to_address)
+                .unwrap()
+                .script_pubkey(),
+            KeychainKind::External,
+            funding_address_kix,
+        )
+        .unwrap();
+    wallet
+        .database
+        .borrow_mut()
+        .set_last_index(KeychainKind::External, funding_address_kix)
+        .unwrap();
+
+    let txid = crate::populate_test_db!(wallet.database.borrow_mut(), tx_meta, Some(100));
+
+    (wallet, descriptors, txid)
+}
+
+#[cfg(test)]
+pub(crate) mod test {
+    use bitcoin::{util::psbt, Network};
+
+    use crate::database::Database;
+    use crate::types::KeychainKind;
+
+    use super::*;
+    use crate::signer::{SignOptions, SignerError};
+    use crate::wallet::AddressIndex::{LastUnused, New, Peek, Reset};
+
+    #[test]
+    fn test_cache_addresses_fixed() {
+        let db = MemoryDatabase::new();
+        let wallet = Wallet::new_offline(
+            "wpkh(L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6)",
+            None,
+            Network::Testnet,
+            db,
+        )
+        .unwrap();
+
+        assert_eq!(
+            wallet.get_address(New).unwrap().to_string(),
+            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
+        );
+        assert_eq!(
+            wallet.get_address(New).unwrap().to_string(),
+            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
+        );
+
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(KeychainKind::External, 0)
+            .unwrap()
+            .is_some());
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(KeychainKind::Internal, 0)
+            .unwrap()
+            .is_none());
+    }
+
+    #[test]
+    fn test_cache_addresses() {
+        let db = MemoryDatabase::new();
+        let wallet = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
+
+        assert_eq!(
+            wallet.get_address(New).unwrap().to_string(),
+            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
+        );
+        assert_eq!(
+            wallet.get_address(New).unwrap().to_string(),
+            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
+        );
+
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE - 1)
+            .unwrap()
+            .is_some());
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE)
+            .unwrap()
+            .is_none());
+    }
+
+    #[test]
+    fn test_cache_addresses_refill() {
+        let db = MemoryDatabase::new();
+        let wallet = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
+
+        assert_eq!(
+            wallet.get_address(New).unwrap().to_string(),
+            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
+        );
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE - 1)
+            .unwrap()
+            .is_some());
+
+        for _ in 0..CACHE_ADDR_BATCH_SIZE {
+            wallet.get_address(New).unwrap();
+        }
+
+        assert!(wallet
+            .database
+            .borrow_mut()
+            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE * 2 - 1)
+            .unwrap()
+            .is_some());
+    }
+
+    pub(crate) fn get_test_wpkh() -> &'static str {
+        "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)"
+    }
+
+    pub(crate) fn get_test_single_sig_csv() -> &'static str {
+        // and(pk(Alice),older(6))
+        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),older(6)))"
+    }
+
+    pub(crate) fn get_test_a_or_b_plus_csv() -> &'static str {
+        // or(pk(Alice),and(pk(Bob),older(144)))
+        "wsh(or_d(pk(cRjo6jqfVNP33HhSS76UhXETZsGTZYx8FMFvR9kpbtCSV1PmdZdu),and_v(v:pk(cMnkdebixpXMPfkcNEjjGin7s94hiehAH4mLbYkZoh9KSiNNmqC8),older(144))))"
+    }
+
+    pub(crate) fn get_test_single_sig_cltv() -> &'static str {
+        // and(pk(Alice),after(100000))
+        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(100000)))"
+    }
+
+    macro_rules! assert_fee_rate {
+        ($tx:expr, $fees:expr, $fee_rate:expr $( ,@dust_change $( $dust_change:expr )* )* $( ,@add_signature $( $add_signature:expr )* )* ) => ({
+            let mut tx = $tx.clone();
+            $(
+                $( $add_signature )*
+                for txin in &mut tx.input {
+                    txin.witness.push([0x00; 108].to_vec()); // fake signature
+                }
+            )*
+
+            #[allow(unused_mut)]
+            #[allow(unused_assignments)]
+            let mut dust_change = false;
+            $(
+                $( $dust_change )*
+                dust_change = true;
+            )*
+
+            let tx_fee_rate = FeeRate::from_wu($fees, tx.get_weight());
+            let fee_rate = $fee_rate;
+
+            if !dust_change {
+                assert!((tx_fee_rate - fee_rate).as_sat_vb().abs() < 0.5, "Expected fee rate of {:?}, the tx has {:?}", fee_rate, tx_fee_rate);
+            } else {
+                assert!(tx_fee_rate >= fee_rate, "Expected fee rate of at least {:?}, the tx has {:?}", fee_rate, tx_fee_rate);
+            }
+        });
+    }
+
+    #[test]
+    #[should_panic(expected = "NoRecipients")]
+    fn test_create_tx_empty_recipients() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        wallet.build_tx().finish().unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "NoUtxosSelected")]
+    fn test_create_tx_manually_selected_empty_utxos() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .manually_selected_only();
+        builder.finish().unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "Invalid version `0`")]
+    fn test_create_tx_version_0() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .version(0);
+        builder.finish().unwrap();
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
+    )]
+    fn test_create_tx_version_1_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .version(1);
+        builder.finish().unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_custom_version() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .version(42);
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.version, 42);
+    }
+
+    #[test]
+    fn test_create_tx_default_locktime() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.lock_time, 0);
+    }
+
+    #[test]
+    fn test_create_tx_default_locktime_cltv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.lock_time, 100_000);
+    }
+
+    #[test]
+    fn test_create_tx_custom_locktime() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .nlocktime(630_000);
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
+    }
+
+    #[test]
+    fn test_create_tx_custom_locktime_compatible_with_cltv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .nlocktime(630_000);
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "TxBuilder requested timelock of `50000`, but at least `100000` is required to spend from this script"
+    )]
+    fn test_create_tx_custom_locktime_incompatible_with_cltv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .nlocktime(50000);
+        builder.finish().unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_no_rbf_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 6);
+    }
+
+    #[test]
+    fn test_create_tx_with_default_rbf_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .enable_rbf();
+        let (psbt, _) = builder.finish().unwrap();
+        // When CSV is enabled it takes precedence over the rbf value (unless forced by the user).
+        // It will be set to the OP_CSV value, in this case 6
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 6);
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "Cannot enable RBF with nSequence `3` given a required OP_CSV of `6`"
+    )]
+    fn test_create_tx_with_custom_rbf_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .enable_rbf_with_sequence(3);
+        builder.finish().unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_no_rbf_cltv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFE);
+    }
+
+    #[test]
+    #[should_panic(expected = "Cannot enable RBF with a nSequence >= 0xFFFFFFFE")]
+    fn test_create_tx_invalid_rbf_sequence() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .enable_rbf_with_sequence(0xFFFFFFFE);
+        builder.finish().unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_custom_rbf_sequence() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .enable_rbf_with_sequence(0xDEADBEEF);
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xDEADBEEF);
+    }
+
+    #[test]
+    fn test_create_tx_default_sequence() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFF);
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "The `change_policy` can be set only if the wallet has a change_descriptor"
+    )]
+    fn test_create_tx_change_policy_no_internal() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .do_not_spend_change();
+        builder.finish().unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_drain_wallet_and_drain_to() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.drain_to(addr.script_pubkey()).drain_wallet();
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
+        assert_eq!(
+            psbt.global.unsigned_tx.output[0].value,
+            50_000 - details.fee.unwrap_or(0)
+        );
+    }
+
+    #[test]
+    fn test_create_tx_drain_wallet_and_drain_to_and_with_recipient() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+        let drain_addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 20_000)
+            .drain_to(drain_addr.script_pubkey())
+            .drain_wallet();
+        let (psbt, details) = builder.finish().unwrap();
+        dbg!(&psbt);
+        let outputs = psbt.global.unsigned_tx.output;
+
+        assert_eq!(outputs.len(), 2);
+        let main_output = outputs
+            .iter()
+            .find(|x| x.script_pubkey == addr.script_pubkey())
+            .unwrap();
+        let drain_output = outputs
+            .iter()
+            .find(|x| x.script_pubkey == drain_addr.script_pubkey())
+            .unwrap();
+        assert_eq!(main_output.value, 20_000,);
+        assert_eq!(drain_output.value, 30_000 - details.fee.unwrap_or(0));
+    }
+
+    #[test]
+    fn test_create_tx_default_fee_rate() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::default(), @add_signature);
+    }
+
+    #[test]
+    fn test_create_tx_custom_fee_rate() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .fee_rate(FeeRate::from_sat_per_vb(5.0));
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(5.0), @add_signature);
+    }
+
+    #[test]
+    fn test_create_tx_absolute_fee() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .drain_to(addr.script_pubkey())
+            .drain_wallet()
+            .fee_absolute(100);
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(details.fee.unwrap_or(0), 100);
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
+        assert_eq!(
+            psbt.global.unsigned_tx.output[0].value,
+            50_000 - details.fee.unwrap_or(0)
+        );
+    }
+
+    #[test]
+    fn test_create_tx_absolute_zero_fee() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .drain_to(addr.script_pubkey())
+            .drain_wallet()
+            .fee_absolute(0);
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(details.fee.unwrap_or(0), 0);
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
+        assert_eq!(
+            psbt.global.unsigned_tx.output[0].value,
+            50_000 - details.fee.unwrap_or(0)
+        );
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_create_tx_absolute_high_fee() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .drain_to(addr.script_pubkey())
+            .drain_wallet()
+            .fee_absolute(60_000);
+        let (_psbt, _details) = builder.finish().unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_add_change() {
+        use super::tx_builder::TxOrdering;
+
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .ordering(TxOrdering::Untouched);
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 2);
+        assert_eq!(psbt.global.unsigned_tx.output[0].value, 25_000);
+        assert_eq!(
+            psbt.global.unsigned_tx.output[1].value,
+            25_000 - details.fee.unwrap_or(0)
+        );
+    }
+
+    #[test]
+    fn test_create_tx_skip_change_dust() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 49_800);
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
+        assert_eq!(psbt.global.unsigned_tx.output[0].value, 49_800);
+        assert_eq!(details.fee.unwrap_or(0), 200);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_create_tx_drain_to_dust_amount() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        // very high fee rate, so that the only output would be below dust
+        let mut builder = wallet.build_tx();
+        builder
+            .drain_to(addr.script_pubkey())
+            .drain_wallet()
+            .fee_rate(FeeRate::from_sat_per_vb(453.0));
+        builder.finish().unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_ordering_respected() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 30_000)
+            .add_recipient(addr.script_pubkey(), 10_000)
+            .ordering(super::tx_builder::TxOrdering::Bip69Lexicographic);
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.output.len(), 3);
+        assert_eq!(
+            psbt.global.unsigned_tx.output[0].value,
+            10_000 - details.fee.unwrap_or(0)
+        );
+        assert_eq!(psbt.global.unsigned_tx.output[1].value, 10_000);
+        assert_eq!(psbt.global.unsigned_tx.output[2].value, 30_000);
+    }
+
+    #[test]
+    fn test_create_tx_default_sighash() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 30_000);
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(psbt.inputs[0].sighash_type, None);
+    }
+
+    #[test]
+    fn test_create_tx_custom_sighash() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 30_000)
+            .sighash(bitcoin::SigHashType::Single);
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(
+            psbt.inputs[0].sighash_type,
+            Some(bitcoin::SigHashType::Single)
+        );
+    }
+
+    #[test]
+    fn test_create_tx_input_hd_keypaths() {
+        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
+        use std::str::FromStr;
+
+        let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.drain_to(addr.script_pubkey()).drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(psbt.inputs[0].bip32_derivation.len(), 1);
+        assert_eq!(
+            psbt.inputs[0].bip32_derivation.values().next().unwrap(),
+            &(
+                Fingerprint::from_str("d34db33f").unwrap(),
+                DerivationPath::from_str("m/44'/0'/0'/0/0").unwrap()
+            )
+        );
+    }
+
+    #[test]
+    fn test_create_tx_output_hd_keypaths() {
+        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
+        use std::str::FromStr;
+
+        let (wallet, descriptors, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)");
+        // cache some addresses
+        wallet.get_address(New).unwrap();
+
+        let addr = testutils!(@external descriptors, 5);
+        let mut builder = wallet.build_tx();
+        builder.drain_to(addr.script_pubkey()).drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(psbt.outputs[0].bip32_derivation.len(), 1);
+        assert_eq!(
+            psbt.outputs[0].bip32_derivation.values().next().unwrap(),
+            &(
+                Fingerprint::from_str("d34db33f").unwrap(),
+                DerivationPath::from_str("m/44'/0'/0'/0/5").unwrap()
+            )
+        );
+    }
+
+    #[test]
+    fn test_create_tx_set_redeem_script_p2sh() {
+        use bitcoin::hashes::hex::FromHex;
+
+        let (wallet, _, _) =
+            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.drain_to(addr.script_pubkey()).drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(
+            psbt.inputs[0].redeem_script,
+            Some(Script::from(
+                Vec::<u8>::from_hex(
+                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
+                )
+                .unwrap()
+            ))
+        );
+        assert_eq!(psbt.inputs[0].witness_script, None);
+    }
+
+    #[test]
+    fn test_create_tx_set_witness_script_p2wsh() {
+        use bitcoin::hashes::hex::FromHex;
+
+        let (wallet, _, _) =
+            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.drain_to(addr.script_pubkey()).drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(psbt.inputs[0].redeem_script, None);
+        assert_eq!(
+            psbt.inputs[0].witness_script,
+            Some(Script::from(
+                Vec::<u8>::from_hex(
+                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
+                )
+                .unwrap()
+            ))
+        );
+    }
+
+    #[test]
+    fn test_create_tx_set_redeem_witness_script_p2wsh_p2sh() {
+        use bitcoin::hashes::hex::FromHex;
+
+        let (wallet, _, _) =
+            get_funded_wallet("sh(wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)))");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.drain_to(addr.script_pubkey()).drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
+
+        let script = Script::from(
+            Vec::<u8>::from_hex(
+                "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac",
+            )
+            .unwrap(),
+        );
+
+        assert_eq!(psbt.inputs[0].redeem_script, Some(script.to_v0_p2wsh()));
+        assert_eq!(psbt.inputs[0].witness_script, Some(script));
+    }
+
+    #[test]
+    fn test_create_tx_non_witness_utxo() {
+        let (wallet, _, _) =
+            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.drain_to(addr.script_pubkey()).drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert!(psbt.inputs[0].non_witness_utxo.is_some());
+        assert!(psbt.inputs[0].witness_utxo.is_none());
+    }
+
+    #[test]
+    fn test_create_tx_only_witness_utxo() {
+        let (wallet, _, _) =
+            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .drain_to(addr.script_pubkey())
+            .only_witness_utxo()
+            .drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert!(psbt.inputs[0].non_witness_utxo.is_none());
+        assert!(psbt.inputs[0].witness_utxo.is_some());
+    }
+
+    #[test]
+    fn test_create_tx_shwpkh_has_witness_utxo() {
+        let (wallet, _, _) =
+            get_funded_wallet("sh(wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.drain_to(addr.script_pubkey()).drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert!(psbt.inputs[0].witness_utxo.is_some());
+    }
+
+    #[test]
+    fn test_create_tx_both_non_witness_utxo_and_witness_utxo_default() {
+        let (wallet, _, _) =
+            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.drain_to(addr.script_pubkey()).drain_wallet();
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert!(psbt.inputs[0].non_witness_utxo.is_some());
+        assert!(psbt.inputs[0].witness_utxo.is_some());
+    }
+
+    #[test]
+    fn test_create_tx_add_utxo() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        let small_output_txid = crate::populate_test_db!(
+            wallet.database.borrow_mut(),
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 30_000)
+            .add_utxo(OutPoint {
+                txid: small_output_txid,
+                vout: 0,
+            })
+            .unwrap();
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(
+            psbt.global.unsigned_tx.input.len(),
+            2,
+            "should add an additional input since 25_000 < 30_000"
+        );
+        assert_eq!(details.sent, 75_000, "total should be sum of both inputs");
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_create_tx_manually_selected_insufficient() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        let small_output_txid = crate::populate_test_db!(
+            wallet.database.borrow_mut(),
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 30_000)
+            .add_utxo(OutPoint {
+                txid: small_output_txid,
+                vout: 0,
+            })
+            .unwrap()
+            .manually_selected_only();
+        builder.finish().unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "SpendingPolicyRequired(External)")]
+    fn test_create_tx_policy_path_required() {
+        let (wallet, _, _) = get_funded_wallet(get_test_a_or_b_plus_csv());
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 30_000);
+        builder.finish().unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_policy_path_no_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_a_or_b_plus_csv());
+
+        let external_policy = wallet.policies(KeychainKind::External).unwrap().unwrap();
+        let root_id = external_policy.id;
+        // child #0 is just the key "A"
+        let path = vec![(root_id, vec![0])].into_iter().collect();
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 30_000)
+            .policy_path(path, KeychainKind::External);
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFF);
+    }
+
+    #[test]
+    fn test_create_tx_policy_path_use_csv() {
+        let (wallet, _, _) = get_funded_wallet(get_test_a_or_b_plus_csv());
+
+        let external_policy = wallet.policies(KeychainKind::External).unwrap().unwrap();
+        let root_id = external_policy.id;
+        // child #1 is or(pk(B),older(144))
+        let path = vec![(root_id, vec![1])].into_iter().collect();
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 30_000)
+            .policy_path(path, KeychainKind::External);
+        let (psbt, _) = builder.finish().unwrap();
+
+        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 144);
+    }
+
+    #[test]
+    fn test_create_tx_global_xpubs_with_origin() {
+        use bitcoin::hashes::hex::FromHex;
+        use bitcoin::util::base58;
+        use bitcoin::util::psbt::raw::Key;
+
+        let (wallet, _, _) = get_funded_wallet("wpkh([73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*)");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .add_global_xpubs();
+        let (psbt, _) = builder.finish().unwrap();
+
+        let type_value = 0x01;
+        let key = base58::from_check("tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3").unwrap();
+
+        let psbt_key = Key { type_value, key };
+
+        // This key has an explicit origin, so it will be encoded here
+        let value_bytes = Vec::<u8>::from_hex("73756c7f30000080000000800000008002000080").unwrap();
+
+        assert_eq!(psbt.global.unknown.len(), 1);
+        assert_eq!(psbt.global.unknown.get(&psbt_key), Some(&value_bytes));
+    }
+
+    #[test]
+    fn test_add_foreign_utxo() {
+        let (wallet1, _, _) = get_funded_wallet(get_test_wpkh());
+        let (wallet2, _, _) =
+            get_funded_wallet("wpkh(cVbZ8ovhye9AoAHFsqobCf7LxbXDAECy9Kb8TZdfsDYMZGBUyCnm)");
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let utxo = wallet2.list_unspent().unwrap().remove(0);
+        let foreign_utxo_satisfaction = wallet2
+            .get_descriptor_for_keychain(KeychainKind::External)
+            .max_satisfaction_weight()
+            .unwrap();
+
+        let psbt_input = psbt::Input {
+            witness_utxo: Some(utxo.txout.clone()),
+            ..Default::default()
+        };
+
+        let mut builder = wallet1.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 60_000)
+            .only_witness_utxo()
+            .add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction)
+            .unwrap();
+        let (mut psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(
+            details.sent - details.received,
+            10_000 + details.fee.unwrap_or(0),
+            "we should have only net spent ~10_000"
+        );
+
+        assert!(
+            psbt.global
+                .unsigned_tx
+                .input
+                .iter()
+                .any(|input| input.previous_output == utxo.outpoint),
+            "foreign_utxo should be in there"
+        );
+
+        let finished = wallet1
+            .sign(
+                &mut psbt,
+                SignOptions {
+                    trust_witness_utxo: true,
+                    ..Default::default()
+                },
+            )
+            .unwrap();
+
+        assert!(
+            !finished,
+            "only one of the inputs should have been signed so far"
+        );
+
+        let finished = wallet2
+            .sign(
+                &mut psbt,
+                SignOptions {
+                    trust_witness_utxo: true,
+                    ..Default::default()
+                },
+            )
+            .unwrap();
+        assert!(finished, "all the inputs should have been signed now");
+    }
+
+    #[test]
+    #[should_panic(expected = "Generic(\"Foreign utxo missing witness_utxo or non_witness_utxo\")")]
+    fn test_add_foreign_utxo_invalid_psbt_input() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let mut builder = wallet.build_tx();
+        let outpoint = wallet.list_unspent().unwrap()[0].outpoint;
+        let foreign_utxo_satisfaction = wallet
+            .get_descriptor_for_keychain(KeychainKind::External)
+            .max_satisfaction_weight()
+            .unwrap();
+        builder
+            .add_foreign_utxo(outpoint, psbt::Input::default(), foreign_utxo_satisfaction)
+            .unwrap();
+    }
+
+    #[test]
+    fn test_add_foreign_utxo_where_outpoint_doesnt_match_psbt_input() {
+        let (wallet1, _, txid1) = get_funded_wallet(get_test_wpkh());
+        let (wallet2, _, txid2) =
+            get_funded_wallet("wpkh(cVbZ8ovhye9AoAHFsqobCf7LxbXDAECy9Kb8TZdfsDYMZGBUyCnm)");
+
+        let utxo2 = wallet2.list_unspent().unwrap().remove(0);
+        let tx1 = wallet1
+            .database
+            .borrow()
+            .get_tx(&txid1, true)
+            .unwrap()
+            .unwrap()
+            .transaction
+            .unwrap();
+        let tx2 = wallet2
+            .database
+            .borrow()
+            .get_tx(&txid2, true)
+            .unwrap()
+            .unwrap()
+            .transaction
+            .unwrap();
+
+        let satisfaction_weight = wallet2
+            .get_descriptor_for_keychain(KeychainKind::External)
+            .max_satisfaction_weight()
+            .unwrap();
+
+        let mut builder = wallet1.build_tx();
+        assert!(
+            builder
+                .add_foreign_utxo(
+                    utxo2.outpoint,
+                    psbt::Input {
+                        non_witness_utxo: Some(tx1),
+                        ..Default::default()
+                    },
+                    satisfaction_weight
+                )
+                .is_err(),
+            "should fail when outpoint doesn't match psbt_input"
+        );
+        assert!(
+            builder
+                .add_foreign_utxo(
+                    utxo2.outpoint,
+                    psbt::Input {
+                        non_witness_utxo: Some(tx2),
+                        ..Default::default()
+                    },
+                    satisfaction_weight
+                )
+                .is_ok(),
+            "shoulld be ok when outpoint does match psbt_input"
+        );
+    }
+
+    #[test]
+    fn test_add_foreign_utxo_only_witness_utxo() {
+        let (wallet1, _, _) = get_funded_wallet(get_test_wpkh());
+        let (wallet2, _, txid2) =
+            get_funded_wallet("wpkh(cVbZ8ovhye9AoAHFsqobCf7LxbXDAECy9Kb8TZdfsDYMZGBUyCnm)");
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let utxo2 = wallet2.list_unspent().unwrap().remove(0);
+
+        let satisfaction_weight = wallet2
+            .get_descriptor_for_keychain(KeychainKind::External)
+            .max_satisfaction_weight()
+            .unwrap();
+
+        let mut builder = wallet1.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 60_000);
+
+        {
+            let mut builder = builder.clone();
+            let psbt_input = psbt::Input {
+                witness_utxo: Some(utxo2.txout.clone()),
+                ..Default::default()
+            };
+            builder
+                .add_foreign_utxo(utxo2.outpoint, psbt_input, satisfaction_weight)
+                .unwrap();
+            assert!(
+                builder.finish().is_err(),
+                "psbt_input with witness_utxo should fail with only witness_utxo"
+            );
+        }
+
+        {
+            let mut builder = builder.clone();
+            let psbt_input = psbt::Input {
+                witness_utxo: Some(utxo2.txout.clone()),
+                ..Default::default()
+            };
+            builder
+                .only_witness_utxo()
+                .add_foreign_utxo(utxo2.outpoint, psbt_input, satisfaction_weight)
+                .unwrap();
+            assert!(
+                builder.finish().is_ok(),
+                "psbt_input with just witness_utxo should succeed when `only_witness_utxo` is enabled"
+            );
+        }
+
+        {
+            let mut builder = builder.clone();
+            let tx2 = wallet2
+                .database
+                .borrow()
+                .get_tx(&txid2, true)
+                .unwrap()
+                .unwrap()
+                .transaction
+                .unwrap();
+            let psbt_input = psbt::Input {
+                non_witness_utxo: Some(tx2),
+                ..Default::default()
+            };
+            builder
+                .add_foreign_utxo(utxo2.outpoint, psbt_input, satisfaction_weight)
+                .unwrap();
+            assert!(
+                builder.finish().is_ok(),
+                "psbt_input with non_witness_utxo should succeed by default"
+            );
+        }
+    }
+
+    #[test]
+    fn test_get_psbt_input() {
+        // this should grab a known good utxo and set the input
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        for utxo in wallet.list_unspent().unwrap() {
+            let psbt_input = wallet.get_psbt_input(utxo, None, false).unwrap();
+            assert!(psbt_input.witness_utxo.is_some() || psbt_input.non_witness_utxo.is_some());
+        }
+    }
+
+    #[test]
+    #[should_panic(
+        expected = "MissingKeyOrigin(\"tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3\")"
+    )]
+    fn test_create_tx_global_xpubs_origin_missing() {
+        let (wallet, _, _) = get_funded_wallet("wpkh(tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*)");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .add_global_xpubs();
+        builder.finish().unwrap();
+    }
+
+    #[test]
+    fn test_create_tx_global_xpubs_master_without_origin() {
+        use bitcoin::hashes::hex::FromHex;
+        use bitcoin::util::base58;
+        use bitcoin::util::psbt::raw::Key;
+
+        let (wallet, _, _) = get_funded_wallet("wpkh(tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL/0/*)");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .add_global_xpubs();
+        let (psbt, _) = builder.finish().unwrap();
+
+        let type_value = 0x01;
+        let key = base58::from_check("tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL").unwrap();
+
+        let psbt_key = Key { type_value, key };
+
+        // This key doesn't have an explicit origin, but it's a master key (depth = 0). So we encode
+        // its fingerprint directly and an empty path
+        let value_bytes = Vec::<u8>::from_hex("997a323b").unwrap();
+
+        assert_eq!(psbt.global.unknown.len(), 1);
+        assert_eq!(psbt.global.unknown.get(&psbt_key), Some(&value_bytes));
+    }
+
+    #[test]
+    #[should_panic(expected = "IrreplaceableTransaction")]
+    fn test_bump_fee_irreplaceable_tx() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        let (psbt, mut details) = builder.finish().unwrap();
+
+        let tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the utxos, we know they can't be used anyways
+        details.transaction = Some(tx);
+        wallet.database.borrow_mut().set_tx(&details).unwrap();
+
+        wallet.build_fee_bump(txid).unwrap().finish().unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "TransactionConfirmed")]
+    fn test_bump_fee_confirmed_tx() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.add_recipient(addr.script_pubkey(), 25_000);
+        let (psbt, mut details) = builder.finish().unwrap();
+
+        let tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the utxos, we know they can't be used anyways
+        details.transaction = Some(tx);
+        details.confirmation_time = Some(ConfirmationTime {
+            timestamp: 12345678,
+            height: 42,
+        });
+        wallet.database.borrow_mut().set_tx(&details).unwrap();
+
+        wallet.build_fee_bump(txid).unwrap().finish().unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "FeeRateTooLow")]
+    fn test_bump_fee_low_fee_rate() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .enable_rbf();
+        let (psbt, mut details) = builder.finish().unwrap();
+
+        let tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the utxos, we know they can't be used anyways
+        details.transaction = Some(tx);
+        wallet.database.borrow_mut().set_tx(&details).unwrap();
+
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_rate(FeeRate::from_sat_per_vb(1.0));
+        builder.finish().unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "FeeTooLow")]
+    fn test_bump_fee_low_abs() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .enable_rbf();
+        let (psbt, mut details) = builder.finish().unwrap();
+
+        let tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the utxos, we know they can't be used anyways
+        details.transaction = Some(tx);
+        wallet.database.borrow_mut().set_tx(&details).unwrap();
+
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_absolute(10);
+        builder.finish().unwrap();
+    }
+
+    #[test]
+    #[should_panic(expected = "FeeTooLow")]
+    fn test_bump_fee_zero_abs() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .enable_rbf();
+        let (psbt, mut details) = builder.finish().unwrap();
+
+        let tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the utxos, we know they can't be used anyways
+        details.transaction = Some(tx);
+        wallet.database.borrow_mut().set_tx(&details).unwrap();
+
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_absolute(0);
+        builder.finish().unwrap();
+    }
+
+    #[test]
+    fn test_bump_fee_reduce_change() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_rate(FeeRate::from_sat_per_vb(2.5)).enable_rbf();
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(details.sent, original_details.sent);
+        assert_eq!(
+            details.received + details.fee.unwrap_or(0),
+            original_details.received + original_details.fee.unwrap_or(0)
+        );
+        assert!(details.fee.unwrap_or(0) > original_details.fee.unwrap_or(0));
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            25_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(2.5), @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_absolute_reduce_change() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 25_000)
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_absolute(200);
+        builder.enable_rbf();
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(details.sent, original_details.sent);
+        assert_eq!(
+            details.received + details.fee.unwrap_or(0),
+            original_details.received + original_details.fee.unwrap_or(0)
+        );
+        assert!(
+            details.fee.unwrap_or(0) > original_details.fee.unwrap_or(0),
+            "{} > {}",
+            details.fee.unwrap_or(0),
+            original_details.fee.unwrap_or(0)
+        );
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            25_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_eq!(details.fee.unwrap_or(0), 200);
+    }
+
+    #[test]
+    fn test_bump_fee_reduce_single_recipient() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .drain_to(addr.script_pubkey())
+            .drain_wallet()
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder
+            .fee_rate(FeeRate::from_sat_per_vb(2.5))
+            .allow_shrinking(addr.script_pubkey())
+            .unwrap();
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(details.sent, original_details.sent);
+        assert!(details.fee.unwrap_or(0) > original_details.fee.unwrap_or(0));
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.output.len(), 1);
+        assert_eq!(tx.output[0].value + details.fee.unwrap_or(0), details.sent);
+
+        assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(2.5), @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_absolute_reduce_single_recipient() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .drain_to(addr.script_pubkey())
+            .drain_wallet()
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder
+            .allow_shrinking(addr.script_pubkey())
+            .unwrap()
+            .fee_absolute(300);
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(details.sent, original_details.sent);
+        assert!(details.fee.unwrap_or(0) > original_details.fee.unwrap_or(0));
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.output.len(), 1);
+        assert_eq!(tx.output[0].value + details.fee.unwrap_or(0), details.sent);
+
+        assert_eq!(details.fee.unwrap_or(0), 300);
+    }
+
+    #[test]
+    fn test_bump_fee_drain_wallet() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        // receive an extra tx so that our wallet has two utxos.
+        let incoming_txid = crate::populate_test_db!(
+            wallet.database.borrow_mut(),
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+        let outpoint = OutPoint {
+            txid: incoming_txid,
+            vout: 0,
+        };
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .drain_to(addr.script_pubkey())
+            .add_utxo(outpoint)
+            .unwrap()
+            .manually_selected_only()
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+        assert_eq!(original_details.sent, 25_000);
+
+        // for the new feerate, it should be enough to reduce the output, but since we specify
+        // `drain_wallet` we expect to spend everything
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder
+            .drain_wallet()
+            .allow_shrinking(addr.script_pubkey())
+            .unwrap()
+            .fee_rate(FeeRate::from_sat_per_vb(5.0));
+        let (_, details) = builder.finish().unwrap();
+        assert_eq!(details.sent, 75_000);
+    }
+
+    #[test]
+    #[should_panic(expected = "InsufficientFunds")]
+    fn test_bump_fee_remove_output_manually_selected_only() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        // receive an extra tx so that our wallet has two utxos. then we manually pick only one of
+        // them, and make sure that `bump_fee` doesn't try to add more. This fails because we've
+        // told the wallet it's not allowed to add more inputs AND it can't reduce the value of the
+        // existing output. In other words, bump_fee + manually_selected_only is always an error
+        // unless you've also set "allow_shrinking" OR there is a change output.
+        let incoming_txid = crate::populate_test_db!(
+            wallet.database.borrow_mut(),
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+        let outpoint = OutPoint {
+            txid: incoming_txid,
+            vout: 0,
+        };
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .drain_to(addr.script_pubkey())
+            .add_utxo(outpoint)
+            .unwrap()
+            .manually_selected_only()
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+        assert_eq!(original_details.sent, 25_000);
+
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder
+            .manually_selected_only()
+            .fee_rate(FeeRate::from_sat_per_vb(255.0));
+        builder.finish().unwrap();
+    }
+
+    #[test]
+    fn test_bump_fee_add_input() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        crate::populate_test_db!(
+            wallet.database.borrow_mut(),
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 45_000)
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_rate(FeeRate::from_sat_per_vb(50.0));
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(details.sent, original_details.sent + 25_000);
+        assert_eq!(details.fee.unwrap_or(0) + details.received, 30_000);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            45_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(50.0), @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_absolute_add_input() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        crate::populate_test_db!(
+            wallet.database.borrow_mut(),
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 45_000)
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_absolute(6_000);
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(details.sent, original_details.sent + 25_000);
+        assert_eq!(details.fee.unwrap_or(0) + details.received, 30_000);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            45_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_eq!(details.fee.unwrap_or(0), 6_000);
+    }
+
+    #[test]
+    fn test_bump_fee_no_change_add_input_and_change() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        let incoming_txid = crate::populate_test_db!(
+            wallet.database.borrow_mut(),
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        // initially make a tx without change by using `drain_to`
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .drain_to(addr.script_pubkey())
+            .add_utxo(OutPoint {
+                txid: incoming_txid,
+                vout: 0,
+            })
+            .unwrap()
+            .manually_selected_only()
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
+
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        // now bump the fees without using `allow_shrinking`. the wallet should add an
+        // extra input and a change output, and leave the original output untouched
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_rate(FeeRate::from_sat_per_vb(50.0));
+        let (psbt, details) = builder.finish().unwrap();
+
+        let original_send_all_amount = original_details.sent - original_details.fee.unwrap_or(0);
+        assert_eq!(details.sent, original_details.sent + 50_000);
+        assert_eq!(
+            details.received,
+            75_000 - original_send_all_amount - details.fee.unwrap_or(0)
+        );
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            original_send_all_amount
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            75_000 - original_send_all_amount - details.fee.unwrap_or(0)
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(50.0), @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_add_input_change_dust() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        crate::populate_test_db!(
+            wallet.database.borrow_mut(),
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 45_000)
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
+        let mut tx = psbt.extract_tx();
+        assert_eq!(tx.input.len(), 1);
+        assert_eq!(tx.output.len(), 2);
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder.fee_rate(FeeRate::from_sat_per_vb(140.0));
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(
+            original_details.received,
+            5_000 - original_details.fee.unwrap_or(0)
+        );
+
+        assert_eq!(details.sent, original_details.sent + 25_000);
+        assert_eq!(details.fee.unwrap_or(0), 30_000);
+        assert_eq!(details.received, 0);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 1);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            45_000
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(140.0), @dust_change, @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_force_add_input() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        let incoming_txid = crate::populate_test_db!(
+            wallet.database.borrow_mut(),
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 45_000)
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        // the new fee_rate is low enough that just reducing the change would be fine, but we force
+        // the addition of an extra input with `add_utxo()`
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder
+            .add_utxo(OutPoint {
+                txid: incoming_txid,
+                vout: 0,
+            })
+            .unwrap()
+            .fee_rate(FeeRate::from_sat_per_vb(5.0));
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(details.sent, original_details.sent + 25_000);
+        assert_eq!(details.fee.unwrap_or(0) + details.received, 30_000);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            45_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(5.0), @add_signature);
+    }
+
+    #[test]
+    fn test_bump_fee_absolute_force_add_input() {
+        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
+        let incoming_txid = crate::populate_test_db!(
+            wallet.database.borrow_mut(),
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 45_000)
+            .enable_rbf();
+        let (psbt, mut original_details) = builder.finish().unwrap();
+        let mut tx = psbt.extract_tx();
+        let txid = tx.txid();
+        // skip saving the new utxos, we know they can't be used anyways
+        for txin in &mut tx.input {
+            txin.witness.push([0x00; 108].to_vec()); // fake signature
+            wallet
+                .database
+                .borrow_mut()
+                .del_utxo(&txin.previous_output)
+                .unwrap();
+        }
+        original_details.transaction = Some(tx);
+        wallet
+            .database
+            .borrow_mut()
+            .set_tx(&original_details)
+            .unwrap();
+
+        // the new fee_rate is low enough that just reducing the change would be fine, but we force
+        // the addition of an extra input with `add_utxo()`
+        let mut builder = wallet.build_fee_bump(txid).unwrap();
+        builder
+            .add_utxo(OutPoint {
+                txid: incoming_txid,
+                vout: 0,
+            })
+            .unwrap()
+            .fee_absolute(250);
+        let (psbt, details) = builder.finish().unwrap();
+
+        assert_eq!(details.sent, original_details.sent + 25_000);
+        assert_eq!(details.fee.unwrap_or(0) + details.received, 30_000);
+
+        let tx = &psbt.global.unsigned_tx;
+        assert_eq!(tx.input.len(), 2);
+        assert_eq!(tx.output.len(), 2);
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey == addr.script_pubkey())
+                .unwrap()
+                .value,
+            45_000
+        );
+        assert_eq!(
+            tx.output
+                .iter()
+                .find(|txout| txout.script_pubkey != addr.script_pubkey())
+                .unwrap()
+                .value,
+            details.received
+        );
+
+        assert_eq!(details.fee.unwrap_or(0), 250);
+    }
+
+    #[test]
+    fn test_sign_single_xprv() {
+        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.drain_to(addr.script_pubkey()).drain_wallet();
+        let (mut psbt, _) = builder.finish().unwrap();
+
+        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
+        assert!(finalized);
+
+        let extracted = psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+
+    #[test]
+    fn test_sign_single_xprv_with_master_fingerprint_and_path() {
+        let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/84h/1h/0h]tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.drain_to(addr.script_pubkey()).drain_wallet();
+        let (mut psbt, _) = builder.finish().unwrap();
+
+        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
+        assert!(finalized);
+
+        let extracted = psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+
+    #[test]
+    fn test_sign_single_xprv_bip44_path() {
+        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/44'/0'/0'/0/*)");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.drain_to(addr.script_pubkey()).drain_wallet();
+        let (mut psbt, _) = builder.finish().unwrap();
+
+        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
+        assert!(finalized);
+
+        let extracted = psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+
+    #[test]
+    fn test_sign_single_xprv_sh_wpkh() {
+        let (wallet, _, _) = get_funded_wallet("sh(wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*))");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.drain_to(addr.script_pubkey()).drain_wallet();
+        let (mut psbt, _) = builder.finish().unwrap();
+
+        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
+        assert!(finalized);
+
+        let extracted = psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+
+    #[test]
+    fn test_sign_single_wif() {
+        let (wallet, _, _) =
+            get_funded_wallet("wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.drain_to(addr.script_pubkey()).drain_wallet();
+        let (mut psbt, _) = builder.finish().unwrap();
+
+        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
+        assert!(finalized);
+
+        let extracted = psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+
+    #[test]
+    fn test_sign_single_xprv_no_hd_keypaths() {
+        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder.drain_to(addr.script_pubkey()).drain_wallet();
+        let (mut psbt, _) = builder.finish().unwrap();
+
+        psbt.inputs[0].bip32_derivation.clear();
+        assert_eq!(psbt.inputs[0].bip32_derivation.len(), 0);
+
+        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
+        assert!(finalized);
+
+        let extracted = psbt.extract_tx();
+        assert_eq!(extracted.input[0].witness.len(), 2);
+    }
+
+    #[test]
+    fn test_include_output_redeem_witness_script() {
+        let (wallet, _, _) = get_funded_wallet("sh(wsh(multi(1,cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW,cRjo6jqfVNP33HhSS76UhXETZsGTZYx8FMFvR9kpbtCSV1PmdZdu)))");
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 45_000)
+            .include_output_redeem_witness_script();
+        let (psbt, _) = builder.finish().unwrap();
+
+        // p2sh-p2wsh transaction should contain both witness and redeem scripts
+        assert!(psbt
+            .outputs
+            .iter()
+            .any(|output| output.redeem_script.is_some() && output.witness_script.is_some()));
+    }
+
+    #[test]
+    fn test_signing_only_one_of_multiple_inputs() {
+        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
+        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .add_recipient(addr.script_pubkey(), 45_000)
+            .include_output_redeem_witness_script();
+        let (mut psbt, _) = builder.finish().unwrap();
+
+        // add another input to the psbt that is at least passable.
+        let dud_input = bitcoin::util::psbt::Input {
+            witness_utxo: Some(TxOut {
+                value: 100_000,
+                script_pubkey: miniscript::Descriptor::<bitcoin::PublicKey>::from_str(
+                    "wpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)",
+                )
+                .unwrap()
+                .script_pubkey(),
+            }),
+            ..Default::default()
+        };
+
+        psbt.inputs.push(dud_input);
+        psbt.global.unsigned_tx.input.push(bitcoin::TxIn::default());
+        let is_final = wallet
+            .sign(
+                &mut psbt,
+                SignOptions {
+                    trust_witness_utxo: true,
+                    ..Default::default()
+                },
+            )
+            .unwrap();
+        assert!(
+            !is_final,
+            "shouldn't be final since we can't sign one of the inputs"
+        );
+        assert!(
+            psbt.inputs[0].final_script_witness.is_some(),
+            "should finalized input it signed"
+        )
+    }
+
+    #[test]
+    fn test_sign_nonstandard_sighash() {
+        let sighash = SigHashType::NonePlusAnyoneCanPay;
+
+        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
+        let addr = wallet.get_address(New).unwrap();
+        let mut builder = wallet.build_tx();
+        builder
+            .drain_to(addr.script_pubkey())
+            .sighash(sighash)
+            .drain_wallet();
+        let (mut psbt, _) = builder.finish().unwrap();
+
+        let result = wallet.sign(&mut psbt, Default::default());
+        assert!(
+            result.is_err(),
+            "Signing should have failed because the TX uses non-standard sighashes"
+        );
+        assert!(
+            matches!(
+                result.unwrap_err(),
+                Error::Signer(SignerError::NonStandardSighash)
+            ),
+            "Signing failed with the wrong error type"
+        );
+
+        // try again after opting-in
+        let result = wallet.sign(
+            &mut psbt,
+            SignOptions {
+                allow_all_sighashes: true,
+                ..Default::default()
+            },
+        );
+        assert!(result.is_ok(), "Signing should have worked");
+        assert!(
+            result.unwrap(),
+            "Should finalize the input since we can produce signatures"
+        );
+
+        let extracted = psbt.extract_tx();
+        assert_eq!(
+            *extracted.input[0].witness[0].last().unwrap(),
+            sighash.as_u32() as u8,
+            "The signature should have been made with the right sighash"
+        );
+    }
+
+    #[test]
+    fn test_unused_address() {
+        let db = MemoryDatabase::new();
+        let wallet = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)",
+                                         None, Network::Testnet, db).unwrap();
+
+        assert_eq!(
+            wallet.get_address(LastUnused).unwrap().to_string(),
+            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
+        );
+        assert_eq!(
+            wallet.get_address(LastUnused).unwrap().to_string(),
+            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
+        );
+    }
+
+    #[test]
+    fn test_next_unused_address() {
+        let descriptor = "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)";
+        let descriptors = testutils!(@descriptors (descriptor));
+        let wallet = Wallet::new_offline(
+            &descriptors.0,
+            None,
+            Network::Testnet,
+            MemoryDatabase::new(),
+        )
+        .unwrap();
+
+        assert_eq!(
+            wallet.get_address(LastUnused).unwrap().to_string(),
+            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
+        );
+
+        // use the above address
+        crate::populate_test_db!(
+            wallet.database.borrow_mut(),
+            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
+            Some(100),
+        );
+
+        assert_eq!(
+            wallet.get_address(LastUnused).unwrap().to_string(),
+            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
+        );
+    }
+
+    #[test]
+    fn test_peek_address_at_index() {
+        let db = MemoryDatabase::new();
+        let wallet = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)",
+                                         None, Network::Testnet, db).unwrap();
+
+        assert_eq!(
+            wallet.get_address(Peek(1)).unwrap().to_string(),
+            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
+        );
+
+        assert_eq!(
+            wallet.get_address(Peek(0)).unwrap().to_string(),
+            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
+        );
+
+        assert_eq!(
+            wallet.get_address(Peek(2)).unwrap().to_string(),
+            "tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2"
+        );
+
+        // current new address is not affected
+        assert_eq!(
+            wallet.get_address(New).unwrap().to_string(),
+            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
+        );
+
+        assert_eq!(
+            wallet.get_address(New).unwrap().to_string(),
+            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
+        );
+    }
+
+    #[test]
+    fn test_peek_address_at_index_not_derivable() {
+        let db = MemoryDatabase::new();
+        let wallet = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/1)",
+                                         None, Network::Testnet, db).unwrap();
+
+        assert_eq!(
+            wallet.get_address(Peek(1)).unwrap().to_string(),
+            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
+        );
+
+        assert_eq!(
+            wallet.get_address(Peek(0)).unwrap().to_string(),
+            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
+        );
+
+        assert_eq!(
+            wallet.get_address(Peek(2)).unwrap().to_string(),
+            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
+        );
+    }
+
+    #[test]
+    fn test_reset_address_index() {
+        let db = MemoryDatabase::new();
+        let wallet = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)",
+                                         None, Network::Testnet, db).unwrap();
+
+        // new index 0
+        assert_eq!(
+            wallet.get_address(New).unwrap().to_string(),
+            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
+        );
+
+        // new index 1
+        assert_eq!(
+            wallet.get_address(New).unwrap().to_string(),
+            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
+        );
+
+        // new index 2
+        assert_eq!(
+            wallet.get_address(New).unwrap().to_string(),
+            "tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2"
+        );
+
+        //  reset index 1 again
+        assert_eq!(
+            wallet.get_address(Reset(1)).unwrap().to_string(),
+            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
+        );
+
+        // new index 2 again
+        assert_eq!(
+            wallet.get_address(New).unwrap().to_string(),
+            "tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2"
+        );
+    }
+
+    #[test]
+    fn test_returns_index_and_address() {
+        let db = MemoryDatabase::new();
+        let wallet = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)",
+                                         None, Network::Testnet, db).unwrap();
+
+        // new index 0
+        assert_eq!(
+            wallet.get_address(New).unwrap(),
+            AddressInfo {
+                index: 0,
+                address: Address::from_str("tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a").unwrap(),
+            }
+        );
+
+        // new index 1
+        assert_eq!(
+            wallet.get_address(New).unwrap(),
+            AddressInfo {
+                index: 1,
+                address: Address::from_str("tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7").unwrap()
+            }
+        );
+
+        // peek index 25
+        assert_eq!(
+            wallet.get_address(Peek(25)).unwrap(),
+            AddressInfo {
+                index: 25,
+                address: Address::from_str("tb1qsp7qu0knx3sl6536dzs0703u2w2ag6ppl9d0c2").unwrap()
+            }
+        );
+
+        // new index 2
+        assert_eq!(
+            wallet.get_address(New).unwrap(),
+            AddressInfo {
+                index: 2,
+                address: Address::from_str("tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2").unwrap()
+            }
+        );
+
+        //  reset index 1 again
+        assert_eq!(
+            wallet.get_address(Reset(1)).unwrap(),
+            AddressInfo {
+                index: 1,
+                address: Address::from_str("tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7").unwrap()
+            }
+        );
+
+        // new index 2 again
+        assert_eq!(
+            wallet.get_address(New).unwrap(),
+            AddressInfo {
+                index: 2,
+                address: Address::from_str("tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2").unwrap()
+            }
+        );
+    }
+}
+
+
+ + \ 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 new file mode 100644 index 0000000000..77838e7d8e --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/signer.rs.html @@ -0,0 +1,1536 @@ +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
+
// 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 std::sync::Arc;
+//! # use std::str::FromStr;
+//! # use bitcoin::secp256k1::{Secp256k1, All};
+//! # use bitcoin::*;
+//! # use bitcoin::util::psbt;
+//! # use bdk::signer::*;
+//! # use bdk::database::*;
+//! # use bdk::*;
+//! # #[derive(Debug)]
+//! # struct CustomHSM;
+//! # impl CustomHSM {
+//! #     fn sign_input(&self, _psbt: &mut psbt::PartiallySignedTransaction, _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 Signer for CustomSigner {
+//!     fn sign(
+//!         &self,
+//!         psbt: &mut psbt::PartiallySignedTransaction,
+//!         input_index: Option<usize>,
+//!         _secp: &Secp256k1<All>,
+//!     ) -> Result<(), SignerError> {
+//!         let input_index = input_index.ok_or(SignerError::InputIndexOutOfRange)?;
+//!         self.device.sign_input(psbt, input_index)?;
+//!
+//!         Ok(())
+//!     }
+//!
+//!     fn id(&self, _secp: &Secp256k1<All>) -> SignerId {
+//!         self.device.get_id()
+//!     }
+//!
+//!     fn sign_whole_tx(&self) -> bool {
+//!         false
+//!     }
+//! }
+//!
+//! let custom_signer = CustomSigner::connect();
+//!
+//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
+//! let mut wallet = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
+//! wallet.add_signer(
+//!     KeychainKind::External,
+//!     SignerOrdering(200),
+//!     Arc::new(custom_signer)
+//! );
+//!
+//! # Ok::<_, bdk::Error>(())
+//! ```
+
+use std::cmp::Ordering;
+use std::collections::BTreeMap;
+use std::fmt;
+use std::ops::Bound::Included;
+use std::sync::Arc;
+
+use bitcoin::blockdata::opcodes;
+use bitcoin::blockdata::script::Builder as ScriptBuilder;
+use bitcoin::hashes::{hash160, Hash};
+use bitcoin::secp256k1::{Message, Secp256k1};
+use bitcoin::util::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey, Fingerprint};
+use bitcoin::util::{bip143, psbt};
+use bitcoin::{PrivateKey, Script, SigHash, SigHashType};
+
+use miniscript::descriptor::{DescriptorSecretKey, DescriptorSinglePriv, DescriptorXKey, KeyMap};
+use miniscript::{Legacy, MiniscriptKey, Segwitv0};
+
+use super::utils::SecpCtx;
+use crate::descriptor::XKeyUtils;
+
+/// 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, PartialEq, Eq, Clone)]
+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 requied 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,
+}
+
+impl fmt::Display for SignerError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self)
+    }
+}
+
+impl std::error::Error for SignerError {}
+
+/// Trait for signers
+///
+/// This trait can be implemented to provide customized signers to the wallet. For an example see
+/// [`this module`](crate::wallet::signer)'s documentation.
+pub trait Signer: fmt::Debug + Send + Sync {
+    /// Sign a PSBT
+    ///
+    /// The `input_index` argument is only provided if the wallet doesn't declare to sign the whole
+    /// transaction in one go (see [`Signer::sign_whole_tx`]). Otherwise its value is `None` and
+    /// can be ignored.
+    fn sign(
+        &self,
+        psbt: &mut psbt::PartiallySignedTransaction,
+        input_index: Option<usize>,
+        secp: &SecpCtx,
+    ) -> Result<(), SignerError>;
+
+    /// Return whether or not the signer signs the whole transaction in one go instead of every
+    /// input individually
+    fn sign_whole_tx(&self) -> bool;
+
+    /// 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
+    }
+}
+
+impl Signer for DescriptorXKey<ExtendedPrivKey> {
+    fn sign(
+        &self,
+        psbt: &mut psbt::PartiallySignedTransaction,
+        input_index: Option<usize>,
+        secp: &SecpCtx,
+    ) -> Result<(), SignerError> {
+        let input_index = input_index.unwrap();
+        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 (public_key, full_path) = match psbt.inputs[input_index]
+            .bip32_derivation
+            .iter()
+            .filter_map(|(pk, &(fingerprint, ref path))| {
+                if self.matches(&(fingerprint, path.clone()), secp).is_some() {
+                    Some((pk, path))
+                } else {
+                    None
+                }
+            })
+            .next()
+        {
+            Some((pk, full_path)) => (pk, full_path.clone()),
+            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(),
+        };
+
+        if &derived_key.private_key.public_key(secp) != public_key {
+            Err(SignerError::InvalidKey)
+        } else {
+            derived_key.private_key.sign(psbt, Some(input_index), secp)
+        }
+    }
+
+    fn sign_whole_tx(&self) -> bool {
+        false
+    }
+
+    fn id(&self, secp: &SecpCtx) -> SignerId {
+        SignerId::from(self.root_fingerprint(secp))
+    }
+
+    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
+        Some(DescriptorSecretKey::XPrv(self.clone()))
+    }
+}
+
+impl Signer for PrivateKey {
+    fn sign(
+        &self,
+        psbt: &mut psbt::PartiallySignedTransaction,
+        input_index: Option<usize>,
+        secp: &SecpCtx,
+    ) -> Result<(), SignerError> {
+        let input_index = input_index.unwrap();
+        if input_index >= psbt.inputs.len() || input_index >= psbt.global.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 = self.public_key(secp);
+        if psbt.inputs[input_index].partial_sigs.contains_key(&pubkey) {
+            return Ok(());
+        }
+
+        // FIXME: use the presence of `witness_utxo` as an indication that we should make a bip143
+        // sig. Does this make sense? Should we add an extra argument to explicitly swith between
+        // these? The original idea was to declare sign() as sign<Ctx: ScriptContex>() and use Ctx,
+        // but that violates the rules for trait-objects, so we can't do it.
+        let (hash, sighash) = match psbt.inputs[input_index].witness_utxo {
+            Some(_) => Segwitv0::sighash(psbt, input_index)?,
+            None => Legacy::sighash(psbt, input_index)?,
+        };
+
+        let signature = secp.sign(
+            &Message::from_slice(&hash.into_inner()[..]).unwrap(),
+            &self.key,
+        );
+
+        let mut final_signature = Vec::with_capacity(75);
+        final_signature.extend_from_slice(&signature.serialize_der());
+        final_signature.push(sighash.as_u32() as u8);
+
+        psbt.inputs[input_index]
+            .partial_sigs
+            .insert(pubkey, final_signature);
+
+        Ok(())
+    }
+
+    fn sign_whole_tx(&self) -> bool {
+        false
+    }
+
+    fn id(&self, secp: &SecpCtx) -> SignerId {
+        SignerId::from(self.public_key(secp).to_pubkeyhash())
+    }
+
+    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
+        Some(DescriptorSecretKey::SinglePriv(DescriptorSinglePriv {
+            key: *self,
+            origin: None,
+        }))
+    }
+}
+
+/// 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 std::default::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 Signer>>);
+
+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.as_public(secp).ok().map(|public| (public, secret)))
+            .collect()
+    }
+}
+
+impl From<KeyMap> for SignersContainer {
+    fn from(keymap: KeyMap) -> SignersContainer {
+        let secp = Secp256k1::new();
+        let mut container = SignersContainer::new();
+
+        for (_, secret) in keymap {
+            match secret {
+                DescriptorSecretKey::SinglePriv(private_key) => container.add_external(
+                    SignerId::from(private_key.key.public_key(&secp).to_pubkeyhash()),
+                    SignerOrdering::default(),
+                    Arc::new(private_key.key),
+                ),
+                DescriptorSecretKey::XPrv(xprv) => container.add_external(
+                    SignerId::from(xprv.root_fingerprint(&secp)),
+                    SignerOrdering::default(),
+                    Arc::new(xprv),
+                ),
+            };
+        }
+
+        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 Signer>,
+    ) -> Option<Arc<dyn Signer>> {
+        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 Signer>> {
+        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 Signer>> {
+        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 Signer>> {
+        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 chould 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,
+}
+
+impl Default for SignOptions {
+    fn default() -> Self {
+        SignOptions {
+            trust_witness_utxo: false,
+            assume_height: None,
+            allow_all_sighashes: false,
+        }
+    }
+}
+
+pub(crate) trait ComputeSighash {
+    fn sighash(
+        psbt: &psbt::PartiallySignedTransaction,
+        input_index: usize,
+    ) -> Result<(SigHash, SigHashType), SignerError>;
+}
+
+impl ComputeSighash for Legacy {
+    fn sighash(
+        psbt: &psbt::PartiallySignedTransaction,
+        input_index: usize,
+    ) -> Result<(SigHash, SigHashType), SignerError> {
+        if input_index >= psbt.inputs.len() || input_index >= psbt.global.unsigned_tx.input.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let psbt_input = &psbt.inputs[input_index];
+        let tx_input = &psbt.global.unsigned_tx.input[input_index];
+
+        let sighash = psbt_input.sighash_type.unwrap_or(SigHashType::All);
+        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((
+            psbt.global
+                .unsigned_tx
+                .signature_hash(input_index, &script, sighash.as_u32()),
+            sighash,
+        ))
+    }
+}
+
+fn p2wpkh_script_code(script: &Script) -> Script {
+    ScriptBuilder::new()
+        .push_opcode(opcodes::all::OP_DUP)
+        .push_opcode(opcodes::all::OP_HASH160)
+        .push_slice(&script[2..])
+        .push_opcode(opcodes::all::OP_EQUALVERIFY)
+        .push_opcode(opcodes::all::OP_CHECKSIG)
+        .into_script()
+}
+
+impl ComputeSighash for Segwitv0 {
+    fn sighash(
+        psbt: &psbt::PartiallySignedTransaction,
+        input_index: usize,
+    ) -> Result<(SigHash, SigHashType), SignerError> {
+        if input_index >= psbt.inputs.len() || input_index >= psbt.global.unsigned_tx.input.len() {
+            return Err(SignerError::InputIndexOutOfRange);
+        }
+
+        let psbt_input = &psbt.inputs[input_index];
+        let tx_input = &psbt.global.unsigned_tx.input[input_index];
+
+        let sighash = psbt_input.sighash_type.unwrap_or(SigHashType::All);
+
+        // 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 script = match psbt_input.witness_script {
+            Some(ref witness_script) => witness_script.clone(),
+            None => {
+                if utxo.script_pubkey.is_v0_p2wpkh() {
+                    p2wpkh_script_code(&utxo.script_pubkey)
+                } else if psbt_input
+                    .redeem_script
+                    .as_ref()
+                    .map(Script::is_v0_p2wpkh)
+                    .unwrap_or(false)
+                {
+                    p2wpkh_script_code(psbt_input.redeem_script.as_ref().unwrap())
+                } else {
+                    return Err(SignerError::MissingWitnessScript);
+                }
+            }
+        };
+
+        Ok((
+            bip143::SigHashCache::new(&psbt.global.unsigned_tx).signature_hash(
+                input_index,
+                &script,
+                value,
+                sighash,
+            ),
+            sighash,
+        ))
+    }
+}
+
+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 bitcoin::secp256k1::{All, Secp256k1};
+    use bitcoin::util::bip32;
+    use bitcoin::util::psbt::PartiallySignedTransaction;
+    use bitcoin::Network;
+    use miniscript::ScriptContext;
+    use std::str::FromStr;
+
+    fn is_equal(this: &Arc<dyn Signer>, 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 (_, keymap) = desc
+            .into_wallet_descriptor(&secp, Network::Testnet)
+            .unwrap();
+
+        let signers = SignersContainer::from(keymap);
+        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 Signer for DummySigner {
+        fn sign(
+            &self,
+            _psbt: &mut PartiallySignedTransaction,
+            _input_index: Option<usize>,
+            _secp: &SecpCtx,
+        ) -> Result<(), SignerError> {
+            Ok(())
+        }
+
+        fn id(&self, _secp: &SecpCtx) -> SignerId {
+            SignerId::Dummy(self.number)
+        }
+
+        fn sign_whole_tx(&self) -> bool {
+            true
+        }
+    }
+
+    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::ExtendedPrivKey::from_str(tprv).unwrap();
+        let tpub = bip32::ExtendedPubKey::from_private(&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/time.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/time.rs.html new file mode 100644 index 0000000000..48832d0f43 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/time.rs.html @@ -0,0 +1,150 @@ +time.rs - source
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+
// Bitcoin Dev Kit
+// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
+//
+// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
+//! Cross-platform time
+//!
+//! This module provides a function to get the current timestamp that works on all the platforms
+//! supported by the library.
+//!
+//! It can be useful to compare it with the timestamps found in
+//! [`TransactionDetails`](crate::types::TransactionDetails).
+
+use std::time::Duration;
+
+#[cfg(target_arch = "wasm32")]
+use js_sys::Date;
+#[cfg(not(target_arch = "wasm32"))]
+use std::time::{Instant as SystemInstant, SystemTime, UNIX_EPOCH};
+
+/// Return the current timestamp in seconds
+#[cfg(not(target_arch = "wasm32"))]
+pub fn get_timestamp() -> u64 {
+    SystemTime::now()
+        .duration_since(UNIX_EPOCH)
+        .unwrap()
+        .as_secs()
+}
+/// Return the current timestamp in seconds
+#[cfg(target_arch = "wasm32")]
+pub fn get_timestamp() -> u64 {
+    let millis = Date::now();
+
+    (millis / 1000.0) as u64
+}
+
+#[cfg(not(target_arch = "wasm32"))]
+pub(crate) struct Instant(SystemInstant);
+#[cfg(target_arch = "wasm32")]
+pub(crate) struct Instant(Duration);
+
+impl Instant {
+    #[cfg(not(target_arch = "wasm32"))]
+    pub fn new() -> Self {
+        Instant(SystemInstant::now())
+    }
+    #[cfg(target_arch = "wasm32")]
+    pub fn new() -> Self {
+        let millis = Date::now();
+
+        let secs = millis / 1000.0;
+        let nanos = (millis % 1000.0) * 1e6;
+
+        Instant(Duration::new(secs as u64, nanos as u32))
+    }
+
+    #[cfg(not(target_arch = "wasm32"))]
+    pub fn elapsed(&self) -> Duration {
+        self.0.elapsed()
+    }
+    #[cfg(target_arch = "wasm32")]
+    pub fn elapsed(&self) -> Duration {
+        let now = Instant::new();
+
+        now.0.checked_sub(self.0).unwrap_or(Duration::new(0, 0))
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/tx_builder.rs.html b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/tx_builder.rs.html new file mode 100644 index 0000000000..732238dba1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/tx_builder.rs.html @@ -0,0 +1,1776 @@ +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
+
// 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::tx_builder::CreateTx;
+//! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+//! # let 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(), 50_000)
+//!     // With a custom fee rate of 5.0 satoshi/vbyte
+//!     .fee_rate(FeeRate::from_sat_per_vb(5.0))
+//!     // Only spend non-change outputs
+//!     .do_not_spend_change()
+//!     // Turn on RBF signaling
+//!     .enable_rbf();
+//! let (psbt, tx_details) = tx_builder.finish()?;
+//! # Ok::<(), bdk::Error>(())
+//! ```
+
+use std::collections::BTreeMap;
+use std::collections::HashSet;
+use std::default::Default;
+use std::marker::PhantomData;
+
+use bitcoin::util::psbt::{self, PartiallySignedTransaction as Psbt};
+use bitcoin::{OutPoint, Script, SigHashType, Transaction};
+
+use miniscript::descriptor::DescriptorTrait;
+
+use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm};
+use crate::{database::BatchDatabase, Error, Utxo, Wallet};
+use crate::{
+    types::{FeeRate, KeychainKind, LocalUtxo, WeightedUtxo},
+    TransactionDetails,
+};
+/// Context in which the [`TxBuilder`] is valid
+pub trait TxBuilderContext: std::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;
+/// # let wallet = doctest_wallet!();
+/// # let addr1 = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+/// # let addr2 = addr1.clone();
+/// // chaining
+/// let (psbt1, details) = {
+///     let mut builder = wallet.build_tx();
+///     builder
+///         .ordering(TxOrdering::Untouched)
+///         .add_recipient(addr1.script_pubkey(), 50_000)
+///         .add_recipient(addr2.script_pubkey(), 50_000);
+///     builder.finish()?
+/// };
+///
+/// // non-chaining
+/// let (psbt2, details) = {
+///     let mut builder = wallet.build_tx();
+///     builder.ordering(TxOrdering::Untouched);
+///     for addr in &[addr1, addr2] {
+///         builder.add_recipient(addr.script_pubkey(), 50_000);
+///     }
+///     builder.finish()?
+/// };
+///
+/// assert_eq!(
+///     psbt1.global.unsigned_tx.output[..2],
+///     psbt2.global.unsigned_tx.output[..2]
+/// );
+/// # Ok::<(), bdk::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, B, D, Cs, Ctx> {
+    pub(crate) wallet: &'a Wallet<B, D>,
+    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<(Script, u64)>,
+    pub(crate) drain_wallet: bool,
+    pub(crate) drain_to: Option<Script>,
+    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<SigHashType>,
+    pub(crate) ordering: TxOrdering,
+    pub(crate) locktime: Option<u32>,
+    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>,
+}
+
+#[derive(Clone, Copy, Debug)]
+pub(crate) struct PreviousFee {
+    pub absolute: u64,
+    pub rate: f32,
+}
+
+#[derive(Debug, Clone, Copy)]
+pub(crate) enum FeePolicy {
+    FeeRate(FeeRate),
+    FeeAmount(u64),
+}
+
+impl std::default::Default for FeePolicy {
+    fn default() -> Self {
+        FeePolicy::FeeRate(FeeRate::default_min_relay_fee())
+    }
+}
+
+impl<'a, Cs: Clone, Ctx, B, D> Clone for TxBuilder<'a, B, D, Cs, Ctx> {
+    fn clone(&self) -> Self {
+        TxBuilder {
+            wallet: self.wallet,
+            params: self.params.clone(),
+            coin_selection: self.coin_selection.clone(),
+            phantom: PhantomData,
+        }
+    }
+}
+
+// methods supported by both contexts, for any CoinSelectionAlgorithm
+impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext>
+    TxBuilder<'a, B, D, Cs, Ctx>
+{
+    /// Set a custom fee rate
+    pub fn fee_rate(&mut self, fee_rate: FeeRate) -> &mut Self {
+        self.params.fee_policy = Some(FeePolicy::FeeRate(fee_rate));
+        self
+    }
+
+    /// Set an absolute fee
+    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();
+    /// # let 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(), 50_000)
+    ///     .policy_path(path, KeychainKind::External);
+    ///
+    /// # Ok::<(), bdk::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, Error> {
+        let utxos = outpoints
+            .iter()
+            .map(|outpoint| self.wallet.get_utxo(*outpoint)?.ok_or(Error::UnknownUtxo))
+            .collect::<Result<Vec<_>, _>>()?;
+
+        for utxo in utxos {
+            let descriptor = self.wallet.get_descriptor_for_keychain(utxo.keychain);
+            let satisfaction_weight = descriptor.max_satisfaction_weight().unwrap();
+            self.params.utxos.push(WeightedUtxo {
+                satisfaction_weight,
+                utxo: Utxo::Local(utxo),
+            });
+        }
+
+        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, Error> {
+        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 foregin 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 `satisfaction_weight` 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_satisfaction_weight`].
+    ///
+    /// This is an **EXPERIMENTAL** feature, API and other major changes are expected.
+    ///
+    /// # 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 `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_satisfaction_weight`]: miniscript::Descriptor::max_satisfaction_weight
+    pub fn add_foreign_utxo(
+        &mut self,
+        outpoint: OutPoint,
+        psbt_input: psbt::Input,
+        satisfaction_weight: usize,
+    ) -> Result<&mut Self, Error> {
+        if psbt_input.witness_utxo.is_none() {
+            match psbt_input.non_witness_utxo.as_ref() {
+                Some(tx) => {
+                    if tx.txid() != outpoint.txid {
+                        return Err(Error::Generic(
+                            "Foreign utxo outpoint does not match PSBT input".into(),
+                        ));
+                    }
+                    if tx.output.len() <= outpoint.vout as usize {
+                        return Err(Error::InvalidOutpoint(outpoint));
+                    }
+                }
+                None => {
+                    return Err(Error::Generic(
+                        "Foreign utxo missing witness_utxo or non_witness_utxo".into(),
+                    ))
+                }
+            }
+        }
+
+        self.params.utxos.push(WeightedUtxo {
+            satisfaction_weight,
+            utxo: Utxo::Foreign {
+                outpoint,
+                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: SigHashType) -> &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: u32) -> &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::util::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::util::psbt::Output::redeem_script) and
+    /// [`psbt::Output::witness_script`](bitcoin::util::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`](super::coin_selection::DefaultCoinSelectionAlgorithm).
+    ///
+    /// Note that this function consumes the builder and returns it so it is usually best to put this as the first call on the builder.
+    pub fn coin_selection<P: CoinSelectionAlgorithm<D>>(
+        self,
+        coin_selection: P,
+    ) -> TxBuilder<'a, B, D, P, Ctx> {
+        TxBuilder {
+            wallet: self.wallet,
+            params: self.params,
+            coin_selection,
+            phantom: PhantomData,
+        }
+    }
+
+    /// Finish the building the transaction.
+    ///
+    /// Returns the [`BIP174`] "PSBT" and summary details about the transaction.
+    ///
+    /// [`BIP174`]: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
+    pub fn finish(self) -> Result<(Psbt, TransactionDetails), Error> {
+        self.wallet.create_tx(self.coin_selection, self.params)
+    }
+
+    /// 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: u32) -> &mut Self {
+        self.params.rbf = Some(RbfValue::Value(nsequence));
+        self
+    }
+}
+
+impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>> TxBuilder<'a, B, D, Cs, CreateTx> {
+    /// Replace the recipients already added with a new list
+    pub fn set_recipients(&mut self, recipients: Vec<(Script, u64)>) -> &mut Self {
+        self.params.recipients = recipients;
+        self
+    }
+
+    /// Add a recipient to the internal list
+    pub fn add_recipient(&mut self, script_pubkey: Script, amount: u64) -> &mut Self {
+        self.params.recipients.push((script_pubkey, amount));
+        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).
+    ///
+    /// 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::tx_builder::CreateTx;
+    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
+    /// # let 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.0))
+    ///     .enable_rbf();
+    /// let (psbt, tx_details) = tx_builder.finish()?;
+    /// # Ok::<(), bdk::Error>(())
+    /// ```
+    ///
+    /// [`allow_shrinking`]: Self::allow_shrinking
+    /// [`add_recipient`]: Self::add_recipient
+    /// [`drain_wallet`]: Self::drain_wallet
+    pub fn drain_to(&mut self, script_pubkey: Script) -> &mut Self {
+        self.params.drain_to = Some(script_pubkey);
+        self
+    }
+}
+
+// methods supported only by bump_fee
+impl<'a, B, D: BatchDatabase> TxBuilder<'a, B, D, DefaultCoinSelectionAlgorithm, BumpFee> {
+    /// Explicitly tells the wallet that it is allowed to reduce the fee 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: Script) -> Result<&mut Self, Error> {
+        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(Error::Generic(format!(
+                "{} was not in the original transaction",
+                script_pubkey
+            ))),
+        }
+    }
+}
+
+/// Ordering of the transaction's inputs and outputs
+#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
+pub enum TxOrdering {
+    /// Randomized (default)
+    Shuffle,
+    /// Unchanged
+    Untouched,
+    /// BIP69 / Lexicographic
+    Bip69Lexicographic,
+}
+
+impl Default for TxOrdering {
+    fn default() -> Self {
+        TxOrdering::Shuffle
+    }
+}
+
+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;
+                #[cfg(test)]
+                use rand::SeedableRng;
+
+                #[cfg(not(test))]
+                let mut rng = rand::thread_rng();
+                #[cfg(test)]
+                let mut rng = rand::rngs::StdRng::seed_from_u64(0);
+
+                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(u32),
+}
+
+impl RbfValue {
+    pub(crate) fn get_value(&self) -> u32 {
+        match self {
+            RbfValue::Default => 0xFFFFFFFD,
+            RbfValue::Value(v) => *v,
+        }
+    }
+}
+
+/// Policy regarding the use of change outputs when creating a transaction
+#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
+pub enum ChangeSpendPolicy {
+    /// Use both change and non-change outputs (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 Default for ChangeSpendPolicy {
+    fn default() -> Self {
+        ChangeSpendPolicy::ChangeAllowed
+    }
+}
+
+impl ChangeSpendPolicy {
+    pub(crate) fn is_satisfied_by(&self, utxo: &LocalUtxo) -> 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 bitcoin::consensus::deserialize;
+    use bitcoin::hashes::hex::FromHex;
+
+    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();
+
+        TxOrdering::Shuffle.sort_tx(&mut tx);
+
+        assert_eq!(original_tx.input, tx.input);
+        assert_ne!(original_tx.output, tx.output);
+    }
+
+    #[test]
+    fn test_output_ordering_bip69() {
+        use std::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, 800);
+        assert_eq!(tx.output[1].script_pubkey, From::from(vec![0xAA]));
+        assert_eq!(tx.output[2].script_pubkey, From::from(vec![0xAA, 0xEE]));
+    }
+
+    fn get_test_utxos() -> Vec<LocalUtxo> {
+        vec![
+            LocalUtxo {
+                outpoint: OutPoint {
+                    txid: Default::default(),
+                    vout: 0,
+                },
+                txout: Default::default(),
+                keychain: KeychainKind::External,
+            },
+            LocalUtxo {
+                outpoint: OutPoint {
+                    txid: Default::default(),
+                    vout: 1,
+                },
+                txout: Default::default(),
+                keychain: KeychainKind::Internal,
+            },
+        ]
+    }
+
+    #[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 new file mode 100644 index 0000000000..5154e583bb --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/src/bdk/wallet/utils.rs.html @@ -0,0 +1,536 @@ +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
+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
+
// 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 miniscript::{MiniscriptKey, Satisfier, ToPublicKey};
+
+// De-facto standard "dust limit" (even though it should change based on the output type)
+pub const DUST_LIMIT_SATOSHI: u64 = 546;
+
+// MSB of the nSequence. If set there's no consensus-constraint, so it must be disabled when
+// spending using CSV in order to enforce CSV rules
+pub(crate) const SEQUENCE_LOCKTIME_DISABLE_FLAG: u32 = 1 << 31;
+// 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;
+// Mask for the bits used to express the timelock
+pub(crate) const SEQUENCE_LOCKTIME_MASK: u32 = 0x0000FFFF;
+
+// Threshold for nLockTime to be considered a block-height-based timelock rather than time-based
+pub(crate) const BLOCKS_TIMELOCK_THRESHOLD: u32 = 500000000;
+
+/// Trait to check if a value is below the dust limit
+// we implement this trait to make sure we don't mess up the comparison with off-by-one like a <
+// instead of a <= etc. The constant value for the dust limit is not public on purpose, to
+// encourage the usage of this trait.
+pub trait IsDust {
+    /// Check whether or not a value is below dust limit
+    fn is_dust(&self) -> bool;
+}
+
+impl IsDust for u64 {
+    fn is_dust(&self) -> bool {
+        *self <= DUST_LIMIT_SATOSHI
+    }
+}
+
+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: u32, csv: u32) -> bool {
+    // This flag cannot be set in the nSequence when spending using OP_CSV
+    if rbf & SEQUENCE_LOCKTIME_DISABLE_FLAG != 0 {
+        return false;
+    }
+
+    let mask = SEQUENCE_LOCKTIME_TYPE_FLAG | SEQUENCE_LOCKTIME_MASK;
+    let rbf = rbf & mask;
+    let csv = csv & mask;
+
+    // Both values should be represented in the same unit (either time-based or
+    // block-height based)
+    if (rbf < SEQUENCE_LOCKTIME_TYPE_FLAG) != (csv < SEQUENCE_LOCKTIME_TYPE_FLAG) {
+        return false;
+    }
+
+    // The value should be at least `csv`
+    if rbf < csv {
+        return false;
+    }
+
+    true
+}
+
+pub(crate) fn check_nlocktime(nlocktime: u32, required: u32) -> bool {
+    // Both values should be expressed in the same unit
+    if (nlocktime < BLOCKS_TIMELOCK_THRESHOLD) != (required < BLOCKS_TIMELOCK_THRESHOLD) {
+        return false;
+    }
+
+    // The value should be at least `required`
+    if nlocktime < required {
+        return false;
+    }
+
+    true
+}
+
+impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for After {
+    fn check_after(&self, n: u32) -> bool {
+        if let Some(current_height) = self.current_height {
+            current_height >= n
+        } 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: u32) -> bool {
+        if let Some(current_height) = self.current_height {
+            // TODO: test >= / >
+            current_height as u64 >= self.create_height.unwrap_or(0) as u64 + n as u64
+        } else {
+            self.assume_height_reached
+        }
+    }
+}
+
+pub(crate) type SecpCtx = Secp256k1<All>;
+
+pub struct ChunksIterator<I: Iterator> {
+    iter: I,
+    size: usize,
+}
+
+#[cfg(any(feature = "electrum", feature = "esplora"))]
+impl<I: Iterator> ChunksIterator<I> {
+    pub fn new(iter: I, size: usize) -> Self {
+        ChunksIterator { iter, size }
+    }
+}
+
+impl<I: Iterator> Iterator for ChunksIterator<I> {
+    type Item = Vec<<I as std::iter::Iterator>::Item>;
+
+    fn next(&mut self) -> Option<Self::Item> {
+        let mut v = Vec::new();
+        for _ in 0..self.size {
+            let e = self.iter.next();
+
+            match e {
+                None => break,
+                Some(val) => v.push(val),
+            }
+        }
+
+        if v.is_empty() {
+            return None;
+        }
+
+        Some(v)
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use super::{
+        check_nlocktime, check_nsequence_rbf, BLOCKS_TIMELOCK_THRESHOLD,
+        SEQUENCE_LOCKTIME_TYPE_FLAG,
+    };
+    use crate::types::FeeRate;
+
+    #[test]
+    fn test_fee_from_btc_per_kb() {
+        let fee = FeeRate::from_btc_per_kvb(1e-5);
+        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
+    }
+
+    #[test]
+    fn test_fee_from_sats_vbyte() {
+        let fee = FeeRate::from_sat_per_vb(1.0);
+        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
+    }
+
+    #[test]
+    fn test_fee_default_min_relay_fee() {
+        let fee = FeeRate::default_min_relay_fee();
+        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_msb_set() {
+        let result = check_nsequence_rbf(0x80000000, 5000);
+        assert!(!result);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_lt_csv() {
+        let result = check_nsequence_rbf(4000, 5000);
+        assert!(!result);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_different_unit() {
+        let result = check_nsequence_rbf(SEQUENCE_LOCKTIME_TYPE_FLAG + 5000, 5000);
+        assert!(!result);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_mask() {
+        let result = check_nsequence_rbf(0x3f + 10_000, 5000);
+        assert!(result);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_same_unit_blocks() {
+        let result = check_nsequence_rbf(10_000, 5000);
+        assert!(result);
+    }
+
+    #[test]
+    fn test_check_nsequence_rbf_same_unit_time() {
+        let result = check_nsequence_rbf(
+            SEQUENCE_LOCKTIME_TYPE_FLAG + 10_000,
+            SEQUENCE_LOCKTIME_TYPE_FLAG + 5000,
+        );
+        assert!(result);
+    }
+
+    #[test]
+    fn test_check_nlocktime_lt_cltv() {
+        let result = check_nlocktime(4000, 5000);
+        assert!(!result);
+    }
+
+    #[test]
+    fn test_check_nlocktime_different_unit() {
+        let result = check_nlocktime(BLOCKS_TIMELOCK_THRESHOLD + 5000, 5000);
+        assert!(!result);
+    }
+
+    #[test]
+    fn test_check_nlocktime_same_unit_blocks() {
+        let result = check_nlocktime(10_000, 5000);
+        assert!(result);
+    }
+
+    #[test]
+    fn test_check_nlocktime_same_unit_time() {
+        let result = check_nlocktime(
+            BLOCKS_TIMELOCK_THRESHOLD + 10_000,
+            BLOCKS_TIMELOCK_THRESHOLD + 5000,
+        );
+        assert!(result);
+    }
+}
+
+
+ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/storage.js b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/storage.js new file mode 100644 index 0000000000..6b16cbd83c --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/storage.js @@ -0,0 +1 @@ +var resourcesSuffix="";var darkThemes=["dark","ayu"];window.currentTheme=document.getElementById("themeStyle");window.mainTheme=document.getElementById("mainThemeStyle");var settingsDataset=(function(){var settingsElement=document.getElementById("default-settings");if(settingsElement===null){return null}var dataset=settingsElement.dataset;if(dataset===undefined){return null}return dataset})();function getSettingValue(settingName){var current=getCurrentValue('rustdoc-'+settingName);if(current!==null){return current}if(settingsDataset!==null){var def=settingsDataset[settingName.replace(/-/g,'_')];if(def!==undefined){return def}}return null}var localStoredTheme=getSettingValue("theme");var savedHref=[];function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(!elem||!elem.classList){return}elem.classList.add(className)}function removeClass(elem,className){if(!elem||!elem.classList){return}elem.classList.remove(className)}function onEach(arr,func,reversed){if(arr&&arr.length>0&&func){var length=arr.length;var i;if(reversed){for(i=length-1;i>=0;--i){if(func(arr[i])){return true}}}else{for(i=0;i=0){updateLocalStorage("rustdoc-preferred-dark-theme",localStoredTheme)}updateSystemTheme()}else{switchTheme(window.currentTheme,window.mainTheme,getSettingValue("theme")||"light",false)} \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/toggle-minus.svg b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/toggle-minus.svg new file mode 100644 index 0000000000..73154788a0 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/toggle-minus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/toggle-plus.svg b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/toggle-plus.svg new file mode 100644 index 0000000000..08b17033e1 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/toggle-plus.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wheel.svg b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wheel.svg new file mode 100644 index 0000000000..01da3b24c7 --- /dev/null +++ b/docs/.vuepress/public/docs-rs/bdk/nightly/latest/wheel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/.vuepress/public/favicon.ico b/docs/.vuepress/public/favicon.ico new file mode 100644 index 0000000000..33555bf2da Binary files /dev/null and b/docs/.vuepress/public/favicon.ico differ diff --git a/docs/.vuepress/public/fonts/ibm-plex-mono-400.woff2 b/docs/.vuepress/public/fonts/ibm-plex-mono-400.woff2 new file mode 100644 index 0000000000..cbe17a36da Binary files /dev/null and b/docs/.vuepress/public/fonts/ibm-plex-mono-400.woff2 differ diff --git a/docs/.vuepress/public/img/bitcoin-dev-kit.svg b/docs/.vuepress/public/img/bitcoin-dev-kit.svg new file mode 100644 index 0000000000..818d8f4603 --- /dev/null +++ b/docs/.vuepress/public/img/bitcoin-dev-kit.svg @@ -0,0 +1 @@ +Bitcoin Dev KitBitcoin Dev Kit \ No newline at end of file diff --git a/docs/.vuepress/public/img/bitfinex.svg b/docs/.vuepress/public/img/bitfinex.svg new file mode 100644 index 0000000000..8d7c3b1eb8 --- /dev/null +++ b/docs/.vuepress/public/img/bitfinex.svg @@ -0,0 +1,35 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + diff --git a/docs/.vuepress/public/img/border.svg b/docs/.vuepress/public/img/border.svg new file mode 100644 index 0000000000..bb92f429f2 --- /dev/null +++ b/docs/.vuepress/public/img/border.svg @@ -0,0 +1 @@ + diff --git a/docs/.vuepress/public/img/brink.png b/docs/.vuepress/public/img/brink.png new file mode 100644 index 0000000000..b8ff73d673 Binary files /dev/null and b/docs/.vuepress/public/img/brink.png differ diff --git a/docs/.vuepress/public/img/favicon/android-chrome-192x192.png b/docs/.vuepress/public/img/favicon/android-chrome-192x192.png new file mode 100644 index 0000000000..15dcea39a2 Binary files /dev/null and b/docs/.vuepress/public/img/favicon/android-chrome-192x192.png differ diff --git a/docs/.vuepress/public/img/favicon/android-chrome-512x512.png b/docs/.vuepress/public/img/favicon/android-chrome-512x512.png new file mode 100644 index 0000000000..be05e1a937 Binary files /dev/null and b/docs/.vuepress/public/img/favicon/android-chrome-512x512.png differ diff --git a/docs/.vuepress/public/img/favicon/apple-touch-icon.png b/docs/.vuepress/public/img/favicon/apple-touch-icon.png new file mode 100644 index 0000000000..605cd0509a Binary files /dev/null and b/docs/.vuepress/public/img/favicon/apple-touch-icon.png differ diff --git a/docs/.vuepress/public/img/favicon/mstile-150x150.png b/docs/.vuepress/public/img/favicon/mstile-150x150.png new file mode 100644 index 0000000000..b7f7b57ead Binary files /dev/null and b/docs/.vuepress/public/img/favicon/mstile-150x150.png differ diff --git a/docs/.vuepress/public/img/favicon/safari-pinned-tab.svg b/docs/.vuepress/public/img/favicon/safari-pinned-tab.svg new file mode 100644 index 0000000000..84c1abbfc2 --- /dev/null +++ b/docs/.vuepress/public/img/favicon/safari-pinned-tab.svg @@ -0,0 +1,20 @@ + + + + safari-pinned-tab + Created with Sketch. + + + + + + + \ No newline at end of file diff --git a/docs/.vuepress/public/img/fee-estimation-for-light-clients/20210125-091313-confirms_in-fee_rate.png b/docs/.vuepress/public/img/fee-estimation-for-light-clients/20210125-091313-confirms_in-fee_rate.png new file mode 100644 index 0000000000..e3d433683b Binary files /dev/null and b/docs/.vuepress/public/img/fee-estimation-for-light-clients/20210125-091313-confirms_in-fee_rate.png differ diff --git a/docs/.vuepress/public/img/fee-estimation-for-light-clients/20210125-091313-error-distribution.png b/docs/.vuepress/public/img/fee-estimation-for-light-clients/20210125-091313-error-distribution.png new file mode 100644 index 0000000000..f889730994 Binary files /dev/null and b/docs/.vuepress/public/img/fee-estimation-for-light-clients/20210125-091313-error-distribution.png differ diff --git a/docs/.vuepress/public/img/fee-estimation-for-light-clients/20210125-091313-model.png b/docs/.vuepress/public/img/fee-estimation-for-light-clients/20210125-091313-model.png new file mode 100644 index 0000000000..47098c458b Binary files /dev/null and b/docs/.vuepress/public/img/fee-estimation-for-light-clients/20210125-091313-model.png differ diff --git a/docs/.vuepress/public/img/fee-estimation-for-light-clients/20210125-091313-train-history.png b/docs/.vuepress/public/img/fee-estimation-for-light-clients/20210125-091313-train-history.png new file mode 100644 index 0000000000..c2af8cb6bd Binary files /dev/null and b/docs/.vuepress/public/img/fee-estimation-for-light-clients/20210125-091313-train-history.png differ diff --git a/docs/.vuepress/public/img/fee-estimation-for-light-clients/20210125-091313-true-and-predictions.png b/docs/.vuepress/public/img/fee-estimation-for-light-clients/20210125-091313-true-and-predictions.png new file mode 100644 index 0000000000..49f351b9bc Binary files /dev/null and b/docs/.vuepress/public/img/fee-estimation-for-light-clients/20210125-091313-true-and-predictions.png differ diff --git a/docs/.vuepress/public/img/fee-estimation-for-light-clients/high-level-graph.svg b/docs/.vuepress/public/img/fee-estimation-for-light-clients/high-level-graph.svg new file mode 100644 index 0000000000..23e156a17c --- /dev/null +++ b/docs/.vuepress/public/img/fee-estimation-for-light-clients/high-level-graph.svg @@ -0,0 +1,139 @@ + + +G + + +cluster_logger + +bitcoin-logger + + +cluster_bitcoind + +bitcoind + + +cluster_csv + +bitcoin-csv + + + +store + +store + + + +flush + +flush + + + +store->flush + + + + + +rpc + +rpc + + + +store->rpc + + +missing data + + + +zmq_reader + +zmq_reader + + + +zmq_reader->store + + + + + +raw_logs + +raw_logs + + + +flush->raw_logs + + + + + +rpc_call + +rpc_call + + + +rpc_call->store + + + + + +rpc_call->rpc + + +estimatesmartfee + + + +zmq + +zmq + + + +zmq->zmq_reader + + +rawtx, rawblock, sequence + + + +raw_logs_reader + +raw_logs_reader + + + +csv_writer + +csv_writer + + + +csv + +csv + + + +csv_writer->csv + + + + + +raw_logs->raw_logs_reader + + + + + \ No newline at end of file diff --git a/docs/.vuepress/public/img/fee-estimation-for-light-clients/the-good-the-bad-the-ugly.jpg b/docs/.vuepress/public/img/fee-estimation-for-light-clients/the-good-the-bad-the-ugly.jpg new file mode 100644 index 0000000000..86e0ba0708 Binary files /dev/null and b/docs/.vuepress/public/img/fee-estimation-for-light-clients/the-good-the-bad-the-ugly.jpg differ diff --git a/docs/.vuepress/public/img/illustrations.svg b/docs/.vuepress/public/img/illustrations.svg new file mode 100644 index 0000000000..4c6b9e47fa --- /dev/null +++ b/docs/.vuepress/public/img/illustrations.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/docs/.vuepress/public/img/kraken.png b/docs/.vuepress/public/img/kraken.png new file mode 100644 index 0000000000..1b64dcbacc Binary files /dev/null and b/docs/.vuepress/public/img/kraken.png differ diff --git a/docs/.vuepress/public/img/logo-wide.jpg b/docs/.vuepress/public/img/logo-wide.jpg new file mode 100755 index 0000000000..ef9ce47b01 Binary files /dev/null and b/docs/.vuepress/public/img/logo-wide.jpg differ diff --git a/docs/.vuepress/public/img/logo.svg b/docs/.vuepress/public/img/logo.svg new file mode 100644 index 0000000000..4acf58b846 --- /dev/null +++ b/docs/.vuepress/public/img/logo.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/docs/.vuepress/public/img/logo2.svg b/docs/.vuepress/public/img/logo2.svg new file mode 100644 index 0000000000..b284a89c4d --- /dev/null +++ b/docs/.vuepress/public/img/logo2.svg @@ -0,0 +1,283 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/.vuepress/public/img/squarecrypto.svg b/docs/.vuepress/public/img/squarecrypto.svg new file mode 100644 index 0000000000..d874e9496b --- /dev/null +++ b/docs/.vuepress/public/img/squarecrypto.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/.vuepress/public/img/tether.png b/docs/.vuepress/public/img/tether.png new file mode 100644 index 0000000000..ad7591b7ef Binary files /dev/null and b/docs/.vuepress/public/img/tether.png differ diff --git a/docs/.vuepress/public/img/wizard.svg b/docs/.vuepress/public/img/wizard.svg new file mode 100644 index 0000000000..5fc405bf16 --- /dev/null +++ b/docs/.vuepress/public/img/wizard.svg @@ -0,0 +1,327 @@ + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/.vuepress/public/js/github-buttons.js b/docs/.vuepress/public/js/github-buttons.js new file mode 100644 index 0000000000..7b87efaec1 --- /dev/null +++ b/docs/.vuepress/public/js/github-buttons.js @@ -0,0 +1,6 @@ +/*! + * github-buttons v2.7.0 + * (c) 2020 なつき + * @license BSD-2-Clause + */ +!function(){"use strict";var e=window.document,t=e.location,o=window.Math,r=window.HTMLElement,n=window.XMLHttpRequest,a="https://buttons.github.io/buttons.html",i=n&&n.prototype&&"withCredentials"in n.prototype,l=i&&r&&r.prototype.attachShadow&&!r.prototype.attachShadow.prototype,c=function(e,t,o,r){null==t&&(t="&"),null==o&&(o="="),null==r&&(r=window.decodeURIComponent);for(var n={},a=e.split(t),i=0,l=a.length;i'},heart:{width:12,height:16,path:''},eye:{width:16,height:16,path:''},star:{width:14,height:16,path:''},"repo-forked":{width:10,height:16,path:''},"repo-template":{width:14,height:16,path:''},"issue-opened":{width:14,height:16,path:''},"cloud-download":{width:16,height:16,path:''}},x={},y=function(e,t){var o=x[e]||(x[e]=[]);if(!(o.push(t)>1)){var r=p((function(){for(delete x[e];t=o.shift();)t.apply(null,arguments)}));if(i){var a=new n;d(a,"abort",r),d(a,"error",r),d(a,"load",(function(){var e;try{e=JSON.parse(a.responseText)}catch(e){return void r(e)}r(200!==a.status,e)})),a.open("GET",e),a.send()}else{var l=this||window;l._=function(e){l._=null,r(200!==e.meta.status,e.data)};var c=u(l.document)("script",{async:!0,src:e+(/\?/.test(e)?"&":"?")+"callback=_"}),s=function(){l._&&l._({meta:{}})};d(c,"load",s),d(c,"error",s),c.readyState&&h(c,/de|m/,s),l.document.getElementsByTagName("head")[0].appendChild(c)}}},k=function(e,t,o){var r=u(e.ownerDocument),n=e.appendChild(r("style",{type:"text/css"})),a="body{margin:0}a{text-decoration:none;outline:0}.widget{display:inline-block;overflow:hidden;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif;font-size:0;white-space:nowrap}.btn,.social-count{position:relative;display:inline-block;height:14px;padding:2px 5px;font-size:11px;font-weight:600;line-height:14px;vertical-align:bottom;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-repeat:repeat-x;background-position:-1px -1px;background-size:110% 110%;border:1px solid}.btn{border-radius:.25em}.btn:not(:last-child){border-radius:.25em 0 0 .25em}.social-count{border-left:0;border-radius:0 .25em .25em 0}.widget-lg .btn,.widget-lg .social-count{height:20px;padding:3px 10px;font-size:12px;line-height:20px}.octicon{display:inline-block;vertical-align:text-top;fill:currentColor}"+function(e){if(null==e)return v.light;var t=c(e,";",":",(function(e){return e.replace(/^[ \t\n\f\r]+|[ \t\n\f\r]+$/g,"")}));return v[b(v,t["no-preference"])?t["no-preference"]:"light"]+m("light",t.light)+m("dark",t.dark)}(t["data-color-scheme"]);n.styleSheet?n.styleSheet.cssText=a:n.appendChild(e.ownerDocument.createTextNode(a));var i,l,d=r("a",{className:"btn",href:t.href,target:"_blank",rel:"noopener",innerHTML:(i=t["data-icon"],l=/^large$/i.test(t["data-size"])?16:14,i=(""+i).toLowerCase().replace(/^octicon-/,""),b(w,i)||(i="mark-github"),'"),"aria-label":t["aria-label"]||void 0},[" ",r("span",{},[t["data-text"]||""])]),s=e.appendChild(r("div",{className:"widget"+(/^large$/i.test(t["data-size"])?" widget-lg":"")},[d])),f=d.hostname.split(".").reverse();if(""===f[0]&&f.shift(),"com"!==f[0]||"github"!==f[1])return d.href="#",d.target="_self",void o(s);var h=f.length,g=(" /"+d.pathname).split(/\/+/);if(((2===h||3===h&&"gist"===f[2])&&"archive"===g[3]||2===h&&"releases"===g[3]&&"download"===g[4]||3===h&&"codeload"===f[2])&&(d.target="_top"),/^true$/i.test(t["data-show-count"])&&2===h){var p,x;if(!g[2]&&g[1])p=x="followers";else if(!g[3]&&g[2])x="stargazers_count",p="stargazers";else if(g[4]||"subscription"!==g[3])if(g[4]||"fork"!==g[3]){if("issues"!==g[3])return void o(s);x="open_issues_count",p="issues"}else x="forks_count",p="network/members";else x="subscribers_count",p="watchers";var k=g[2]?"/repos/"+g[1]+"/"+g[2]:"/users/"+g[1];y.call(this,"https://api.github.com"+k,(function(e,t){if(!e){var n=t[x];s.appendChild(r("a",{className:"social-count",href:t.html_url+"/"+p,target:"_blank",rel:"noopener","aria-label":n+" "+x.replace(/_count$/,"").replace("_"," ").slice(0,n<2?-1:void 0)+" on GitHub"},[(""+n).replace(/\B(?=(\d{3})+(?!\d))/g,",")]))}o(s)}))}else o(s)},C=window.devicePixelRatio||1,z=function(e){return(C>1?o.ceil(o.round(e*C)/C*2)/2:o.ceil(e))||0},F=function(e,t){e.style.width=t[0]+"px",e.style.height=t[1]+"px"},M=function(t,r){if(null!=t&&null!=r)if(t.getAttribute&&(t=function(e){for(var t={href:e.href,title:e.title,"aria-label":e.getAttribute("aria-label")},o=["icon","color-scheme","text","size","show-count"],r=0,n=o.length;r { + if (el !== null) { + htmlElement.appendChild(el); + } + }); + } + + return htmlElement; +} + + +/** + * @param {Object} node + * @return {HTMLElement} + */ +function createExpandedElement(node) { + const iElem = createElement('i'); + + if (node.expanded) { + iElem.className = 'fas fa-caret-down'; + } else { + iElem.className = 'fas fa-caret-right'; + } + + const caretElem = createElement('div', { + className: 'caret-icon', + children: [iElem], + }); + + const handleClick = node.toggle.bind(node); + caretElem.addEventListener('click', handleClick); + + const indexElem = createElement('div', { + className: 'json-index', + content: node.key, + }); + + const typeElem = createElement('div', { + className: 'json-type', + content: node.type, + }); + + const keyElem = createElement('div', { + className: 'json-key', + content: node.key, + }); + + const sizeElem = createElement('div', { + className: 'json-size' + }); + + if (node.type === 'array') { + sizeElem.innerText = '[' + node.children.length + ']'; + } else if (node.type === 'object') { + sizeElem.innerText = '{' + node.children.length + '}'; + } + + let lineChildren; + if (node.key === null) { + lineChildren = [caretElem, typeElem, sizeElem] + } else if (node.parent.type === 'array') { + lineChildren = [caretElem, indexElem, sizeElem] + } else { + lineChildren = [caretElem, keyElem, sizeElem] + } + + const lineElem = createElement('div', { + className: 'line', + children: lineChildren + }); + + if (node.depth > 0) { + lineElem.style = 'margin-left: ' + node.depth * 24 + 'px;'; + } + + return lineElem; +} + + +/** + * @param {Object} node + * @return {HTMLElement} + */ +function createNotExpandedElement(node) { + const caretElem = createElement('div', { + className: 'empty-icon', + }); + + const keyElem = createElement('div', { + className: 'json-key', + content: node.key + }); + + const separatorElement = createElement('div', { + className: 'json-separator', + content: ':' + }); + + const valueType = ' json-' + typeof node.value; + const valueContent = String(node.value); + const valueElement = createElement('div', { + className: 'json-value' + valueType, + content: valueContent + }); + + const lineElem = createElement('div', { + className: 'line', + children: [caretElem, keyElem, separatorElement, valueElement] + }); + + if (node.depth > 0) { + lineElem.style = 'margin-left: ' + node.depth * 24 + 'px;'; + } + + return lineElem; +} + + +/** + * create tree node + * @return {Object} + */ +function createNode() { + return { + key: null, + parent: null, + value: null, + expanded: false, + type: null, + children: null, + elem: null, + depth: 0, + + setCaretIconRight() { + const icon = this.elem.querySelector('.fas'); + icon.classList.replace('fa-caret-down', 'fa-caret-right'); + }, + + setCaretIconDown() { + const icon = this.elem.querySelector('.fas'); + icon.classList.replace('fa-caret-right', 'fa-caret-down'); + }, + + hideChildren() { + if (this.children !== null) { + this.children.forEach((item) => { + item.elem.classList.add('hide'); + if (item.expanded) { + item.hideChildren(); + } + }); + } + }, + + showChildren() { + if (this.children !== null) { + this.children.forEach((item) => { + item.elem.classList.remove('hide'); + if (item.expanded) { + item.showChildren(); + } + }); + } + }, + + toggle: function() { + if (this.expanded) { + this.expanded = false; + this.hideChildren(); + this.setCaretIconRight(); + } else { + this.expanded = true; + this.showChildren(); + this.setCaretIconDown(); + } + } + } +} + + +/** + * Return object length + * @param {Object} obj + * @return {number} + */ +function getLength(obj) { + let length = 0; + for (let key in obj) { + length += 1; + }; + return length; +} + + +/** + * Return variable type + * @param {*} val + */ +function getType(val) { + let type = typeof val; + if (Array.isArray(val)) { + type = 'array'; + } else if (val === null) { + type = 'null'; + } + return type; +} + + +/** + * Recursively traverse json object + * @param {Object} obj parsed json object + * @param {Object} parent of object tree + */ +function traverseObject(obj, parent) { + for (let key in obj) { + const child = createNode(); + child.parent = parent; + child.key = key; + child.type = getType(obj[key]); + child.depth = parent.depth + 1; + child.expanded = false; + + if (typeof obj[key] === 'object') { + child.children = []; + parent.children.push(child); + traverseObject(obj[key], child); + child.elem = createExpandedElement(child); + } else { + child.value = obj[key]; + child.elem = createNotExpandedElement(child); + parent.children.push(child); + } + } +} + + +/** + * Create root of a tree + * @param {Object} obj Json object + * @return {Object} + */ +function createTree(obj) { + const tree = createNode(); + tree.type = getType(obj); + tree.children = []; + tree.expanded = true; + + traverseObject(obj, tree); + tree.elem = createExpandedElement(tree); + + return tree; +} + + +/** + * Recursively traverse Tree object + * @param {Object} node + * @param {Callback} callback + */ +function traverseTree(node, callback) { + callback(node); + if (node.children !== null) { + node.children.forEach((item) => { + traverseTree(item, callback); + }); + } +} + + +/** + * Render Tree object + * @param {Object} tree + * @param {String} targetElem + */ +function render(tree, rootElem) { + /*if (targetElem) { + rootElem = document.querySelector(targetElem); + } else { + rootElem = document.body; + }*/ + + traverseTree(tree, (node) => { + if (!node.expanded) { + node.hideChildren(); + } + rootElem.appendChild(node.elem); + }); +} + + +/* Export jsonView object */ +window.jsonView = { + /** + * Render JSON into DOM container + * @param {String} jsonData + * @param {String} targetElem + */ + format: function(jsonData, targetElem) { + let parsedData = jsonData; + if (typeof jsonData === 'string' || jsonData instanceof String) parsedData = JSON.parse(jsonData); + const tree = createTree(parsedData); + render(tree, targetElem); + } +} + +})(); diff --git a/docs/.vuepress/public/js/main.js b/docs/.vuepress/public/js/main.js new file mode 100644 index 0000000000..f8c170f557 --- /dev/null +++ b/docs/.vuepress/public/js/main.js @@ -0,0 +1,6 @@ +jQuery(document).ready(function() { + $('div.json[data-json]').each(function(index, element) { + var json = $(element).attr('data-json').replace(/[\u201C\u201D]/g, '"'); + jsonView.format(json, element); + }); +}); diff --git a/docs/.vuepress/public/site.webmanifest b/docs/.vuepress/public/site.webmanifest new file mode 100644 index 0000000000..45827873ee --- /dev/null +++ b/docs/.vuepress/public/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "BDK Docs", + "short_name": "BDK Docs", + "icons": [ + { + "src": "/img/favicon/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/img/favicon/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/docs/.vuepress/styles/palette.styl b/docs/.vuepress/styles/palette.styl new file mode 100644 index 0000000000..b223ba52df --- /dev/null +++ b/docs/.vuepress/styles/palette.styl @@ -0,0 +1 @@ +$accentColor = #F7931A diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..420619aacf --- /dev/null +++ b/docs/README.md @@ -0,0 +1,54 @@ +--- +home: true +heroText: Bitcoin Dev Kit +tagline: With BDK, you can seamlessly build cross platform mobile wallets +actionText: Get started +actionLink: /getting-started/ +features: +- title: "Customizable" + details: "Designed from the ground up to be easily customized to your application needs: blockchain backends, databases, signers, coin selection, key management and more." + image: "customizable" +- title: "Focus on what matters" + details: "All of the low-level Bitcoin logic is handled by us, so you can focus on crafting custom-tailored user experiences." + image: "focus" +- title: "High performance & compact" + details: "As lightweight as you need it to be and optimized to run on all modern-day embedded devices such as mobile phones, IoT devices, PoS terminals and more." + image: "mobile" +--- + +
+ +

Why BDK?

+

The simplest way to integrate Bitcoin wallet features into any application

+ +
+ +
+
+

Multi-Language Support

+ +We are building native API's for C, Swift, Java & Kotlin so you can easily integrate Bitcoin in your preferred programming language on mobile. + +
+ +
+

Descriptors

+ +Through descriptors and miniscript we support generalized wallet spending conditions. This provides wallets with first class support for very complex spending policies, without having to individually translate them into code. + +
+ +
+

Custom Block Data Sources

+ +Use a local full node, an SPV node, or your own Electrum or Esplora server with API access to source data about the blockchain. You choose exactly what's right for your project. + +
+ +
+

Cross Platform

+ +The core logic is feature rich allowing you to build any wallet from scratch on mobile, desktop and even WebAssembly. + +
+
diff --git a/docs/_blog/compact_filters_demo.md b/docs/_blog/compact_filters_demo.md new file mode 100644 index 0000000000..283597fa8a --- /dev/null +++ b/docs/_blog/compact_filters_demo.md @@ -0,0 +1,385 @@ +--- +title: "Using BDK to create BIP157 SPV wallet (aka Neutrino)" +description: "Tutorial showing usage of compact filters (BIP157) using bdk-cli command line tools" +authors: + - Rajarshi Maitra +date: "2021-06-20" +tags: ["tutorial", "BDK", "bdk-cli", "compact_filters", "BIP157", "Neutrino"] +permalink: "/blog/2021/06/using-bdk-to-create-bip157-spv-wallet-aka-neutrino/" +--- + +## Introduction + +#### Compact Filters: +Compact filters are the latest specification of Bitcoin SPV node implementation as per [BIP157](https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki) and [BIP158](https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki). Such light clients were envisioned by Satoshi himself in his original white paper, but due to lack of robust privacy and trust guarantees using conventional [bloomfilters](https://github.com/bitcoin/bips/blob/master/bip-0037.mediawiki), these type of nodes never got popular. + +Enters [BIP157](https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki), which described a new type of filters for Bitcoin Blockchain data, known as `compact_filters`. The [Neutrino](https://github.com/lightninglabs/neutrino) project pioneered the use of compact filter based light client nodes for using with Lightning Network wallets. Using compact filters, a light-node can talk to one or more full nodes, and fetch relevant information from the blockchain, with much more robust privacy and security guarantees than previously possible. Compact filter based nodes are best suitable to be used with mobile wallets, to create more trustless mobile applications on Bitcoin. Any wallet application that needs to have an "eye on the blockchain" has an use for such light clients. + +`BIP157` type filters allows to create tiny sized SPV nodes, that can fetch blockchain data and can identify inconsistency, so it can actively defend itself, while also preserving its privacy. Such nodes are most useful for Lightning Network mobile applications. + +Example of such `compact_filters` wallets in wild is [Breeze](https://github.com/breez/breezmobile) Lightning mobile wallet. + +Bitcoin core supports serving `BIP157` type filters from `v0.21.0`. + +#### BDK and Compact filters +BDK is a bitcoin wallet development library that can be used to create bitcoin wallets with custom `Database` and `Blockchain` backends. BDK is a [descriptor](https://bitcoindevkit.org/descriptors/) based wallet, i.e. the wallet keychain is described by a set of descriptors. + +Using BDK one can instantiate wallets of various kinds as per requirement. BDK abstracts away all the heavy lifting works, and allow wallet devs to concentrate on logic that they care about, i.e. writing wallet codes. For more detailed documentation on BDK capabilities check these [blog](https://bitcoindevkit.org/blog/2020/12/hello-world/), [bog](https://bitcoindevkit.org/blog/2020/11/descriptors-in-the-wild/) and [docs](https://docs.rs/bdk/). + +The main three components of abstraction in BDK are + - `Database` + - `Descriptors` + - `Blockchain` + +BDK comes with default implementations of all them that developers can start with out of the box. Developers can also create there own custom implementations and plug it into BDK (thanks to rust magic of `Traits`). + +BDK also supports [BIP158](https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki) communication protocol, which allows creation of `BIP157` type compact filter SPV nodes. This capability is extended to wallet with BDK's `Blockchain` data structure. The [API](https://docs.rs/bdk/0.8.0/bdk/blockchain/trait.Blockchain.html) for `compact_filters` backend is similar to any other kind of backends, so wallet devs don't need to worry about all the details. Its ok if the dev haven't even heard of `BIP157`, BDK takes care of that in background. + +This capability can be unlocked by compiling BDK with the `compact_filters` feature. Once enabled, BDK will be able to create wallets with the `compact_filters` type `Blockchain` backend. (The default backend is electrum server) + +#### bdk-cli +`bdk-cli` is a lightweight [REPL](https://codewith.mu/en/tutorials/1.0/repl) wrapper over the BDK library to facilitate quick and easy demonstration of BDK capabilities in command-line. Wallet devs can use this tool to quickly try out different possibilities with BDK. + +In this tutorial, We will use `bdk-cli` to demonstrate some basic wallet functionalities using `compact_filters` backend. + +## Tutorial Scope +Basic wallet workflow we will cover: + + - create and sync a wallet, + - receive a transaction, + - create a transaction, + - sign and broadcast the transaction, + - fetch updated balance, + +The BDK wallet will have a `BIP157` SPV backend (aka `compact_filters` backend) that will connect with a Bitcoin core node serving filter data. + +It will publish and extract transaction data through that node. + +We will have a Bitcoin Core wallet and a BDK wallet, sending and receiving transactions between each other, in regtest. + +## Prerequisites +Following things are required to start with the tutorial. + +1. A Bitcoin Core regtest node listening at `localhost:18444` signalling for compact filter support. +2. `bdk-cli` compiled with `compact_filter` features. + +If you already have these two setup and working, you can skip this and jump to the [Tutorial](#tutorial) section. + +#### Install and run `bitcoind` +You can definitely do it with your own `bitcoind` installation. `BIP157` support has been included in Bitcoin Core `v0.21.0`. So anything above that will work. + +You also need to ensure proper configuration settings for signalling `compact_filters` support. + +For ease of testing, the BDK project hosts docker images that can be used to spawn Bitcoin Core with all the relevant configurations. + +- spawn a regtest node using [bitcoin-regtest-box](https://github.com/bitcoindevkit/bitcoin-regtest-box) docker file. + + Start the regtest box docker container. + + ```shell + $ docker run --detach --rm -p 127.0.0.1:18443-18444:18443-18444/tcp --name bdk-box bitcoindevkit/bitcoind + ``` + This will spin up a docker container running `bicoind` and listening to port `18444` and `18333`. You can keep this terminal alive to see communication events with BDK and the node. + +- Check node is reachable + + In another terminal try connecting to the node with `bitcoin-cli` + ```shell + $ docker exec -it bdk-box /root/bitcoin-cli -regtest getnetworkinfo + { + "version": 210000, + "subversion": "/Satoshi:0.21.1/", + "protocolversion": 70016, + "localservices": "0000000000000449", + "localservicesnames": [ + "NETWORK", + "WITNESS", + "COMPACT_FILTERS", + "NETWORK_LIMITED" + ... + ], + } + + ``` + In the output, the `version` should show `210000`. `localservicesnames` should contain `"COMPACT_FILTERS"`. If you see this, then Bitcoin Core is correctly configured. + +#### Install and run bdk-cli +- Install `bdk-cli` with `compact_filters` feature + + ```shell + $ cargo install --git https://github.com/bitcoindevkit/bdk-cli.git bdk-cli --features compact_filters + ``` +- Check installation + ```shell + $ bdk-cli --help + ... + USAGE: + bdk-cli [OPTIONS] + FLAGS: + -h, --help Prints help information + -V, --version Prints version information + OPTIONS: + -n, --network Sets the network [default: testnet] + + SUBCOMMANDS: + help Prints this message or the help of the given subcommand(s) + key Key management sub-commands + repl Enter REPL command loop mode + wallet Wallet options and sub-commands + ``` +Once these are setup correctly, you can start with the tutorial next. + + + +## Tutorial +[Note: For brevity `bdk-cli` results are stored in command line variables using `jq` tool. It is recommended to check the full results to see different information returned by `bdk-cli` commands.] + +### Bitcoin Core Wallet Generation + +This is standard procedure with `bitcoin-cli`. + +- Create a wallet and generate 101 blocks. + ```shell + $ docker exec -it bdk-box /root/bitcoin-cli -regtest createwallet test + { + "name": "test", + "warning": "" + } + ``` + + ```shell + $ docker exec -it bdk-box /root/bitcoin-cli -regtest getnewaddress + bcrt1qatd7yq0jukwusuaufltlejmeydpvnpv43r5gc2 + ``` + ```shell + $ docker exec -it bdk-box /root/bitcoin-cli -regtest generatetoaddress 101 bcrt1qatd7yq0jukwusuaufltlejmeydpvnpv43r5gc2 + [ + "3813ed6eb716f4743b9657d918799acf743add985a8ded28d8aa3629dd4496b6", + "70da855913bdf791b6e458c611cebdef79b7a9840eb103ce58c71c1c7e3c49bc", + "682ca732ef72719cd6f82c5047c7690fb1cd2df2543d035ac4ea99e974b8d172", + "78799e4771017d4f46aa3c240054e2d61f54cea07ec44cb18ae712761e0aaa1e", + ... + ] + ``` + ```shell + $ docker exec -it bdk-box /root/bitcoin-cli -regtest getbalance + 50.00000000 + ``` + Now the core wallet has generated new blocks and is funded with test bitcoin. + + +### BDK Wallet Generation +BDK is a descriptor based wallet library. So in order to use it we will need some descriptors to work with. + +BDK wallet will ask for two descriptors as input, corresponding to `receive` and `change` addresses. Its recommended to have these two descriptors separate as BDK will handle them separately and ensure `change` addresses are never used for receiving funds. + +Or developers can decide to use a single descriptor too, in that case BDK will use that descriptor for deriving both `receive` and `change` addresses. + +We will use `bdk-cli` itself to generate such descriptors. + +- #### Generate a privatekey + ```shell + $ BDK_xprv=$(bdk-cli key generate | jq -r '.xprv') + $ echo $BDK_xprv + tprv8ZgxMBicQKsPefY7tdq7EKny81n9tfSvUYfSHAZByXdjPAZVysvaB6sFd2YavqfqMBgbHaXUG5oWM6sYvdJn6vnUizzQKTYAJ36bQsfPv4N + ``` + `bdk-cli key generate` will generate a fresh master key with `mnemonic` and `xprv`. We have extracted the value of extended private key and stored it in `BDK_xprv` variable. + + The returned `mnemonic` can be used to restore back the wallet if wallet data directory is lost. + +- #### Generate Descriptors + `bdk-cli key derive` can derive an `xpub`s given a `master key` and `derivation_path`. + + We will use the following paths for our `receive` and `change` descriptors + + - `receive` path: `m/84h/1h/0h/0` + - `change` path: `m/84h/1h/0h/1`, + + We can then simply wrap them in a `"wpkh()"` to create our descriptors string and store them. + + When asked for a new address, BDK will derive one from the `receive` descriptor. + + And while constructing transaction, BDK will use the `change` descriptor to derive change address. + + ```shell + $ BDK_recv_desc="wpkh($(bdk-cli key derive --path m/84h/1h/0h/0 --xprv $BDK_xprv | jq -r '.xprv'))" + $ echo $BDK_recv_desc + wpkh([ff09c7c9/84'/1'/0'/0]tprv8hkdEGgwLLnqsdfkJFidpTj5d6z5qFdP6Qwzsviea3HrS9C2mXXaDivPKCCgcaWvnGNX9eciLUQs91PWYXJqrChfnAagViCgG6L5phaNyWr/*) + ``` + ```shell + $ BDK_chng_desc="wpkh($(bdk-cli key derive --path m/84h/1h/0h/1 --xprv $BDK_xprv | jq -r '.xprv'))" + $ echo $BDK_chng_desc + wpkh([ff09c7c9/84'/1'/0'/1]tprv8hkdEGgwLLnqtbYkGG7fSy7v43RF2SQGGjNuZtmBzEHh7H8xgpXBETQAbVPqi8rkvLNFKLYY4rDzXA4fn5Ha1yuazZqhQPe3uNKmFS7648s/*) + ``` + Note: `BDK_xprv` has been used as the `master key`, this will allow BDK to have signing capabilities. + We could have used an `xpub` master key here instead, that would create an `watch-only` wallet. + +- #### Create and Sync a wallet + We will now instruct BDK to create a new wallet with following instructions + + ```shell + $ bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc sync + {} + ``` + - name (`--wallet`) `bdk-test`, + - `receive` descriptor (`-d`) as `$BDK_recv_desc` and change descriptor (`-c`) as `$BDK_chng_desc`, + - connected to a full node (`--node`) listening at `127.0.0.1:18444`, + - and finally create and sync the wallet with the `sync` command. + + If you are using a `regtest` node, also add `--network regtest`, the default is `testnet`. + + `bdk-cli` makes multiple parallel connections that can be configured with the `--conn-count` parameter (default is 4). This makes syncing parallel and fast. Use `bdk-cli --help` to see all other options. + + Getting an empty return means wallet creation succeeded. + + BDK has created a wallet named `bdk-test` in its data directory. Which is by default stored at `~/.bdk-bitcoin/compact_filters` folder. + + Looking into that folder different files and directories maintained by BDK can be seen. + ```shell + $ ls .bdk-bitcoin/compact_filters/ + 000004.log CURRENT LOCK MANIFEST-000003 OPTIONS-000010 + bdk-test IDENTITY LOG OPTIONS-000008 + ``` +### Recieve Coins + +We will use the `core` wallet to send 5 BTC to our`bdk-test` wallet. + +- Fetch a new address using `bdk-cli` + ```shell + $ bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc get_new_address + { + "address": "bcrt1qx2479wywulf50pqx5uy64zhxq9f3tuvlh8u0s9" + } + ``` + +- Transfer funds to the previous address and generate a block, using `bitcoin-cli` + ```shell + $ docker exec -it bdk-box /root/bitcoin-cli -regtest sendtoaddress bcrt1qx2479wywulf50pqx5uy64zhxq9f3tuvlh8u0s9 5 + + + $ docker exec -it bdk-box /root/bitcoin-cli -regtest generatetoaddress 1 bcrt1qw3ht9xtc9pgyvmqay0ap9fw8mxd27az8el0uz3 + ``` + + `core` has sent 5 BTC to our `bdk-test` wallet. Which is confirmed in a new block. + + `bdk-test` can see that now by syncing again. + + (Note: BDK required explicit `sync()` calls to give wallet developers flexibility on when to sync). + ```shell + $ bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc sync + {} + + $ bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc get_balance + { + "satoshi": 500000000 + } + ``` + + We can see `500000000` sats balance in our `bdk-test` wallet. + + BDK has fetched blockchain details concerning its wallet descriptors, from the core node, using compact filters. + +### Creating a transaction. + Now we want to create a transaction sending coins from `bdk-test` wallet to the `core` wallet. + +- fetch a new `core` address + ```shell + $ core_addrs=$(docker exec -it bdk-box /root/bitcoin-cli -regtest getnewaddress | tr -d '\r') + ``` + +- Create a raw transaction using `bdk-cli` to the above address. This will generate a `psbt` which we will sign. + ```shell + $ psbt=$(bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc create_tx --to $core_addrs:200000000 | jq -r '.psbt') + ``` + (Recommended to check all the other information returned by `bdk-cli create_tx`) + +### Sign and Broadcast the transaction +Asking BDK to sign a transaction is as straight forward as it can get. BDK already holds the `xprv` deatils to sign a transaction. It returns a finalised `signed_psbt` which we will next broadcast to the network. + +- Sign the transaction + ```shell + $ signed_psbt=$(bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc sign --psbt $psbt | jq -r '.psbt') + ``` + +- Broadcast the transaction + ```shell + $ bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc broadcast --psbt $signed_psbt + { + "txid": "c343f5b25372e285308eba912d1fe8fade9f64afde6d95306e248e52e0852252" + } + ``` + This makes BDK broadcast the transaction via the connected core node, and it returns the corresponding Txid. + +### Confirming the Transaction + The transaction has been received by the `core` node and waiting in its mempool for inclusion in block. + We can see the transaction via its `txid` received in previous step. + +- Check transaction in mempool + ```shell + $ docker exec -it bdk-box /root/bitcoin-cli -regtest gettransaction c343f5b25372e285308eba912d1fe8fade9f64afde6d95306e2248e52e0852252 + { + "amount": 2.00000000, + "confirmations": 0, + "trusted": false, + "txid": "c343f5b25372e285308eba912d1fe8fade9f64afde6d95306e248e52e0852252", + "walletconflicts": [ + ], + "time": 1621697202, + "timereceived": 1621697202, + "bip125-replaceable": "no", + "details": [ + { + "address": "bcrt1q3h4hs6mve5dcl7da3d4acmlp20hh8c3t4mldwe", + "category": "receive", + "amount": 2.00000000, + "label": "", + "vout": 1 + } + ], + "hex": "01000000000101d84e8cb7477f9fe6f265b56d5416ff47da9a70be18f65ec50731b8257c67f2bd0100000000ffffffff0273a2e11100000000160014874270187001febc4cebd8cb083cf2c783e8f1ac00c2eb0b000000001600148deb786b6ccd1b8ff9bd8b6bdc6fe153ef73e22b0247304402201037d9ef5b80392296311c8899b1f12a0987778d694a442a88bafa6fbd7a7c9a022011293176255897444d9c71b0b9cd13b2aedb749b142577566c90a63d61025e2c01210202427d16b29c1c8546255363a74326ee9ab3196770bb3fccc7b679d52f9c1ccf00000000" + } + ``` + This means, core has recieved the transaction in its mempool and waiting for confirmation. + +- Generate 1 block to confirm the transaction + ```shell + $ docker exec -it bdk-box /root/bitcoin-cli -regtest generatetoaddress 1 bcrt1qatd7yq0jukwusuaufltlejmeydpvnpv43r5gc2 + [ + "55436ff0169bbb3e70ab10cb7cdd45ab86204d5d7864a109142d91120d023197" + ] + ``` + +- Sync the `bdk-test` wallet and ask for available balance. + ```shell + $ bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc sync + {} + + $ bdk-cli --network regtest wallet --node "127.0.0.1:18444" --wallet bdk-test -d $BDK_recv_desc -c $BDK_chng_desc get_balance + { + "satoshi": 299999859 + } + ``` + + If you see the balance updated, voila! + + What happened here is: + - core created a new block containing the transaction. + - `bdk-cli` fetched the corresponding filter data. + - It noticed it got a concerning transaction. + - It asked for the details of that transaction from the core node. + - It updated its wallet details with this new information. + - The update is reflected in the wallet balance. + +### Shutdown Docker ### + +You may now shutdown the regtest docker container. + +Note: This will also clean up any data in the bitcoin core, including the wallet. + +```shell +$ docker kill bdk-box +``` + +## End Words + +In this tutorial we went through the process of receiving, creating, signing and broadcasting transaction using the BDK wallet with `compact_filters` feature. This demonstrates how BDK capabilities can be used to create SPV light wallets with integrated `BIP157` type `compact_filters` node. diff --git a/docs/_blog/descriptor_based_paper_wallet.md b/docs/_blog/descriptor_based_paper_wallet.md new file mode 100644 index 0000000000..a0ed8a2e85 --- /dev/null +++ b/docs/_blog/descriptor_based_paper_wallet.md @@ -0,0 +1,190 @@ +--- +title: "Descriptor-based paper wallets" +description: "Demonstrate how to create descriptor-based paper wallet and how to spend them with bdk" +authors: + - Riccardo Casatta + - Steve Myers +date: "2021-03-30" +tags: ["guide", "descriptor", "paper wallets"] +permalink: "/blog/2021/03/descriptor-based-paper-wallets/" +--- + +In this post, we will use the [Rusty Paper Wallet] tool to create a multi-owned descriptor-based paper wallet. We will use [bdk] via the [bdk-cli] tool to test our descriptor and to be able to sweep the funds from our paper wallet to a new address. + +## About paper wallets + +Paper wallets have a lot of drawbacks, as explained in the [paper wallet Wiki article], as always, do your own research before deciding to use it with mainnet bitcoins. In this post we will +only be using testnet coins. + +## Descriptors + +The [previous version] of the [Rusty Paper Wallet] followed the original paper wallet design: WIF[^WIF] as secret part with the option to generate a different kind of addresses (legacy, nested segwit, and segwit). + +There were plans to [support mnemonic](https://github.com/RCasatta/rusty-paper-wallet/issues/5) instead of WIF keys because it may[^WIF core] save the sweep transaction[^sweep] and there are more wallets capable of importing a mnemonic instead of a WIF. + +However, choosing a single address type or having wallet support for a specific format is the kind of problem [descriptors] solve perfectly, so the latest [Rusty Paper Wallet] version now accepts a descriptor and the network as parameters. + +## Example use case + +So let's say your grandma wants to buy bitcoin and asked for your help. + +You are a little afraid she may lose the private key. At the same time, you don't want to duplicate the keys and give those to her daughters Alice and Barbara, because both of them could spend and accuse the other of having done so. + +Even though we trust everyone in the family it is better to play it safe and divide the responsibility of protecting Grandma's bitcoin. + +This is a perfect case for a 2 of 3 multi-signature paper wallet. This way also protects the participants from having their copy of the wallet stolen. To compromise Grandma's wallet a thief would need to find and steal at least two of them. + +Note that you as the wallet creator are still the single point of trust because you are going to generate the keys for everyone. Setups combining self generated keys from the participants is possible future work. + +## Creating the paper wallet + +For this example the spending descriptor would be: + +`wsh(multi(2,Grandma,Alice,Barbara))` + +You need [rust] installed to use [Rusty Paper Wallet]. The -n option below explicitly selects +generating `testnet` keys. Use `rusty-paper-wallet --help` to see usage instructions and other +options. + +```shell +$ cargo install rusty-paper-wallet +$ rusty-paper-wallet "wsh(multi(2,Grandma,Alice,Barbara))" -n testnet +data:text/html;base64,PCFET0N... +``` + +The [output] of the command is very long and has been shortened. The string is a [data URI scheme] paste-able in the address bar of a browser. By using a data URI no files are written on the hard disk, leaving less trace of secret material on the computer. +It's also a good idea to use incognito mode in the browser to prevent it from saving the page in the history. + +The following is the result: + + + +Under the hood, the command created a key pair randomly for every alias present in the descriptor, then replaced the aliases with the created keys and generated the corresponding address. This address is the same for every paper wallet and it is shown in the upper part of the paper wallet (the public part) along with the alias, linking the paper wallet to the owner. + +The lower part is the secret part, the written part is the descriptor with the aliases, followed by a legend linking the aliases with the keys. In the legend, all the keys are public but the one of the owner which is a private WIF. The secret QR code instead contains the descriptor already with the keys. + +The paper wallet must then be printed, and it is better to use a printer without wifi and also to be aware that some sensitive data may remain in the printer's cache. + +Then the paper wallet must be cut along the dotted lines, the secret part should be folded twice over the black zone[^black zone]. The black zone helps to avoid showing the secret parts in the presence of back-light. Once the folding is done the paper wallet should be plasticized to prevent being damaged by water. + +## BDK + +Any descriptor based wallet can be used to check the balance of and sweep the funds from +Grandma's paper wallet. For this post we'll demonstrate using the [bdk-cli] tool to do these steps. +Another area where [bdk] could be used with [Rusty Paper Wallet] is to compile a more +complicated miniscript spending policy into a descriptor, as we have done in the [spending policy demo] post. + +## Funding tx + +Since Grandma's wallet was created as a `wsh` descriptor, bitcoin can be sent to it from any +segwit capable wallet, we'll use a public [bitcoin testnet faucet]. Once the funds are sent the +deposit address `tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw` we can also use this +address and a testnet explorer to [confirm the funds were received]. + +## Sweep tx + +Now that Grandma's paper wallet is funded it's time to demonstrate how to use [bdk-cli] to sweep these +funds to a new address. Let's assume Grandma lost her original paper wallet and has asked +her daughters to sweep them to a new single signature wallet so she can spend them. + +### Step 1: Alice creates and signs a PSBT + +Alice uses the private text or QR code from her paper wallet to find her private key and the +public keys for Grandma and Barbara. With this info she creates a PSBT to sweep Grandma's funds +to a new address (in this example we'll send them back to our [bitcoin testnet faucet]). Notice how Alice +includes her wallet's descriptor checksum '#em3q73l5', this [guarantees] she has entered her descriptor correctly. + +```shell +$ SWEEP_TO_ADDR=tb1qm5tfegjevj27yvvna9elym9lnzcf0zraxgl8z2 + +$ ALICE_WIF=cSSKRHDmQEEutp5LD14tAcixu2ehSNPDTqNek1zMa9Pet98qxHq3 +$ BARBARA_PUBKEY=02a3f3f2658b9812ddeabfbde2fde03f8a65369e4ed621f29fa8ba0cc519b789fb +$ GRANDMA_PUBKEY=03f1bd2bff8e9c61f58a8d46d18fd8f3149b1f2d76b3c423a7874a5d5811d67cee +$ ALICE_DESCRIPTOR="wsh(multi(2,$GRANDMA_PUBKEY,$ALICE_WIF,$BARBARA_PUBKEY))#em3q73l5" + +# confirm descriptor creates the expected deposit address +$ bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR get_new_address +{ + "address": "tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw" +} + +# sync the wallet and show the balance +$ bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR sync +{} + +$ bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR get_balance +{ + "satoshi": 10000 +} + +# create and sign PSBT +$ UNSIGNED_PSBT=$(bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR create_tx --send_all --to $SWEEP_TO_ADDR:0 | jq -r ".psbt") + +$ ALICE_SIGNED_PSBT=$(bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR sign --psbt $UNSIGNED_PSBT | jq -r ".psbt") +``` + +### Step 2: Barbara signs Alice's signed PSBT and broadcasts the tx + +Now it's Barbara's turn to use the private text or QR code from her paper wallet to get her private +key and the public keys for Grandma and Alice. With this info plus Alice's signed PSBT she can +create a fully signed PSBT to broadcast and complete the sweep of Grandma's funds. + +```shell +$ ALICE_PUBKEY=02e486e32f0f87136fa042cb53219ace8537ea1d036deb2f4293570b94325d11cb +$ BARBARA_WIF=cSfMLzSZ9NjWUTqL3sFpgWJssnu2qgmE2cm5N1jPDRRJuDcrsPEB +$ GRANDMA_PUBKEY=03f1bd2bff8e9c61f58a8d46d18fd8f3149b1f2d76b3c423a7874a5d5811d67cee +$ BARBARA_DESCRIPTOR="wsh(multi(2,$GRANDMA_PUBKEY,$ALICE_PUBKEY,$BARBARA_WIF))#nxfa5n0z" + +# confirm descriptor creates the expected deposit address +$ bdk-cli wallet -w barbara -d $BARBARA_DESCRIPTOR get_new_address +{ + "address": "tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw" +} + +# sync the wallet and show the balance +$ bdk-cli wallet -w barbara -d $BARBARA_DESCRIPTOR sync +{} + +$ bdk-cli wallet -w barbara -d $BARBARA_DESCRIPTOR get_balance +{ + "satoshi": 10000 +} + +$ FINAL_PSBT=$(bdk-cli wallet -w barbara -d $BARBARA_DESCRIPTOR sign --psbt $ALICE_SIGNED_PSBT | jq -r ".psbt") + +$ bdk-cli wallet -w barbara -d $BARBARA_DESCRIPTOR broadcast --psbt $FINAL_PSBT +{ + "txid": "9ecd8e6be92b7edd8bf1799f8f7090e58f813825f826bdb771b4cdb444cdeb59" +} +``` + +And finally we verify that Alice and Barbara successfully created and broadcast Grandma's [sweep tx]. + +## Conclusion + +In this post we showed how to create a multi-sig descriptor based paper wallet using +[Rusty Paper Wallet] and then sweep the funds from our example paper wallet to a new address. If you +found this post interesting please comment below. Or give it a try yourself and if you run into any +problems or would like to suggest improvements leave an issue in the [Rusty Paper Wallet] or +[bdk-cli] github repos. Thanks! + +[paper wallet wiki article]: https://en.bitcoin.it/wiki/Paper_wallet +[previous version]: https://github.com/RCasatta/rusty-paper-wallet/tree/339fa4418d94f6fdd96f3d0301cab8a0bc09e8bd +[Rusty Paper Wallet]: https://github.com/RCasatta/rusty-paper-wallet +[support mnemonic]: https://github.com/RCasatta/rusty-paper-wallet/issues/5 +[descriptors]: /descriptors +[bdk]: https://github.com/bitcoindevkit/bdk +[rust]: https://www.rust-lang.org/tools/install +[output]: /descriptor-based-paper-wallets/data-url.txt +[data URI scheme]: https://en.wikipedia.org/wiki/Data_URI_scheme +[bdk-cli]: https://github.com/bitcoindevkit/bdk-cli +[bitcoin testnet faucet]: https://bitcoinfaucet.uo1.net/ +[confirm the funds were received]: https://mempool.space/testnet/address/tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw +[sweep tx]: https://mempool.space/testnet/tx/9ecd8e6be92b7edd8bf1799f8f7090e58f813825f826bdb771b4cdb444cdeb59 +[spending policy demo]: /blog/2021/02/spending-policy-demo/#step-4-create-wallet-descriptors-for-each-participant +[guarantees]: https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md#checksums + +[^WIF]: Wallet Input Format, a string encoding a ECDSA private key https://en.bitcoin.it/wiki/Wallet_import_format +[^WIF core]: Unless the user import the WIF directly into bitcoin core +[^sweep]: Some wallets refers to sweep as the action to create a transaction taking all the funds from the paper wallet and sending those to the wallet itself. +[^black zone]: Ideally, the black zone should be twice as long as the secret part to cover it back and front, long descriptor may leave a shorter black zone, ensure to have you printer set with vertical layout for best results. diff --git a/docs/_blog/descriptors_in_the_wild.md b/docs/_blog/descriptors_in_the_wild.md new file mode 100644 index 0000000000..74634e78dc --- /dev/null +++ b/docs/_blog/descriptors_in_the_wild.md @@ -0,0 +1,344 @@ +--- +title: "Descriptors in the wild" +description: "Guide to setup a 2-of-2 multisig using Bitcoin Core and BDK" +authors: + - Gabriele Domenichini +date: "2020-11-18" +tags: ["guide", "descriptor"] +permalink: "/blog/2020/11/descriptors-in-the-wild/" +--- + +I have tried to setup a 2 of 2 multi signature infrastructure with two +different wallets, which know nothing about each other, but are compliant with +two very important protocols: [Output Descriptors] and [Partially Signed +Bitcoin Transactions][PSBT] described in BIP 174. + +Before these two protocols came into existence, making a multi signature setup +and spending from it was possible only if the involved parties were using the +same wallet (eg. Electrum Desktop Wallet). This limitation was due to the fact +that the two parties had to agree: + +* on the particular type of script and address to use +* on the way the transaction would be shared composed and signed with all the +involved parties. + +[Output Descriptors] are a way to express which kind scriptPubKey and +addresses to produce with a key or a series of keys. + +[PSBT] is instead the standard protocol used to create a transaction and to enrich +it with the necessary signatures and other components, to make it valid and complete. + +Together they provide a common ground to create and use a multi signature +infrastructure in a heterogeneous environment, and this is what I have put +to test. + +## The use case + +Imagine Alice and Bob owning a company and being willing to put the corporate cash +in a 2of2 multi signature setup, so that each one of them have to agree and sign each +transaction. + +## The role of Descriptors + +If Alice and Bob cannot agree on the software to use, to monitor the same financial +situation, the two software must control and produce exactly the same series +of multisignature addresses. + +To make two different software produce the same addresses in a deterministic way +we must ensure that they: +* produce the same pair of public keys +* combine them in the same order +* put them inside the same scriptPubKey to produce the same address + +Here is where the [Output Descriptors] come into play. They describe: + +* the sequence of public keys each extended key (xpub) will produce +* the sequence in which the new public keys of various parties will enter into +the script +* the type of script the wallet will prepare with that group keys and so the type +of address the group of keys will produce. + +**By sharing the same Descriptor, every compliant wallet will derive +deterministically the same series of multisig addresses**. + +Imagine Alice using Bitcoin Core (from now on ["Core"][Bitcoin Core]) as a +Wallet and Bob using a "Last generation" wallet, Bitcoin Development Kit +(from now on ["BDK"][BDK]), which uses descriptors and miniscript natively. + +Each of these two software wallets should be able to: + +* Create a new address which is seen as belonging to the multi signature +wallet in both software +* Express the consent of each party by partially signing the transaction in a way +the other wallet can understand and complete it with its own signature. + +The infrastructure of multiple Extended keys combined toghether to produce +multiple multisignature addresses is often referred as +*[Hierarchical Deterministic][HDWallet] multi signature wallet or HDM*. + +What follows are the steps to create the HDM usable both in Core and +in BDK. + +*Note: In Core, [Descriptor wallets] are still experimental and in general, +both wallets should be tested for descriptor capabilities only in testnet.* + +## Our playground + +We will build a 2of2 key set up that will be used cooperatively by Bitcoin Core +and Bitcoin Development Kit. +The steps Alice and Bob will do are: + +1. creation of the seed and the derived Extended Master Public and send it to +the other party +2. Create the multi signature descriptor for each wallet +3. Use each other's software to receive testnet coins from a faucet +4. return part of the coins to the faucet signing the transaction with both +wallets. + +We need: +* [Bitcoin Dev Kit][BDK] +* [Bitcoin Core] (v0.21.0 or later) + +### 1. Creating the seeds and the derived Extended Public keys + +#### Seeds and Extended Master Public + +We build an Extended Private Master Key for both wallet and derive a BIP84 +Extended Master Public for Bitcoin Core and then for BDK. + +For Bitcoin Core (Alice): + +``` +# new Extended wallet data +export core_key=$(bdk-cli key generate) + +# New Extended Master Private + +export core_xprv=$(echo $core_key | jq -r '.xprv') + +# Now I derive the xpubs (one for receiving and one for the change) +# together with informations about the derivation path to be communicated +# to BDK wallet's owner (Bob). + +export core_xpub_84_for_rec_desc=$(bdk-cli key derive --path m/84h/0h/0h/0 --xprv $core_xprv | jq -r '.xpub') +export core_xpub_84_for_chg_desc=$(bdk-cli key derive --path m/84h/0h/0h/1 --xprv $core_xprv | jq -r '.xpub') +``` + +For BDK (Bob) we do the same: + +``` +# new Extended wallet data + +export BDK_key=$(bdk-cli key generate) + +# New Extended Master Private + +export BDK_xprv=$(echo $BDK_key | jq -r '.xprv') + +# Now I build the derived xpubs to be communicated (to Alice). + +export BDK_xpub_84_for_rec_desc=$(bdk-cli key derive --path m/84h/0h/0h/0 --xprv $BDK_xprv | jq -r '.xpub') +export BDK_xpub_84_for_chg_desc=$(bdk-cli key derive --path m/84h/0h/0h/1 --xprv $BDK_xprv | jq -r '.xpub') +``` + +### 2. Creation of the multi signature descriptor for each wallet + +To build a multisig wallet, each wallet owner must compose the descriptor +adding: +* his derived extended **private** key AND +* all the extended **public** keys of the other wallets involved in the +multi signature setup + +*The different nature of the two keys (one is private and one is public) is +due to the fact that each wallet, to be able to partially sign the transaction, +**must manage the private key of the wallet's owner*** AND have the other +party's public key. Otherwise, if we put both public keys, we would obtain +a watch-only wallet unable to sign the transactions. If we +had both extended private keys inside the descriptor, we would allow each party +to finalize the transactions autonomously. + +#### In Bitcoin Core: + +In our case, the multi signature descriptor for Bitcoin Core will be composed +with: + +* The BIP84 derived Extended **Public** Key from BDK +* The BIP84 derived Extended **Private** Key from Core. + +BDK wallet's owner will send to Core's owner the derived xpub for this purpose. +This is how the Core's multisig descriptor will be created and put into an +environment variable: + +``` +export core_rec_desc="wsh(multi(2,$BDK_xpub_84_for_rec_desc,$core_xprv/84'/0'/0'/0/*))" +``` + +Where of course `$BDK_xpub_84_for_rec_desc`is the derived master public created +in BDK and received by Core's owner. + +The meaning of what is before and after is illustrated in the doc that explain +the use of [Output Descriptors in Bitcoin Core][Output Descriptors]. + +We add the necessary checksum using the specific `bitcoin-cli` call. + +``` +export core_rec_desc_chksum=$core_rec_desc#$(bitcoin-cli -testnet getdescriptorinfo $core_rec_desc | jq -r '.checksum') +``` + +We repeat the same to build the descriptor to receive the change. + +``` +export core_chg_desc="wsh(multi(2,$BDK_xpub_84_for_chg_desc,$core_xprv/84'/0'/0'/1/*))" +export core_chg_desc_chksum=$core_chg_desc#$(bitcoin-cli -testnet getdescriptorinfo $core_chg_desc|jq -r '.checksum') +``` + +#### In BDK: + +For BDK we set the derivation for receiving addresses and change addresses +in the command line (maybe setting an alias) + +Building the descriptor: + +``` +export BDK_rec_desc="wsh(multi(2,$BDK_xprv/84'/0'/0'/0/*,$core_xpub_84_for_rec_desc))"` +``` + +Please note that the order of the extended key in the descriptor MUST be the +same in the 2 wallets. + +*We have chosen to put BDK first and in each software wallet, the public key +derived from BDK will always come first. In alternative, we could have chosen to +produce the descriptor, [chosing a `soretedmulti` multisignature setup][sortedmulti]*. + +``` +export BDK_rec_desc_chksum=$BDK_rec_desc#$(bitcoin-cli -testnet getdescriptorinfo $BDK_rec_desc | jq -r '.checksum') +export BDK_chg_desc="wsh(multi(2,$BDK_xprv/84'/0'/0'/1/*,$core_xpub_84_for_chg_desc))" +export BDK_chg_desc_chksum=$BDK_chg_desc#$(bitcoin-cli -testnet getdescriptorinfo $BDK_chg_desc | jq -r '.checksum') +``` + +To take a look at the variables we have produced so far: +``` +env | grep 'core_' +env | grep 'BDK_' +``` + +Now we will use the multisig descriptor wallet to receive testnet coins with +Alice and Bob's software + +### 3. Use each other's software to receive testnet coins from a faucet + +#### In Bitcoin Core + +Alice must create an empty, experimental new "descriptors wallet" in Core and +to import the multisig Output Descriptor. + +``` +bitcoin-cli -testnet createwallet "multisig2of2withBDK" false true "" false true false +```` +The flag are to: +* use the private keys +* make it empty +* no password provided to the wallet +* reusing of addresses not allowed +* "new experimental descriptors wallet" +* don't load it on start up + +``` +bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK importdescriptors "[{\"desc\":\"$core_rec_desc_chksum\",\"timestamp\":\"now\",\"active\":true,\"internal\":false},{\"desc\":\"$core_chg_desc_chksum\",\"timestamp\":\"now\",\"active\":true,\"internal\":true}]" +``` +Now Alice asks for her first receiving multisignature address. + +``` +export first_address=$(bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK getnewaddress) +echo $first_address +``` + +#### BDK +In BDK Bob can specify directly the descriptors on the command line to produce +the multisig address, because BDK is descriptors aware natively. + +``` +repl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint get_new_address` +``` + +Et voilà: if we have done everything correctly, the newly created address in +Core is the same of the newly created address in BDK. this is part of the +"miracle" of descriptors' interoperability. + +#### We ask for testnet coins giving the first created address. + +To find testnet coins for free, you can just google "testnet faucet" and you +should find some satoshis to play with. Just give to the site your first +generated address and, in twenty minutes, you will find the satoshis in +your balance both in Core and in BDK. + +``` +# to check it in Core: + +bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK getbalance + +# In BDK: + +# Sync with the blockchain +repl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint sync +# Get the balance +repl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint get_balance +``` +Some testnet faucets have an address to send back the unused satoshi after +the use. Take note of that because we will use it in the next step. + +### 4. we return part of the satoshis received back to the faucet + +``` +export psbt=$(bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK walletcreatefundedpsbt "[]" "[{\"tb1qrcesfj9f2d7x40xs6ztnlrcgxhh6vsw8658hjdhdy6qgkf6nfrds9rp79a\":0.000012}]" | jq -r '.psbt') + +export psbt=$(bitcoin-cli -testnet -rpcwallet=multisig2of2withBDK walletprocesspsbt $psbt | jq -r '.psbt') +{ + "psbt": "cHNidP8BAIkCAAAAATj90EC+NAuXj7y6SseZJucoJM6sGnUcVm9koTveZECTAAAAAAD+////AmACAAAAAAAAIgAg98ol9j4AalD71E0mV5QV0uM6/vCT+pi2twxr/zrvLROwBAAAAAAAACIAIB4zBMipU3xqvNDQlz+PCDXvpkHH1Q95Nu0mgIsnU0jbAAAAAAABAIkCAAAAAQS+ObgGG6UwtvaO3KYph2E3/ws7Q83RbmR3rxC0fKYSAQAAAAD+////AtAHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNDAHQAAAAAAACIAIBQpiDTgPIMt0ld8cmuYqlY+EIPjvrmMqZruDhs61hQNAAAAAAEBK9AHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNAiAgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAAQEFR1IhArn3tec7n7318rnWqf0dIIwtLtfxo6Zt0HV70UvZYaWvIQNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfVKuIgYCufe15zufvfXyudap/R0gjC0u1/Gjpm3QdXvRS9lhpa8YNEw2cFQAAIAAAACAAAAAgAAAAAAAAAAAIgYDbdI+wHtIgO6pS6Ja7jai1pDwPeidKoDCytTO1jhjAH0YO/laXFQAAIAAAACAAAAAgAAAAAAAAAAAAAEBR1IhAqccvA3rL13D1K4GeWjcahDsO3P8oaVNBttk4MlCKXIcIQLHKhjmPuCQjyS77ZfaMN2tdgNKcf/+57VXGZhz/UWTl1KuIgICpxy8DesvXcPUrgZ5aNxqEOw7c/yhpU0G22TgyUIpchwYNEw2cFQAAIAAAACAAAAAgAEAAAADAAAAIgICxyoY5j7gkI8ku+2X2jDdrXYDSnH//ue1VxmYc/1Fk5cYO/laXFQAAIAAAACAAAAAgAEAAAADAAAAAAA=", + "complete": false +} +``` + +Exactly! Note the `"complete": false`. We have processed the transaction with +Core but we miss one of the necessary key of the multisig 2of2 setup (The one +contained inside BDK). + +`tb1qrcesfj9f2d7x40xs6ztnlrcgxhh6vsw8658hjdhdy6qgkf6nfrds9rp79a` is the address +we got from the faucet site to return the satoshis. + +The [PSBT] is sent over to the BDK wallet owner who tries to sign the +transaction: + +``` +repl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint sign --psbt $psbt +{ + "is_finalized": true, + "psbt": "cHNidP8BAIkCAAAAATj90EC+NAuXj7y6SseZJucoJM6sGnUcVm9koTveZECTAAAAAAD+////AmACAAAAAAAAIgAg98ol9j4AalD71E0mV5QV0uM6/vCT+pi2twxr/zrvLROwBAAAAAAAACIAIB4zBMipU3xqvNDQlz+PCDXvpkHH1Q95Nu0mgIsnU0jbAAAAAAABAIkCAAAAAQS+ObgGG6UwtvaO3KYph2E3/ws7Q83RbmR3rxC0fKYSAQAAAAD+////AtAHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNDAHQAAAAAAACIAIBQpiDTgPIMt0ld8cmuYqlY+EIPjvrmMqZruDhs61hQNAAAAAAEBK9AHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNAiAgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAASICArn3tec7n7318rnWqf0dIIwtLtfxo6Zt0HV70UvZYaWvRzBEAiBkVDLgVEwvENnLx+04o7gGpGjFDBwAXTJmf8Yvo35oygIgbuBkHsvPC9jmZcMZ9P+Pwp01yxSaWo+5feyPmd3ai1kBAQVHUiECufe15zufvfXyudap/R0gjC0u1/Gjpm3QdXvRS9lhpa8hA23SPsB7SIDuqUuiWu42otaQ8D3onSqAwsrUztY4YwB9Uq4iBgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfRg7+VpcVAAAgAAAAIAAAACAAAAAAAAAAAAiBgK597XnO5+99fK51qn9HSCMLS7X8aOmbdB1e9FL2WGlrxg0TDZwVAAAgAAAAIAAAACAAAAAAAAAAAABBwABCNoEAEcwRAIgZFQy4FRMLxDZy8ftOKO4BqRoxQwcAF0yZn/GL6N+aMoCIG7gZB7LzwvY5mXDGfT/j8KdNcsUmlqPuX3sj5nd2otZAUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAAUdSIQK597XnO5+99fK51qn9HSCMLS7X8aOmbdB1e9FL2WGlryEDbdI+wHtIgO6pS6Ja7jai1pDwPeidKoDCytTO1jhjAH1SrgABAUdSIQKnHLwN6y9dw9SuBnlo3GoQ7Dtz/KGlTQbbZODJQilyHCECxyoY5j7gkI8ku+2X2jDdrXYDSnH//ue1VxmYc/1Fk5dSriICAqccvA3rL13D1K4GeWjcahDsO3P8oaVNBttk4MlCKXIcGDRMNnBUAACAAAAAgAAAAIABAAAAAwAAACICAscqGOY+4JCPJLvtl9ow3a12A0px//7ntVcZmHP9RZOXGDv5WlxUAACAAAAAgAAAAIABAAAAAwAAAAAA" +} +``` +The signature has succeded (note the "is_finalized": true,) and now we can +broadcast the transction. +``` +repl -d "$BDK_rec_desc_chksum" -c "$BDK_chg_desc_chksum" -n testnet -w $BDK_fingerprint broadcast --psbt "cHNidP8BAIkCAAAAATj90EC+NAuXj7y6SseZJucoJM6sGnUcVm9koTveZECTAAAAAAD+////AmACAAAAAAAAIgAg98ol9j4AalD71E0mV5QV0uM6/vCT+pi2twxr/zrvLROwBAAAAAAAACIAIB4zBMipU3xqvNDQlz+PCDXvpkHH1Q95Nu0mgIsnU0jbAAAAAAABAIkCAAAAAQS+ObgGG6UwtvaO3KYph2E3/ws7Q83RbmR3rxC0fKYSAQAAAAD+////AtAHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNDAHQAAAAAAACIAIBQpiDTgPIMt0ld8cmuYqlY+EIPjvrmMqZruDhs61hQNAAAAAAEBK9AHAAAAAAAAIgAg6GXadcNj7k4yKUbnVlTLiedXQFXYdCBoNygop/PISNAiAgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAASICArn3tec7n7318rnWqf0dIIwtLtfxo6Zt0HV70UvZYaWvRzBEAiBkVDLgVEwvENnLx+04o7gGpGjFDBwAXTJmf8Yvo35oygIgbuBkHsvPC9jmZcMZ9P+Pwp01yxSaWo+5feyPmd3ai1kBAQVHUiECufe15zufvfXyudap/R0gjC0u1/Gjpm3QdXvRS9lhpa8hA23SPsB7SIDuqUuiWu42otaQ8D3onSqAwsrUztY4YwB9Uq4iBgNt0j7Ae0iA7qlLolruNqLWkPA96J0qgMLK1M7WOGMAfRg7+VpcVAAAgAAAAIAAAACAAAAAAAAAAAAiBgK597XnO5+99fK51qn9HSCMLS7X8aOmbdB1e9FL2WGlrxg0TDZwVAAAgAAAAIAAAACAAAAAAAAAAAABBwABCNoEAEcwRAIgZFQy4FRMLxDZy8ftOKO4BqRoxQwcAF0yZn/GL6N+aMoCIG7gZB7LzwvY5mXDGfT/j8KdNcsUmlqPuX3sj5nd2otZAUcwRAIgS6x0i1J1HRzllIPf4WlFY+Dl8kCCLK81TL2djZxTFXMCICJVBKkKNxu1w1mRVor6iFTSVXiJjmWwBXVeJLISvBwAAUdSIQK597XnO5+99fK51qn9HSCMLS7X8aOmbdB1e9FL2WGlryEDbdI+wHtIgO6pS6Ja7jai1pDwPeidKoDCytTO1jhjAH1SrgABAUdSIQKnHLwN6y9dw9SuBnlo3GoQ7Dtz/KGlTQbbZODJQilyHCECxyoY5j7gkI8ku+2X2jDdrXYDSnH//ue1VxmYc/1Fk5dSriICAqccvA3rL13D1K4GeWjcahDsO3P8oaVNBttk4MlCKXIcGDRMNnBUAACAAAAAgAAAAIABAAAAAwAAACICAscqGOY+4JCPJLvtl9ow3a12A0px//7ntVcZmHP9RZOXGDv5WlxUAACAAAAAgAAAAIABAAAAAwAAAAAA" +{ + "txid": "a0b082e3b0579822d4a0b0fa95a4c4662f6b128ffd43fdcfe53c37473ce85dee" +} +``` + +## Conclusion + +We have built an HDM and we have used it with two indipendent wallets, which +are compatible with [BIP 174][PSBT] and [Output Descriptors]. Hopefully we +will see many other compatible wallets beyound [Bitcoin Core] and [BDK], +with which we will be able to easily set up multi signature schemes. + + +[Descriptor wallets]: https://github.com/bitcoin/bitcoin/pull/16528 +[Electrum]: https://electrum.org +[Output Descriptors]: https://bitcoinops.org/en/topics/output-script-descriptors/ +[PSBT]: https://en.bitcoin.it/wiki/BIP_0174 +[HDWallet]: https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki +[sortedmulti]: https://github.com/bitcoin/bitcoin/pull/17056?ref=tokendaily +[BDK]: https://bitcoindevkit.org/ +[Bitcoin Core]: https://bitcoincore.org/ +[pycoin]: https://github.com/richardkiss/pycoin diff --git a/docs/_blog/fee_estimation_for_light_clients_part_1.md b/docs/_blog/fee_estimation_for_light_clients_part_1.md new file mode 100644 index 0000000000..c52cbe57fc --- /dev/null +++ b/docs/_blog/fee_estimation_for_light_clients_part_1.md @@ -0,0 +1,121 @@ +--- +title: "Fee estimation for light-clients (Part 1)" +description: "Applying machine learning to the bitcoin fee estimation problem" +authors: + - Riccardo Casatta +date: "2021-01-25" +tags: ["fee", "machine learning"] +permalink: "/blog/2021/01/fee-estimation-for-light-clients-part-1/" +--- + +This post is part 1 of 3 of a series. ([Part 2], [Part 3]) + +- [Introduction: what is fee estimation?](#introduction-what-is-fee-estimation) +- [The problem](#the-problem) + + [The challenges and the solution](#the-challenges-and-the-solution) + + [The question](#the-question) + + [The data logger](#the-data-logger) + +## Introduction: what is fee estimation? + +Fee estimation is the process of selecting the fee rate[^fee rate] for a bitcoin transaction being created, according to two main factors: + +* The current congestion of the Bitcoin network. +* The urgency, or lack thereof, for the transaction confirmation, i.e, its inclusion in a block. + +A fee rate should be adequate to the above factors: a fee too high would be a waste of money, because the same result could have been achieved with a lower expense. On the other hand, a fee rate too low would wait for a confirmation longer than planned or, even worse, the transaction could not be confirmed at all. + +## The problem + +Bitcoin Core offers fee estimation through the [`estimatesmartfee`] RPC method, and there are also a lot of third-party [fee estimators] online, so do we need yet another estimator? + +The model used by Bitcoin Core is not well suited for light-clients such as mobile wallets, even when running in pruned mode. Online estimators are lacking in terms of: + +* Privacy: Contacting the server leaks your IP (unless you are using Tor or a VPN), and the request timing may be used to correlate the request to a transaction broadcasted to the network soon thereafter. +* Security: A malicious estimator could provide a high fee rate leading to a waste of money, or a low fee rate hampering the transaction confirmation. + +Replace By Fee (RBF) and Child Pays For Parent (CPFP) are techniques that can somewhat minimize the fee estimation problem, because one could simply underestimate the fee rate and then raise it when necessary, however: +* RBF and CPFP may leak more information, such as patterns that may allow to detect the kind of wallet used, or which one of the transaction outputs is the change. +* Requires additional interaction: the client must come back "online" to perform the fee bump. Sometimes this might be impractical or risky, for instance when using an offline signer or a multisignature with geographically distributed keys. + +Thus, this work is an effort to build a **good fee estimator for purely peer to peer light clients** such as [neutrino] based ones, or at least determine whether the approach we take is infeasible and open the discussion +for other, better, models. + +In the meantime, another sub-goal is pursued: attract the interest of data scientists; Indeed the initial step for this analysis consists in constructing a data set, which could also also help kickstart other studies on fee estimation or, more broadly, on the Bitcoin mempool. + +#### The challenges and the solution + +The hardest part of doing fee estimation on a light client is the lack of information: for example, Bitcoin Core's `estimatesmartfee` uses up to the last 1008 blocks and knows everything about the mempool[^mempool], such as the fee rate of every transaction it contains, but a light-client does not. + +Also, there are other factors that may help doing fee estimation, such as the day of the week (the mempool usually empties during the [weekend]) or the time of the day to anticipate recurring daily events +(such as the batch of [bitmex withdrawals]). + +The idea is to apply Machine Learning (ML) techniques[^disclaimer] to discover patterns over what a light-client knows and see if they are enough to achieve consistently good estimations. + +#### The question + +We are going to use a DNN (Deep Neural Network), a ML technique in the supervised learning branch. The "ELI5" is: give a lot of example inputs and the desired output to a black box; if there are correlations between inputs and outputs, +and there are enough examples, the black box will eventually start predicting the correct output even with inputs it has never seen before. + +To define our inputs and outputs, we need to start from the question we want to answer. For a fee estimator this is: + +*"Which minimum fee rate should I use if I want this transaction to be confirmed in at most `n` blocks?"* + +This can be translated to a table with many rows like: + +confirms_in | other_information | fee_rate +-|-|- +1|...|100.34 +2|...| 84.33 +10|...| 44.44 + +where the `fee_rate` column is the output we want, also called the "*target*" or "*label*" in ML terminology, and the other columns are our inputs. + +Can we build this table just by looking at the Bitcoin blockchain? Unfortunately, we can't: +The main thing that's missing is an indication of when the node first saw a transaction that has been later confirmed in a block. With that knowledge we can say that the fee rate of that transaction was the exact value required to confirm +within the number of blocks it actually took to be confirmed. For instance, if we see transaction `t` when the blockchain is at height `1000` and then we notice that `t` has been included in block `1006`, we can deduce that the +fee rate paid by `t` was the exact value required to get confirmed within the next `6` blocks. + +So to build our model, we first need to gather these data, and machine learning needs a *lot* of data to work well. + +#### The data logger + +The [data logger] is built with the purpose of collecting all the data we need, and it's MIT licensed open source software written in Rust. + +We need to register the moment in time when transactions enter in the node's mempool; to be efficient and precise we should not only call the RPC endpoints but listen to [ZMQ] events. Luckily, the just released bitcoin core 0.21.0 added a new [ZMQ] topic `zmqpubsequence` notifying mempool events (and block events). The logger is also listening to `zmqpubrawtx` and `zmqpubrawblock` topics, to make less RPC calls. + +We are not only interested in the timestamp of the transaction entering the mempool, but also how many blocks it will take until the same transaction is confirmed. +In the final dataset this field is called `confirms_in`[^blocks target]; if `confirms_in = 1` it means the transaction is confirmed in the first block created after it has been seen for the first time. + +Another critical piece of information logged by the data logger is the `fee_rate` of the transaction, since the absolute fee value paid by a bitcoin transaction is not available nor derivable given only the transaction itself, as the inputs don't have explicit amounts. + +All these data (apart from the time of the transaction entering in the mempool) can actually be reconstructed simply by looking at the blockchain. However, querying the bitcoin node can be fairly slow, and during the model training iterations we want to recreate the ML dataset rapidly[^fast], for example whenever we need to modify or add a new field. + +For these reasons, the logger is split into two parts: a process listening to the events sent by our node, which creates raw logs, and then a second process that uses these logs to create the final CSV dataset. +Raw logs are self-contained: for example, they contain all the previous transaction output values for every relevant transaction. This causes some redundancy, but in this case it's better to trade some efficiency for more performance +when recreating the dataset. + +![High level graph](/img/fee-estimation-for-light-clients/high-level-graph.svg) + +My logger instance started collecting data on the 18th of December 2020, and as of today (25th January 2020), the raw logs are about 16GB. + +I expect (or at least hope) the raw logs, the CSV dataset, or the data logger will be useful also for other projects as well, like monitoring the propagation of transactions or other works involving raw mempool data. We will share raw logs data through torrent soon. + +In the following [Part 2] we are going to talk about the dataset. + +[^fee rate]: The transaction fee rate is the ratio between the absolute fee expressed in satoshi, over the weight of the transaction measured in virtual bytes. The weight of the transaction is similar to the byte size, however a part of the transaction (the segwit part) is discounted, their byte size is considered less because it creates less burden for the network. +[^mempool]: mempool is the set of transactions that are valid by consensus rules (for example, they are spending existing bitcoin), broadcasted in the bitcoin peer to peer network, but they are not yet part of the blockchain. +[^disclaimer]: DISCLAIMER: I am not an expert data-scientist! +[^blocks target]: Conceptually similar to bitcoin core `estimatesmartfee` parameter called "blocks target", however, `confirms_in` is the real value not the desired target. +[^fast]: 16GB of compressed raw logs are processed and a compressed CSV produced in about 5 minutes. + +[Part 1]: /blog/2021/01/fee-estimation-for-light-clients-part-1/ +[Part 2]: /blog/2021/01/fee-estimation-for-light-clients-part-2/ +[Part 3]: /blog/2021/01/fee-estimation-for-light-clients-part-3/ +[`estimatesmartfee`]: https://bitcoincore.org/en/doc/0.20.0/rpc/util/estimatesmartfee/ +[bitmex withdrawals]: https://b10c.me/mempool-observations/2-bitmex-broadcast-13-utc/ +[fee estimators]: https://b10c.me/blog/003-a-list-of-public-bitcoin-feerate-estimation-apis/ +[neutrino]: https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki +[weekend]: https://www.blockchainresearchlab.org/2020/03/30/a-week-with-bitcoin-transaction-timing-and-transaction-fees/ +[ZMQ]: https://github.com/bitcoin/bitcoin/blob/master/doc/zmq.md +[data logger]: https://github.com/RCasatta/bitcoin_logger diff --git a/docs/_blog/fee_estimation_for_light_clients_part_2.md b/docs/_blog/fee_estimation_for_light_clients_part_2.md new file mode 100644 index 0000000000..4e7faf3ebb --- /dev/null +++ b/docs/_blog/fee_estimation_for_light_clients_part_2.md @@ -0,0 +1,122 @@ +--- +title: "Fee estimation for light-clients (Part 2)" +description: "Applying machine learning to the bitcoin fee estimation problem" +authors: + - Riccardo Casatta +date: "2021-01-25" +tags: ["fee", "machine learning"] +permalink: "/blog/2021/01/fee-estimation-for-light-clients-part-2/" +--- + +This post is part 2 of 3 of a series. ([Part 1], [Part 3]) + +- [The dataset](#the-dataset) + + [The mempool](#the-mempool) + + [The outliers](#the-outliers) + + [Recap](#recap) + +## The dataset + +The [dataset] is publicly available (~500MB gzip compressed, ~2GB as plain CSV). + +The output of the model is the fee rate, expressed in `[satoshi/vbytes]`. + +What about the inputs? Generally speaking, we have two main requirements for what can be included as input for our model: + +* It must be correlated to the output, even with a non-linear relation. +* It must be available to a light client: for instance, assuming to have knowledge and an index of the last 1000 blocks is considered too much. + +To evaluate the approach we are taking, we also want to compare our model's results with another available estimation: for this reason the dataset includes data to compute the error agains Bitcoin Core's `estimatesmartfee` results, even though we are not going to use it for this model. + +The dataset will contain only transactions that spend already confirmed inputs. If we wanted to include transactions with unconfirmed inputs as well, the fee rate would have to be computed as a whole; +for example if transaction `t2` spends an unconfirmed input from `t1` (while `t1` only spends confirmed inputs, and all its other outputs are unspent), the aggregated fee rate would have to be used. +Supposing `f()` is extracts the absolute fee and `w()` the transaction weight, the aggregated fee rate would be `(f(t1) + f(t2)) / (w(t1) + w(t2))`. Thus, as already said previously, to keep things simple the model simply discards all the transaction +that would need to perform this computation. + +For the same reason the dataset has the `parent_in_cpfp` flag. When a transaction has inputs confirmed (so it's not excluded by the previous rule) but one or more of its output have been spent by a transaction confirmed in the same block, `parent_in_cpfp` is `1`. +Transactions with `parent_in_cpfp = 1` are included in the dataset but excluded by the current model, since the miner probably considered an aggregated fee rate while picking the transactions to build a block. + +#### The mempool + +The most important input of our model is the current *status* of the mempool itself. However, we cannot feed the model with a list of the fee rate of every unconfirmed transaction, because this array would have a variable length. +To overcome this, the transaction contained in the mempool are grouped in "buckets" which are basically subsets of the mempool where all the transactions contained in a bucket have a similar fee rate. In particular we only care about the +*number* of transaction in every *bucket*, not which transactions it contains. + +The mempool buckets array is defined by two parameters, the `percentage_increment` and the `array_max` value. +Starting from the minimum fee rate value `min_relay_fee=1.0`, the `ith` element is: `a_i=min_relay_fee * (1+percentage_increment)^(i+1)` + +For instance, choosing the mempool buckets array to have parameters `percentage_increment = 50%` and `array_max = 500.0 sat/vbytes` the buckets would be constructed like so: + +bucket | bucket min fee rate | bucket max fee rate +-|-|- +a_0| 1.0 | 1.5 +a_1| 1.5 | 2.25 +a_2| 2.25 | 3.375 +a_15| 437.89 | inf + +The array stops at `a15` because `a16` would have a bucket min greater than `array_max`. + +The model is for light-client such as [neutrino] based ones. In these clients the mempool is already available (it's needed to check for received transactions) but we can't compute fee rates of this transactions because previous confirmed inputs are not in the mempool! + +Luckily, **thanks to temporal locality [^temporal locality], an important part of mempool transactions spend outputs created very recently**, for example in the last 6 blocks. +The blocks are available through the p2p network, and downloading the last 6 is considered a good compromise between resource consumption and accurate prediction. We need the model to be built with the same data available in the prediction phase, as a consequence *the mempool data in the dataset refers only to transactions having their inputs in the last 6 blocks*. However the `bitcoin-csv` tool inside the [data logger] allows to configure this parameter. + +#### The outliers + +The dataset also contains the block percentile fee rate `q_k`, considering `r_i` to be the rate of the `ith` transaction in a block, `q_k` is the fee rate value such that for each transaction in a block `r_i` < `q_k` returns the `k%` transactions in the block that are paying lower fees. + +Percentiles are not used to feed the model but to filter some outliers tx. +Removing this observations is controversial at best and considered cheating at worse. However, it should be considered that Bitcoin Core `estimatesmartfee` doesn't even bother to give estimation for the next block, we think this is due to the fact that many transactions that are confirming in the next block are huge overestimation, or clearly errors like [this one] we found when we started logging data. +These outliers are several for transactions confirming in the next block (`confirms_in=1`), less so for `confirms_in=2`, mostly disappeared for `confirms_in=3` or more. It's counterintuitive that overestimation exists for `confirms_in>1`, by definition an overestimation is a fee rate way higher than needed, so how is possible that an overestimation doesn't enter the very next block? There are a couple of reasons why a block is discovered without containing a transaction with high fee rate: +* network latency: my node saw the transaction but the miner didn't see that transaction yet, +* block building latency: the miner saw the transaction, but didn't finish to rebuild the block template or decided it's more efficient to finish a cycle on the older block template. + +To keep the model balanced, when overestimation is filtered out, underestimation are filtered out as well. This also has the effect to remove some of the transactions possibly included because a fee is payed out-of-band. +Another reason to filter transactions is that the dataset is over-represented by transactions with low `confirms_in`: more than 50% of transactions get confirmed in the next block, so we think it's good to filter some of these transactions. + +The applied filters are the following: + +confirms_in|lower|higher +-|-|- +1|q45|q55 +2|q30|q70 +3|q1|q99 + +Not yet convinced by the removal of these outliers? The [dataset] contains all the observations, make your model :) + +#### Recap + +column | used in the model | description +-|-|- +txid | no | Transaction hash, useful for debugging +timestamp | converted | The time when the transaction has been added in the mempool, in the model is used in the form `day_of_week` and `hour` +current_height | no | The blockchain height seen by the node in this moment +confirms_in | yes | This transaction confirmed at block height `current_height+confirms_in` +fee_rate | target | This transaction fee rate measured in `[sat/vbytes]` +fee_rate_bytes | no | fee rate in satoshi / bytes, used to check Bitcoin Core `estimatesmartfee` predictions +block_avg_fee | no | block average fee rate `[sat/vbytes]` of block `current_height+confirms_in` +core_econ | no | bitcoin `estimatesmartfee` result for `confirms_in` block target and in economic mode. Could be not available `?` when a block is connected more recently than the estimation has been requested, estimation are requested every 10 secs. +core_cons | no | Same as above but with conservative mode +mempool_len | no | Sum of the mempool transactions with fee rate available (sum of every `a*` field) +parent_in_cpfp | no | It's 1 when the transaction has outputs that are spent in the same block in which the transaction is confirmed (they are parent in a CPFP relations). +q1-q30-... | no | Transaction confirming fast could be outliers, usually paying a lot more than required, this percentiles are used to filter those transactions, +a1-a2-... | yes | Contains the number of transaction in the mempool with known fee rate in the ith bucket. + + +![The good, the bad and the ugly](/img/fee-estimation-for-light-clients/the-good-the-bad-the-ugly.jpg) +
My biological neural network fired this, I think it's because a lot of chapters start with "The"
+

+ +In the previous [Part 1] we talked about the problem. + +In the following [Part 3] we are going to talk about the model. + +[^temporal locality]: In computer science temporal locality refers to the tendency to access recent data more often than older data. + +[Part 1]: /blog/2021/01/fee-estimation-for-light-clients-part-1/ +[Part 2]: /blog/2021/01/fee-estimation-for-light-clients-part-2/ +[Part 3]: /blog/2021/01/fee-estimation-for-light-clients-part-3/ +[neutrino]: https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki +[data logger]: https://github.com/RCasatta/bitcoin_logger +[this one]: https://blockstream.info/tx/33291156ab79e9b4a1019b618b0acfa18cbdf8fa6b71c43a9eed62a849b86f9a +[dataset]: https://storage.googleapis.com/bitcoin_log/dataset_18.csv.gz diff --git a/docs/_blog/fee_estimation_for_light_clients_part_3.md b/docs/_blog/fee_estimation_for_light_clients_part_3.md new file mode 100644 index 0000000000..241b2eca05 --- /dev/null +++ b/docs/_blog/fee_estimation_for_light_clients_part_3.md @@ -0,0 +1,226 @@ +--- +title: "Fee estimation for light-clients (Part 3)" +description: "Applying machine learning to the bitcoin fee estimation problem" +authors: + - Riccardo Casatta +date: "2021-01-25" +tags: ["fee", "machine learning"] +permalink: "/blog/2021/01/fee-estimation-for-light-clients-part-3/" +--- + +This post is part 3 of 3 of a series. ([Part 1], [Part 2]) + +- [The model](#the-model) + + [Splitting](#splitting) + + [Preprocessing](#preprocessing) + + [Build](#build) + + [Finally, training](#finally--training) +- [The prediction phase](#the-prediction-phase) +- [Conclusion and future development](#conclusion-and-future-development) +- [Acknowledgements](#acknowledgements) + +## The model + +The code building and training the model with [tensorflow] is available in [google colab notebook] (jupyter notebook); you can also download the file as plain python and run it locally. At least 1 hour is needed to train the full model, but it heavily depends on the hardware available. + +![graph confirm_in blocks vs fee_rate](/img/fee-estimation-for-light-clients/20210125-091313-confirms_in-fee_rate.png) +
Do you want to choose the fee without a model? In the last 5 weeks a ~50 sat/vbyte transaction never took more than a day to confirm and a ~10 sat/vbyte never took more than a week

+ +As a reference, in the code we have a calculation of the bitcoin core `estimatesmartfee` MAE[^MAE] and drift[^drift]. +MAE is computed as `avg(abs(fee_rate - core_econ))` when `core_econ` is available (about 1.2M observations, sometime the value is not available when considered too old). + + +estimatesmartfee mode | MAE [satoshi/vbytes] | drift +-|-|- +economic| 28.77 | 20.79 +conservative | 46.49 | 44.73 + +As seen from the table, the error is quite high, but the positive drift suggests `estimatesmartfee` prefers to overestimate to avoid transactions not confirming. + +As we said in the introduction, network traffic is correlated with time and we have the timestamp of when the transaction has been first seen, however a ML model doesn't like plain numbers too much, but it behaves better with "number that repeats", like categories, so we are converting the timestamp in `day_of_week` a number from 0 to 6, and `hours` a number from 0 to 24. + +#### Splitting + +The dataset is splitted in training and test data with a 80/20 proportion. As the name suggest the training part is used to train the model, the test is composed of other observations to test if the model is good with observations that has never seen (proving the model can generalize, not just memorizing the answer). + +During the training the data is splitted again in 80/20 for training and validation respectively, validation is basically testing during training. + +During splitting, the dataset is converted from a pandas data frame to tensorflow dataset, decreasing training times. + +#### Preprocessing + +The preprocessing phase is part of the model however it contains transformations without parameters trained by the model. +This transformations are useful because model trains better if data are in some format, and having this phase inside the model helps to avoid to prepare the data before feeding the model at prediction phase. + +Our model performs 2 kind of preprocessing: + +* Normalization: model trains faster if numerical features have mean 0 and standard deviation equal to 1, so this layer is built by computing the `mean` and `std` from the series of a feature before training, and the model is feed with `(feature - mean)/std`. Our model normalize `confirms_in` feature and all the buckets `a*` + +* one-hot vector: Numerical categories having a small number of different unique values like our `day_of_week` and `hours` could be trained better/faster by being converted in one hot vector. For example `day_of_week=6` (Sunday) is converted in a vector `['0', '0', '0', '0', '0', '0', '1']` while `day_of_week=5` (Saturday) is converted in the vector `['0', '0', '0', '0', '0', '1', '0']` + +#### Build + +```python +all_features = tf.keras.layers.concatenate(encoded_features) +x = tf.keras.layers.Dense(64, activation="relu")(all_features) +x = tf.keras.layers.Dense(64, activation="relu")(x) +output = tf.keras.layers.Dense(1, activation=clip)(x) +model = tf.keras.Model(all_inputs, output) +optimizer = tf.optimizers.Adam(learning_rate=0.01) +model.compile(loss='mse', + optimizer=optimizer, + metrics=['mae', 'mse']) +``` + +![model graph](/img/fee-estimation-for-light-clients/20210125-091313-model.png) + +The model is fed with the `encoded_features` coming from the processing phase, then there are 2 layers with 64 neurons each followed by one neuron giving the `fee_rate` as output. + +With this configurations the model has: +* Total params: `7,412` +* Trainable params: `7,361` +* Non-trainable params: `51` + +Non-trainable params comes from the normalization layer and are computed in the pre-processing phase (it contains, for example, the mean of a series). Trainable parameters are values initialized randomly and changed during the training phase. The trainable parameters are `7,361`, this number comes from the following, every neuron has an associated bias and a weight for every element in the inputs, thus: + +```shell +(48 input_values_weights + 1 bias) * (64 first_layer_neurons) ++ (64 input_values_weights + 1 bias) * (64 second layer neurons) ++ (64 input values weights + 1 bias) + +49*64+65*64+65 = 7361 +``` + +Honestly, neural network parameters are mostly the one taken from this tensorflow [example], we even tried to [tune hyperparameters], however, we decided to follow this [advice]: *"The simplest way to prevent overfitting is to start with a small model:"*. We hope this work will attract other data scientists to this bitcoin problem, improving the model. We also think that a longer time for the data collection is needed to capture various situations. + +A significant part of a ML model are the activation functions, `relu` (Rectified Linear Unit) is one of the most used lately, because it's simple and works well as we learned in this [introducing neural network video]. `relu` it's equal to zero for negative values and equal to the input for positive values. Being non-linear allows the whole model to be non-linear. + +For the last layer it is different: we want to enforce a minimum for the output, which is the minimum relay fee `1.0`[^minimum relay fee]. One could not simply cut the output of the model after prediction because all the training would not consider this constraint. So we need to build a custom activation function that the model training will be able to use for the [gradient descent] optimization step. Luckily this is very simple using tensorflow primitives: + +``` +def clip(x): + min = tf.constant(1.0) + return tf.where(tf.less(x, min), min, x) +``` + +Another important part is the optimizer, when we first read the aforementioned [example] the optimizer used was `RMSProp` however the example updated lately and we noticed the optimizer changed in favor of `Adam` which we read is the [latest trend] in data science. We changed the model to use `Adam` and effectively the training is faster with `Adam` and even slightly lower error is achieved. +Another important parameter is the learning rate, which we set to `0.01` after manual trials; however there might be space for improvements such as using [exponential decay], starting with an high learning rate and decreasing it through training epochs. + +The last part of the model configuration is the loss function: the objective of the training is to find the minimum of this function. Usually for regression problem (the ones having a number as output, not a category) the most used is the Mean squared error (MSE). MSE is measured as the average of squared difference between predictions and actual observations, giving larger penalties to large difference because of the square. An interesting property is that the bigger the error the faster the changes is good at the beginning of the training, while slowing down when the model predicts better is desirable to avoid "jumping out" the local minimum. + +#### Finally, the model training + +``` +PATIENCE = 20 +MAX_EPOCHS = 200 + +def train(): + early_stop = keras.callbacks.EarlyStopping(monitor='val_loss', patience=PATIENCE) + history = model.fit(train_ds, epochs=MAX_EPOCHS, validation_data=val_ds, verbose=1, callbacks=[early_stop]) + return history + +history = train() +``` + +This steps is the core of the neural network, it takes a while, let's analyze the output: + +``` +Epoch 1/200 +7559/7559 [==============================] - 34s 3ms/step - loss: 547.8023 - mae: 16.9547 - mse: 547.8023 - val_loss: 300.5965 - val_ma +e: 11.9202 - val_mse: 300.5965 +... +Epoch 158/200 +7559/7559 [==============================] - 31s 3ms/step - loss: 163.2548 - mae: 8.3126 - mse: 163.2548 - val_loss: 164.8296 - val_mae: 8.3402 - val_mse: 164.8296 +``` + +Training is done in epochs, under every epoch all the training data is iterated and model parameters updated to minimize the loss function. + +The number `7559` represent the number of steps. Theoretically the whole training data should be processed at once and parameters updated accordingly, however in practice this is infeasible for example for memory resource, thus the training happens in batch. In our case we have `1,934,999` observations in the training set and our batch size is `256`, thus we have `1,437,841/256=7,558.58` which by excess result in `7559` steps. + +The `~31s` is the time it takes to process the epoch on a threadripper CPU but GPU or TPU could do better. + +The value `loss` is the MSE on the training data while `val_loss` is the MSE value on the validation data. As far as we understand the separated validation data helps to detect the machine learning enemy, overfitting. Because in case of overfitting the value `loss` continue to improve (almost indefinitely) while `val_loss` start improving with the loss but a certain point diverge, indicating the network is memorizing the training data to improve `loss` but in doing so losing generalizing capabilities. + +Our model doesn't look to suffer overfitting cause `loss` and `val_loss` doesn't diverge during training + +![train history](/img/fee-estimation-for-light-clients/20210125-091313-train-history.png) + +While we told the training to do 200 epochs, the training stopped at 158 because we added an `early_stop` call back with `20` as `PATIENCE`, meaning that after 20 epoch and no improvement in `val_loss` the training is halted, saving time and potentially avoiding overfitting. + +## The prediction phase + +A [prediction test tool] is available on github. At the moment it uses a bitcoin core node to provide network data for simplicity, but it queries it only for the mempool and the last 6 blocks, so it's something that also a light-client could do[^disabled bloom filter]. + +The following chart is probably the best visualization to evaluate the model, on the x axis there is the real fee rate while on the y axis there is the prediction, the more the points are centered on the bisection, the more the model is good. +We can see the model is doing quite well, the MAE is 8 which is way lower than `estimatesmartfee`. However, there are big errors some times, in particular for prediction for fast confirmation (`confirms_in=1 or confirms_in=2`) as shown by the orange points. Creating a model only for blocks target greater than 2 instead of simply remove some observations may be an option. + +![prediction results](/img/fee-estimation-for-light-clients/20210125-091313-true-and-predictions.png) + +The following chart is instead a distribution of the errors, which for good model should resemble the normal distribution centered in 0, and it loooks like the model is respecting that. + +![error distribution](/img/fee-estimation-for-light-clients/20210125-091313-error-distribution.png) + +## Conclusion and future development + +The results have shown deep neural network are a tool capable of good bitcoin transaction fee estimations; this suggests that further ML research in this area might be promising. + +This is just a starting point, there are many future improvements such as: + +* Build a separate model with full knowledge, thus for full, always-connected nodes could be interesting and improve network resource allocation with respect to current estimators. +* Tensorflow is a huge dependency, and since it contains all the feature to build and train a model, most of the feature are not needed in the prediction phase. In fact tensorflow lite exists which is specifically created for embedded and mobile devices; the [prediction test tool] and the final integration in [bdk] should use it. +* Explore other fields to improve model predictions such as: + * A bucket array of the transactions in the last 6 blocks with known fee rates. This should in particular help estimations with almost empty mempool. + * Transaction weight + * Time from last block +* Some fields are very important and could benefit from pre-processing expansion, for instance applying [hashed feature columns] to `confirms_in`. +* Bitcoin logger could be improved by a merge command to unify raw logs files, reducing redundancy and consequently disk occupation. +* The dataset could be created in multiple files to allow more parallelism and use less memory during training. +* Saving the dataset in [TFRecord format] instead of CSV +* At the moment we are training the model on a threadripper CPU, training the code on GPU or even TPU will be needed to decrease training time, especially because input data will grow. +* The [prediction test tool] should estimate only using the p2p bitcoin network, without requiring a node. This work would be propedeutic for [bdk] integration +* At the moment mempool buckets are multiple inputs `a*` as show in the model graph; since they are related, is it possible to merge them in one TensorArray? +* Sometimes the model does not learn and [gets stuck]. The reason is the `clip` function applied in the last layer is constant for a value lower than 1. In this case, the derivative is 0 and the gradient descent doesn't know where to go. Instead of using the `clip` function apply penalties to the loss function for values lower than 1. +* There are issues regarding dead neurons (going to 0) or neurons with big weight, weight results should be monitored for this events, and also weight decay and L2 regularization should be explored. +* Tune hyper-parameters technique should be re-tested. +* Predictions should be monotonic decreasing for growing `confirms_in` parameter; for obvious reason it doesn't make sense that an higher fee rate will result in a higher confirmation time. But since this is not enforced anywhere in the model, at the moment this could happen. +* Since nodes with bloom filter disabled doesn't serve the mempool anymore, a model based only on last blocks should be evaluated. + +## Acknowledgements + +Thanks to [Square crypto] for sponsoring this work and thanks to the reviewers: [Leonardo Comandini], [Domenico Gabriele], [Alekos Filini], [Ferdinando Ametrano]. + +And also this tweet that remembered me [I] had this work in my TODO list + + + +This is the final part of the series. In the previous [Part 1] we talked about the problem and in [Part 2] we talked about the dataset. + +[^MAE]: MAE is Mean Absolute Error, which is the average of the series built by the absolute difference between the real value and the estimation. +[^drift]: drift like MAE, but without the absolute value +[^minimum relay fee]: Most node won't relay transactions with fee lower than the min relay fee, which has a default of `1.0` +[^disabled bloom filter]: An important issue emerged after the article came out, a bitcoin core client with bloom filter disabled (default as of 0.21) doesn't serve the mempool via p2p. + +[Part 1]: /blog/2021/01/fee-estimation-for-light-clients-part-1/ +[Part 2]: /blog/2021/01/fee-estimation-for-light-clients-part-2/ +[Part 3]: /blog/2021/01/fee-estimation-for-light-clients-part-3/ +[google colab notebook]: https://colab.research.google.com/drive/1yamwh8nE4NhmGButep-pfUT-1uRKs49a?usp=sharing +[example]: https://www.tensorflow.org/tutorials/keras/regression +[tune hyperparameters]: https://www.tensorflow.org/tutorials/keras/keras_tuner +[advice]: https://www.tensorflow.org/tutorials/keras/overfit_and_underfit#demonstrate_overfitting +[introducing neural network video]: https://youtu.be/aircAruvnKk?t=1035 +[gradient descent]: https://en.wikipedia.org/wiki/Gradient_descent#:~:text=Gradient%20descent%20is%20a%20first,the%20direction%20of%20steepest%20descent. +[latest trend]: https://towardsdatascience.com/adam-latest-trends-in-deep-learning-optimization-6be9a291375c +[exponential decay]: https://www.tensorflow.org/api_docs/python/tf/compat/v1/train/exponential_decay +[prediction test tool]: https://github.com/RCasatta/estimate_ml_fee +[bdk]: https://github.com/bitcoindevkit/bdk +[Square crypto]: https://squarecrypto.org/ +[get stuck]: https://github.com/RCasatta/bitcoin_logger/blob/master/notes.md +[hashed feature columns]: https://www.tensorflow.org/tutorials/structured_data/feature_columns#hashed_feature_columns +[tensorflow]: https://www.tensorflow.org/ +[TFRecord format]: https://www.tensorflow.org/tutorials/load_data/tfrecord +[gets stuck]: https://github.com/RCasatta/bitcoin_logger/blob/master/notes.md +[Leonardo Comandini]: https://twitter.com/LeoComandini +[Domenico Gabriele]: https://twitter.com/domegabri +[Alekos Filini]: https://twitter.com/afilini +[Ferdinando Ametrano]: https://twitter.com/Ferdinando1970 +[I]: https://twitter.com/RCasatta diff --git a/docs/_blog/hello-world.md b/docs/_blog/hello-world.md new file mode 100644 index 0000000000..ad85dc3e83 --- /dev/null +++ b/docs/_blog/hello-world.md @@ -0,0 +1,208 @@ +--- +title: "Hello World!" +description: "Getting started using the BDK library in a very simple Rust project" +authors: + - Alekos Filini +date: "2020-12-18" +tags: ["getting started", "rust"] +permalink: "/blog/2020/12/hello-world/" +--- + +## Introduction + +This article should serve as a "getting started" guide for developers who are considering integrating BDK in their projects: it tries to introduce the reader to the basic concepts behind the library and some of its +modules and components that can be used to build a very simple functioning Bitcoin wallet. All the information written in this article are valid for the current `master` git branch, and should remain valid for the upcoming [`v0.2.0` release](https://github.com/bitcoindevkit/bdk/projects/1) +which is planned to be tagged pretty soon. + +## Design Goals + +The main goal of the library is to be a solid foundation for Bitcoin wallets of any kind, on any platform: in practice, this means that the library should be: + +- Very *well-reviewed* and tested +- *Lightweight*, so that it can be used easily on mobile devices as well +- *Extendable*, so that it can be adapted to perfectly suit different use-cases +- *Generalized*, meaning that it supports different types of Bitcoin scripts and wallets through the use of [descriptors][descriptor] +- *Reasonably easy* to use, exposing a "high level" interface to the user and hiding all the complexity inside + +These goals have a direct impact on the design of the internal components of the library, and as a consequence on the APIs that are exposed to the final user, which might in some cases feel counter-intuitive at first. +Throughout the article, I will try to focus on those points and try to explain them as best as I can. + +## The `Wallet` Structure + +The [`Wallet`][wallet] structure is in many ways the heart of the library: it represents an instance of a wallet and exposes some APIs to perform all the typical operations one might want to do with a Bitcoin wallet, +such as generating a new address, listing the transactions received, creating a transaction, etc. + +A `Wallet` instance can be constructed given at least one [descriptor] which would be used to derive both [`External`][KeychainKind] and [`Internal`][KeychainKind] addresses, or two if one prefers to keep them separated. `External` addresses are the +ones returned by an explicit [`Wallet::get_new_address()`][get_new_address] call, while `Internal` addresses are generated internally to receive the change whenever a new transaction is created. + +A `Wallet` also needs at least one other component to function properly, its [`Database`][Database]: it will be used as a *cache* to store the list of transactions synchronized with the blockchain, the UTXOs, the addresses generated, and a few other things. It's important +to note that the `Database` will never store any secret. Securely storing keys is explicitly left to the user of the library to implement, mainly because there isn't really one good way to do it, that would work reliably on every platform. On +mobile devices, for instance, the OS' keychain could be used, to allow unlocking the secrets with the use of biometric data (FaceID or fingerprint), while on desktop platform there isn't generally a similar +framework available and the user would have to implement something that meets their needs. It's not excluded that in the future we could provide a "reference implementation" of secure multi-platform storage for keys, +but that would very likely be released as a separate module outside of the `Wallet` structure, or potentially even as a separate library that could be reused for other applications as well. + +Going back to our `Wallet`: given a descriptor and a `Database` we can build an "air-gapped", or "Offline" wallet: basically, a wallet that physically can't to connect to the Bitcoin network. It will still be able to generate addresses and +sign [PSBTs][PSBT], but with a greatly reduced attack surface because a sizable part of the code that handles the logic to synchronize with the network would be entirely omitted in the final executable binary. + +This is how an `OfflineWallet` can be created. Notice that we are using [`MemoryDatabase`][MemoryDatabase] as our `Database`. We'll get to that in a second. + +```rust +use bdk::{Wallet, OfflineWallet}; +use bdk::database::MemoryDatabase; +use bdk::bitcoin::Network; + +fn main() -> Result<(), Box> { + let external_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/0/*)"; + let internal_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/1/*)"; + + let wallet: OfflineWallet<_> = Wallet::new_offline( + external_descriptor, + Some(internal_descriptor), + Network::Testnet, + MemoryDatabase::new(), + )?; + + Ok(()) +} +``` + +Once we have our `Wallet` instance we can generate a new address and print it out: + +```rust +// ... + +println!("Generated Address: {}", wallet.get_new_address()?); +``` + +Building and running this code will print out: + +```text +Generated Address: tb1q7w0t936xp5p994qx506xj53gjdcmzjr2mkqghn +``` + +Before we've talked about the benefits of an air-gapped wallet, but we should also talk about the disadvantages: the biggest one is the fact that it cannot create new transactions because +it doesn't know which UTXOs belong to the wallet. To get this information we generally need to `sync` with the network, but this wallet can't physically do that. + +To fix this we can add one more component to our `Wallet`: a [`Blockchain`][Blockchain] backend. In particular, we are going to use the [`ElectrumBlockchain`][ElectrumBlockchain] which syncs with an `Electrum` server, +since that's available out of the box in BDK and is pretty fast. + +We can change our `Wallet` construction to look something like this: + +```rust +use bdk::blockchain::ElectrumBlockchain; +use bdk::electrum_client::Client; + +// ... + +let wallet = Wallet::new( + external_descriptor, + Some(internal_descriptor), + Network::Testnet, + MemoryDatabase::new(), + ElectrumBlockchain::from(Client::new("ssl://electrum.blockstream.info:60002").unwrap()), +)?; +``` + +This piece of code is very similar to the one we wrote before, but this time we are using the [`Wallet::new()`][Wallet_new] constructor instead of [`Wallet::new_offline()`][Wallet_new_offline], and this takes an extra argument for the `Blockchain` type to use. +Specifically here, we create an `ElectrumBlockchain` and connect to Blockstream's public Electrum Testnet servers over SSL. + +Now, since we are running in the `Testnet` network, we can try to get some funds from a faucet online to this address we've generated. Once we have an incoming transaction we can do the first `sync` of our *online* wallet. +this is again something that might seem counterintuitive at first: why do we have to manually ask the `Wallet` to *sync* itself? Can't it do it periodically in background? The answer is that yes, that would definitely be possible, +but it would remove some control on what's happening inside the wallet from the user. This can be especially problematic on mobile platforms, where the OS tries very aggressively to suspend apps in background to save +battery. Having a thread running and trying to make network requests while the app is in background would very likely cause errors or potentially crashes somewhere. So for this reason this operation has to be performed manually, +to allow the user to call that function only at the right time. + +```rust +use bdk::blockchain::noop_progress; + +// ... + +wallet.sync(noop_progress(), None)?; +``` + +In this case, we are not interested in receiving updates about the progress, and we just want to use the default settings, so we use [`noop_progress()`][noop_progress] and `None` as arguments. This will make queries to the Electrum server +and store the list of transactions and UTXOs in our `Database`. In this case, we are using a `MemoryDatabase`, so those data are only going to be kept in RAM and dropped once our `Wallet` is dropped. This is very useful +for playing around and experimenting, but not so great for real-world wallets: for that, you can use [sled][sled] which is supported out of the box, or even use a custom database. More on that later! + +So now that we've synced with the blockchain we can create our first transaction. First of all, we will print out the balance of our wallet to make sure that our wallet has seen the incoming transaction. Then we +will create the actual transaction and we will specify some flags using the [`TxBuilder`][TxBuilder]. To finish it off, we will ask the wallet to sign the transaction and then broadcast it to the network. + +Right now we will not get into details of all the available options in `TxBuilder` since that is definitely out of the scope of a "getting started" guide. For now, you can just imagine the builder as your way to tell the library +how to build transactions. We'll come back to this in a future article. + +```rust +use std::str::FromStr; + +use bdk::bitcoin::Address; +use bdk::TxBuilder; + +// ... + +let balance = wallet.get_balance()?; +println!("Wallet balance in SAT: {}", balance); + +let faucet_address = Address::from_str("mkHS9ne12qx9pS9VojpwU5xtRd4T7X7ZUt")?; +let (unsigned_psbt, tx_details) = wallet.create_tx( + TxBuilder::with_recipients(vec![(faucet_address.script_pubkey(), balance / 2)]) + .enable_rbf(), +)?; +println!("Transaction details: {:#?}", tx_details); +``` + +In this case, we are sending back half the balance to the faucet's address and we are also enabling RBF since the default fees are at 1 satoshi/vbyte. With RBF we will be able to *bump the fees* of the transaction, should it get +stuck in the mempool due to the low fee rate. + +All that's left to do once we have our unsigned PSBT is to sign it: + +```rust +// ... + +let (signed_psbt, tx_finalized) = wallet.sign(unsigned_psbt, None)?; +assert!(tx_finalized, "Tx has not been finalized"); +``` + +And then broadcast it: + +```rust +// ... + +let raw_transaction = signed_psbt.extract_tx(); +let txid = wallet.broadcast(raw_transaction)?; +println!( + "Transaction sent! TXID: {txid}.\nExplorer URL: https://blockstream.info/testnet/tx/{txid}", + txid = txid +); +``` + +## Custom Database and Blockchain types + +We briefly mentioned before that for our example we used the `MemoryDatabase`, but that it could also be swapped for a different one: this is one example of the *modularity* of BDK. By default, some database +types are implemented in the library, namely (as of now) the `MemoryDatabase` which only keeps data in RAM and the [sled][sled] database that can store data on a filesystem. But since the `Database` trait is public, +users of the library can also implement different database types more suitable for their use-case. + +The same is true for the `Blockchain` types: the library provides (through the use of opt-in features) implementations for the `Electrum`, `Esplora` and `CompactFilters` (*Neutrino*) backends. Those again can also be +swapped with custom types if the user desires to do so. + +## Conclusion + +Hopefully, this article will help you get started with BDK! This is just a very quick and gentle introduction to the library, and only barely scratches the surface of what's inside: we will keep publishing more +articles in the future to explain some of the more advanced features of BDK, like key generation, using complex [descriptors][descriptor] with multiple keys and/or timelocks, using external signers, etc. + +If you'd like to learn more about the library feel free to ask any questions in the comment section down below, or join our [Discord Community](https://discord.gg/d7NkDKm) to chat with us directly! + + +[descriptor]: /descriptors +[PSBT]: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki +[sled]: https://docs.rs/sled/ + +[Wallet]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html +[KeychainKind]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.KeychainKind.html +[get_new_address]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html#method.get_new_address +[Database]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.Database.html +[MemoryDatabase]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/struct.MemoryDatabase.html +[Blockchain]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.Blockchain.html +[ElectrumBlockchain]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/struct.ElectrumBlockchain.html +[Wallet_new]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html#method.new +[Wallet_new_offline]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html#method.new_offline +[noop_progress]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.noop_progress.html +[TxBuilder]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.TxBuilder.html diff --git a/docs/_blog/release-0.2.0.md b/docs/_blog/release-0.2.0.md new file mode 100644 index 0000000000..6958354714 --- /dev/null +++ b/docs/_blog/release-0.2.0.md @@ -0,0 +1,190 @@ +--- +title: "Release v0.2.0" +description: "Announcing the v0.2.0 release of BDK" +authors: + - Alekos Filini +date: "2020-12-21" +tags: ["rust", "release"] +permalink: "/blog/2020/12/release-v0.2.0/" +--- + +A new release of BDK is finally out! The `v0.2.0` release contains many exciting new features, bug fixes and overall improvements. This release also marks the beginning of our new regular [release schedule][release_schedule], which will see us pushing +out a new release every four weeks. We think this is a good compromise to ensure that developers using BDK have access to all the new features and fixes as soon as possible, at least while the library is still evolving very fast as it is +right now. After `v1.0.0` we will increase this time to a more relaxed 6 weeks. + +You can find the full [v0.2.0 changelog][changelog] on GitHub. + +## What's new in v0.2.0 + +Considering the sheer amount of new things being added we don't have room here to explain every new feature in detail, but below is a quick overview of some you could find useful in your projects. + +### A new name + +The `0.1.0-beta.1` release was tagged right before the project was renamed `bdk`: at that time the library was still called "Magical Bitcoin Library", or `magical` for short. With this release we have now renamed it to `bdk`. If you were using the library +before, it should only be a matter of renaming the imports to match the new name. Alternatively you can also rename `bdk` to `magical` in your Cargo.toml, but you'll still have to do some changes here and there because the APIs have been changed in a few +places. + +This release being particularly large contains a few different API-breaking changes: going forward we expect to make the interface more and more stable, which in turn will make applying updates easier. + +### Branch and Bound coin selection + +We now support the state-of-the-art coin selection algorithm called "branch and bound", with an implementation derived straight from Bitcoin Core. This algorithm is now enabled by default, but it can be replaced with a different one (either +the old default, [`LargestFirstCoinSelection`][`LargestFirstCoinSelection`] or a custom [`CoinSelectionAlgorithm`][`CoinSelectionAlgorithm`]) by using the [`TxBuilder::coin_selection()`][`TxBuilder::coin_selection()`] option. + +Branch and bound works by trying to find a set of inputs that perfectly matches the amount being sent by a transaction, to avoid making an extra change output which takes up more space in the transaction, requires more fees, and in general lowers the privacy +of a user if the change is later spent together with other outputs. + +### Key generation + +If you need to generate a new `bip32::ExtendedPrivKey`, or perhaps a new BIP39 mnemonic, you can use the unified [`GeneratableKey`][`GeneratableKey`] trait to do so: paired with [`GeneratableDefaultOptions`][`GeneratableDefaultOptions`] they provide many different ways to generate keys, +with or without a custom source of entropy, and with or without customized options. + +```rust +use bdk::bitcoin::PrivateKey; +use bdk::keys::{GeneratableKey, GeneratableDefaultOptions, PrivateKeyGenerateOptions}; + +let default_options_key = PrivateKey::generate_default()?; +let custom_options_key = PrivateKey::generate(PrivateKeyGenerateOptions { compressed: false })?; +``` + +### Generic key types + +With this update there's now a generalized trait for keys that can be used in descriptors, which is called [`ToDescriptorKey`][`ToDescriptorKey`]. This trait is already implemented for the native `rust-bitcoin` key types, like `PrivateKey`, `PublicKey`, `bip32::ExtendedPrivKey` +and `bip32::ExtendedPubKey`. It's also implemented for BIP39 mnemonic and seeds, when the the opt-in `keys-bip39` feature is enabled. As always, being this a public trait, you can also implement it for custom types to better suit your needs. + +```rust +impl ToDescriptorKey for MyKeyType { + fn to_descriptor_key(self) -> Result, KeyError> { + // Custom conversion to `bitcoin::PrivateKey` + let privkey: bitcoin::PrivateKey = ... ; + privkey.to_descriptor_key() + } +} +``` + +If your custom key type is simply a different representation of an `xprv` or `xpub`, you can also consider implementing the [`DerivableKey`][`DerivableKey`] trait instead: for a type `K` that implements [`DerivableKey`][`DerivableKey`], the [`ToDescriptorKey`][`ToDescriptorKey`] trait is automatically +implemented for the [`(K, bip32::DerivationPath)`][K_path] and [`(K, bip32::KeySource, bip32::DerivationPath)`][K_src_path] tuples. + +```rust +impl DerivableKey for MyKeyType { + fn add_metadata( + self, + origin: Option, + derivation_path: DerivationPath + ) -> Result, KeyError> { + // Custom conversion to `bip32::ExtendedPrivKey` + let xprv: bip32::ExtendedPrivKey = ... ; + xprv.add_metadata(origin, derivation_path) + } +} +``` + +### Descriptor templates + +Instead of having to serialize keys to strings using `format!()` just to place them somewhere inside a descriptor, you can now use descriptor templates to build a descriptor starting from a key and some other options +in a couple of lines of code. You can use one of the [provided templates][desc_templates_mod] or make a custom one by implementing the [`DescriptorTemplate`][`DescriptorTemplate`] trait on a `struct` or `enum`. + +```rust +let key = bip32::ExtendedPrivKey::from_str("...")?; +let wallet: OfflineWallet<_> = Wallet::new_offline( + BIP84(key.clone(), KeychainKind::External), + Some(BIP84(key, KeychainKind::Internal)), + Network::Testnet, + MemoryDatabase::default(), +)?; +``` + +### Easier creation of `Blockchain` and `Database` + +We've added a new way to create a [`Blockchain`][`Blockchain`] instance from a configuration, with the [`ConfigurableBlockchain`][`ConfigurableBlockchain`] trait. All the [`Blockchain`][`Blockchain`] types provided by the library implement this trait, which allows you to easily build an +instance of them starting from a configuration `struct`: moreover, the configuration structures implement `Serialize` and `Deserialize`, so that they can be easily stored/loaded using `serde`. + +We've also added a new [`Blockchain`][`Blockchain`] type called [`AnyBlockchain`][`AnyBlockchain`], which is essentially an `enum` that wraps all the [`Blockchain`][`Blockchain`] types exposed by the library. This allows you to build a [`Wallet`][`Wallet`] that always has the same +Rust type, but that can internally use different [`Blockchain`][`Blockchain`] backends chosen at runtime. + +```rust +use bdk::blockchain::{AnyBlockchain, AnyBlockchainConfig, ConfigurableBlockchain, ElectrumBlockchainConfig}; + +let config = r#"{"Electrum":{"url":"ssl://electrum.blockstream.info:50002","socks5":null,"retry":3,"timeout":5}}"#; +let config = serde_json::from_str(config)?; +let blockchain = AnyBlockchain::from_config(&config)?; +``` + +The same is true for [`Database`][`Database`] types, thanks to the [`ConfigurableDatabase`][`ConfigurableDatabase`] trait and the [`AnyDatabase`][`AnyDatabase`] `enum`. While we think most people generally prefer to choose a single database type and then stick to it, it's still good +to offer the choice to switch them at runtime, should somebody need that. + +### `descriptor!()` macro + +If you start writing complex descriptor templates, you'll soon find yourself with the need of building large descriptor syntax trees: you can very easily do that with the [`descriptor!()`][`descriptor!()`] macro, with the added bonus that some additional checks on the +syntax of your descriptor will be performed at compile-time, rather than at runtime by. You can use any type that implements [`ToDescriptorKey`][`ToDescriptorKey`] (even strings!) as keys in `pk()`, `multi()` and `sortedmulti()` fragments, and you can even mix +them in the same descriptor. + +The syntax supported by the macro is almost exactly the same as the standard descriptor syntax we all know, with the only difference that modifiers should be specified individually rather than +grouped in a series of characters (see the example below). + +```rust +pub struct TimeDecayingMultisig { + pk_a: K, + pk_b: K, + timelock: u32, +} + +impl> DescriptorTemplate for TimeDecayingMultisig { + fn build(self) -> Result { + Ok(bdk::descriptor!(wsh(thresh(2,pk(self.pk_a),s:pk(self.pk_b),s:d:v:older(self.timelock)))) + .map_err(|e| KeyError::Message(e.to_string()))?) + } +} +``` + +### Support for `sortedmulti()` + +Thanks to the addition of `sortedmulti()` in `rust-miniscript`, we can now also support them in BDK, which means we are getting more and more compatible with other descriptor-based wallets out there like Bitcoin Core. + +## Contributors + +A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports. + +Since the `0.1.0-beta.1` release over three months ago, we've had `213` new commits made by `10` different contributors for a total of `9990` additions and `2993` deletions. Here's the [full diff][gh_diff]. + +A special thanks to the `7` new contributors: + +- [@eupn][@eupn] +- [@justinmoon][@justinmoon] - Justin Moon +- [@Xekyo][@Xekyo] - Mark Erhardt +- [@RCasatta][@RCasatta] - Riccardo Casatta +- [@ulrichard][@ulrichard] - Richard Ulrich +- [@notmandatory][@notmandatory] - Steve Myers +- [@willcl-ark][@willcl-ark] - Will Clark + +[release_schedule]: https://github.com/bitcoindevkit/bdk/blob/7d6cd6d4f5a26194830f90e6460e0b82bddf9594/DEVELOPMENT_CYCLE.md +[changelog]: https://github.com/bitcoindevkit/bdk/blob/7d6cd6d4f5a26194830f90e6460e0b82bddf9594/CHANGELOG.md#v020---010-beta1 +[gh_diff]: https://github.com/bitcoindevkit/bdk/compare/0.1.0-beta.1...v0.2.0 + +[`LargestFirstCoinSelection`]: https://docs.rs/bdk/0.2.0/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html +[`CoinSelectionAlgorithm`]: https://docs.rs/bdk/0.2.0/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html +[`TxBuilder::coin_selection()`]: https://docs.rs/bdk/0.2.0/bdk/wallet/tx_builder/struct.TxBuilder.html#method.coin_selection +[`ToDescriptorKey`]: https://docs.rs/bdk/0.2.0/bdk/keys/trait.ToDescriptorKey.html +[`DerivableKey`]: https://docs.rs/bdk/0.2.0/bdk/keys/trait.DerivableKey.html +[K_path]: https://docs.rs/bdk/0.2.0/bdk/keys/trait.ToDescriptorKey.html#impl-ToDescriptorKey%3CCtx%3E-for-(T%2C%20DerivationPath) +[K_src_path]: https://docs.rs/bdk/0.2.0/bdk/keys/trait.ToDescriptorKey.html#impl-ToDescriptorKey%3CCtx%3E-for-(T%2C%20KeySource%2C%20DerivationPath) +[`GeneratableKey`]: https://docs.rs/bdk/0.2.0/bdk/keys/trait.GeneratableKey.html +[`GeneratableDefaultOptions`]: https://docs.rs/bdk/0.2.0/bdk/keys/trait.GeneratableDefaultOptions.html +[`DescriptorTemplate`]: https://docs.rs/bdk/0.2.0/bdk/descriptor/template/trait.DescriptorTemplate.html +[desc_templates_mod]: https://docs.rs/bdk/0.2.0/bdk/descriptor/template/index.html +[`Blockchain`]: https://docs.rs/bdk/0.2.0/bdk/blockchain/trait.Blockchain.html +[`ConfigurableBlockchain`]: https://docs.rs/bdk/0.2.0/bdk/blockchain/trait.ConfigurableBlockchain.html +[`Database`]: https://docs.rs/bdk/0.2.0/bdk/database/trait.Database.html +[`ConfigurableDatabase`]: https://docs.rs/bdk/0.2.0/bdk/database/trait.ConfigurableDatabase.html +[`AnyBlockchain`]: https://docs.rs/bdk/0.2.0/bdk/blockchain/any/enum.AnyBlockchain.html +[`AnyDatabase`]: https://docs.rs/bdk/0.2.0/bdk/database/any/enum.AnyDatabase.html +[`Wallet`]: https://docs.rs/bdk/0.2.0/bdk/wallet/struct.Wallet.html +[`descriptor!()`]: https://docs.rs/bdk/0.2.0/bdk/macro.descriptor.html + +[@notmandatory]: https://github.com/notmandatory +[@willcl-ark]: https://github.com/willcl-ark +[@ulrichard]: https://github.com/ulrichard +[@Xekyo]: https://github.com/Xekyo +[@RCasatta]: https://github.com/RCasatta +[@justinmoon]: https://github.com/justinmoon +[@eupn]: https://github.com/eupn diff --git a/docs/_blog/release-0.3.0.md b/docs/_blog/release-0.3.0.md new file mode 100644 index 0000000000..7d213d2dbb --- /dev/null +++ b/docs/_blog/release-0.3.0.md @@ -0,0 +1,78 @@ +--- +title: "Release v0.3.0" +description: "Announcing the v0.3.0 release of BDK" +authors: + - Alekos Filini +date: "2021-01-20" +tags: ["rust", "release"] +permalink: "/blog/2021/01/release-v0.3.0/" +--- + +A new release of BDK is out: the [`v0.3.0`] is a relatively small update compared to `v0.2.0`, but it still brings some nice APIs improvements and general bugfixes. + +You can find the full [v0.3.0 changelog][changelog] on GitHub. + +## What's new in v0.3.0 + +Below are some highlights of the new improved APIs coming with this release: + +### Less verbosity when using `Wallet::new_offline()` + +Now you don't have to explicitly provide the `OfflineWallet<_>` type anymore, saving you one import and making it much less verbose to use. + +Where before you were doing: + +```rust +let wallet: OfflineWallet<_> = Wallet::new_offline(...)?; +``` + +Now you can just write: + +```rust +let wallet = Wallet::new_offline(...)?; +``` + +### No more error conversions in `DescriptorTemplate` + +The `DescriptorTemplate` trait has been updated to return a [`descriptor::error::Error`] instead of a `KeyError`. The [`descriptor!()`] macro has been updated as well, which means that now you can use the macro inside a `DescriptorTemplate::build()` implementation +without having to [map the error](/blog/2020/12/release-v0.2.0/#descriptor-macro), like so: + +```rust +pub struct TimeDecayingMultisig { + pk_a: K, + pk_b: K, + timelock: u32, +} + +impl> DescriptorTemplate for TimeDecayingMultisig { + fn build(self) -> Result { + bdk::descriptor!(wsh(thresh(2,pk(self.pk_a),s:pk(self.pk_b),s:d:v:older(self.timelock)))) + } +} +``` + +### A new repo for the CLI + +The `cli` module (and it's related `cli-utils` feature) have been removed from the main BDK repo and moved to their new home, the [bdk-cli] repo. The APIs exposed were mainly used internally, for the `repl` and the [playground](/bdk-cli/playground) +in our website, but in case you were using one of those keep that in mind. + +## Contributors + +A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports. + +Since the `v0.2.0` release around a month ago, we've had `24` new commits made by `6` different contributors for a total of `404` additions and `1243` deletions. Here's the [full diff][gh_diff]. + +A special thanks to the new contributor for this release: + +- [@tcharding][@tcharding] - Tobin C. Harding + +[changelog]: https://github.com/bitcoindevkit/bdk/blob/75669049268bbc294564f8c6e0528e07a546258f/CHANGELOG.md#v030---v020 +[gh_diff]: https://github.com/bitcoindevkit/bdk/compare/v0.2.0...v0.3.0 +[bdk-cli]: https://github.com/bitcoindevkit/bdk-cli + +[`descriptor!()`]: https://docs.rs/bdk/0.3.0/bdk/macro.descriptor.html +[`descriptor::error::Error`]: https://docs.rs/bdk/0.3.0/bdk/descriptor/error/enum.Error.html + +[`v0.3.0`]: https://crates.io/crates/bdk/0.3.0 + +[@tcharding]: https://github.com/tcharding diff --git a/docs/_blog/release-0.4.0.md b/docs/_blog/release-0.4.0.md new file mode 100644 index 0000000000..21f31cb103 --- /dev/null +++ b/docs/_blog/release-0.4.0.md @@ -0,0 +1,107 @@ +--- +title: "Release v0.4.0" +description: "Announcing the v0.4.0 release of BDK" +authors: + - Alekos Filini +date: "2021-02-17" +tags: ["rust", "release"] +permalink: "/blog/2021/02/release-v0.4.0/" +--- + +A new release of BDK is out: the [`v0.4.0`] release brings updated dependencies, more sanity checks and an overhauled API to build transactions. + +You can find the full [v0.4.0 changelog][changelog] on GitHub. + +## What's new in v0.4.0 + +Below are some highlights of the new improved APIs coming with this release: + +### A new API to build transaction + +The star of this release is the new API designed and implemented by [@llfourn] that brings much more flexibility to the way we create transactions: originally the process of making a transaction involved the creation of a `TxBuilder` which was used +to configure *how* the wallet should build the transaction. Things like which outputs to create, what `nLockTime` to use, which UTXOs to spend, and much more. + +Once fully configured, this builder was then given to the `Wallet` itself in a `Wallet::create_tx()` or `Wallet::bump_fee()` call: the `Wallet` would try to follow the *instructions* given by the builder, but in +case of conflicting or straight-up wrong options it would have to fail and force the user to start over. + +The new API maintains the concept of a *builder*, but it changes the way it's created so that it always contains a reference to the main `Wallet` instance. What this means is that most checks can now be performed right +when something is added to the builder, not at the end, allowing the user to recover from errors instead of having to start over. + +This also opens the door to even more improvements and additions, such as a way to [spend foreign utxos][foreign_utxo] in a transaction, or even a way to [bump the fees of multiple transactions at once][bump_fee_batched] by batching them together, which +saves a bit of space and money. + +```rust +let send_to = wallet.get_new_address()?; +let (psbt, details) = { + let mut builder = wallet.build_tx(); + builder + .add_recipient(send_to.script_pubkey(), 50_000) + .enable_rbf() + .do_not_spend_change() + .fee_rate(FeeRate::from_sat_per_vb(5.0)); + builder.finish()? +}; +``` + +### Upgraded dependencies + +This release also brings many updates to our dependencies, including: + +- `bitcoin` to `v0.26` +- `miniscript` to `v5.1` +- `electrum-client` to `v0.6` +- `tokio` to `v1` +- `reqwest` to `v0.11` +- `cc` to `>= v1.0.64` + +### Compact Filters example + +Thanks to the upgrade to `bitcoin v0.26` all the issues related to new networking messages in the P2P Bitcoin network have been fixed, which means that we can finally use our (experimental) compact filters `Blockchain` with +standard Bitcoin Core 0.21 full nodes. + +The following example has also been added to the repository and can be run with `cargo run --features=compact_filters --example compact_filters_balance`. + +```rust +/// This will return wallet balance using compact filters +/// Requires a synced local bitcoin node 0.21 running on testnet with blockfilterindex=1 and peerblockfilters=1 +fn main() -> Result<(), CompactFiltersError> { + env_logger::init(); + info!("start"); + + let num_threads = 4; + let mempool = Arc::new(Mempool::default()); + let peers = (0..num_threads) + .map(|_| Peer::connect("localhost:18333", Arc::clone(&mempool), Network::Testnet)) + .collect::>()?; + let blockchain = CompactFiltersBlockchain::new(peers, "./wallet-filters", Some(500_000))?; + info!("done {:?}", blockchain); + let descriptor = "wpkh(tpubD6NzVbkrYhZ4X2yy78HWrr1M9NT8dKeWfzNiQqDdMqqa9UmmGztGGz6TaLFGsLfdft5iu32gxq1T4eMNxExNNWzVCpf9Y6JZi5TnqoC9wJq/*)"; + + let database = MemoryDatabase::default(); + let wallet = + Arc::new(Wallet::new(descriptor, None, Network::Testnet, database, blockchain).unwrap()); + wallet.sync(noop_progress(), None).unwrap(); + info!("balance: {}", wallet.get_balance()?); + Ok(()) +} +``` + +## Contributors + +A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports. + +Since the `v0.3.0` release around a month ago, we've had `59` new commits made by `8` different contributors for a total of `2463` additions and `1991` deletions. Here's the [full diff][gh_diff]. + +A special thanks to the new contributor for this release: + +- [@luckysori][@luckysori] - Lucas Soriano + +[changelog]: https://github.com/bitcoindevkit/bdk/blob/5e352489a0ac9dd92002a73aa64789a9ae2f0794/CHANGELOG.md#v040---v030 +[foreign_utxo]: https://github.com/bitcoindevkit/bdk/pull/279 +[bump_fee_batched]: https://github.com/bitcoindevkit/bdk/issues/280 +[gh_diff]: https://github.com/bitcoindevkit/bdk/compare/v0.3.0...v0.4.0 + +[`v0.4.0`]: https://crates.io/crates/bdk/0.4.0 + +[@luckysori]: https://github.com/luckysori +[@llfourn]: https://github.com/llfourn diff --git a/docs/_blog/release-0.5.0.md b/docs/_blog/release-0.5.0.md new file mode 100644 index 0000000000..664591f4cd --- /dev/null +++ b/docs/_blog/release-0.5.0.md @@ -0,0 +1,53 @@ +--- +title: "Release v0.5.0" +description: "Announcing the v0.5.0 release of BDK" +authors: + - Alekos Filini +date: "2021-03-18" +tags: ["rust", "release"] +permalink: "/blog/2021/03/release-v0.5.0/" +--- + +A new release of BDK is out: [`v0.5.0`] is our first release licensed under Apache 2.0 and MIT, brings new features, bugfixes and some internal refactoring. + +You can find the full [v0.5.0 changelog][changelog] on GitHub. + +## What's new in v0.5.0 + +Below are some highlights of the new release: + +### Dual Licensing + +From now on BDK will be released under both Apache 2.0 and MIT, at your discretion. This change aligns our project with many other Rust crates and reiterates our commitment to a permissive licensing model. + +### Spending *foreign* UTXOs + +This release adds a new `TxBuilder` method called [`add_foreign_utxo()`], which can be used to spend UTXOs that don't belong to the `Wallet`. We think this is going to be very useful to developers working on multiparty +protocols like CoinJoins, Pay Join, etc. + +It's as easy as giving the library a PSBT input and the satisfaction cost for that input: + +```rust +let mut builder = wallet.build_tx(); +builder + .add_recipient(addr.script_pubkey(), 60_000) + .add_foreign_utxo(foreign_utxo.outpoint, foreign_utxo_psbt_input, foreign_utxo_satisfaction_weight)? +``` + +## Contributors + +A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports. + +Since the `v0.4.0` release around a month ago, we've had `54` new commits made by `7` different contributors for a total of `1430` additions and `1212` deletions. Here's the [full diff][gh_diff]. + +A special thanks to the new contributor for this release: + +- [@davemo88][@davemo88] + +[changelog]: https://github.com/bitcoindevkit/bdk/blob/f786f0e6241a3df47b96bbb07f1aba374bc73b2f/CHANGELOG.md#v050---v040 +[gh_diff]: https://github.com/bitcoindevkit/bdk/compare/v0.4.0...v0.5.0 + +[`add_foreign_utxo()`]: https://docs.rs/bdk/0.5.0/bdk/wallet/tx_builder/struct.TxBuilder.html#method.add_foreign_utxo +[`v0.5.0`]: https://crates.io/crates/bdk/0.5.0 + +[@davemo88]: https://github.com/davemo88 diff --git a/docs/_blog/release-0.6.0.md b/docs/_blog/release-0.6.0.md new file mode 100644 index 0000000000..049b211a58 --- /dev/null +++ b/docs/_blog/release-0.6.0.md @@ -0,0 +1,85 @@ +--- +title: "Release v0.6.0" +description: "Announcing the v0.6.0 release of BDK" +authors: + - Alekos Filini +date: "2021-04-15" +tags: ["rust", "release"] +permalink: "/blog/2021/04/release-v0.6.0/" +--- + +A new release of BDK is out: [`v0.6.0`] brings some new API calls, renamed types and some bugfixes. + +You can find the full [v0.6.0 changelog][changelog] on GitHub. + +## What's new in v0.6.0 + +Below are some highlights of the new release: + +### A new way to generate addresses + +The old `get_new_address()` method has been upgraded into a more generic `get_address()`, which takes a [`AddressIndex`] argument. `AddressIndex` is defined as an enum with the following variants: +- `AddressIndex::New` increments the derivation index stored in the database and returns a new address. It's equivalent to the old `get_new_address()`. +- `AddressIndex::LastUnused` returns the address for the current derivation index if no usage has been detected. `sync()` should be called to ensure the internal database is up to date. +- `AddressIndex::Peek(index)` returns the address at a given derivation index, without updating the database. +- `AddressIndex::Reset(index)` returns the address at a given derivation index, and stores that value in the database. + +```rust +// Prints the first ten addresses without updating the derivation index +for index in 0..10 { + println!("Address #{}: {}", index, wallet.get_address(AddressIndex::Peek(index)?)); +} +``` + +### Easier multiparty transaction creation + +A new method called [`get_psbt_input()`] has been added to the `Wallet` structure, and it makes it very easy to get a complete PSBT input with all the required metadata for a given UTXO. This can be very convenient +when working with `add_foreign_utxo()`, which was added in the previous release: + +```rust +// On Alice's wallet +let alice_utxo = LocalUtxo { ... }; +let alice_psbt_input = wallet_alice.get_psbt_input(alice_utxo.clone())?; +send_input_to_bob(alice_utxo.outpoint, alice_psbt_input)?; + +// On Bob's wallet +let mut builder = wallet_bob.build_tx(); +builder + .add_recipient(addr.script_pubkey(), 60_000) + .add_foreign_utxo(alice_outpoint, alice_psbt_input, satisfaction_weight)? + .... +``` + +### Renamed types + +To keep our coding style in line with the best practices defined by the Rust language, we've renamed some of our types and enum variants to avoid using [upper case acronyms](https://rust-lang.github.io/rust-clippy/master/index.html#upper_case_acronyms). + +Some examples are: +- `UTXO` -> `Utxo` +- `RBFValue` -> `RbfValue` +- `BIP69Lexicographic` -> `Bip69Lexicographic` +- `P2PKH` -> `P2Pkh` +- `BIP44Public` -> `Bip44Public` + +### New MSRV + +Due to some changes in one of our dependency, our MSRV has been bumped up from `1.45` to `1.46`, which was released in August 2020. The last release fully supporting `1.45` is `v0.5.1`. + +## Contributors + +A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports. + +Since the `v0.5.1` release around a month ago, we've had `37` new commits made by `7` different contributors for a total of `1092` additions and `548` deletions. Here's the [full diff][gh_diff]. + +A special thanks to the new contributor for this release: + +- [@da-kami][@da-kami] - Daniel Karzel + +[changelog]: https://github.com/bitcoindevkit/bdk/blob/2bddd9baedc3744cd7647176c2f31405ee7bb54a/CHANGELOG.md#v060---v051 +[gh_diff]: https://github.com/bitcoindevkit/bdk/compare/v0.5.1...v0.6.0 + +[`AddressIndex`]: https://docs.rs/bdk/0.6.0/bdk/wallet/enum.AddressIndex.html +[`get_psbt_input()`]: https://docs.rs/bdk/0.6.0/bdk/wallet/struct.Wallet.html#method.get_psbt_input +[`v0.6.0`]: https://crates.io/crates/bdk/0.6.0 + +[@da-kami]: https://github.com/da-kami diff --git a/docs/_blog/release-0.7.0.md b/docs/_blog/release-0.7.0.md new file mode 100644 index 0000000000..f1b18eb132 --- /dev/null +++ b/docs/_blog/release-0.7.0.md @@ -0,0 +1,82 @@ +--- +title: "Release v0.7.0" +description: "Announcing the v0.7.0 release of BDK" +authors: + - Alekos Filini +date: "2021-05-17" +tags: ["rust", "release"] +permalink: "/blog/2021/05/release-v0.7.0/" +--- + +A new release of BDK is out: [`v0.7.0`] improved APIs, a more robust signing process and various bugfixes and improvements. + +You can find the full [v0.7.0 changelog][changelog] on GitHub. + +## What's new in v0.7.0 + +Below are some highlights of the new release: + +### New Signing API + +The `Wallet::sign()` method has been updated to take a *mutable reference* to a PSBT rather than consuming it entirely. This makes it easier to sign the same PSBT multiple times with different signers: + +```rust +let mut psbt = ...; + +let alice_finalized = wallet_alice.sign(&mut psbt, SignOptions::default())?; +let bob_finalized = wallet_bob.sign(&mut psbt, SignOptions::default())?; +``` + +Under the hood, even more has changed around the way we make signatures: starting from this release, our signer will require by default that SegWit PSBTs also provide the `non_witness_utxo` to mitigate the fee bruning "[SegWit bug][segwit_bug]". + +For this reason, the second argument of `Wallet::sign()`, which was initially used to optionally provide a different "current height" that the wallet would consider when trying to finalize the transaction, has been replaced with a more generic "options" +argument of type [`SignOptions`]. This allows setting a different assumed block height and also opting out of requiring `non_witness_utxo` by enabling the `trust_witness_utxo` flag. + +As a result of these new more strict requirements, BDK will also, by default, fill-in the `non_witness_utxo` field when creating new PSBTs. The `TxBuilder::force_non_witness_utxo()` option has been removed and a new one called +`TxBuilder::only_witness_utxo()` has been added, to allow users to opt-out of this new default behavior. + +```rust +// Make a transaction that only contains the `witness_utxo` +let (psbt, details) = { + let mut builder = wallet.build_tx(); + builder + .add_recipient(send_to.script_pubkey(), 50_000) + .only_witness_utxo(); + builder.finish()? +}; +// Sign it by explicitly trusting just the `witness_utxo` +let finalized = wallet.sign(&mut psbt, SignOptions { trust_witness_utxo: true, ..Default::default() })?; +``` + +### Support Timelocks in the `policy` Module + +A less-known part of BDK is its "policy" module: its goal is to take a descriptor and encode the spending policy represented by that descriptor in a more "user-friendly" format. On top of that, the module +tries to provide a summary for what a user's descriptor can *contribute* to a transaction. For instance, given a 2-of-2 multisig policy, a descriptor that contains only the two public keys can't *contribute* anything, +while a descriptor that has one or both private keys can, respectively, *contribute to* and *satisfy* the policy by making signatures. + +In release `v0.5.0` we added support for computing which parts of a policy are already satisfied by a given PSBT. This, combined with the contribution part, allow users to get a complete picture of what's already present +and what's missing to fully satisfy a descriptor. + +In this release we are starting to take timelocks into consideration when computing the *satisfaction* component of a policy: this means that we can consider timelocks that are already expired as fully satisfied and also +exclude policy branches that require specific `nLockTime` or `nSequence` values, if those aren't correctly set in the transaction. + +Ultimately with those changes we are able to give our users a more complete picture of the completion stage of a PSBT, which also takes into account the expiration of timelocks. + +## Contributors + +A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports. + +Since the `v0.6.0` release around a month ago, we've had `39` new commits made by `6` different contributors for a total of `698` additions and `309` deletions. Here's the [full diff][gh_diff]. + +A special thanks to the new contributor for this release: + +- [@rajarshimaitra][@rajarshimaitra] - Raj + +[changelog]: https://github.com/bitcoindevkit/bdk/blob/aaa9943a5f614da522cdac44af80adf941879210/CHANGELOG.md#v070---v060 +[gh_diff]: https://github.com/bitcoindevkit/bdk/compare/v0.6.0...v0.7.0 + +[segwit_bug]: https://blog.trezor.io/details-of-firmware-updates-for-trezor-one-version-1-9-1-and-trezor-model-t-version-2-3-1-1eba8f60f2dd +[`SignOptions`]: https://docs.rs/bdk/0.7.0/bdk/wallet/signer/struct.SignOptions.html +[`v0.7.0`]: https://crates.io/crates/bdk/0.7.0 + +[@rajarshimaitra]: https://github.com/rajarshimaitra diff --git a/docs/_blog/release-0.8.0.md b/docs/_blog/release-0.8.0.md new file mode 100644 index 0000000000..6ba4216587 --- /dev/null +++ b/docs/_blog/release-0.8.0.md @@ -0,0 +1,65 @@ +--- +title: "Release v0.8.0" +description: "Announcing the v0.8.0 release of BDK" +authors: + - Alekos Filini +date: "2021-06-14" +tags: ["rust", "release"] +permalink: "/blog/2021/06/release-v0.8.0/" +--- + +A new release of BDK is out: [`v0.8.0`] brings new APIs and other minor bugfixes and internal improvements. + +You can find the full [v0.8.0 changelog][changelog] on GitHub. + +## What's new in v0.8.0 + +Below are some highlights of the new release: + +### Getting the Derivation Index + +The `Wallet::get_address()` method now returns an [`AddressInfo`] structure, rather than a simple `Address`. This new structure contains the address but also the derivation index, which can be useful in some contexts. + +Since the structure implements `Deref` it can be used directly as a `&Address`, which simplifies migrating to this change a little bit. + +```rust +let address_info = wallet.get_address(AddressInfo::New)?; + +// Print the address and derivation index +println!("Address #{}: {}", address_info.index, address_info.address); + +// Use the `AddressInfo` structure directly like an `Address` +let script_pubkey = address_info.script_pubkey(); +``` + +### Explicitly Enable non-ALL Sighashes + +To mitigate potential attacks in multiparty protocols, this release includes a new [`SignOptions::allow_all_sighashes`][sign_option] option that must be explicitly enabled to let the signers produce signatures +with any non-ALL sighash. + +```rust +let mut psbt = ...; + +// Fails if the psbt uses non-ALL sighashes +let finalized = wallet.sign(&mut psbt, SignOptions::default())?; + +// Produces a signature successfully +let finalized = wallet.sign(&mut psbt, SignOptions { allow_all_sighashes: true, ..Default::default() })?; +``` + +## Contributors + +A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports. + +Since the `v0.7.0` release around a month ago, we've had `39` new commits made by `6` different contributors for a total of `1540` additions and `1380` deletions. Here's the [full diff][gh_diff]. + +A special thanks to the new contributor for this release: + +- [@futurepaul][@futurepaul] - Paul Miller + +[changelog]: https://github.com/bitcoindevkit/bdk/blob/67714adc80669129eff2cad8991609d3b1c41cb9/CHANGELOG.md +[gh_diff]: https://github.com/bitcoindevkit/bdk/compare/v0.7.0...v0.8.0 + +[`AddressInfo`]: https://docs.rs/bdk/0.8.0/bdk/wallet/struct.AddressInfo.html +[sign_option]: https://docs.rs/bdk/0.8.0/bdk/wallet/signer/struct.SignOptions.html#structfield.allow_all_sighashes +[`v0.8.0`]: https://crates.io/crates/bdk/0.8.0 diff --git a/docs/_blog/release-0.9.0.md b/docs/_blog/release-0.9.0.md new file mode 100644 index 0000000000..d34c3b5247 --- /dev/null +++ b/docs/_blog/release-0.9.0.md @@ -0,0 +1,76 @@ +--- +title: "Release v0.9.0" +description: "Announcing the v0.9.0 release of BDK" +authors: + - Alekos Filini +date: "2021-07-11" +tags: ["rust", "release"] +permalink: "/blog/2021/07/release-v0.9.0/" +--- + +A new release of BDK is out: [`v0.9.0`] brings support for Bitcoin Core backends, more sanity checks and bugfixes. + +You can find the full [v0.9.0 changelog][changelog] on GitHub. + +## What's new in v0.9.0 + +Below are some highlights of the new release: + +## Bitcoin Core `Blockchain` Backend + +This release finally adds support for using a Bitcoin Core node as the `Blockchain` backend for a wallet, through the RPC. This is still considered experimental for the time being, since there are a few missing +things that we'd like to add, and adding those could force us to change the API a little. + +Nonetheless, if you don't mind a breaking-change later on it's already fully functional. + +The backend works by importing addresses in Bitcoin Core using the `importmulti` call. + +Using it is pretty straightforward, here's a quick example: + +```rust +let config = RpcConfig { + url: "127.0.0.1:18332".to_string(), + auth: bitcoincore_rpc::Auth::CookieFile("/home/user/.bitcoin/.cookie".into()), + network: bdk::bitcoin::Network::Testnet, + wallet_name: "wallet_name".to_string(), + skip_blocks: None, +}; +let blockchain = RpcBlockchain::from_config(&config); +``` + +Similarly to the compact filters backend, the `skip_blocks` field allows for starting a rescan of the blockchain at a given height rather than the genesis, saving some time. The rescan is only performed once, the +first time an address is imported. Afterwards every `sync()` call will only perform a few queries on the node and it will be much faster. + +## Updated `TransactionDetails` Struct + +To better accomodate the Bitcoin Core RPC and potentially more future new backends, the [`TransactionDetails`] structure have been updated as follows: + +- The `fees` field has been renamed to `fee` and it has been made optional. `Blockchain` backends can set this to `None` when they have no way of computing the fee of a transaction +- The `timestamp` and `height` fields have been merged into an optional [`ConfirmationTime`] struct + +## Verify Downloaded TXs + +This release also introduces an opt-in feature called `verify` that can be enabled to verify the unconfirmed transactions that BDK downloads from untrusted sources like Electrum servers. + +Verifying the transactions against the consensus rules can be an additional protection against some kind of attacks that could trick a wallet into creating wrong RBF (BIP 125) "bump" transactions. Check out [the issue][issue_verify] +for more details. + +## Contributors + +A huge thanks to everybody who contributed to this new release with suggestions, pull requests and bug reports. + +Since the `v0.8.0` release around a month ago, we've had `45` new commits made by `6` different contributors for a total of `1336` additions and `266` deletions. Here's the [full diff][gh_diff]. + +A special thanks to the new contributor for this release: + +- [@jb55][@jb55] - William Casarin + +[changelog]: https://github.com/bitcoindevkit/bdk/blob/7a9b691f68c41116dc7857bc0267a2e3b2eafdd3/CHANGELOG.md +[gh_diff]: https://github.com/bitcoindevkit/bdk/compare/v0.8.0...v0.9.0 + +[issue_verify]: https://github.com/bitcoindevkit/bdk/issues/352 + +[`TransactionDetails`]: https://docs.rs/bdk/0.9.0/bdk/struct.TransactionDetails.html +[`ConfirmationTime`]: https://docs.rs/bdk/0.9.0/bdk/struct.ConfirmationTime.html + +[`v0.9.0`]: https://crates.io/crates/bdk/0.9.0 diff --git a/docs/_blog/spending_policy_demo.md b/docs/_blog/spending_policy_demo.md new file mode 100644 index 0000000000..b0ebde02a2 --- /dev/null +++ b/docs/_blog/spending_policy_demo.md @@ -0,0 +1,441 @@ +--- +title: "Spending Policy Demo" +description: "Demonstrate how to use a descriptor wallet with different spending policies" +authors: + - Steve Myers + - Thunderbiscuit +date: "2021-02-23" +tags: ["guide", "descriptor"] +permalink: "/blog/2021/02/spending-policy-demo/" +--- + +In this post we will use the [bdk-cli](https://github.com/bitcoindevkit/bdk-cli) tool to demonstrate how to use the [bdk](https://github.com/bitcoindevkit/bdk) library to: + +1. generate *testnet* public and private keys +2. create [PSBT](https://bitcoinops.org/en/topics/psbt/)s that can be spent based on different [miniscript spending policies](http://bitcoin.sipa.be/miniscript/) +3. cooperatively sign and finalize the resulting PSBTs +4. broadcast and confirm spending transactions + +The scenario we will simulate is a wallet with two spending policies: + +A. **three** out of **three** signers must sign spending transaction input [UTXO](https://developer.bitcoin.org/glossary.html)s, **OR** + +B. **two** out of **three** signers must sign **AND** the input UTXOs must be a relative number of blocks older than the spending transaction's block + +In a real-world wallet a longer relative time-lock would probably be used, but we chose a two block time-lock to make testing easier. + +*Note: If you repeat these instructions on your own your extended keys, addresses, and other values will be different than shown in this post, but the end results should be the same.* + +## Initial Setup + +### Step 0: Install a recent version `bdk-cli` + +```bash +cargo install bdk-cli --features repl,electrum,esplora + +# confirm bdk-cli is installed +bdk-cli --version +BDK CLI 0.2.0 + +# bdk-cli usage can be explored with the `help` sub-command +bdk-cli help +``` + +### Step 1: Generate private extended keys + +Generate new extended private keys for each of our wallet participants: + +```bash +bdk-cli key generate | tee alice-key.json +{ + "fingerprint": "5adb4683", + "mnemonic": "witness poverty pulse crush era item game rose bargain quantum spawn sure way behave also basket journey worry stem entry toddler floor way bone", + "xprv": "tprv8ZgxMBicQKsPeAuGznXJZwfWHgWo86dFuufRBZN7ZT44UzoNG2cYmZLNLrnsm7eXhGSeccRU2nTtxunT11UkpqrRhJQefBnFJeHBddF68bg" +} + +bdk-cli key generate | tee bob-key.json +{ + "fingerprint": "5fdec309", + "mnemonic": "shiver atom february jealous spy gallery upset height captain snake tooth master ugly orbit amazing nice parrot elevator own olympic great relief ozone violin", + "xprv": "tprv8ZgxMBicQKsPei56wJPNt9u2132Ynncp2qXdfSHszobnyjaGjQwxQBGASUidc1unmEmpyMQ9XzLgvbN36MDW7LNziVFdXVGMrx6ckMHuRmd" +} + +bdk-cli key generate | tee carol-key.json +{ + "fingerprint": "de41e56d", + "mnemonic": "upon bridge side tool style lounge need faculty middle nation armed corn valve that undo ribbon rent digital adapt capable embody zero shiver carpet", + "xprv": "tprv8ZgxMBicQKsPf2edJLnXsF2AKwkCshCy2Z7fQD6FxiNVGsbkvpLRfxM8FSKrLqqpLFzLzVUBwgE9F5MQASrbedKCrGk1NG8oJgqYtmTLQEU" +} +``` + +### Step 2: Extract private extended keys + +Here we use the `jq` Unix command to parse the json output of the `bdk-cli` commands. + +```bash +export ALICE_XPRV=$(cat alice-key.json | jq -r '.xprv') + +export BOB_XPRV=$(cat bob-key.json | jq -r '.xprv') + +export CAROL_XPRV=$(cat carol-key.json | jq -r '.xprv') +``` + +### Step 3: Derive public extended keys + +For this example we are using the [BIP-84](https://github.com/bitcoin/bips/blob/master/bip-0084.mediawiki) key path: `m/84h/1h/0h/0/*` to derive extended public keys to share with other wallet participants. + +Note that the `key derive` sub-command will generate a tpub for the last hardened node in the given derivation path. You'll also notice that `bdk-cli` will returns our tpub with the key origin (fingerprint/path) added to it (the metadata part that looks like `[5adb4683/84'/1'/0']` right before the tpub). This key origin information is not necessary in order to use a tpub and generate addresses, but it's good practice to include it because some signers require it. + +```bash +export ALICE_XPUB=$(bdk-cli key derive --xprv $ALICE_XPRV --path "m/84'/1'/0'/0" | jq -r ".xpub") +echo \"$ALICE_XPUB\" +"[5adb4683/84'/1'/0']tpubDCyRBuncqwyAjSNiw1GWLmwQsWyhgPMEBpx3ZNpnCwZwf3HXerspTpaneN81KRxkwj8vjqH9pNWEPgNhen7dfE212SHfxBBbsCywxQGxvvu/0/*" + +export BOB_XPUB=$(bdk-cli key derive --xprv $BOB_XPRV --path "m/84'/1'/0'/0" | jq -r ".xpub") +echo \"$BOB_XPUB\" +"[5fdec309/84'/1'/0']tpubDDQcUeBH9JFtgZEsHZBhmRu8AuZ8ceJY1umnipPVEg1had2coGMCWdFBXNnZWKoCPic3EMgDZTdmkAVNoakwNZu2ESSW36rQvts6VXGx4bU/0/*" + +export CAROL_XPUB=$(bdk-cli key derive --xprv $CAROL_XPRV --path "m/84'/1'/0'/0" | jq -r ".xpub") +echo \"$CAROL_XPUB\" +"[de41e56d/84'/1'/0']tpubDCdxmvzJ5QBjTN8oCjjyT2V58AyZvA1fkmCeZRC75QMoaHcVP2m45Bv3hmnR7ttAwkb2UNYyoXdHVt4gwBqRrJqLUU2JrM43HippxiWpHra/0/*" +``` + +### Step 4: Create wallet descriptors for each participant + +We used the [BDK Playground Policy Compiler](https://bitcoindevkit.org/bdk-cli/playground/) to compile the [miniscript](http://bitcoin.sipa.be/miniscript/) policy: + +`thresh(3,pk(Alice),pk(Bob),pk(Carol),older(2))` + +To the [output descriptor](https://bitcoindevkit.org/descriptors/): + +`wsh(thresh(3,pk(Alice),s:pk(Bob),s:pk(Carol),sdv:older(2)))` + +This descriptor requires spending transaction inputs must be signed by all three signers, or by two signers and the spent UTXOs must be older than two blocks. + +Each participant's descriptor only uses their own XPRV key plus the XPUB keys of the other participants. + +```bash +export ALICE_DESCRIPTOR="wsh(thresh(3,pk($ALICE_XPRV/84'/1'/0'/0/*),s:pk($BOB_XPUB),s:pk($CAROL_XPUB),sdv:older(2)))" + +export BOB_DESCRIPTOR="wsh(thresh(3,pk($ALICE_XPUB),s:pk($BOB_XPRV/84'/1'/0'/0/*),s:pk($CAROL_XPUB),sdv:older(2)))" + +export CAROL_DESCRIPTOR="wsh(thresh(3,pk($ALICE_XPUB),s:pk($BOB_XPUB),s:pk($CAROL_XPRV/84'/1'/0'/0/*),sdv:older(2)))" +``` + +## Policy A. Three signatures + +### Step 1a: Create a testnet [segwit0](https://en.bitcoin.it/wiki/Segregated_Witness) receive address + +This step can be done independently by Alice, Bob, or Carol. + +```bash +bdk-cli wallet -w carol -d $CAROL_DESCRIPTOR get_new_address +{ + "address": "tb1qpqglt6yntay0se5vj3a7g36rql5pyzzp0w6jknfch2c0unwphsxs22g96e" +} +``` + +### Step 2a: Send testnet bitcoin from a faucet to receive address + +After a faucet payment is sent, use a testnet block explorer to confirm the transaction was included in a block. + +[https://mempool.space/testnet/address/tb1qpqglt6yntay0se5vj3a7g36rql5pyzzp0w6jknfch2c0unwphsxs22g96e](https://mempool.space/testnet/address/tb1qpqglt6yntay0se5vj3a7g36rql5pyzzp0w6jknfch2c0unwphsxs22g96e) + +### Step 3a: Sync participant wallets and confirm balance + +This step must be done by Alice, Bob, and Carol so their individual descriptor wallets know about the faucet transaction they will later be spending the output of. + +```bash +bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR sync +{} +bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR get_balance +{ + "satoshi": 10000 +} + +bdk-cli wallet -w bob -d $BOB_DESCRIPTOR sync +{} +bdk-cli wallet -w bob -d $BOB_DESCRIPTOR get_balance +{ + "satoshi": 10000 +} + +bdk-cli wallet -w carol -d $CAROL_DESCRIPTOR sync +{} +bdk-cli wallet -w carol -d $CAROL_DESCRIPTOR get_balance +{ + "satoshi": 10000 +} +``` + +### Step 4a: View wallet spending policies + +This can also be done by any wallet participant, as long as they have the same descriptor and extended public keys from the other particpants.. + +```bash +bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR policies +{ + "external": { + "contribution": { + "conditions": { + "0": [ + {} + ], + "3": [ + { + "csv": 2 + } + ] + }, + "items": [ + 0, + 3 + ], + "m": 3, + "n": 4, + "type": "PARTIAL" + }, + "id": "ydtnup84", + "items": [ + { + "contribution": { + "condition": {}, + "type": "COMPLETE" + }, + "fingerprint": "5adb4683", + "id": "uyxvyzqt", + "satisfaction": { + "type": "NONE" + }, + "type": "SIGNATURE" + }, + { + "contribution": { + "type": "NONE" + }, + "fingerprint": "5fdec309", + "id": "dzkmxcgu", + "satisfaction": { + "type": "NONE" + }, + "type": "SIGNATURE" + }, + { + "contribution": { + "type": "NONE" + }, + "fingerprint": "de41e56d", + "id": "ekfu5uaw", + "satisfaction": { + "type": "NONE" + }, + "type": "SIGNATURE" + }, + { + "contribution": { + "condition": { + "csv": 2 + }, + "type": "COMPLETE" + }, + "id": "8kel7sdw", + "satisfaction": { + "type": "NONE" + }, + "type": "RELATIVETIMELOCK", + "value": 2 + } + ], + "satisfaction": { + "type": "NONE" + }, + "threshold": 3, + "type": "THRESH" + }, + "internal": null +} +``` + +### Step 5a: Create spending transaction + +The transaction can also be created by Alice, Bob, or Carol, or even an untrusted coordinator that only has all three tpubs. + +Note that the argument provided to the --external_policy flag contains the id retrieved from the `policies` subcommand in the above step, in this case `ydtnup84`. + +```bash +bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR create_tx -a --to tb1qm5tfegjevj27yvvna9elym9lnzcf0zraxgl8z2:0 --external_policy "{\"ydtnup84\": [0,1,2]}" +{ + "details": { + "fees": 169, + "height": null, + "received": 0, + "sent": 10000, + "timestamp": 1614058791, + "transaction": null, + "txid": "3b9a7ac610afc91f1d1a0dd844e609376278fe7210c69b7ef663c5a8e8308f3e" + }, + "psbt": "cHNidP8BAFIBAAAAAYx7T0cL7EoUYBEU0mSL6+DS4VQafUzJgAf0Ftlbkya5AQAAAAD/////AWcmAAAAAAAAFgAU3RacollkleIxk+lz8my/mLCXiH0AAAAAAAEBKxAnAAAAAAAAIgAgCBH16JNfSPhmjJR75EdDB+gSCEF7tStNOLqw/k3BvA0BBXchA3c1Ak2kcGOzOh6eRXFKfpnpzP1lzfcXIYhxFGZG51mxrHwhA75YDXRLDLt+eX5UsE03mIGUSsQP2MrJ9lm17cGXDw2mrJN8IQIvNjaP+mwNC0DtgaB6ENB/DPPlbUDR6+NZ4Sw070jzOKyTfHZjUrJpaJNThyIGAi82No/6bA0LQO2BoHoQ0H8M8+VtQNHr41nhLDTvSPM4DO66tnIAAAAAAAAAACIGA3c1Ak2kcGOzOh6eRXFKfpnpzP1lzfcXIYhxFGZG51mxGFrbRoNUAACAAQAAgAAAAIAAAAAAAAAAACIGA75YDXRLDLt+eX5UsE03mIGUSsQP2MrJ9lm17cGXDw2mDEMxpeYAAAAAAAAAAAAA" +} + +export UNSIGNED_PSBT=$(bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR create_tx -a --to tb1qm5tfegjevj27yvvna9elym9lnzcf0zraxgl8z2:0 --external_policy "{\"ydtnup84\": [0,1,2]}" | jq -r ".psbt") +``` + +### Step 6a: Sign and finalize PSBTs + +```bash +# ALICE SIGNS +export ALICE_SIGNED_PSBT=$(bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR sign --psbt $UNSIGNED_PSBT | jq -r ".psbt") + +# BOB SIGNS +export ALICE_BOB_SIGNED_PSBT=$(bdk-cli wallet -w bob -d $BOB_DESCRIPTOR sign --psbt $ALICE_SIGNED_PSBT | jq -r ".psbt") + +# CAROL SIGNS +export FINAL_PSBT=$(bdk-cli wallet -w carol -d $CAROL_DESCRIPTOR sign --psbt $ALICE_BOB_SIGNED_PSBT | jq -r ".psbt") + +## PSBT is finalized +bdk-cli wallet -w carol -d $CAROL_DESCRIPTOR sign --psbt $ALICE_BOB_SIGNED_PSBT +{ + "is_finalized": true, + "psbt": "cHNidP8BAFIBAAAAAYx7T0cL7EoUYBEU0mSL6+DS4VQafUzJgAf0Ftlbkya5AQAAAAD/////AWcmAAAAAAAAFgAU3RacollkleIxk+lz8my/mLCXiH0AAAAAAAEBKxAnAAAAAAAAIgAgCBH16JNfSPhmjJR75EdDB+gSCEF7tStNOLqw/k3BvA0iAgIvNjaP+mwNC0DtgaB6ENB/DPPlbUDR6+NZ4Sw070jzOEcwRAIgRPXSwFLfzD1YQzw5FGYA0TgiQ+D88hSOVDbvyUZDiPUCIAbguaSGgCbBAXo5sIxpZ4c1dcGkYyrrqnDjc1jcdJ1CASICA3c1Ak2kcGOzOh6eRXFKfpnpzP1lzfcXIYhxFGZG51mxSDBFAiEA0kdkvlA+k5kUBWVUM8SkR4Ua9pnXF66ECVwIM1l0doACIF0aMiORVC35+M3GHF2Vl8Q7t455mebrr1HuLaAyxBOYASICA75YDXRLDLt+eX5UsE03mIGUSsQP2MrJ9lm17cGXDw2mRzBEAiBPJlQEnuVDHgfgOdTZNlIcRZz2iqHoMWfDmLMFqJSOQAIgCuOcTKp/VaaqwIjnYfMKO3eQ1k9pOygSWt6teT1o13QBAQV3IQN3NQJNpHBjszoenkVxSn6Z6cz9Zc33FyGIcRRmRudZsax8IQO+WA10Swy7fnl+VLBNN5iBlErED9jKyfZZte3Blw8NpqyTfCECLzY2j/psDQtA7YGgehDQfwzz5W1A0evjWeEsNO9I8zisk3x2Y1KyaWiTU4ciBgIvNjaP+mwNC0DtgaB6ENB/DPPlbUDR6+NZ4Sw070jzOBjeQeVtVAAAgAEAAIAAAACAAAAAAAAAAAAiBgN3NQJNpHBjszoenkVxSn6Z6cz9Zc33FyGIcRRmRudZsQwpbm6KAAAAAAAAAAAiBgO+WA10Swy7fnl+VLBNN5iBlErED9jKyfZZte3Blw8NpgxDMaXmAAAAAAAAAAABBwABCP1TAQUARzBEAiBE9dLAUt/MPVhDPDkUZgDROCJD4PzyFI5UNu/JRkOI9QIgBuC5pIaAJsEBejmwjGlnhzV1waRjKuuqcONzWNx0nUIBRzBEAiBPJlQEnuVDHgfgOdTZNlIcRZz2iqHoMWfDmLMFqJSOQAIgCuOcTKp/VaaqwIjnYfMKO3eQ1k9pOygSWt6teT1o13QBSDBFAiEA0kdkvlA+k5kUBWVUM8SkR4Ua9pnXF66ECVwIM1l0doACIF0aMiORVC35+M3GHF2Vl8Q7t455mebrr1HuLaAyxBOYAXchA3c1Ak2kcGOzOh6eRXFKfpnpzP1lzfcXIYhxFGZG51mxrHwhA75YDXRLDLt+eX5UsE03mIGUSsQP2MrJ9lm17cGXDw2mrJN8IQIvNjaP+mwNC0DtgaB6ENB/DPPlbUDR6+NZ4Sw070jzOKyTfHZjUrJpaJNThwAA" +``` + +### Step 7a: Broadcast finalized PSBT + +```bash +bdk-cli wallet -w carol -d $CAROL_DESCRIPTOR broadcast --psbt $FINAL_PSBT +{ + "txid": "3b9a7ac610afc91f1d1a0dd844e609376278fe7210c69b7ef663c5a8e8308f3e" +} +``` + +### Step 8a: Confirm transaction included in a testnet block + +[https://mempool.space/testnet/tx/3b9a7ac610afc91f1d1a0dd844e609376278fe7210c69b7ef663c5a8e8308f3e](https://mempool.space/testnet/tx/3b9a7ac610afc91f1d1a0dd844e609376278fe7210c69b7ef663c5a8e8308f3e) + +And new wallet balance is now zero. + +```bash +bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR sync +{} +bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR get_balance +{ + "satoshi": 0 +} +``` + +### DONE! + +## Policy B. Two signatures after a relative time lock + +Now we will use the same extended private and public keys, and the same descriptors to receive and spend testnet bitcoin using only two of our participants signatures after the transaction input's relative time-lock has expired. + +### Step 1b: Create a new testnet receive address + +The receive address can still be generated by Alice, Bob, or Carol. + +```bash +bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR get_new_address +{ + "address": "tb1q886w2zmtakwxpngs9kn7y0a7tvd6e24u58sse2sv92zrjpnenfhqtfnmw9" +} +``` + +### Step 2b: Fund new address from testnet faucet + +After the faucet payment is sent, confirm using a testnet block explorer to verify the transaction was included in a block. + +[https://mempool.space/testnet/address/tb1q886w2zmtakwxpngs9kn7y0a7tvd6e24u58sse2sv92zrjpnenfhqtfnmw9](https://mempool.space/testnet/address/tb1q886w2zmtakwxpngs9kn7y0a7tvd6e24u58sse2sv92zrjpnenfhqtfnmw9) + +### Step 3b: Sync wallet and confirm wallet balance + +This step must be done by Alice and Bob so their individual descriptor wallets know about the faucet transaction they will later be spending the output of. + +```bash +bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR sync +{} +bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR get_balance +{ + "satoshi": 10000 +} + +bdk-cli wallet -w bob -d $BOB_DESCRIPTOR sync +{} +bdk-cli wallet -w bob -d $BOB_DESCRIPTOR get_balance +{ + "satoshi": 10000 +} + +# NO CAROL SHE LOST HER KEY! +``` + +### Step 4b: Create spending transaction + +This spending transaction uses Alice and Bob's keys plus a two block relative time-lock, see above [Step 4a](#step-4a-view-wallet-spending-policies) for the policy id. The transaction can be created by Alice or Bob. + +A time based relative time-lock can be used instead of one based on blocks but is slightly more complicated to calculate. See +[BIP-68](https://github.com/bitcoin/bips/blob/master/bip-0068.mediawiki#specification) for the details. + +```bash +bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR create_tx -a --to tb1qm5tfegjevj27yvvna9elym9lnzcf0zraxgl8z2:0 --external_policy "{\"ydtnup84\": [0,1,3]}" +{ + "details": { + "fees": 169, + "height": null, + "received": 0, + "sent": 10000, + "timestamp": 1614059434, + "transaction": null, + "txid": "6a04c60dff8eeb14dc0848c663d669c34ddc30125d9564364c9414e3ff4a7d28" + }, + "psbt": "cHNidP8BAFICAAAAAYmc6mhj4Cf4pcJyBvxSbCd9IB1yDGs+plzb95t7++v0AAAAAAACAAAAAWcmAAAAAAAAFgAU3RacollkleIxk+lz8my/mLCXiH0AAAAAAAEBKxAnAAAAAAAAIgAgOfTlC2vtnGDNEC2n4j++Wxusqryh4QyqDCqEOQZ5mm4BBXchAlUVWMkNwGkCxDe4ZAcyz7HI+Vpmo4A5//OvkV33PCpprHwhAq9NOHBbPEdKr8IzYEomNTk1eokAkLQ9+ZMuS/OlX+nFrJN8IQOrU70B/wo/oUUCKFQ2cIsBxx6SysE7uVwxyu0ozM4zYqyTfHZjUrJpaJNThyIGAlUVWMkNwGkCxDe4ZAcyz7HI+Vpmo4A5//OvkV33PCppGFrbRoNUAACAAQAAgAAAAIAAAAAAAQAAACIGAq9NOHBbPEdKr8IzYEomNTk1eokAkLQ9+ZMuS/OlX+nFDEMxpeYAAAAAAQAAACIGA6tTvQH/Cj+hRQIoVDZwiwHHHpLKwTu5XDHK7SjMzjNiDO66tnIAAAAAAQAAAAAA" +} + +export UNSIGNED_PSBT2=$(bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR create_tx -a --to tb1qm5tfegjevj27yvvna9elym9lnzcf0zraxgl8z2:0 --external_policy "{\"ydtnup84\": [0,1,3]}" | jq -r ".psbt") +``` + +### Step 5b: Sign and finalize PSBTs + +```bash +# ALICE SIGNS +export ALICE_SIGNED_PSBT2=$(bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR sign --psbt $UNSIGNED_PSBT2 | jq -r ".psbt") + +# BOB SIGNS +export FINAL_PSBT2=$(bdk-cli wallet -w bob -d $BOB_DESCRIPTOR sign --psbt $ALICE_SIGNED_PSBT2 | jq -r ".psbt") + +# CAROL DOES *NOT* SIGN +``` + +### Step 6b: Broadcast finalized PSBT + +```bash +bdk-cli wallet -w bob -d $BOB_DESCRIPTOR broadcast --psbt $FINAL_PSBT2 +thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Electrum(Protocol(String("sendrawtransaction RPC error: {\"code\":-26,\"message\":\"non-BIP68-final\"}")))', src/bdk_cli.rs:168:50 + +# Oops we didn't wait long enough for the relative time lock to expire + +# Try again in ~20 mins and it is successfully broadcast + +bdk-cli wallet -w bob -d $BOB_DESCRIPTOR broadcast --psbt $FINAL_PSBT2 +{ + "txid": "6a04c60dff8eeb14dc0848c663d669c34ddc30125d9564364c9414e3ff4a7d28" +} +``` + +### Step 7b: View confirmed transaction + +[https://mempool.space/testnet/tx/6a04c60dff8eeb14dc0848c663d669c34ddc30125d9564364c9414e3ff4a7d28](https://mempool.space/testnet/tx/6a04c60dff8eeb14dc0848c663d669c34ddc30125d9564364c9414e3ff4a7d28) + +And wallet balance is again zero + +```bash +bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR sync +{} +bdk-cli wallet -w alice -d $ALICE_DESCRIPTOR get_balance +{ + "satoshi": 0 +} +``` + +### Done again! + +In this demo we showed how to receive and spend bitcoin using two different descriptor wallet policies using the `bdk` library and `bdk-cli` wallet tool. diff --git a/docs/bdk-cli/README.md b/docs/bdk-cli/README.md new file mode 100644 index 0000000000..cba8b41e75 --- /dev/null +++ b/docs/bdk-cli/README.md @@ -0,0 +1,5 @@ +# BDK-CLI + +The [bdk-cli](https://github.com/bitcoindevkit/bdk-cli) repo has an example interactive shell built +using the `bdk` library called `bdk-cli` that acts both as a reference implementation of a wallet +and a tool to quickly experiment with descriptors and transactions. diff --git a/docs/bdk-cli/compiler.md b/docs/bdk-cli/compiler.md new file mode 100644 index 0000000000..6c6c556985 --- /dev/null +++ b/docs/bdk-cli/compiler.md @@ -0,0 +1,145 @@ +# Compiler + +## Introduction + +If you want to play around with more complicated spending policies, you'll start to find it harder and harder to manually create the descriptors. This is where the miniscript compiler comes in! The `bdk` library +includes a very simple compiler that can produce a descriptor given a spending policy. The syntax used to encode the spending policy is very well described [in this page](http://bitcoin.sipa.be/miniscript/), +specifically in the "Policy to Miniscript compiler". The compiler included in BDK does basically the same job, but produces descriptors for `rust-miniscript` that have some minor differences from +the ones made by the C++ implementation used in that website. + +## Installation + +To install the miniscript compiler run the following command: + +```bash +cargo install --git https://github.com/bitcoindevkit/bdk --features="compiler" --example miniscriptc +``` + +Once the command is done, you should have a `miniscriptc` command available. You can check if that's the case by running `miniscriptc --help`. + +## Usage + +In this case the interface is very simple: it accepts two arguments called "POLICY" and "TYPE", in this order. The first one, as the name implies, sets the spending policy to compile. The latter defines the type +of address that should be used to encapsulate the produced script, like a P2SH, P2WSH, etc. + +Optionally, the `--parsed_policy` flag can be enabled and it will make the compiler print the JSON "human-readable" version of the spending policy, as described in the [`policies subcommand`](/bdk-cli/interface/#policies) of the CLI. + +The `--network` flag can be used to change the network encoding of the address shown. + +::: tip Tip +Keep in mind that since the compiler loads and interprets the descriptor, all the public keys specified in the policy must be valid public keys. This differs from the web tool linked above that also accepts +placeholders too. As described in the previous sections of this guide, the keys can be either `xpub`/`xprv` with or without metadata and a derivation path, WIF keys or raw hex public keys. +::: + +## Example + +Let's take this policy for example: + +```bash +miniscriptc --parsed_policy "and(pk(cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR),or(50@pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),older(1000)))" sh-wsh +``` + +The compiler should print something like: + +```text +[2020-04-29T10:42:05Z INFO miniscriptc] Compiling policy: and(pk(cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR),or(50@pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),older(1000))) +[2020-04-29T10:42:05Z INFO miniscriptc] ... Descriptor: sh(wsh(and_v(or_c(c:pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),v:older(1000)),c:pk(cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR)))) +[2020-04-29T10:42:05Z INFO miniscriptc] ... First address: 2MsqrJuZewY3o3ADAy1Uhi5vsBqTANjH3Cf +``` + +JSON policy: + +```json +{ + "type":"THRESH", + "items":[ + { + "type":"THRESH", + "items":[ + { + "type":"SIGNATURE", + "pubkey":"02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c", + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"NONE" + } + }, + { + "type":"RELATIVETIMELOCK", + "value":1000, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"COMPLETE", + "condition":{ + "csv":1000 + } + } + } + ], + "threshold":1, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"PARTIALCOMPLETE", + "n":2, + "m":1, + "items":[ + 1 + ], + "conditions":{ + "[1]":[ + { + "csv":1000 + } + ] + } + } + }, + { + "type":"SIGNATURE", + "pubkey":"02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c", + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"COMPLETE", + "condition":{ + + } + } + } + ], + "threshold":2, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"PARTIALCOMPLETE", + "n":2, + "m":2, + "items":[ + 0, + 1 + ], + "conditions":{ + "[0, 1]":[ + { + "csv":1000 + } + ] + } + } +} +``` + +## Troubleshooting + +#### Nothing is printed + +This might mean that you have a `RUST_LOG` variable set to a value that suppresses the compiler's log. You can try adding `miniscriptc=info` to your `RUST_LOG` value and see if that works, or open a new clean +shell. diff --git a/docs/bdk-cli/concept.md b/docs/bdk-cli/concept.md new file mode 100644 index 0000000000..a536422d10 --- /dev/null +++ b/docs/bdk-cli/concept.md @@ -0,0 +1,20 @@ +# Concept + +Now, in order to better grasp some of the design choices made by BDK, it's important to understand the main concept driving the development of this project, and the goal that it's trying to +achieve. + +BDK is aiming first of all to be a **set of libraries and tools**, all meant to be very reusable and adaptable. Developers working on their own wallets or other projects that are trying to integrate +Bitcoin can pick the tools they need and piece them together to prototype and quickly ship a working product. This means that the `bdk-cli` that we've just installed is designed to be a **very thin layer** over the +APIs exposed by the various components of the library, **not a full, end-user-ready Bitcoin wallet**. + +This concept leads to a few design choices that are arguably very bad for the "UX" of this wallet, but that allow developers to work more directly with the underlying library. For instance: + +* BDK has an internal database that's used to store data about received transactions, spendable UTXOs, etc. This database is stored by default in your home folder, in `~/.bdk-bitcoin`. The database + **will never** contain any data that can't be recreated purely by looking at the blockchain. Keys, descriptors, Electrum endpoints **are not stored in the database**. This explains why you'll have to specify them every + time in the command line. It can be seen more like a *cache* and can be safely deleted without risking funds. +* BDK doesn't automatically "monitor" the blockchain, instead there's a `sync` command that has to be called by the user. +* When you create a transaction and then sign it, it's not automatically broadcast to the network. There's a `broadcast` command that does this. Moreover, the command doesn't accept a normal Bitcoin raw transaction, + but instead a *PSBT*. That's because internally transactions are always moved as PSBTs, and again, the `broadcast` command is just a very thin wrapper over the raw library call. + +There are probably more of these examples, but hopefully by this point you'll have more or less understood the gist of it. If you are not a developer, some parts of this will feel weird, inefficient, hard +to understand, and that's absolutely normal. Just try to survive through the pain and you'll be rewarded! diff --git a/docs/bdk-cli/installation.md b/docs/bdk-cli/installation.md new file mode 100644 index 0000000000..a93ed53e49 --- /dev/null +++ b/docs/bdk-cli/installation.md @@ -0,0 +1,68 @@ +# Installation + +## Requirements + +The only requirement to run the `bdk-cli` tool is a Linux/macOS system with a fairly recent Rust +toolchain installed. Since Linux distros tend to lag behind with updates, the quickest way to +install the Rust compiler and Cargo is [rustup.rs](https://rustup.rs/). You can head there and +follow their instructions, after which you can test if everything went fine by running +`cargo version`, which should print something like: + +``` +cargo 1.53.0 (53cb7b09b 2021-06-17) +``` + +If you really don't want to pipe the output of `curl` into `sh`, you can also try using a +[Docker image](https://hub.docker.com/_/rust) and working inside of it, but that's meant for more +advanced users and won't be covered in this guide. + +::: tip Note +At the time of writing, the project requires cargo >= 1.46.0, which is our minimum supported rust version (MSRV) as of July 2021. If you have an older version installed with rustup.rs, you can upgrade it with `rustup update`. +::: + +## Installing the `bdk-cli` tool + +Once Cargo is installed, you can proceed to install the interactive `bdk-cli` tool directly from +the GitHub repository, by running: + +```bash +# all features +cargo install --git https://github.com/bitcoindevkit/bdk-cli --features=esplora,compiler + +# minimal install +cargo install --git https://github.com/bitcoindevkit/bdk-cli +``` + +This command may take a while to finish, since it will fetch and compile all the dependencies and the `bdk` library itself. + +Once it's done, you can check if everything went fine by running `bdk-cli --help` which should print something like this: + +```text +BDK CLI 0.2.1-dev +Alekos Filini :Riccardo Casatta :Steve Myers +Top level options and command modes + +USAGE: + bdk-cli [OPTIONS] + +FLAGS: + -h, --help Prints help information + -V, --version Prints version information + +OPTIONS: + -n, --network Sets the network [default: testnet] + +SUBCOMMANDS: + compile Compile a miniscript policy to an output descriptor + help Prints this message or the help of the given subcommand(s) + key Key management sub-commands + repl Enter REPL command loop mode + wallet Wallet options and sub-commands + +``` + +An example command to sync a testnet wallet to a default electrum server looks like this: + +```bash +bdk-cli wallet -w example --descriptor "wpkh(tprv8ZgxMBicQKsPexGYyaFwnAsCXCjmz2FaTm6LtesyyihjbQE3gRMfXqQBXKM43DvC1UgRVv1qom1qFxNMSqVAs88qx9PhgFnfGVUdiiDf6j4/0/*)" sync +``` diff --git a/docs/bdk-cli/interface.md b/docs/bdk-cli/interface.md new file mode 100644 index 0000000000..7d072c3d8d --- /dev/null +++ b/docs/bdk-cli/interface.md @@ -0,0 +1,525 @@ +# Interface + +Remember the `bdk-cli --help` command you ran before? Let's analyze its output here to figure out the interface: + +## Flags + +```text +FLAGS: + -h, --help Prints help information + -V, --version Prints version information +``` + +These are the optional flags that can be set with every command. The `-h` flag prints the help message, the `-V` flag only prints the version. + +### Verbosity + +If you want to increase the verbosity of the output, you should use the `RUST_LOG` environment variable. You can set it like so to see a lot more of what's going on behind the scenes, before running the `bdk-cli` +command. You only have to do this once when you open a new shell, after that you can run the `bdk-cli` command multiple times. + +```bash +export RUST_LOG="bdk=debug" +``` + +## Options + +```text +OPTIONS: + -c, --change_descriptor Sets the descriptor to use for internal addresses + -d, --descriptor Sets the descriptor to use for the external addresses + --esplora_concurrency Concurrency of requests made to the esplora server [default: 4] + -e, --esplora Use the esplora server if given as parameter + -n, --network Sets the network [default: testnet] + -p, --proxy Sets the SOCKS5 proxy for the Electrum client + -s, --server + Sets the Electrum server to use [default: ssl://electrum.blockstream.info:60002] + + -w, --wallet Selects the wallet to use [default: main] +``` + +These are the global options that can be set. They are pretty much like the flags, but they also take a value. The only **required** one is the `--descriptor` or `-d` flag, since every wallet **must have an +associated descriptor**. + +The `--change-descriptor` flag can be used to set a different descriptor for the change addresses, sometimes called "internal" addresses in Bitcoin Core. Unfortunately there isn't +[really consensus](https://freenode.irclog.whitequark.org/bitcoin-wizards/2020-01-25#26222504;) on a nice way to encode information about the change derivation inside the standard descriptor, so we are +stuck with having two separate ones. Keep in mind though, that even if you don't specify a change descriptor, you'll still be able to create transactions - the change address will simply be generated from the +standard descriptor. + +The `--network` flag can be used to change the network. Right now only `testnet` and `regtest` are supported since the code is very much not production-ready yet. + +The `--server` flag can be used to select the Electrum server to use. By default it's connecting to Blockstream's electrum servers, which seems pretty stable. +If you are having connection issues, you can also try with one of the other servers [listed here](https://1209k.com/bitcoin-eye/ele.php?chain=tbtc) and see if you have more luck with those. +Right now both plaintext and ssl servers are supported (prefix `tcp://` or no prefix at all for tcp, prefix `ssl://` for ssl). + +The `--esplora` flag can be used to connect to an Esplora instance instead of using Electrum. It should be set to the API's "base url". For public instances of Esplora this is `https://blockstream.info/api` for mainnet +and `https://blockstream.info/testnet/api` for testnet. + +The `--proxy` flag can be optionally used to specify a SOCKS5 proxy to use when connecting to the Electrum server. Spawning a local Tor daemon and using it as a proxy will allow you to connect to `.onion` Electrum +URLs. **Keep in mind that only plaintext server are supported over a proxy.** + +The `--wallet` flag can be used to select which wallet to use, if you have more than one of them. If you get a `ChecksumMismatch` error when you make some changes to your descriptor, it's because it does not +match anymore the one you've used to initialize the cache. One solution could be to switch to a new wallet name, or delete the cache directory at `~/.bdk-bitcoin` and start from scratch. + +## Subcommands + +| Command | Description | +| ------- | ----------- | +| [broadcast](#broadcast) | Broadcasts a transaction to the network. Takes either a raw transaction or a PSBT to extract | +| [bump_fee](#bump-fee) | Bumps the fees of an RBF transaction | +| [combine_psbt](#combine-psbt) | Combines multiple PSBTs into one | +| [create_tx](#create-tx) | Creates a new unsigned tranasaction | +| [extract_psbt](#extract-psbt) | Extracts a raw transaction from a PSBT | +| [finalize_psbt](#finalize-psbt) | Finalizes a psbt | +| [get_balance](#get-balance) | Returns the current wallet balance | +| [get_new_address](#get-new-address) | Generates a new external address | +| [list_transactions](#list-transactions) | Lists all the incoming and outgoing transactions of the wallet | +| [list_unspent](#list-unspent) | Lists the available spendable UTXOs | +| [policies](#policies) | Returns the available spending policies for the descriptor | +| [public_descriptor](#public-descriptor) | Returns the public version of the wallet's descriptor(s) | +| [repl](#repl) | Opens an interactive shell | +| [sign](#sign) | Signs and tries to finalize a PSBT | +| [sync](#sync) | Syncs with the chosen Electrum server | + +These are the main "functions" of the wallet. Most of them are pretty self explanatory, but we'll go over them quickly anyways. You can get more details about every single command by running `bdk-cli --help`. + +### broadcast + +```text +OPTIONS: + --psbt Sets the PSBT to extract and broadcast + --tx Sets the raw transaction to broadcast +``` + +Broadcasts a transaction. The transaction can be a raw hex transaction or a PSBT, in which case it also has to be "finalizable" (i.e. it should contain enough partial signatures to construct a finalized valid scriptsig/witness). + +### bump\_fee + +```text +FLAGS: + -a, --send_all Allows the wallet to reduce the amount of the only output in order to increase fees. This is + generally the expected behavior for transactions originally created with `send_all` + +OPTIONS: + -f, --fee_rate The new targeted fee rate in sat/vbyte + -t, --txid TXID of the transaction to update + --unspendable ... Marks an utxo as unspendable, in case more inputs are needed to cover the extra + fees + --utxos ... Selects which utxos *must* be added to the tx. Unconfirmed utxos cannot be used +``` + +Bumps the fee of a transaction made with RBF. The transaction to bump is specified using the `--txid` flag and the new fee rate with `--fee_rate`. + +The `--send_all` flag should be enabled if the original transaction was also made with `--send_all`. + +### combine\_psbt + +```text +OPTIONS: + --psbt ... Add one PSBT to comine. This option can be repeated multiple times, one for each PSBT +``` + +Combines multiple PSBTs by merging metadata and partial signatures. It can be used to merge multiple signed PSBTs into a single PSBT that contains every signature and is ready to be [finalized](#finalize-psbt). + +### create\_tx + +```text +FLAGS: + -r, --enable_rbf Enables Replace-By-Fee (BIP125) + --offline_signer Make a PSBT that can be signed by offline signers and hardware wallets. Forces the addition + of `non_witness_utxo` and more details to let the signer identify the change output + -a, --send_all Sends all the funds (or all the selected utxos). Requires only one recipients of value 0 + +OPTIONS: + --to ... Adds a recipient to the transaction + --unspendable ... Marks a utxo as unspendable + --external_policy + Selects which policy should be used to satisfy the external descriptor + + --internal_policy + Selects which policy should be used to satisfy the internal descriptor + + --utxos ... Selects which utxos *must* be spent + -f, --fee_rate Fee rate to use in sat/vbyte +``` + +Creates a new unsigned PSBT. The flags allow to set a custom fee rate (the default is 1.0 sat/vbyte) with `--fee_rate` or `-f`, the list of UTXOs that should be considered unspendable with `--unspendable` (this +option can be specified multiple times) and a list of UTXOs that must be spent with `--utxos` (again, this option can also be specified multiple times). + +The `--to` option sets the receiver address of the transaction, and should contain the address and amount in Satoshi separated by a colon, like: `--to 2NErbQPsooXRatRJdrXDm9wKR2fRiZDT9wL:50000`. This option +can also be specified multiple times to send to multiple addresses at once. + +The `--send_all` flag can be used to send the value of all the spendable UTXOs to a single address, without creating a change output. If this flag is set, there must be only one `--to` address, and its value will +be ignored (it can be set to 0). + +The `--external_policy` and `--internal_policy` options are two advanced flags that can be used to select the spending policy that the sender intends to satisfy in this transaction. They are normally not required if there's no ambiguity, but sometimes +with a complex descriptor one or both of them have to be specified, or you'll get a `SpendingPolicyRequired` error. Those flags should be set to a JSON object that maps a policy node id to the list of child indexes that +the user intends to satisfy for that node. This is probably better explained with an example: + +Let's assume our descriptor is: `sh(thresh(2,pk(A),sj:and_v(v:pk(B),n:older(6)),snj:and_v(v:pk(C),after(630000))))`. There are three conditions and we need to satisfy two of them to be able to spend. The conditions are: + +1. Sign with the key corresponding to `pk(A)` +2. Sign with the key corresponding to `pk(B)` AND wait 6 blocks +2. Sign with the key corresponding to `pk(C)` AND wait that block 630,000 is reached + +So if we write down all the possible outcomes when we combine them, we get: + +1. Sign with `pk(A)` + `pk(B)` + wait 6 blocks +2. Sign with `pk(A)` + `pk(C)` + wait block 630,000 +3. Sign with `pk(B)` + `pk(C)` + wait 6 blocks + wait block 630,000 + +In other words: + +* If we choose option #1, the final transaction will need to have the `nSequence` of its inputs set to a value greather than or equal to 6, but the `nLockTime` can stay at 0. +* If we choose option #2, the final transaction will need to have its `nLockTime` set to a value greater than or equal to 630,000, but the `nSequence` can be set to a final value. +* If we choose option #3, both the `nSequence` and `nLockTime` must be set. + +The wallet can't choose by itself which one of these combination to use, so the user has to provide this information with the `--external_policy` flag. + +Now, let's draw the condition tree to understand better how the chosen policy is represented: every node has its id shown right next to its name, like `qd3um656` for the root node. These ids can be seen by running the [policies](#policies) command. +Some ids have been omitted since they are not particularly relevant, in this example we will actually only use the root id. + +```mermaid +graph TD; + subgraph " " + R["Root - qd3um656"] --> A["pk(A) - ykfuwzkl"] + R["Root - qd3um656"] --> B["B - ms3xjley"] + B["B - ms3xjley"] --> B_0["pk(B)"] + B["B - ms3xjley"] --> B_1["older(6)"] + end + C["C - d8jph6ax"] --> C_0["pk(C)"] + C["C - d8jph6ax"] --> C_1["after(630,000)"] + R["Root - qd3um656"] --> C["C - d8jph6ax"] +``` + +Let's imagine that we are walking down from the root, and we want to use option #1. So we will have to select `pk(A)` + the whole `B` node. Since these nodes have an id, we can use it to refer to them and say which children +we want to use. In this case we want to use children #0 and #1 of the root, so our final policy will be: `--external_policy {"qd3um656":[0,1]}`. + +### extract\_psbt + +```text +OPTIONS: + --psbt Sets the PSBT to extract +``` + +Extracts the global transaction from a PSBT. **Note that partial signatures are ignored in this step. If you want to merge the partial signatures back into the global transaction first, please use [finalize_psbt](#finalize-psbt) first** + +### finalize\_psbt + +```text +OPTIONS: + --psbt Sets the PSBT to finalize + --assume_height Assume the blockchain has reached a specific height +``` + +Tries to finalize a PSBT by merging all the partial signatures and other elements back into the global transaction. This command fails if there are timelocks that have not yet expired, but the check can be overridden +by specifying `--assume_height` to make the wallet assume that a future height has already been reached. + +### get\_balance + +This subcommand has no extra flags, and simply returns the available balance in Satoshis. This command **should normally be called after [`sync`](#sync)**, since it only looks into the local cache to determine the list of UTXOs. + +### get\_new\_address + +This subcommand has no extra flags and returns a new address. It internally increments the derivation index and saves it in the database. + +### list\_transactions + +This subcommand has no extra flags and returns the history of transactions made or received by the wallet, with their txid, confirmation height and the amounts (in Satoshi) "sent" (meaning, the sum of the wallet's inputs spent in the transaction) and +"received" (meaning, the sum of the outputs received by the wallet). Just like [`get_balance`](#get-balance) it **should normally be called after [`sync`](#sync)**, since it only operates +on the internal cache. + +### list\_unspent + +This subcommand has no extra flags and returns the list of available UTXOs and their value in Satoshi. Just like [`get_balance`](#get-balance) it **should normally be called after [`sync`](#sync)**, since it only operates +on the internal cache. + +### policies + +This subcommand has no extra flags and returns the spending policies encoded by the descriptor in a more human-readable format. As an example, running the `policies` command on the descriptor shown earlier for the +in the explanation of the [create_tx](#create-tx) command, it will return this: + +```json +{ + "id":"qd3um656", + "type":"THRESH", + "items":[ + { + "id":"ykfuwzkl", + "type":"SIGNATURE", + "pubkey":"...", + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"COMPLETE", + "condition":{ + + } + } + }, + { + "id":"ms3xjley", + "type":"THRESH", + "items":[ + { + "id":"xgfnp9rt", + "type":"SIGNATURE", + "pubkey":"...", + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"COMPLETE", + "condition":{ + + } + } + }, + { + "id":"5j96ludf", + "type":"RELATIVETIMELOCK", + "value":6, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"COMPLETE", + "condition":{ + "csv":6 + } + } + } + ], + "threshold":2, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"PARTIALCOMPLETE", + "n":2, + "m":2, + "items":[ + 0, + 1 + ], + "conditions":{ + "[0, 1]":[ + { + "csv":6 + } + ] + } + } + }, + { + "id":"d8jph6ax", + "type":"THRESH", + "items":[ + { + "id":"gdl039m6", + "type":"SIGNATURE", + "pubkey":"...", + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"COMPLETE", + "condition":{ + + } + } + }, + { + "id":"xpf2twg8", + "type":"ABSOLUTETIMELOCK", + "value":630000, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"COMPLETE", + "condition":{ + "timelock":630000 + } + } + } + ], + "threshold":2, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"PARTIALCOMPLETE", + "n":2, + "m":2, + "items":[ + 0, + 1 + ], + "conditions":{ + "[0, 1]":[ + { + "timelock":630000 + } + ] + } + } + } + ], + "threshold":2, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"PARTIALCOMPLETE", + "n":3, + "m":2, + "items":[ + 0, + 1, + 2 + ], + "conditions":{ + "[0, 1]":[ + { + "csv":6 + } + ], + "[0, 2]":[ + { + "timelock":630000 + } + ], + "[1, 2]":[ + { + "csv":6, + "timelock":630000 + } + ] + } + } +} +``` + +This is a tree-like recursive structure, so it tends to get huge as more and more pieces are added, but it's in fact fairly simple. Let's analyze a simple node of the tree: + +```json +{ + "id":"qd3um656", + "type":"SIGNATURE", + "pubkey":"...", + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"COMPLETE", + "condition":{} + } +} +``` + +* `id` is a unique identifier to this specific node in the tree. +* `type`, as the name implies, represents the type of node. It defines what should be provided to satisfy that particular node. Generally some other data are provided to give meaning to + the type itself (like the `pubkey` field here in the example). There are basically two families of types: some of them can only be used as leaves, while some other can only be used as intermediate nodes. + + Possible leaf nodes are: + - `SIGNATURE`, requires a signature made with the specified key. Has a `pubkey` if it's a single key, a `fingerprint` if the key is an xpub, or a `pubkey_hash` if the full public key is not present in the descriptor. + - `SIGNATUREKEY`, requires a signature plus the raw public key. Again, it can have a `pubkey`, `fingerprint` or `pubkey_hash`. + - `SHA256PREIMAGE`, requires the preimage of a given `hash`. + - `HASH256PREIMAGE`, requires the preimage of a given `hash`. + - `RIPEMD160PREIMAGE`, requires the preimage of a given `hash`. + - `HASH160PREIMAGE`, requires the preimage of a given `hash`. + - `ABSOLUTETIMELOCK`, doesn't technically require anything to be satisfied, just waiting for the timelock to expire. Has a `value` field with the raw value of the timelock (can be both in blocks or time-based). + - `RELATIVETIMELOCK`, again only requires waiting for the timelock to expire. Has a `value` like `ABSOLUTETIMELOCK`. + + Possible non-leaf nodes are: + - `THRESH`, defines a threshold of policies that has to be met to satisfy the node. Has an `items` field, which is a list of policies to satisfy and a `threshold` field that defines the threshold. + - `MULTISIG`, Similar to `THRESH`, has a `keys` field, which is a list of keys represented again as either `pubkey`, `fingerprint` or `pubkey_hash` and a `threshold` field. + +* `satisfaction` is currently not implemented and will be used to provide PSBT introspection, like understanding whether or not a node is already satisfied and to which extent in a PSBT. +* `contribution` represents if so and how much, the provided descriptor can contribute to the node. + + The possible types are: + - `NONE`, which means that the descriptor cannot contribute. + - `COMPLETE`, which means that the descriptor by itself is enough to completely satisfy the node. It also adds a `condition` field which represent any potential extra condition that has to be met to + consider the node complete. An example are the timelock nodes, that are always complete *but* they have an extra `csv` or `timelock` condition. + - `PARTIAL`, which means that the descriptor can partially satisfy the descriptor. This adds a `m`, `n`, `items` that respectively represent the threshold, the number of available items to satisfy and the items + that the provided descriptor can satisfy. Also adds a `conditions` field which is an integer to list of conditions map. The key is the child index and the map are all the possibile extra conditions that + have to be satisfied if that node is used in the threshold. For instance, if you have a threshold of a SIGNATURE and a RELATIVETIMELOCK, in this order, the `conditions` field will be `1 ⇒ csv(x)`, + because the item at index 1 needs the extra csv condition. + - `PARTIALCOMPLETE`, which is basically a `PARTIAL` with the size of `items` >= `m`. It's treated as a separate entity to make the code a bit more clean and easier to implement. Like `PARTIAL`, it also has + a `m`, `n`, `items` fields but the `conditions field` is a bit different: it's a list of integers to list of conditions map. The key represents the combination that can be used to satisfy the threshold, + and the value contains all the possible conditions that also have to be satisfied. For instance, if you have a 2-of-2 threshold of a TIMELOCK and a RELATIVETIMELOCK, the `conditions` field will be `[0, 1] ⇒ + csv(x) + timelock(y)`, because if the combination of items 0 and 1 is picked, both of their conditions will have to be meet too. + +While the structure contains all of the intermediate nodes too, the root node is the most important one because defines how the descriptor can contribute to spend outputs sent to its addresses. + +For instance, looking at the root node of the previous example (with the internal `items` omitted) from a descriptor that has all the three private keys for keys A, B and C, we can clearly see that it can satisfy +the descriptor (type = `PARTIALCOMPLETE`) and the three options are `[0, 1] ⇒ csv(6)` (Option #1), `[0, 2] ⇒ timelock(630,000)` (Option #2) or `[1, 2] ⇒ csv(6) + timelock(630,000)` (Option #3). + +```json +{ + "type":"THRESH", + "items":[], + "threshold":2, + "satisfaction":{ + "type":"NONE" + }, + "contribution":{ + "type":"PARTIALCOMPLETE", + "n":3, + "m":2, + "items":[ + 0, + 1, + 2 + ], + "conditions":{ + "[0, 1]":[ + { + "csv":6 + } + ], + "[0, 2]":[ + { + "timelock":630000 + } + ], + "[1, 2]":[ + { + "csv":6, + "timelock":630000 + } + ] + } + } +} +``` + +### `public_descriptor` + +This subcommand has no extra flags and returns the "public" version of the wallet's descriptor(s). It can be used to bootstrap a watch-only instance for the wallet. + +### `repl` + +This subcommand has no extra flags and launches an interactive shell session. + +### `sign` + +```text +OPTIONS: + --psbt Sets the PSBT to sign + --assume_height Assume the blockchain has reached a specific height. This affects the transaction + finalization, if there are timelocks in the descriptor +``` + +Adds to the PSBT all the signatures it can produce with the secrets embedded in the descriptor (xprv or WIF keys). Returns the signed PSBT and, if there are enough item to satisfy the script, also the extracted raw +Bitcoin transaction. + +Optionally, the `assume_height` option can be specified to let the wallet assume the blockchain has reached a specific height. This affects the finalization of the PSBT which is done right at the end of the signing +process: the wallet tries to satisfy the spending condition of each input using the partial signatures collected. In case timelocks are present the wallet needs to know whether or not they have expired. This flag +is particularly useful for offline wallets. + +### `sync` + +This subcommand has no extra flags. It connects to the chosen Electrum server and synchronizes the list of transactions received and available UTXOs. diff --git a/docs/bdk-cli/playground.md b/docs/bdk-cli/playground.md new file mode 100644 index 0000000000..0c40014ffc --- /dev/null +++ b/docs/bdk-cli/playground.md @@ -0,0 +1,3 @@ +# Playground + + diff --git a/docs/bdk-cli/regtest.md b/docs/bdk-cli/regtest.md new file mode 100644 index 0000000000..ed2cc1c9d3 --- /dev/null +++ b/docs/bdk-cli/regtest.md @@ -0,0 +1,46 @@ +# Regtest + +Running the `bdk-cli` tool in regtest requires having a local Electrum server set-up. There are two main implementations, [`electrs`](https://github.com/romanz/electrs) in Rust and [`ElectrumX`](https://github.com/spesmilo/electrumx) in Python. Since the Rust toolchain is already required to +use BDK, this page will focus mostly on the former. + +Electrs can be installed by running: + +```bash +cargo install --git https://github.com/romanz/electrs --bin electrs +``` + +Just like before, this command will probably take a while to finish. + +Once it's done, assuming you have a regtest bitcoind running in background, you can launch a new terminal and run the following command to actually start electrs: + +```bash +electrs -vv --timestamp --db-dir /tmp/electrs-db --electrum-rpc-addr="127.0.0.1:50001" --network=regtest --cookie-file=$HOME/.bitcoin/regtest/.cookie +``` + +on macOS you should change the cookie-file to `$HOME/Library/Application Support/Bitcoin/regtest/.cookie`. + +This will start the Electrum server on port 50001. You can then add the `-n regtest -s 127.0.0.1:50001` to the `bdk-cli` commands to switch to the local regtest. + +## Troubleshooting + +#### Stuck with "*wait until bitcoind is synced (i.e. initialblockdownload = false)*" + +Just generate a few blocks with `bitcoin-cli generatetoaddress 1
` + +## Bonus: Docker + +If you have already installed Docker on your machine, you can also use 🍣 [Nigiri CLI](https://github.com/vulpemventures/nigiri) to spin-up a complete development environment in `regtest` that includes a `bitcoin` node, an `electrs` explorer and the [`esplora`](https://github.com/blockstream/esplora) web-app to visualize blocks and transactions in the browser. + +Install 🍣 Nigiri +```bash +$ curl https://getnigiri.vulpem.com | bash +``` + +Start Docker daemon and run Nigiri box +``` +$ nigiri start +``` + +This will start electrum RPC interface on port `51401`, the REST interface on `3000` and the esplora UI on `5000` (You can visit with the browser and look for blocks, addresses and transactions) + +You can then add the `-n regtest -s 127.0.0.1:51401` to the `bdk-cli` commands to switch to the local regtest. diff --git a/docs/descriptors/README.md b/docs/descriptors/README.md new file mode 100644 index 0000000000..9cd39f6bda --- /dev/null +++ b/docs/descriptors/README.md @@ -0,0 +1,115 @@ +# Descriptors + +Descriptors are a compact and semi-standard way to easily encode, or "describe", how scripts (and subsequently, addresses) of a wallet should be generated. They can be especially helpful when working with multisigs or even +more complex scripts, where the structure of the script itself is not trivial. They are a big step forward in making wallets more portable across different tools and apps, because for the first time they create a common +language to describe a full bitcoin script that developers can use and integrate in their software. + +The ecosystem around descriptors is still very much in its early stage, but they are starting to see some adoption in [Bitcoin Core](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md) and other projects. BDK +aims to produce the first "Native Descriptor" Bitcoin library that can be used by developers to build their own ["Native Descriptor Wallets"](https://www.youtube.com/watch?v=xC25NzIjzog). + +### Compatibility Matrix + +Below are some tables to highlight the differences between Bitcoin Core's descriptor support, rust-miniscript's one and BDK's. + +#### Key Types + +
+ +| Key Type | BDK | rust-miniscript | Bitcoin Core | +| -------- | --------------- | --------------- | ------------ | +| Hex PublicKey | ✓ | ✓ | ✓ | +| WIF PrivateKey | ✓ | ✗ | ✓ | +| Extended Keys (xpub/xprv) | ✓ | ✗ | ✓ | + +
+ +#### Script Types (top level) + +
+ +| Script Type | BDK | rust-miniscript | Bitcoin Core | +| -------- | --------------- | --------------- | ------------ | +| `pk()` | ✓ | ✓ | ✓ | +| `pkh()` | ✓ | ✓ | ✓ | +| `wpkh()` | ✓ | ✓ | ✓ | +| `sh(wpkh())` | ✓ | ✓ | ✓ | +| `sh()` | ✓ | ✓ | ✓ | +| `wsh()` | ✓ | ✓ | ✓ | +| `sh(wsh())` | ✓ | ✓ | ✓ | +| `combo()` | ✗ | ✗ | ✓ | +| `addr()` | ✗ | ✗ | ✓ | +| `raw()` | ✗ | ✗ | ✓ | +| Bare scripts | ✓ | ✓ | ✗ | + +
+ +#### Operators + +
+ +| Operator | BDK | rust-miniscript | Bitcoin Core | +| -------- | --------------- | --------------- | ------------ | +| `pk()` | ✓ | ✓ | ✓ | +| `pk_h()` | ✓ | ✓ | ✓ - as `pkh()` | +| `older()` | ✓ | ✓ | ✗ | +| `after()` | ✓ | ✓ | ✗ | +| `sha256()` | ✓ | ✓ | ✗ | +| `hash256()` | ✓ | ✓ | ✗ | +| `ripemd160()` | ✓ | ✓ | ✗ | +| `hash160()` | ✓ | ✓ | ✗ | +| `andor()` | ✓ | ✓ | ✗ | +| `and_{v,b,n}()` | ✓ | ✓ | ✗ | +| `or_{b,c,d,i}()` | ✓ | ✓ | ✗ | +| `multi()` | ✓ | ✓ | ✓ | +| `thresh()` | ✓ | ✓ | ✗ | +| `sortedmulti()` | ✓ | ✓ | ✓ | + +
+ +#### Modifiers + +
+ +| Script Type | BDK | rust-miniscript | Bitcoin Core | +| -------- | --------------- | --------------- | ------------ | +| `a:` | ✓ | ✓ | ✗ | +| `s:` | ✓ | ✓ | ✗ | +| `c:` | ✓ | ✓ | ✗ | +| `t:` | ✓ | ✓ | ✗ | +| `d:` | ✓ | ✓ | ✗ | +| `v:` | ✓ | ✓ | ✗ | +| `j:` | ✓ | ✓ | ✗ | +| `n:` | ✓ | ✓ | ✗ | +| `l:` | ✓ | ✓ | ✗ | +| `u:` | ✓ | ✓ | ✗ | + +
+ +For a more thorough description of these operators and modifiers see [Sipa's Miniscript Page](http://bitcoin.sipa.be/miniscript/) and [Bitcoin Core's](https://github.com/bitcoin/bitcoin/blob/master/doc/descriptors.md). + +### Examples + +Some examples of valid BDK descriptors are: + +
+ +| Spending Policy | Descriptor | Address 0 | Address 1 | +| --------------- | ---------- | --------- | --------- | +| Static P2PKH | `pkh(cSQPHDBwXGjVzWRqAHm6zfvQhaTuj1f2bFH58h55ghbjtFwvmeXR)` | mrkwtj5xpYQjHeJe5wsweNjVeTKkvR5fCr | mrkwtj5xpYQjHeJe5wsweNjVeTKkvR5fCr | +| Static P2PKH, watch-only | `pkh(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)` | mrkwtj5xpYQjHeJe5wsweNjVeTKkvR5fCr | mrkwtj5xpYQjHeJe5wsweNjVeTKkvR5fCr | +| P2WSH 2-of-2 with one private key | `wsh(multi(2,tprv8ZgxMBicQKsPePmENhT9N9yiSfTtDoC1f39P7nNmgEyCB6Nm4Qiv1muq4CykB9jtnQg2VitBrWh8PJU8LHzoGMHTrS2VKBSgAz7Ssjf9S3P/0/*,tpubDBYDcH8P2PedrEN3HxWYJJJMZEdgnrqMsjeKpPNzwe7jmGwk5M3HRdSf5vudAXwrJPfUsfvUPFooKWmz79Lh111U51RNotagXiGNeJe3i6t/1/*))` | tb1qqsat6c82fvdy73rfzye8f7nwxcz3xny7t56azl73g95mt3tmzvgs9a8vjs | tb1q7sgx6gscgtau57jduend6a8l445ahpk3dt3u5zu58rx5qm27lhkqgfdjdr | +| P2WSH-P2SH one key + 10 days timelock | `sh(wsh(and_v(vc:pk_h(tprv8ZgxMBicQKsPePmENhT9N9yiSfTtDoC1f39P7nNmgEyCB6Nm4Qiv1muq4CykB9jtnQg2VitBrWh8PJU8LHzoGMHTrS2VKBSgAz7Ssjf9S3P/0/*),older(1440))))` | 2Mtk2nyS98MCi2P7TkoBGLaJviBy956XxB1 | 2MuEStKzYhqb5HCFgHz9153tZsL5sVqV5xC | + +
+ +### Implementation Details + +BDK extends the capabilities of [rust-miniscript](https://github.com/apoelstra/rust-miniscript) by introducing the concept of an *ExtendedDescriptor*: it represents a descriptor that contains one or more "derivable keys" like `xpubs` or `xprvs` +and can be "derived" to a normal Descriptor by deriving every single one of its keys. It is currently called "StringDescriptor" in the code, because it's implemented as a wrapped `miniscript::Descriptor`. + +ExtendedDescriptors are derived using a single index instead of a full derivation path: this is because normally most of the path is fixed and can be represented right after the xpub/xprv itself, and only the +final index changes for each address. This is what's normally called a *DescriptorExtendedKey* in codebase, and it's the represented with a similar syntax to Bitcoin Core's, such as: + +``` +[d34db33f/44'/0'/0']xpub6ERApfZwUNrhL.......rBGRjaDMzQLcgJvLJuZZvRcEL/0/* +``` diff --git a/docs/getting-started.md b/docs/getting-started.md new file mode 100644 index 0000000000..627603fc50 --- /dev/null +++ b/docs/getting-started.md @@ -0,0 +1,31 @@ +# Bitcoin Dev Kit + +The [Bitcoin Dev Kit (BDK)](https://github.com/bitcoindevkit) project (originally called Magical Bitcoin 🧙) aims to build a collection of tools and libraries that are designed to be a solid foundation for cross platform Bitcoin wallets, along with a fully working *reference implementation* wallet called Magical Bitcoin. +All BDK components are designed to be lightweight and modular so that they can be adapted for virtually any use-case: from single-sig mobile wallets to multi-billion-dollar cold storage vaults. + +The main long-term goal is to concentrate the development efforts of multiple people and companies into one open source and very well reviewed project, instead of dispersing them over multiple closed/semi-closed or +poorly designed projects. + +While some parts of the library are still considered "experimental" (check the docs for more info), the core `Wallet` architecture is now considered stable. We still can't commit to keeping this same exact API forever, +but we are not expecting to do any major breaking change in that area. + +If you want to try out the library for your projects, now it's finally a good time to do it! You can start by checking out the ["getting started"](/blog/tags/getting%20started/) section in our blog or joining our [Discord](https://discord.gg/dstn4dQ) +server to chat with us. + +## Playground + +As a way of demonstrating the flexibly of this project, a minimalistic command line tool (called `bdk-cli`) is available as a debugging tool in the [`bdk-cli`](https://github.com/bitcoindevkit/bdk-cli) +repo. It has been compiled to WebAssembly and can be used directly from the browser. See the [playground](/bdk-cli/playground) section to give it a try! + +The playground relies on [Esplora](https://blockstream.info) to monitor the blockchain and is currently locked in testnet-only mode, for obvious safety reasons. The native command line tool can also be used in regtest mode when installed on +a computer. See the [bdk-cli](/bdk-cli) section to learn more. + +## Descriptors + +One of the original milestones of this project was to provide wallets with "almost magically" support for very complex spending policies, without having to individually translate them into code. It may sound disappointing, but there isn't, in fact, +any real magic in this wallet: the generalization is achieved thanks to *descriptors*, that are now slowly starting to see adoption in a few other Bitcoin projects as well. + +The author of this project strongly believes descriptors will be a big part of the future generation of Bitcoin wallets, since they provide a very flexible scripting language that can also be extended as the +technology and tooling of Bitcoin evolves and changes (Schnorr signatures, Taproot, etc). + +To learn more, check out the specific [Descriptors section](/descriptors). diff --git a/docs/supporters/README.md b/docs/supporters/README.md new file mode 100644 index 0000000000..b4f92bb41b --- /dev/null +++ b/docs/supporters/README.md @@ -0,0 +1,32 @@ +# Supporters + +The Bitcoin Dev Kit project is proudly supported by: + + diff --git a/docs/tutorials/hello-world.md b/docs/tutorials/hello-world.md new file mode 100644 index 0000000000..0b9146c371 --- /dev/null +++ b/docs/tutorials/hello-world.md @@ -0,0 +1,200 @@ +# Hello World + +## Introduction + +This article should serve as a "getting started" guide for developers who are considering integrating BDK in their projects: it tries to introduce the reader to the basic concepts behind the library and some of its +modules and components that can be used to build a very simple functioning Bitcoin wallet. All the information written in this article are valid for the current `master` git branch, and should remain valid for the upcoming [`v0.2.0` release](https://github.com/bitcoindevkit/bdk/projects/1) +which is planned to be tagged pretty soon. + +## Design Goals + +The main goal of the library is to be a solid foundation for Bitcoin wallets of any kind, on any platform: in practice, this means that the library should be: + +- Very *well-reviewed* and tested +- *Lightweight*, so that it can be used easily on mobile devices as well +- *Extendable*, so that it can be adapted to perfectly suit different use-cases +- *Generalized*, meaning that it supports different types of Bitcoin scripts and wallets through the use of [descriptors][descriptor] +- *Reasonably easy* to use, exposing a "high level" interface to the user and hiding all the complexity inside + +These goals have a direct impact on the design of the internal components of the library, and as a consequence on the APIs that are exposed to the final user, which might in some cases feel counter-intuitive at first. +Throughout the article, I will try to focus on those points and try to explain them as best as I can. + +## The `Wallet` Structure + +The [`Wallet`][wallet] structure is in many ways the heart of the library: it represents an instance of a wallet and exposes some APIs to perform all the typical operations one might want to do with a Bitcoin wallet, +such as generating a new address, listing the transactions received, creating a transaction, etc. + +A `Wallet` instance can be constructed given at least one [descriptor] which would be used to derive both [`External`][KeychainKind] and [`Internal`][KeychainKind] addresses, or two if one prefers to keep them separated. `External` addresses are the +ones returned by an explicit [`Wallet::get_new_address()`][get_new_address] call, while `Internal` addresses are generated internally to receive the change whenever a new transaction is created. + +A `Wallet` also needs at least one other component to function properly, its [`Database`][Database]: it will be used as a *cache* to store the list of transactions synchronized with the blockchain, the UTXOs, the addresses generated, and a few other things. It's important +to note that the `Database` will never store any secret. Securely storing keys is explicitly left to the user of the library to implement, mainly because there isn't really one good way to do it, that would work reliably on every platform. On +mobile devices, for instance, the OS' keychain could be used, to allow unlocking the secrets with the use of biometric data (FaceID or fingerprint), while on desktop platform there isn't generally a similar +framework available and the user would have to implement something that meets their needs. It's not excluded that in the future we could provide a "reference implementation" of secure multi-platform storage for keys, +but that would very likely be released as a separate module outside of the `Wallet` structure, or potentially even as a separate library that could be reused for other applications as well. + +Going back to our `Wallet`: given a descriptor and a `Database` we can build an "air-gapped", or "Offline" wallet: basically, a wallet that physically can't to connect to the Bitcoin network. It will still be able to generate addresses and +sign [PSBTs][PSBT], but with a greatly reduced attack surface because a sizable part of the code that handles the logic to synchronize with the network would be entirely omitted in the final executable binary. + +This is how an `OfflineWallet` can be created. Notice that we are using [`MemoryDatabase`][MemoryDatabase] as our `Database`. We'll get to that in a second. + +```rust +use bdk::{Wallet, OfflineWallet}; +use bdk::database::MemoryDatabase; +use bdk::bitcoin::Network; + +fn main() -> Result<(), Box> { + let external_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/0/*)"; + let internal_descriptor = "wpkh(tprv8ZgxMBicQKsPdy6LMhUtFHAgpocR8GC6QmwMSFpZs7h6Eziw3SpThFfczTDh5rW2krkqffa11UpX3XkeTTB2FvzZKWXqPY54Y6Rq4AQ5R8L/84'/0'/0'/1/*)"; + + let wallet: OfflineWallet<_> = Wallet::new_offline( + external_descriptor, + Some(internal_descriptor), + Network::Testnet, + MemoryDatabase::new(), + )?; + + Ok(()) +} +``` + +Once we have our `Wallet` instance we can generate a new address and print it out: + +```rust +// ... + +println!("Generated Address: {}", wallet.get_new_address()?); +``` + +Building and running this code will print out: + +```text +Generated Address: tb1q7w0t936xp5p994qx506xj53gjdcmzjr2mkqghn +``` + +Before we've talked about the benefits of an air-gapped wallet, but we should also talk about the disadvantages: the biggest one is the fact that it cannot create new transactions because +it doesn't know which UTXOs belong to the wallet. To get this information we generally need to `sync` with the network, but this wallet can't physically do that. + +To fix this we can add one more component to our `Wallet`: a [`Blockchain`][Blockchain] backend. In particular, we are going to use the [`ElectrumBlockchain`][ElectrumBlockchain] which syncs with an `Electrum` server, +since that's available out of the box in BDK and is pretty fast. + +We can change our `Wallet` construction to look something like this: + +```rust +use bdk::blockchain::ElectrumBlockchain; +use bdk::electrum_client::Client; + +// ... + +let wallet = Wallet::new( + external_descriptor, + Some(internal_descriptor), + Network::Testnet, + MemoryDatabase::new(), + ElectrumBlockchain::from(Client::new("ssl://electrum.blockstream.info:60002").unwrap()), +)?; +``` + +This piece of code is very similar to the one we wrote before, but this time we are using the [`Wallet::new()`][Wallet_new] constructor instead of [`Wallet::new_offline()`][Wallet_new_offline], and this takes an extra argument for the `Blockchain` type to use. +Specifically here, we create an `ElectrumBlockchain` and connect to Blockstream's public Electrum Testnet servers over SSL. + +Now, since we are running in the `Testnet` network, we can try to get some funds from a faucet online to this address we've generated. Once we have an incoming transaction we can do the first `sync` of our *online* wallet. +this is again something that might seem counterintuitive at first: why do we have to manually ask the `Wallet` to *sync* itself? Can't it do it periodically in background? The answer is that yes, that would definitely be possible, +but it would remove some control on what's happening inside the wallet from the user. This can be especially problematic on mobile platforms, where the OS tries very aggressively to suspend apps in background to save +battery. Having a thread running and trying to make network requests while the app is in background would very likely cause errors or potentially crashes somewhere. So for this reason this operation has to be performed manually, +to allow the user to call that function only at the right time. + +```rust +use bdk::blockchain::noop_progress; + +// ... + +wallet.sync(noop_progress(), None)?; +``` + +In this case, we are not interested in receiving updates about the progress, and we just want to use the default settings, so we use [`noop_progress()`][noop_progress] and `None` as arguments. This will make queries to the Electrum server +and store the list of transactions and UTXOs in our `Database`. In this case, we are using a `MemoryDatabase`, so those data are only going to be kept in RAM and dropped once our `Wallet` is dropped. This is very useful +for playing around and experimenting, but not so great for real-world wallets: for that, you can use [sled][sled] which is supported out of the box, or even use a custom database. More on that later! + +So now that we've synced with the blockchain we can create our first transaction. First of all, we will print out the balance of our wallet to make sure that our wallet has seen the incoming transaction. Then we +will create the actual transaction and we will specify some flags using the [`TxBuilder`][TxBuilder]. To finish it off, we will ask the wallet to sign the transaction and then broadcast it to the network. + +Right now we will not get into details of all the available options in `TxBuilder` since that is definitely out of the scope of a "getting started" guide. For now, you can just imagine the builder as your way to tell the library +how to build transactions. We'll come back to this in a future article. + +```rust +use std::str::FromStr; + +use bdk::bitcoin::Address; +use bdk::TxBuilder; + +// ... + +let balance = wallet.get_balance()?; +println!("Wallet balance in SAT: {}", balance); + +let faucet_address = Address::from_str("mkHS9ne12qx9pS9VojpwU5xtRd4T7X7ZUt")?; +let (unsigned_psbt, tx_details) = wallet.create_tx( + TxBuilder::with_recipients(vec![(faucet_address.script_pubkey(), balance / 2)]) + .enable_rbf(), +)?; +println!("Transaction details: {:#?}", tx_details); +``` + +In this case, we are sending back half the balance to the faucet's address and we are also enabling RBF since the default fees are at 1 satoshi/vbyte. With RBF we will be able to *bump the fees* of the transaction, should it get +stuck in the mempool due to the low fee rate. + +All that's left to do once we have our unsigned PSBT is to sign it: + +```rust +// ... + +let (signed_psbt, tx_finalized) = wallet.sign(unsigned_psbt, None)?; +assert!(tx_finalized, "Tx has not been finalized"); +``` + +And then broadcast it: + +```rust +// ... + +let raw_transaction = signed_psbt.extract_tx(); +let txid = wallet.broadcast(raw_transaction)?; +println!( + "Transaction sent! TXID: {txid}.\nExplorer URL: https://blockstream.info/testnet/tx/{txid}", + txid = txid +); +``` + +## Custom Database and Blockchain types + +We briefly mentioned before that for our example we used the `MemoryDatabase`, but that it could also be swapped for a different one: this is one example of the *modularity* of BDK. By default, some database +types are implemented in the library, namely (as of now) the `MemoryDatabase` which only keeps data in RAM and the [sled][sled] database that can store data on a filesystem. But since the `Database` trait is public, +users of the library can also implement different database types more suitable for their use-case. + +The same is true for the `Blockchain` types: the library provides (through the use of opt-in features) implementations for the `Electrum`, `Esplora` and `CompactFilters` (*Neutrino*) backends. Those again can also be +swapped with custom types if the user desires to do so. + +## Conclusion + +Hopefully, this article will help you get started with BDK! This is just a very quick and gentle introduction to the library, and only barely scratches the surface of what's inside: we will keep publishing more +articles in the future to explain some of the more advanced features of BDK, like key generation, using complex [descriptors][descriptor] with multiple keys and/or timelocks, using external signers, etc. + +If you'd like to learn more about the library feel free to ask any questions in the comment section down below, or join our [Discord Community](https://discord.gg/d7NkDKm) to chat with us directly! + + +[descriptor]: /descriptors +[PSBT]: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki +[sled]: https://docs.rs/sled/ + +[Wallet]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html +[KeychainKind]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.KeychainKind.html +[get_new_address]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html#method.get_new_address +[Database]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.Database.html +[MemoryDatabase]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/struct.MemoryDatabase.html +[Blockchain]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.Blockchain.html +[ElectrumBlockchain]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/struct.ElectrumBlockchain.html +[Wallet_new]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html#method.new +[Wallet_new_offline]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html#method.new_offline +[noop_progress]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.noop_progress.html +[TxBuilder]: /docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.TxBuilder.html diff --git a/layouts/authors/list.html b/layouts/authors/list.html deleted file mode 100644 index 54fe9ccdd4..0000000000 --- a/layouts/authors/list.html +++ /dev/null @@ -1,53 +0,0 @@ -{{ partial "header.html" . }} - -

{{ .Params.name }}

- -{{ with .Params.photo }} - -{{ end }} - -{{ with .Content }} -

Bio

-{{ .Content }} -{{ end }} - -

Links

-{{ with .Params.twitter }} - - -

Articles

- - -{{ partial "footer.html" . }} \ No newline at end of file diff --git a/layouts/authors/terms.html b/layouts/authors/terms.html deleted file mode 100644 index 4d10c2263a..0000000000 --- a/layouts/authors/terms.html +++ /dev/null @@ -1,9 +0,0 @@ -{{ partial "header.html" . }} - - - -{{ partial "footer.html" . }} \ No newline at end of file diff --git a/layouts/blog/list.html b/layouts/blog/list.html deleted file mode 100644 index 128b9e98d2..0000000000 --- a/layouts/blog/list.html +++ /dev/null @@ -1,36 +0,0 @@ -{{ partial "header.html" . }} - -{{ if eq .Kind "section" }} - {{ .Content }} -{{end}} - -{{ range (where .Site.Pages "Type" "blog").GroupByDate "2006" }} -

Posts in {{ .Key }}

- - {{ range where .Pages ".Kind" "!=" "section" }} -

{{ .Date.Format "Jan 2" }}

- {{ if isset .Params "tags" }} - - {{ end }} - {{ end }} -{{ end }} - -{{ partial "footer.html" . }} diff --git a/layouts/partials/custom-comments.html b/layouts/partials/custom-comments.html deleted file mode 100644 index defeba7f4b..0000000000 --- a/layouts/partials/custom-comments.html +++ /dev/null @@ -1,12 +0,0 @@ -{{ if and (eq .Type "blog") (ne .Kind "section" ) }} - - - -{{ end }} diff --git a/layouts/partials/custom-footer.html b/layouts/partials/custom-footer.html deleted file mode 100644 index 15a980ea92..0000000000 --- a/layouts/partials/custom-footer.html +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/layouts/partials/favicon.html b/layouts/partials/favicon.html deleted file mode 100644 index 1eccb39c15..0000000000 --- a/layouts/partials/favicon.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/layouts/partials/header.html b/layouts/partials/header.html deleted file mode 100644 index d4d33919c4..0000000000 --- a/layouts/partials/header.html +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - {{ hugo.Generator }} - {{ partial "meta.html" . }} - {{ partial "favicon.html" . }} - {{ .Title }} {{ default "::" .Site.Params.titleSeparator }} {{ .Site.Title }} - - {{ $assetBusting := not .Site.Params.disableAssetsBusting }} - - - - - - - - - - {{with .Site.Params.themeVariant}} - - {{end}} - {{ range .Site.Params.custom_css -}} - - {{- end }} - - {{ template "_internal/opengraph.html" . }} - {{ template "_internal/twitter_cards.html" . }} - - - - - {{ partial "custom-header.html" . }} - - - {{ partial "menu.html" . }} -
-
-
- {{if not .IsHome}} -
-
- {{ if and (or .IsPage .IsSection) .Site.Params.editURL }} - {{ $File := .File }} - {{ $Site := .Site }} - {{with $File.Path }} - - {{ end }} - {{ end }} - {{$toc := (and (not .Params.disableToc) (not .Params.chapter))}} - - {{ if $toc }} - {{ partial "toc.html" . }} - {{ end }} -
-
- {{ end }} -
- {{ partial "tags.html" . }} -
- {{ if .Params.chapter }} -
- {{ end }} -
- {{if and (not .IsHome) (not .Params.chapter) }} - {{ if (eq .Type "blog") }} -

{{ .Title }}

- {{ if isset .Params "authors" }} - By - {{- range $index, $author := .Params.authors }} - {{- with $.Site.GetPage "taxonomyTerm" (printf "authors/%s" (urlize .)) -}} - {{- if gt $index 0 -}} - , - {{- end -}} - {{ .Params.name }} - {{- end -}} - {{ end }} - {{ end }} - {{ else }} -

- {{ if or (eq .Kind "taxonomy") (eq .Kind "term") }} - {{.Data.Singular}} :: - {{ end }} - {{.Title}} -

- {{ end }} - {{end}} - - {{define "breadcrumb"}} - {{$parent := .page.Parent }} - {{ if $parent }} - {{ $value := (printf "%s > %s" $parent.RelPermalink $parent.Title .value) }} - {{ template "breadcrumb" dict "page" $parent "value" $value }} - {{else}} - {{.value|safeHTML}} - {{end}} - {{end}} diff --git a/layouts/partials/logo.html b/layouts/partials/logo.html deleted file mode 100644 index 069ca1ce10..0000000000 --- a/layouts/partials/logo.html +++ /dev/null @@ -1,3 +0,0 @@ - diff --git a/layouts/partials/menu-footer.html b/layouts/partials/menu-footer.html deleted file mode 100644 index fff01b7cc9..0000000000 --- a/layouts/partials/menu-footer.html +++ /dev/null @@ -1,10 +0,0 @@ - - -
- - Watch - Star - Fork -
- -
Built with Hugo
diff --git a/layouts/partials/menu.html b/layouts/partials/menu.html deleted file mode 100644 index d43a1763f3..0000000000 --- a/layouts/partials/menu.html +++ /dev/null @@ -1,163 +0,0 @@ - - - - - - -{{ define "section-tree-nav" }} -{{ $showvisitedlinks := .showvisitedlinks }} -{{ $currentNode := .currentnode }} -{{ $currentFileUniqueID := "" }} -{{ with $currentNode.File }}{{ $currentFileUniqueID = .UniqueID }}{{ end }} - {{with .sect}} - {{if and .IsSection (or (not .Params.hidden) $.showhidden)}} - {{safeHTML .Params.head}} -
  • - - {{safeHTML .Params.Pre}}{{or .Params.menuTitle .LinkTitle .Title}}{{safeHTML .Params.Post}} - {{ if $showvisitedlinks}} - - {{ end }} - - {{ $numberOfPages := (add (len ( where .Pages "Params.hidden" "ne" true )) (len ( where .Sections "Params.hidden" "ne" true ))) }} - {{ if ne $numberOfPages 0 }} -
      - {{ $currentNode.Scratch.Set "pages" .Pages }} - {{ if .Sections}} - {{ $currentNode.Scratch.Set "pages" (.Pages | union .Sections) }} - {{end}} - {{ $pages := ($currentNode.Scratch.Get "pages") }} - - {{if eq .Site.Params.ordersectionsby "title"}} - {{ range $pages.ByTitle }} - {{ if and .Params.hidden (not $.showhidden) }} - {{else}} - {{ template "section-tree-nav" dict "sect" . "currentnode" $currentNode "showvisitedlinks" $showvisitedlinks }} - {{end}} - {{ end }} - {{else}} - {{ range $pages.ByWeight }} - {{ if and .Params.hidden (not $.showhidden) }} - {{else}} - {{ template "section-tree-nav" dict "sect" . "currentnode" $currentNode "showvisitedlinks" $showvisitedlinks }} - {{end}} - {{ end }} - {{end}} -
    - {{ end }} -
  • - {{else}} - {{ if not .Params.Hidden }} -
  • - - {{safeHTML .Params.Pre}}{{or .Params.menuTitle .LinkTitle .Title}}{{safeHTML .Params.Post}} - {{ if $showvisitedlinks}}{{end}} - -
  • - {{ end }} - {{end}} - {{ end }} -{{ end }} diff --git a/layouts/partials/tags.html b/layouts/partials/tags.html deleted file mode 100644 index 75bb3a4667..0000000000 --- a/layouts/partials/tags.html +++ /dev/null @@ -1,9 +0,0 @@ - - -{{ if .Params.tags }} -
    -{{range .Params.tags}} - {{ . }} -{{end}} -
    -{{end}} diff --git a/layouts/shortcodes/json.html b/layouts/shortcodes/json.html deleted file mode 100644 index 62d3bdb167..0000000000 --- a/layouts/shortcodes/json.html +++ /dev/null @@ -1,2 +0,0 @@ -{{ $_hugo_config := `{ "version": 1 }` }} -
    diff --git a/layouts/shortcodes/playground.html b/layouts/shortcodes/playground.html deleted file mode 100644 index 41f5d6091c..0000000000 --- a/layouts/shortcodes/playground.html +++ /dev/null @@ -1,131 +0,0 @@ - - -
    -
    - -

    Policy Compiler

    -
    -
    -
    - -
    -
    -
    - - -
    -
    - - Map every alias to an existing key or generate a new one. You can also specify known keys directly in the visual editor or the policy input field. -
    -
    - - - -
    
    -        
    -
    -
    - -
    -
    - -

    Wallet

    -
    -
    -
    -
    - - -
    -
    - - -
    - -
    - - - -
    -
    - -
    
    -
    -        
    - > - -
    -
    -
    - - - - diff --git a/layouts/shortcodes/sponsors.html b/layouts/shortcodes/sponsors.html deleted file mode 100644 index 72cfd59e9c..0000000000 --- a/layouts/shortcodes/sponsors.html +++ /dev/null @@ -1,27 +0,0 @@ -{{ $_hugo_config := `{ "version": 1 }` }} - diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000000..de598fded7 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,29985 @@ +{ + "name": "bitcoindevkit.org", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "bitcoindevkit.org", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "broken-link-checker": "0.7.8", + "serve": "12.0.1", + "squarecrypto-vuepress-devkit-theme": "0.1.10", + "start-server-and-test": "1.14.0", + "vuepress": "1.8.2" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.5.tgz", + "integrity": "sha512-kixrYn4JwfAVPa0f2yfzc2AWti6WRRyO3XjWW5PJAvtE11qhSayrrcrEnee05KAtNaPC+EwehE8Qt1UedEVB8w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.6.tgz", + "integrity": "sha512-gJnOEWSqTk96qG5BoIrl5bVtc23DCycmIePPYnamY9RboYdI4nFy5vAQMSl81O5K/W0sLDWfGysnOECC+KUUCA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.14.5", + "@babel/helper-compilation-targets": "^7.14.5", + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helpers": "^7.14.6", + "@babel/parser": "^7.14.6", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.1.2", + "semver": "^6.3.0", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.5.tgz", + "integrity": "sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz", + "integrity": "sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.14.5.tgz", + "integrity": "sha512-YTA/Twn0vBXDVGJuAX6PwW7x5zQei1luDDo2Pl6q1qZ7hVNl0RZrhHCQG/ArGpR29Vl7ETiB8eJyrvpuRp300w==", + "dev": true, + "dependencies": { + "@babel/helper-explode-assignable-expression": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz", + "integrity": "sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.14.5", + "@babel/helper-validator-option": "^7.14.5", + "browserslist": "^4.16.6", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.6.tgz", + "integrity": "sha512-Z6gsfGofTxH/+LQXqYEK45kxmcensbzmk/oi8DmaQytlQCgqNZt9XQF8iqlI/SeXWVjaMNxvYvzaYw+kh42mDg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-member-expression-to-functions": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz", + "integrity": "sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "regexpu-core": "^4.7.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz", + "integrity": "sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-explode-assignable-expression": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.14.5.tgz", + "integrity": "sha512-Htb24gnGJdIGT4vnRKMdoXiOIlqOLmdiUYpAQ0mYfgVT/GDm8GOYhgi4GL+hMKrkiPRohO4ts34ELFsGAPQLDQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-function-name": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", + "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", + "dev": true, + "dependencies": { + "@babel/helper-get-function-arity": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-get-function-arity": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", + "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-hoist-variables": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", + "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.5.tgz", + "integrity": "sha512-UxUeEYPrqH1Q/k0yRku1JE7dyfyehNwT6SVkMHvYvPDv4+uu627VXBckVj891BO8ruKBkiDoGnZf4qPDD8abDQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", + "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.5.tgz", + "integrity": "sha512-iXpX4KW8LVODuAieD7MzhNjmM6dzYY5tfRqT+R9HDXWl0jPn/djKmA+G9s/2C2T9zggw5tK1QNqZ70USfedOwA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-simple-access": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", + "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", + "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz", + "integrity": "sha512-rLQKdQU+HYlxBwQIj8dk4/0ENOUEhA/Z0l4hN8BexpvmSMN9oA9EagjnhnDpNsRdWCfjwa4mn/HyBXO9yhQP6A==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-wrap-function": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz", + "integrity": "sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==", + "dev": true, + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.5.tgz", + "integrity": "sha512-nfBN9xvmCt6nrMZjfhkl7i0oTV3yxR4/FztsbOASyTvVcoYd0TRHh7eMLdlEcCqobydC0LAF3LtC92Iwxo0wyw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz", + "integrity": "sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-split-export-declaration": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", + "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", + "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", + "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.14.5.tgz", + "integrity": "sha512-YEdjTCq+LNuNS1WfxsDCNpgXkJaIyqco6DAelTUjT4f2KIWC1nBcaCaSdHTBqQVLnTBexBcVcFhLSU1KnYuePQ==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.6.tgz", + "integrity": "sha512-yesp1ENQBiLI+iYHSJdoZKUtRpfTlL1grDIX9NRlAVppljLw/4tTyYupIB7uIYmC3stW/imAv8EqaKaS/ibmeA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.6.tgz", + "integrity": "sha512-oG0ej7efjEXxb4UgE+klVx+3j4MVo+A2vCzm7OUN4CLo6WhQ+vSOD2yJ8m7B+DghObxtLxt3EfgMWpq+AsWehQ==", + "dev": true, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.14.5.tgz", + "integrity": "sha512-ZoJS2XCKPBfTmL122iP6NM9dOg+d4lc9fFk3zxc8iDjvt8Pk4+TlsHSKhIPf6X+L5ORCdBzqMZDjL/WHj7WknQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", + "@babel/plugin-proposal-optional-chaining": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.5.tgz", + "integrity": "sha512-tbD/CG3l43FIXxmu4a7RBe4zH7MLJ+S/lFowPFO7HetS2hyOZ/0nnnznegDuzFzfkyQYTxqdTH/hKmuBngaDAA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-remap-async-to-generator": "^7.14.5", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz", + "integrity": "sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.14.5.tgz", + "integrity": "sha512-KBAH5ksEnYHCegqseI5N9skTdxgJdmDoAOc0uXa+4QMYKeZD0w5IARh4FMlTNtaHhbB8v+KzMdTgxMMzsIy6Yg==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.14.5.tgz", + "integrity": "sha512-LYz5nvQcvYeRVjui1Ykn28i+3aUiXwQ/3MGoEy0InTaz1pJo/lAzmIDXX+BQny/oufgHzJ6vnEEiXQ8KZjEVFg==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-decorators": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-dynamic-import": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz", + "integrity": "sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-namespace-from": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz", + "integrity": "sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-json-strings": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz", + "integrity": "sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz", + "integrity": "sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz", + "integrity": "sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz", + "integrity": "sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.5.tgz", + "integrity": "sha512-VzMyY6PWNPPT3pxc5hi9LloKNr4SSrVCg7Yr6aZpW4Ym07r7KqSU/QXYwjXLVxqwSv0t/XSXkFoKBPUkZ8vb2A==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.14.5", + "@babel/helper-compilation-targets": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz", + "integrity": "sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz", + "integrity": "sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-methods": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz", + "integrity": "sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-62EyfyA3WA0mZiF2e2IV9mc9Ghwxcg8YTu8BS4Wss4Y3PY725OmS9M0qLORbJwLqFtGh+jiE4wAmocK2CTUK2Q==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-create-class-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz", + "integrity": "sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.14.5.tgz", + "integrity": "sha512-c4sZMRWL4GSvP1EXy0woIP7m4jkVcEuG8R1TOZxPBPtp4FSM/kiPZub9UIs/Jrb5ZAOzvTUSGYrWsrSu1JvoPw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz", + "integrity": "sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz", + "integrity": "sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz", + "integrity": "sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-remap-async-to-generator": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz", + "integrity": "sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.5.tgz", + "integrity": "sha512-LBYm4ZocNgoCqyxMLoOnwpsmQ18HWTQvql64t3GvMUzLQrNoV1BDG0lNftC8QKYERkZgCCT/7J5xWGObGAyHDw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.5.tgz", + "integrity": "sha512-J4VxKAMykM06K/64z9rwiL6xnBHgB1+FVspqvlgCdwD1KUbQNfszeKVVOMh59w3sztHYIZDgnhOC4WbdEfHFDA==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz", + "integrity": "sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.5.tgz", + "integrity": "sha512-wU9tYisEbRMxqDezKUqC9GleLycCRoUsai9ddlsq54r8QRLaeEhc+d+9DqCG+kV9W2GgQjTZESPTpn5bAFMDww==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz", + "integrity": "sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz", + "integrity": "sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz", + "integrity": "sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==", + "dev": true, + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz", + "integrity": "sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz", + "integrity": "sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==", + "dev": true, + "dependencies": { + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz", + "integrity": "sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz", + "integrity": "sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz", + "integrity": "sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.5.tgz", + "integrity": "sha512-en8GfBtgnydoao2PS+87mKyw62k02k7kJ9ltbKe0fXTHrQmG6QZZflYuGI1VVG7sVpx4E1n7KBpNlPb8m78J+A==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-simple-access": "^7.14.5", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz", + "integrity": "sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA==", + "dev": true, + "dependencies": { + "@babel/helper-hoist-variables": "^7.14.5", + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.5", + "babel-plugin-dynamic-import-node": "^2.3.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz", + "integrity": "sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.5.tgz", + "integrity": "sha512-+Xe5+6MWFo311U8SchgeX5c1+lJM+eZDBZgD+tvXu9VVQPXwwVzeManMMjYX6xw2HczngfOSZjoFYKwdeB/Jvw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz", + "integrity": "sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz", + "integrity": "sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz", + "integrity": "sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz", + "integrity": "sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz", + "integrity": "sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==", + "dev": true, + "dependencies": { + "regenerator-transform": "^0.14.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz", + "integrity": "sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.14.5.tgz", + "integrity": "sha512-fPMBhh1AV8ZyneiCIA+wYYUH1arzlXR1UMcApjvchDhfKxhy2r2lReJv8uHEyihi4IFIGlr1Pdx7S5fkESDQsg==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "babel-plugin-polyfill-corejs2": "^0.2.2", + "babel-plugin-polyfill-corejs3": "^0.2.2", + "babel-plugin-polyfill-regenerator": "^0.2.2", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz", + "integrity": "sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz", + "integrity": "sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz", + "integrity": "sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz", + "integrity": "sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz", + "integrity": "sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz", + "integrity": "sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz", + "integrity": "sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.5.tgz", + "integrity": "sha512-ci6TsS0bjrdPpWGnQ+m4f+JSSzDKlckqKIJJt9UZ/+g7Zz9k0N8lYU8IeLg/01o2h8LyNZDMLGgRLDTxpudLsA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.14.5", + "@babel/helper-compilation-targets": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-validator-option": "^7.14.5", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.14.5", + "@babel/plugin-proposal-async-generator-functions": "^7.14.5", + "@babel/plugin-proposal-class-properties": "^7.14.5", + "@babel/plugin-proposal-class-static-block": "^7.14.5", + "@babel/plugin-proposal-dynamic-import": "^7.14.5", + "@babel/plugin-proposal-export-namespace-from": "^7.14.5", + "@babel/plugin-proposal-json-strings": "^7.14.5", + "@babel/plugin-proposal-logical-assignment-operators": "^7.14.5", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5", + "@babel/plugin-proposal-numeric-separator": "^7.14.5", + "@babel/plugin-proposal-object-rest-spread": "^7.14.5", + "@babel/plugin-proposal-optional-catch-binding": "^7.14.5", + "@babel/plugin-proposal-optional-chaining": "^7.14.5", + "@babel/plugin-proposal-private-methods": "^7.14.5", + "@babel/plugin-proposal-private-property-in-object": "^7.14.5", + "@babel/plugin-proposal-unicode-property-regex": "^7.14.5", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.14.5", + "@babel/plugin-transform-async-to-generator": "^7.14.5", + "@babel/plugin-transform-block-scoped-functions": "^7.14.5", + "@babel/plugin-transform-block-scoping": "^7.14.5", + "@babel/plugin-transform-classes": "^7.14.5", + "@babel/plugin-transform-computed-properties": "^7.14.5", + "@babel/plugin-transform-destructuring": "^7.14.5", + "@babel/plugin-transform-dotall-regex": "^7.14.5", + "@babel/plugin-transform-duplicate-keys": "^7.14.5", + "@babel/plugin-transform-exponentiation-operator": "^7.14.5", + "@babel/plugin-transform-for-of": "^7.14.5", + "@babel/plugin-transform-function-name": "^7.14.5", + "@babel/plugin-transform-literals": "^7.14.5", + "@babel/plugin-transform-member-expression-literals": "^7.14.5", + "@babel/plugin-transform-modules-amd": "^7.14.5", + "@babel/plugin-transform-modules-commonjs": "^7.14.5", + "@babel/plugin-transform-modules-systemjs": "^7.14.5", + "@babel/plugin-transform-modules-umd": "^7.14.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.5", + "@babel/plugin-transform-new-target": "^7.14.5", + "@babel/plugin-transform-object-super": "^7.14.5", + "@babel/plugin-transform-parameters": "^7.14.5", + "@babel/plugin-transform-property-literals": "^7.14.5", + "@babel/plugin-transform-regenerator": "^7.14.5", + "@babel/plugin-transform-reserved-words": "^7.14.5", + "@babel/plugin-transform-shorthand-properties": "^7.14.5", + "@babel/plugin-transform-spread": "^7.14.5", + "@babel/plugin-transform-sticky-regex": "^7.14.5", + "@babel/plugin-transform-template-literals": "^7.14.5", + "@babel/plugin-transform-typeof-symbol": "^7.14.5", + "@babel/plugin-transform-unicode-escapes": "^7.14.5", + "@babel/plugin-transform-unicode-regex": "^7.14.5", + "@babel/preset-modules": "^0.1.4", + "@babel/types": "^7.14.5", + "babel-plugin-polyfill-corejs2": "^0.2.2", + "babel-plugin-polyfill-corejs3": "^0.2.2", + "babel-plugin-polyfill-regenerator": "^0.2.2", + "core-js-compat": "^3.14.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz", + "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.5.tgz", + "integrity": "sha512-G3BiS15vevepdmFqmUc9X+64y0viZYygubAMO8SvBmKARuF6CPSZtH4Ng9vi/lrWlZFGe3FWdXNy835akH8Glg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-hoist-variables": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/@babel/types": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.5.tgz", + "integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.5", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@braintree/sanitize-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-3.1.0.tgz", + "integrity": "sha512-GcIY79elgB+azP74j8vqkiXz8xLFfIzbQJdlwOPisgbKT00tviJQuEghOXSMVxJ00HoYJbGswr4kcllUc4xCcg==", + "dev": true + }, + "node_modules/@hapi/hoek": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.0.tgz", + "integrity": "sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug==", + "dev": true + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dev": true, + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "dependencies": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@sideway/address": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.2.tgz", + "integrity": "sha512-idTz8ibqWFrPU8kMirL0CoPH/A29XOzzAzpyN3zQ4kAWnzmNfFmRaoMNN6VI8ske5M73HZyhIaW4OuSFIdM4oA==", + "dev": true, + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==", + "dev": true + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "dev": true + }, + "node_modules/@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "dependencies": { + "defer-to-connect": "^1.0.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", + "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", + "dev": true + }, + "node_modules/@types/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "15.12.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz", + "integrity": "sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww==", + "dev": true + }, + "node_modules/@types/q": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", + "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==", + "dev": true + }, + "node_modules/@vssue/api-github-v3": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@vssue/api-github-v3/-/api-github-v3-1.4.7.tgz", + "integrity": "sha512-ukhOnzGQarmj606ZiYN9iCMyr3EJS3YEPdZXX+zBLVsuzjTL5ffLbbpXsEtPBh2XNt3Ig3XdzCvA9bVXhwy4mQ==", + "dev": true, + "dependencies": { + "@vssue/utils": "^1.4.7", + "axios": "^0.21.1" + } + }, + "node_modules/@vssue/utils": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@vssue/utils/-/utils-1.4.7.tgz", + "integrity": "sha512-e94karP4szmSNT2L4bgIT+VGToBSY3bdlgmGcomcD2qCXTWDK4krSOYm8ES+BhHTcmCvzQYU/xenHR4tzrythA==", + "dev": true, + "dependencies": { + "date-fns": "^1.29.0", + "qs": "^6.6.0" + } + }, + "node_modules/@vssue/utils/node_modules/qs": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", + "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", + "dev": true, + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@vssue/vuepress-plugin-vssue": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@vssue/vuepress-plugin-vssue/-/vuepress-plugin-vssue-1.4.8.tgz", + "integrity": "sha512-0QzegHl/Rx4/XgXswThIJi4Yk+b6AIaM450jX6p4RbOM6yOTzEKLTMduUo54Rvhq/NHNusu4Yy/w1iY8NTqBEg==", + "dev": true, + "dependencies": { + "vssue": "^1.4.8" + }, + "peerDependencies": { + "vuepress": "^1.0.0" + } + }, + "node_modules/@vue/babel-helper-vue-jsx-merge-props": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.2.1.tgz", + "integrity": "sha512-QOi5OW45e2R20VygMSNhyQHvpdUwQZqGPc748JLGCYEy+yp8fNFNdbNIGAgZmi9e+2JHPd6i6idRuqivyicIkA==", + "dev": true + }, + "node_modules/@vue/babel-helper-vue-transform-on": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.2.tgz", + "integrity": "sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==", + "dev": true + }, + "node_modules/@vue/babel-plugin-jsx": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.0.6.tgz", + "integrity": "sha512-RzYsvBhzKUmY2YG6LoV+W5PnlnkInq0thh1AzCmewwctAgGN6e9UFon6ZrQQV1CO5G5PeME7MqpB+/vvGg0h4g==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "@vue/babel-helper-vue-transform-on": "^1.0.2", + "camelcase": "^6.0.0", + "html-tags": "^3.1.0", + "svg-tags": "^1.0.0" + } + }, + "node_modules/@vue/babel-plugin-jsx/node_modules/camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@vue/babel-plugin-transform-vue-jsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.2.1.tgz", + "integrity": "sha512-HJuqwACYehQwh1fNT8f4kyzqlNMpBuUK4rSiSES5D4QsYncv5fxFsLyrxFPG2ksO7t5WP+Vgix6tt6yKClwPzA==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", + "html-tags": "^2.0.0", + "lodash.kebabcase": "^4.1.1", + "svg-tags": "^1.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-plugin-transform-vue-jsx/node_modules/html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@vue/babel-preset-app": { + "version": "4.5.13", + "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-4.5.13.tgz", + "integrity": "sha512-pM7CR3yXB6L8Gfn6EmX7FLNE3+V/15I3o33GkSNsWvgsMp6HVGXKkXgojrcfUUauyL1LZOdvTmu4enU2RePGHw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.0", + "@babel/helper-compilation-targets": "^7.9.6", + "@babel/helper-module-imports": "^7.8.3", + "@babel/plugin-proposal-class-properties": "^7.8.3", + "@babel/plugin-proposal-decorators": "^7.8.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-jsx": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.11.0", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.0", + "@vue/babel-plugin-jsx": "^1.0.3", + "@vue/babel-preset-jsx": "^1.2.4", + "babel-plugin-dynamic-import-node": "^2.3.3", + "core-js": "^3.6.5", + "core-js-compat": "^3.6.5", + "semver": "^6.1.0" + }, + "peerDependencies": { + "@babel/core": "*", + "core-js": "^3", + "vue": "^2 || ^3.0.0-0" + }, + "peerDependenciesMeta": { + "core-js": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/@vue/babel-preset-app/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@vue/babel-preset-jsx": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@vue/babel-preset-jsx/-/babel-preset-jsx-1.2.4.tgz", + "integrity": "sha512-oRVnmN2a77bYDJzeGSt92AuHXbkIxbf/XXSE3klINnh9AXBmVS1DGa1f0d+dDYpLfsAKElMnqKTQfKn7obcL4w==", + "dev": true, + "dependencies": { + "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", + "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", + "@vue/babel-sugar-composition-api-inject-h": "^1.2.1", + "@vue/babel-sugar-composition-api-render-instance": "^1.2.4", + "@vue/babel-sugar-functional-vue": "^1.2.2", + "@vue/babel-sugar-inject-h": "^1.2.2", + "@vue/babel-sugar-v-model": "^1.2.3", + "@vue/babel-sugar-v-on": "^1.2.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-composition-api-inject-h": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-inject-h/-/babel-sugar-composition-api-inject-h-1.2.1.tgz", + "integrity": "sha512-4B3L5Z2G+7s+9Bwbf+zPIifkFNcKth7fQwekVbnOA3cr3Pq71q71goWr97sk4/yyzH8phfe5ODVzEjX7HU7ItQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-composition-api-render-instance": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-render-instance/-/babel-sugar-composition-api-render-instance-1.2.4.tgz", + "integrity": "sha512-joha4PZznQMsxQYXtR3MnTgCASC9u3zt9KfBxIeuI5g2gscpTsSKRDzWQt4aqNIpx6cv8On7/m6zmmovlNsG7Q==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-functional-vue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.2.2.tgz", + "integrity": "sha512-JvbgGn1bjCLByIAU1VOoepHQ1vFsroSA/QkzdiSs657V79q6OwEWLCQtQnEXD/rLTA8rRit4rMOhFpbjRFm82w==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-inject-h": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.2.2.tgz", + "integrity": "sha512-y8vTo00oRkzQTgufeotjCLPAvlhnpSkcHFEp60+LJUwygGcd5Chrpn5480AQp/thrxVm8m2ifAk0LyFel9oCnw==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-v-model": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.2.3.tgz", + "integrity": "sha512-A2jxx87mySr/ulAsSSyYE8un6SIH0NWHiLaCWpodPCVOlQVODCaSpiR4+IMsmBr73haG+oeCuSvMOM+ttWUqRQ==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", + "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", + "camelcase": "^5.0.0", + "html-tags": "^2.0.0", + "svg-tags": "^1.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-v-model/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@vue/babel-sugar-v-model/node_modules/html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@vue/babel-sugar-v-on": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.2.3.tgz", + "integrity": "sha512-kt12VJdz/37D3N3eglBywV8GStKNUhNrsxChXIV+o0MwVXORYuhDTHJRKPgLJRb/EY3vM2aRFQdxJBp9CLikjw==", + "dev": true, + "dependencies": { + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", + "camelcase": "^5.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/babel-sugar-v-on/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@vue/component-compiler-utils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.2.2.tgz", + "integrity": "sha512-rAYMLmgMuqJFWAOb3Awjqqv5X3Q3hVr4jH/kgrFJpiU0j3a90tnNBplqbj+snzrgZhC9W128z+dtgMifOiMfJg==", + "dev": true, + "dependencies": { + "consolidate": "^0.15.1", + "hash-sum": "^1.0.2", + "lru-cache": "^4.1.2", + "merge-source-map": "^1.1.0", + "postcss": "^7.0.36", + "postcss-selector-parser": "^6.0.2", + "source-map": "~0.6.1", + "vue-template-es2015-compiler": "^1.9.0" + }, + "optionalDependencies": { + "prettier": "^1.18.2" + } + }, + "node_modules/@vue/component-compiler-utils/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@vuepress/core": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/core/-/core-1.8.2.tgz", + "integrity": "sha512-lh9BLC06k9s0wxTuWtCkiNj49fkbW87enp0XSrFZHEoyDGSGndQjZmMMErcHc5Hx7nrW1nzc33sPH1NNtJl0hw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.8.4", + "@vue/babel-preset-app": "^4.1.2", + "@vuepress/markdown": "1.8.2", + "@vuepress/markdown-loader": "1.8.2", + "@vuepress/plugin-last-updated": "1.8.2", + "@vuepress/plugin-register-components": "1.8.2", + "@vuepress/shared-utils": "1.8.2", + "autoprefixer": "^9.5.1", + "babel-loader": "^8.0.4", + "cache-loader": "^3.0.0", + "chokidar": "^2.0.3", + "connect-history-api-fallback": "^1.5.0", + "copy-webpack-plugin": "^5.0.2", + "core-js": "^3.6.4", + "cross-spawn": "^6.0.5", + "css-loader": "^2.1.1", + "file-loader": "^3.0.1", + "js-yaml": "^3.13.1", + "lru-cache": "^5.1.1", + "mini-css-extract-plugin": "0.6.0", + "optimize-css-assets-webpack-plugin": "^5.0.1", + "portfinder": "^1.0.13", + "postcss-loader": "^3.0.0", + "postcss-safe-parser": "^4.0.1", + "toml": "^3.0.0", + "url-loader": "^1.0.1", + "vue": "^2.6.10", + "vue-loader": "^15.7.1", + "vue-router": "^3.4.5", + "vue-server-renderer": "^2.6.10", + "vue-template-compiler": "^2.6.10", + "vuepress-html-webpack-plugin": "^3.2.0", + "vuepress-plugin-container": "^2.0.2", + "webpack": "^4.8.1", + "webpack-chain": "^6.0.0", + "webpack-dev-server": "^3.5.1", + "webpack-merge": "^4.1.2", + "webpackbar": "3.2.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/@vuepress/core/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@vuepress/core/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@vuepress/markdown": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/markdown/-/markdown-1.8.2.tgz", + "integrity": "sha512-zznBHVqW+iBkznF/BO/GY9RFu53khyl0Ey0PnGqvwCJpRLNan6y5EXgYumtjw2GSYn5nDTTALYxtyNBdz64PKg==", + "dev": true, + "dependencies": { + "@vuepress/shared-utils": "1.8.2", + "markdown-it": "^8.4.1", + "markdown-it-anchor": "^5.0.2", + "markdown-it-chain": "^1.3.0", + "markdown-it-emoji": "^1.4.0", + "markdown-it-table-of-contents": "^0.4.0", + "prismjs": "^1.13.0" + } + }, + "node_modules/@vuepress/markdown-loader": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/markdown-loader/-/markdown-loader-1.8.2.tgz", + "integrity": "sha512-mWzFXikCUcAN/chpKkqZpRYKdo0312hMv8cBea2hvrJYV6y4ODB066XKvXN8JwOcxuCjxWYJkhWGr+pXq1oTtw==", + "dev": true, + "dependencies": { + "@vuepress/markdown": "1.8.2", + "loader-utils": "^1.1.0", + "lru-cache": "^5.1.1" + } + }, + "node_modules/@vuepress/markdown-loader/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@vuepress/markdown-loader/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/@vuepress/plugin-active-header-links": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-active-header-links/-/plugin-active-header-links-1.8.2.tgz", + "integrity": "sha512-JmXAQg8D7J8mcKe2Ue3BZ9dOCzJMJXP4Cnkkc/IrqfDg0ET0l96gYWZohCqlvRIWt4f0VPiFAO4FLYrW+hko+g==", + "dev": true, + "dependencies": { + "lodash.debounce": "^4.0.8" + } + }, + "node_modules/@vuepress/plugin-back-to-top": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-back-to-top/-/plugin-back-to-top-1.8.2.tgz", + "integrity": "sha512-htAf2m8+6cGmYQexWerznGBY10y1E4TBfebYC3Y3wqNjFjvXUmRKcAG/u6Yxvey4OFkQUxbth2ilKi/GlIW8aQ==", + "dev": true, + "dependencies": { + "lodash.debounce": "^4.0.8" + } + }, + "node_modules/@vuepress/plugin-blog": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-blog/-/plugin-blog-1.9.4.tgz", + "integrity": "sha512-7A4Y3mYrSOUKdzsTjeVOKt0XgZ0m1Iqq7BeZn7y9YeZfDcZ4Fx6UldsPfK2+THwtYwGzQ7Not3zO8djyk7z3ew==", + "dev": true, + "dependencies": { + "@vssue/api-github-v3": "^1.1.2", + "@vssue/vuepress-plugin-vssue": "^1.2.0", + "dayjs": "^1.10.3", + "vuejs-paginate": "^2.1.0", + "vuepress-plugin-disqus": "^0.2.0", + "vuepress-plugin-feed": "^0.1.8", + "vuepress-plugin-mailchimp": "^1.4.1", + "vuepress-plugin-sitemap": "^2.3.1" + } + }, + "node_modules/@vuepress/plugin-last-updated": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-last-updated/-/plugin-last-updated-1.8.2.tgz", + "integrity": "sha512-pYIRZi52huO9b6HY3JQNPKNERCLzMHejjBRt9ekdnJ1xhLs4MmRvt37BoXjI/qzvXkYtr7nmGgnKThNBVRTZuA==", + "dev": true, + "dependencies": { + "cross-spawn": "^6.0.5" + } + }, + "node_modules/@vuepress/plugin-medium-zoom": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-medium-zoom/-/plugin-medium-zoom-1.8.2.tgz", + "integrity": "sha512-Mljso/8E6IbNmIKmwKeC6FDfnhKY3fsOUSs5kEGzz3RQwd54eshqHAMRVwW4LZkYZHhwQXF8+qk7YqoMZB7jjg==", + "dev": true, + "dependencies": { + "medium-zoom": "^1.0.4" + } + }, + "node_modules/@vuepress/plugin-nprogress": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-nprogress/-/plugin-nprogress-1.8.2.tgz", + "integrity": "sha512-3TOBee2NM3WLr1tdjDTGfrAMggjN+OlEPyKyv8FqThsVkDYhw48O3HwqlThp9KX7UbL3ExxIFBwWRFLC+kYrdw==", + "dev": true, + "dependencies": { + "nprogress": "^0.2.0" + } + }, + "node_modules/@vuepress/plugin-register-components": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-register-components/-/plugin-register-components-1.8.2.tgz", + "integrity": "sha512-6SUq3nHFMEh9qKFnjA8QnrNxj0kLs7+Gspq1OBU8vtu0NQmSvLFZVaMV7pzT/9zN2nO5Pld5qhsUJv1g71MrEA==", + "dev": true, + "dependencies": { + "@vuepress/shared-utils": "1.8.2" + } + }, + "node_modules/@vuepress/plugin-search": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-search/-/plugin-search-1.8.2.tgz", + "integrity": "sha512-JrSJr9o0Kar14lVtZ4wfw39pplxvvMh8vDBD9oW09a+6Zi/4bySPGdcdaqdqGW+OHSiZNvG+6uyfKSBBBqF6PA==", + "dev": true + }, + "node_modules/@vuepress/shared-utils": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/shared-utils/-/shared-utils-1.8.2.tgz", + "integrity": "sha512-6kGubc7iBDWruEBUU7yR+sQ++SOhMuvKWvWeTZJKRZedthycdzYz7QVpua0FaZSAJm5/dIt8ymU4WQvxTtZgTQ==", + "dev": true, + "dependencies": { + "chalk": "^2.3.2", + "escape-html": "^1.0.3", + "fs-extra": "^7.0.1", + "globby": "^9.2.0", + "gray-matter": "^4.0.1", + "hash-sum": "^1.0.2", + "semver": "^6.0.0", + "toml": "^3.0.0", + "upath": "^1.1.0" + } + }, + "node_modules/@vuepress/shared-utils/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@vuepress/theme-default": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/theme-default/-/theme-default-1.8.2.tgz", + "integrity": "sha512-rE7M1rs3n2xp4a/GrweO8EGwqFn3EA5gnFWdVmVIHyr7C1nix+EqjpPQF1SVWNnIrDdQuCw38PqS+oND1K2vYw==", + "dev": true, + "dependencies": { + "@vuepress/plugin-active-header-links": "1.8.2", + "@vuepress/plugin-nprogress": "1.8.2", + "@vuepress/plugin-search": "1.8.2", + "docsearch.js": "^2.5.2", + "lodash": "^4.17.15", + "stylus": "^0.54.8", + "stylus-loader": "^3.0.2", + "vuepress-plugin-container": "^2.0.2", + "vuepress-plugin-smooth-scroll": "^0.0.3" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "dependencies": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "dependencies": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "node_modules/@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "node_modules/@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "node_modules/@zeit/schemas": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.6.0.tgz", + "integrity": "sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg==", + "dev": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "node_modules/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "dependencies": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/agentkeepalive": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-2.2.0.tgz", + "integrity": "sha1-xdG9SxKQCPEWPyNvhuX66iAm4u8=", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true, + "peerDependencies": { + "ajv": ">=5.0.0" + } + }, + "node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/algoliasearch": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-3.35.1.tgz", + "integrity": "sha512-K4yKVhaHkXfJ/xcUnil04xiSrB8B8yHZoFEhWNpXg23eiCnqvTZw1tn/SqvdsANlYHLJlKl0qi3I/Q2Sqo7LwQ==", + "dev": true, + "dependencies": { + "agentkeepalive": "^2.2.0", + "debug": "^2.6.9", + "envify": "^4.0.0", + "es6-promise": "^4.1.0", + "events": "^1.1.0", + "foreach": "^2.0.5", + "global": "^4.3.2", + "inherits": "^2.0.1", + "isarray": "^2.0.1", + "load-script": "^1.0.0", + "object-keys": "^1.0.11", + "querystring-es3": "^0.2.1", + "reduce": "^1.0.1", + "semver": "^5.1.0", + "tunnel-agent": "^0.6.0" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/algoliasearch/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, + "node_modules/alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", + "dev": true + }, + "node_modules/ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "dev": true, + "dependencies": { + "string-width": "^2.0.0" + } + }, + "node_modules/ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true, + "engines": [ + "node >= 0.8.0" + ], + "bin": { + "ansi-html": "bin/ansi-html" + } + }, + "node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "dependencies": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + } + }, + "node_modules/anymatch/node_modules/normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "dependencies": { + "remove-trailing-separator": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "node_modules/arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/arg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arg/-/arg-2.0.0.tgz", + "integrity": "sha512-XxNTUzKnz1ctK3ZIcI2XUPlD96wbHP2nGqkPKpvk/HNRlPveYrXIVSTk9m3LcqOgDPg3B1nMvdV/K8wZd7PG4w==", + "dev": true + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "node_modules/array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "dependencies": { + "array-uniq": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/asn1.js/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "dependencies": { + "object-assign": "^4.1.1", + "util": "0.10.3" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/assert/node_modules/inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "node_modules/assert/node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/assert/node_modules/util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "dependencies": { + "inherits": "2.0.1" + } + }, + "node_modules/assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "node_modules/atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true, + "bin": { + "atob": "bin/atob.js" + }, + "engines": { + "node": ">= 4.5.0" + } + }, + "node_modules/autocomplete.js": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/autocomplete.js/-/autocomplete.js-0.36.0.tgz", + "integrity": "sha512-jEwUXnVMeCHHutUt10i/8ZiRaCb0Wo+ZyKxeGsYwBDtw6EJHqEeDrq4UwZRD8YBSvp3g6klP678il2eeiVXN2Q==", + "dev": true, + "dependencies": { + "immediate": "^3.2.3" + } + }, + "node_modules/autoprefixer": { + "version": "9.8.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz", + "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==", + "dev": true, + "dependencies": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "colorette": "^1.2.1", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + }, + "node_modules/aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "dev": true + }, + "node_modules/axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "dev": true, + "dependencies": { + "follow-redirects": "^1.10.0" + } + }, + "node_modules/babel-loader": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz", + "integrity": "sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==", + "dev": true, + "dependencies": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^1.4.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + }, + "engines": { + "node": ">= 8.9" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "webpack": ">=2" + } + }, + "node_modules/babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "dependencies": { + "object.assign": "^4.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz", + "integrity": "sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.2.2", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.3.tgz", + "integrity": "sha512-rCOFzEIJpJEAU14XCcV/erIf/wZQMmMT5l5vXOpL5uoznyOGfDIjPj6FVytMvtzaKSTSVKouOCTPJ5OMUZH30g==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.2.2", + "core-js-compat": "^3.14.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz", + "integrity": "sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.2.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "dependencies": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "node_modules/bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "dependencies": { + "tweetnacl": "^0.14.3" + } + }, + "node_modules/bhttp": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/bhttp/-/bhttp-1.2.8.tgz", + "integrity": "sha512-ZwEA5FKEUhc98EHRX+BkNmUOs48RTnglvfze2+p0HrMPwhQBtVw1aAYyylnCtRl6x6vltCkzGo2+twQ6LVfm6Q==", + "dev": true, + "dependencies": { + "bluebird": "^2.8.2", + "concat-stream": "^1.4.7", + "debug": "^2.1.1", + "dev-null": "^0.1.1", + "errors": "^0.2.0", + "extend": "^2.0.0", + "form-data2": "^1.0.0", + "form-fix-array": "^1.0.0", + "lodash.clonedeep": "^4.5.0", + "lodash.merge": "^4.6.2", + "stream-length": "^1.0.2", + "through2-sink": "^1.0.0", + "through2-spy": "^1.2.0", + "tough-cookie": "^2.3.1" + } + }, + "node_modules/bhttp/node_modules/extend": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-2.0.2.tgz", + "integrity": "sha512-AgFD4VU+lVLP6vjnlNfF7OeInLTyeyckCNPEsuxz1vi786UuK/nk6ynPuhn/h+Ju9++TQyr5EpLRI14fc1QtTQ==", + "dev": true + }, + "node_modules/big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bluebird": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=", + "dev": true + }, + "node_modules/bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true + }, + "node_modules/body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/body-parser/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "dependencies": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "node_modules/boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "dev": true, + "dependencies": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/boxen/node_modules/camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "dependencies": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/broken-link-checker": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/broken-link-checker/-/broken-link-checker-0.7.8.tgz", + "integrity": "sha512-/zH4/nLMNKDeDH5nVuf/R6WYd0Yjnar1NpcdAO2+VlwjGKzJa6y42C03UO+imBSHwe6BefSkVi82fImE2Rb7yg==", + "dev": true, + "dependencies": { + "bhttp": "^1.2.1", + "calmcard": "~0.1.1", + "chalk": "^1.1.3", + "char-spinner": "^1.0.1", + "condense-whitespace": "^1.0.0", + "default-user-agent": "^1.0.0", + "errno": "~0.1.4", + "extend": "^3.0.0", + "http-equiv-refresh": "^1.0.0", + "humanize-duration": "^3.9.1", + "is-stream": "^1.0.1", + "is-string": "^1.0.4", + "limited-request-queue": "^2.0.0", + "link-types": "^1.1.0", + "maybe-callback": "^2.1.0", + "nopter": "~0.3.0", + "parse5": "^3.0.2", + "robot-directives": "~0.3.0", + "robots-txt-guard": "~0.1.0", + "robots-txt-parse": "~0.0.4", + "urlcache": "~0.7.0", + "urlobj": "0.0.11" + }, + "bin": { + "blc": "bin/blc", + "broken-link-checker": "bin/blc" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/broken-link-checker/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/broken-link-checker/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/broken-link-checker/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/broken-link-checker/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/broken-link-checker/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "node_modules/browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "dependencies": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "dependencies": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "node_modules/browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "dependencies": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "node_modules/browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "dependencies": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + } + }, + "node_modules/browserify-sign/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/browserify-sign/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "dependencies": { + "pako": "~1.0.5" + } + }, + "node_modules/browserslist": { + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "dev": true, + "dependencies": { + "caniuse-lite": "^1.0.30001219", + "colorette": "^1.2.2", + "electron-to-chromium": "^1.3.723", + "escalade": "^3.1.1", + "node-releases": "^1.1.71" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "dependencies": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "node_modules/buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "node_modules/buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "node_modules/buffer-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-json/-/buffer-json-2.0.0.tgz", + "integrity": "sha512-+jjPFVqyfF1esi9fvfUs3NqM0pH1ziZ36VP4hmA/y/Ssfo/5w5xHKfTw9BwQjoJ1w/oVtpLomqwUHKdefGyuHw==", + "dev": true + }, + "node_modules/buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "node_modules/builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cac": { + "version": "6.7.3", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.3.tgz", + "integrity": "sha512-ECVqVZh74qgSuZG9YOt2OJPI3wGcf+EwwuF/XIOYqZBD0KZYLtgPWqFPxmDPQ6joxI1nOlvVgRV6VT53Ooyocg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "dependencies": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + } + }, + "node_modules/cacache/node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/cacache/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "dependencies": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cache-loader": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cache-loader/-/cache-loader-3.0.1.tgz", + "integrity": "sha512-HzJIvGiGqYsFUrMjAJNDbVZoG7qQA+vy9AIoKs7s9DscNfki0I589mf2w6/tW+kkFH3zyiknoWV5Jdynu6b/zw==", + "dev": true, + "dependencies": { + "buffer-json": "^2.0.0", + "find-cache-dir": "^2.1.0", + "loader-utils": "^1.2.3", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.1", + "schema-utils": "^1.0.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/cache-loader/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cache-loader/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cache-loader/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cache-loader/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cache-loader/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cache-loader/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/cache-loader/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cache-loader/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/node_modules/normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", + "dev": true + }, + "node_modules/caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "dependencies": { + "callsites": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-callsite/node_modules/callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "dependencies": { + "callsites": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/calmcard": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/calmcard/-/calmcard-0.1.1.tgz", + "integrity": "sha1-NawrZkkrDtOa0GqJOg/25hEk5Ek=", + "deprecated": "no longer maintained", + "dev": true + }, + "node_modules/camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, + "dependencies": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "node_modules/camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001237", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001237.tgz", + "integrity": "sha512-pDHgRndit6p1NR2GhzMbQ6CkRrp4VKuSsqbcLeOQppYPKOYkKT/6ZvZDvKJUqcmtyWIAHuZq3SVS2vc1egCZzw==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + } + }, + "node_modules/caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/char-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/char-spinner/-/char-spinner-1.0.1.tgz", + "integrity": "sha1-5upnvSR+EHESmDt6sEee02KAAIE=", + "dev": true + }, + "node_modules/check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "deprecated": "Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.", + "dev": true, + "dependencies": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "optionalDependencies": { + "fsevents": "^1.2.7" + } + }, + "node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "node_modules/chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/class-utils/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/clean-css": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "dev": true, + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/clean-css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cli-table": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.6.tgz", + "integrity": "sha512-ZkNZbnZjKERTY5NwC2SeMeLeifSPq/pubeRoTpdr3WchLlnZg6hEgvHkK5zL7KNFdd9PmHN8lxrENUwI3cE8vQ==", + "dev": true, + "dependencies": { + "colors": "1.0.3" + }, + "engines": { + "node": ">= 0.2.0" + } + }, + "node_modules/clipboardy": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", + "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", + "dev": true, + "dependencies": { + "arch": "^2.1.1", + "execa": "^1.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "dependencies": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + } + }, + "node_modules/coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dev": true, + "dependencies": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "dependencies": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz", + "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.1", + "color-string": "^1.5.4" + } + }, + "node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/color-string": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz", + "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==", + "dev": true, + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, + "node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true, + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/combined-stream2": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/combined-stream2/-/combined-stream2-1.1.2.tgz", + "integrity": "sha1-9uFLegFWZvjHsKH6xQYkAWSsNXA=", + "dev": true, + "dependencies": { + "bluebird": "^2.8.1", + "debug": "^2.1.1", + "stream-length": "^1.0.1" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "node_modules/component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz", + "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.14", + "debug": "2.6.9", + "on-headers": "~1.0.1", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/condense-whitespace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/condense-whitespace/-/condense-whitespace-1.0.0.tgz", + "integrity": "sha1-g3bZjvAo5sss0kaOKM5CxcZasak=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", + "dev": true + }, + "node_modules/console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "node_modules/consolidate": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", + "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", + "dev": true, + "dependencies": { + "bluebird": "^3.1.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/consolidate/node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "node_modules/content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.1" + } + }, + "node_modules/cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "node_modules/copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "dependencies": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "node_modules/copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/copy-webpack-plugin": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.1.2.tgz", + "integrity": "sha512-Uh7crJAco3AjBvgAy9Z75CjK8IG+gxaErro71THQ+vv/bl4HaQcpkexAY8KVW/T6D2W2IRr+couF/knIRkZMIQ==", + "dev": true, + "dependencies": { + "cacache": "^12.0.3", + "find-cache-dir": "^2.1.0", + "glob-parent": "^3.1.0", + "globby": "^7.1.1", + "is-glob": "^4.0.1", + "loader-utils": "^1.2.3", + "minimatch": "^3.0.4", + "normalize-path": "^3.0.0", + "p-limit": "^2.2.1", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "webpack-log": "^2.0.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/copy-webpack-plugin/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/copy-webpack-plugin/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "dev": true, + "dependencies": { + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/copy-webpack-plugin/node_modules/globby/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/copy-webpack-plugin/node_modules/ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "node_modules/copy-webpack-plugin/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/copy-webpack-plugin/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/copy-webpack-plugin/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/copy-webpack-plugin/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/copy-webpack-plugin/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/copy-webpack-plugin/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/copy-webpack-plugin/node_modules/slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/core-js": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.14.0.tgz", + "integrity": "sha512-3s+ed8er9ahK+zJpp9ZtuVcDoFzHNiZsPbNAAE4KXgrRHbjSqqNN6xGSXq6bq7TZIbKj4NLrLb6bJ5i+vSVjHA==", + "dev": true, + "hasInstallScript": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.14.0.tgz", + "integrity": "sha512-R4NS2eupxtiJU+VwgkF9WTpnSfZW4pogwKHd8bclWU2sp93Pr5S1uYJI84cMOubJRou7bcfL0vmwtLslWN5p3A==", + "dev": true, + "dependencies": { + "browserslist": "^4.16.6", + "semver": "7.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "dependencies": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + } + }, + "node_modules/create-ecdh/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "node_modules/create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "dependencies": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + } + }, + "node_modules/css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + }, + "engines": { + "node": ">4" + } + }, + "node_modules/css-loader": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.1.tgz", + "integrity": "sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w==", + "dev": true, + "dependencies": { + "camelcase": "^5.2.0", + "icss-utils": "^4.1.0", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.14", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^2.0.6", + "postcss-modules-scope": "^2.1.0", + "postcss-modules-values": "^2.0.0", + "postcss-value-parser": "^3.3.0", + "schema-utils": "^1.0.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/css-loader/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/css-loader/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/css-loader/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", + "dev": true, + "dependencies": { + "css": "^2.0.0" + } + }, + "node_modules/css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "node_modules/css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", + "dev": true + }, + "node_modules/css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/css-tree/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.11.tgz", + "integrity": "sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g==", + "dev": true, + "dependencies": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.8", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-preset-default": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz", + "integrity": "sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ==", + "dev": true, + "dependencies": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.3", + "postcss-unique-selectors": "^4.0.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dev": true, + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dev": true, + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/csso/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "dev": true + }, + "node_modules/csso/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, + "node_modules/d3": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-5.16.0.tgz", + "integrity": "sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==", + "dev": true, + "dependencies": { + "d3-array": "1", + "d3-axis": "1", + "d3-brush": "1", + "d3-chord": "1", + "d3-collection": "1", + "d3-color": "1", + "d3-contour": "1", + "d3-dispatch": "1", + "d3-drag": "1", + "d3-dsv": "1", + "d3-ease": "1", + "d3-fetch": "1", + "d3-force": "1", + "d3-format": "1", + "d3-geo": "1", + "d3-hierarchy": "1", + "d3-interpolate": "1", + "d3-path": "1", + "d3-polygon": "1", + "d3-quadtree": "1", + "d3-random": "1", + "d3-scale": "2", + "d3-scale-chromatic": "1", + "d3-selection": "1", + "d3-shape": "1", + "d3-time": "1", + "d3-time-format": "2", + "d3-timer": "1", + "d3-transition": "1", + "d3-voronoi": "1", + "d3-zoom": "1" + } + }, + "node_modules/d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==", + "dev": true + }, + "node_modules/d3-axis": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz", + "integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==", + "dev": true + }, + "node_modules/d3-brush": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz", + "integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==", + "dev": true, + "dependencies": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, + "node_modules/d3-chord": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz", + "integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==", + "dev": true, + "dependencies": { + "d3-array": "1", + "d3-path": "1" + } + }, + "node_modules/d3-collection": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", + "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==", + "dev": true + }, + "node_modules/d3-color": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", + "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==", + "dev": true + }, + "node_modules/d3-contour": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz", + "integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==", + "dev": true, + "dependencies": { + "d3-array": "^1.1.1" + } + }, + "node_modules/d3-dispatch": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz", + "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==", + "dev": true + }, + "node_modules/d3-drag": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz", + "integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==", + "dev": true, + "dependencies": { + "d3-dispatch": "1", + "d3-selection": "1" + } + }, + "node_modules/d3-dsv": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", + "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", + "dev": true, + "dependencies": { + "commander": "2", + "iconv-lite": "0.4", + "rw": "1" + }, + "bin": { + "csv2json": "bin/dsv2json", + "csv2tsv": "bin/dsv2dsv", + "dsv2dsv": "bin/dsv2dsv", + "dsv2json": "bin/dsv2json", + "json2csv": "bin/json2dsv", + "json2dsv": "bin/json2dsv", + "json2tsv": "bin/json2dsv", + "tsv2csv": "bin/dsv2dsv", + "tsv2json": "bin/dsv2json" + } + }, + "node_modules/d3-ease": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz", + "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==", + "dev": true + }, + "node_modules/d3-fetch": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz", + "integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==", + "dev": true, + "dependencies": { + "d3-dsv": "1" + } + }, + "node_modules/d3-force": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz", + "integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==", + "dev": true, + "dependencies": { + "d3-collection": "1", + "d3-dispatch": "1", + "d3-quadtree": "1", + "d3-timer": "1" + } + }, + "node_modules/d3-format": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", + "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==", + "dev": true + }, + "node_modules/d3-geo": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz", + "integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==", + "dev": true, + "dependencies": { + "d3-array": "1" + } + }, + "node_modules/d3-hierarchy": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", + "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==", + "dev": true + }, + "node_modules/d3-interpolate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", + "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", + "dev": true, + "dependencies": { + "d3-color": "1" + } + }, + "node_modules/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "dev": true + }, + "node_modules/d3-polygon": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz", + "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==", + "dev": true + }, + "node_modules/d3-quadtree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz", + "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==", + "dev": true + }, + "node_modules/d3-random": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz", + "integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==", + "dev": true + }, + "node_modules/d3-scale": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz", + "integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==", + "dev": true, + "dependencies": { + "d3-array": "^1.2.0", + "d3-collection": "1", + "d3-format": "1", + "d3-interpolate": "1", + "d3-time": "1", + "d3-time-format": "2" + } + }, + "node_modules/d3-scale-chromatic": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz", + "integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==", + "dev": true, + "dependencies": { + "d3-color": "1", + "d3-interpolate": "1" + } + }, + "node_modules/d3-selection": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz", + "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==", + "dev": true + }, + "node_modules/d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "dev": true, + "dependencies": { + "d3-path": "1" + } + }, + "node_modules/d3-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", + "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==", + "dev": true + }, + "node_modules/d3-time-format": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", + "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", + "dev": true, + "dependencies": { + "d3-time": "1" + } + }, + "node_modules/d3-timer": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", + "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==", + "dev": true + }, + "node_modules/d3-transition": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz", + "integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==", + "dev": true, + "dependencies": { + "d3-color": "1", + "d3-dispatch": "1", + "d3-ease": "1", + "d3-interpolate": "1", + "d3-selection": "^1.1.0", + "d3-timer": "1" + } + }, + "node_modules/d3-voronoi": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", + "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==", + "dev": true + }, + "node_modules/d3-zoom": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz", + "integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==", + "dev": true, + "dependencies": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, + "node_modules/dagre": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", + "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", + "dev": true, + "dependencies": { + "graphlib": "^2.1.8", + "lodash": "^4.17.15" + } + }, + "node_modules/dagre-d3": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/dagre-d3/-/dagre-d3-0.6.4.tgz", + "integrity": "sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ==", + "dev": true, + "dependencies": { + "d3": "^5.14", + "dagre": "^0.8.5", + "graphlib": "^2.1.8", + "lodash": "^4.17.15" + } + }, + "node_modules/dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true + }, + "node_modules/dayjs": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.6.tgz", + "integrity": "sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw==", + "dev": true + }, + "node_modules/de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=", + "dev": true + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "dependencies": { + "mimic-response": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "dependencies": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deepmerge": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", + "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "dev": true, + "dependencies": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/default-user-agent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-user-agent/-/default-user-agent-1.0.0.tgz", + "integrity": "sha1-FsRu/cq6PtxF8k8r1IaLAbfCrcY=", + "dev": true, + "dependencies": { + "os-name": "~1.0.3" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "node_modules/define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.0.12" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/del/node_modules/globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "dependencies": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del/node_modules/globby/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/del/node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "node_modules/dev-null": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dev-null/-/dev-null-0.1.1.tgz", + "integrity": "sha1-WiBc48Ky73e2I41roXnrdMag6Bg=", + "dev": true + }, + "node_modules/diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + } + }, + "node_modules/diffie-hellman/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "dependencies": { + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "node_modules/dns-packet": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", + "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", + "dev": true, + "dependencies": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "dependencies": { + "buffer-indexof": "^1.0.0" + } + }, + "node_modules/docsearch.js": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/docsearch.js/-/docsearch.js-2.6.3.tgz", + "integrity": "sha512-GN+MBozuyz664ycpZY0ecdQE0ND/LSgJKhTLA0/v3arIS3S1Rpf2OJz6A35ReMsm91V5apcmzr5/kM84cvUg+A==", + "dev": true, + "dependencies": { + "algoliasearch": "^3.24.5", + "autocomplete.js": "0.36.0", + "hogan.js": "^3.0.2", + "request": "^2.87.0", + "stack-utils": "^1.0.1", + "to-factory": "^1.0.0", + "zepto": "^1.2.0" + } + }, + "node_modules/dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "dependencies": { + "utila": "~0.4" + } + }, + "node_modules/dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + } + }, + "node_modules/dom-serializer/node_modules/domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/dom-serializer/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", + "dev": true + }, + "node_modules/domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true, + "engines": { + "node": ">=0.4", + "npm": ">=1.2" + } + }, + "node_modules/domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "node_modules/domhandler": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz", + "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==", + "dev": true, + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/domhandler/node_modules/domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/dompurify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.1.tgz", + "integrity": "sha512-xGWt+NHAQS+4tpgbOAI08yxW0Pr256Gu/FNE2frZVTbgrBUn8M7tz7/ktS/LZ2MHeGqz6topj0/xY+y8R5FBFw==", + "dev": true + }, + "node_modules/domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "dependencies": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "node_modules/duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "node_modules/duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "dependencies": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.3.752", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.752.tgz", + "integrity": "sha512-2Tg+7jSl3oPxgsBsWKh5H83QazTkmWG/cnNwJplmyZc7KcN61+I10oUgaXSVk/NwfvN3BdkKDR4FYuRBQQ2v0A==", + "dev": true + }, + "node_modules/elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "dependencies": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/elliptic/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "node_modules/emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/enhanced-resolve/node_modules/memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + }, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "node_modules/envify": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/envify/-/envify-4.1.0.tgz", + "integrity": "sha512-IKRVVoAYr4pIx4yIWNsz9mOsboxlNXiu7TNBnem/K/uTHdkyzXWDzHCK7UTolqBbgaBz0tQHsD3YNls0uIIjiw==", + "dev": true, + "dependencies": { + "esprima": "^4.0.0", + "through": "~2.3.4" + }, + "bin": { + "envify": "bin/envify" + } + }, + "node_modules/envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true, + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/eol": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eol/-/eol-0.2.0.tgz", + "integrity": "sha1-L22whqJDpG4+Xb0OE0Ncfr6/Cd0=", + "dev": true + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/errors": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/errors/-/errors-0.2.0.tgz", + "integrity": "sha1-D1Hoidqj4RsZ5xhtEfEEqmbrJAM=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/es-abstract": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", + "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.3", + "is-string": "^1.0.6", + "object-inspect": "^1.10.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dev": true, + "dependencies": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, + "node_modules/event-stream/node_modules/stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "dependencies": { + "duplexer": "~0.1.1" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "node_modules/events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/eventsource": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.0.tgz", + "integrity": "sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==", + "dev": true, + "dependencies": { + "original": "^1.0.0" + }, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "dependencies": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "dependencies": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expand-brackets/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "dependencies": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express/node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "node_modules/express/node_modules/content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "dependencies": { + "safe-buffer": "5.1.2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express/node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "node_modules/express/node_modules/qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/express/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "node_modules/extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "dependencies": { + "is-extendable": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "dependencies": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extglob/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true, + "engines": [ + "node >=0.6.0" + ] + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "dependencies": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", + "dev": true, + "dependencies": { + "punycode": "^1.3.2" + } + }, + "node_modules/faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "dependencies": { + "websocket-driver": ">=0.5.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/feed": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/feed/-/feed-2.0.4.tgz", + "integrity": "sha512-sWatfulDP6d18qVaWcu34qmq9ml6UeN6nHSBJpNZ2muBqxjPAdT375whPYAHP+gqLfyabtYU5qf2Dv4nqtlp0w==", + "dev": true, + "dependencies": { + "luxon": "^1.3.3", + "xml": "^1.0.1" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/file-loader": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz", + "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==", + "dev": true, + "dependencies": { + "loader-utils": "^1.0.2", + "schema-utils": "^1.0.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/file-loader/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "node_modules/fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/avajs/find-cache-dir?sponsor=1" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "node_modules/follow-redirects": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", + "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "node_modules/forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 0.12" + } + }, + "node_modules/form-data2": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/form-data2/-/form-data2-1.0.4.tgz", + "integrity": "sha512-buz4C3F6/7Vpdxt7dNU/tSfjQO/5z9Pyjfb43VhlVvSos5zVhCcMuW9sF1yJ2FdxZRCD2sWQ9WhqUiYLt+AUVQ==", + "dev": true, + "dependencies": { + "bluebird": "^2.8.2", + "combined-stream2": "^1.0.2", + "debug": "^2.1.1", + "mime": "^1.3.4", + "uuid": "^2.0.1" + } + }, + "node_modules/form-fix-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/form-fix-array/-/form-fix-array-1.0.0.tgz", + "integrity": "sha1-oTR6R+UxF6t7zb8+Lz7JHGZ2m8g=", + "dev": true + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "dependencies": { + "map-cache": "^0.2.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "deprecated": "fsevents 1 will break on node v14+ and could be using insecure binaries. Upgrade to fsevents 2.", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + }, + "engines": { + "node": ">= 4.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0" + } + }, + "node_modules/github-markdown-css": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/github-markdown-css/-/github-markdown-css-3.0.1.tgz", + "integrity": "sha512-9G5CIPsHoyk5ObDsb/H4KTi23J8KE1oDd4KYU51qwqeM+lKWAiO7abpSgCkyWswgmSKBiuE7/4f8xUz7f2qAiQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "dependencies": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + } + }, + "node_modules/glob-parent/node_modules/is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "dev": true + }, + "node_modules/global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "dev": true, + "dependencies": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, + "node_modules/global-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", + "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", + "dev": true, + "dependencies": { + "ini": "1.3.7" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/global-dirs/node_modules/ini": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", + "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", + "dev": true + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/globby": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", + "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", + "dev": true, + "dependencies": { + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "dependencies": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "node_modules/graphlib": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", + "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + } + }, + "node_modules/gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dev": true, + "dependencies": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "node_modules/har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "deprecated": "this library is no longer supported", + "dev": true, + "dependencies": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-ansi/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "dependencies": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-values/node_modules/kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hash-base/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/hash-base/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", + "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", + "dev": true + }, + "node_modules/hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "node_modules/he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true, + "bin": { + "he": "bin/he" + } + }, + "node_modules/hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", + "dev": true + }, + "node_modules/hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "dependencies": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "node_modules/hogan.js": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz", + "integrity": "sha1-TNnhq9QpQUbnZ55B14mHMrAse/0=", + "dev": true, + "dependencies": { + "mkdirp": "0.3.0", + "nopt": "1.0.10" + }, + "bin": { + "hulk": "bin/hulk" + } + }, + "node_modules/hogan.js/node_modules/mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/hogan.js/node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "node_modules/hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", + "dev": true + }, + "node_modules/hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", + "dev": true + }, + "node_modules/html-entities": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", + "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==", + "dev": true + }, + "node_modules/html-minifier": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", + "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", + "dev": true, + "dependencies": { + "camel-case": "3.0.x", + "clean-css": "4.2.x", + "commander": "2.17.x", + "he": "1.2.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" + }, + "bin": { + "html-minifier": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/html-minifier/node_modules/commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + }, + "node_modules/html-tags": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", + "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + } + }, + "node_modules/htmlparser2/node_modules/dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/htmlparser2/node_modules/domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/htmlparser2/node_modules/domutils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz", + "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/htmlparser2/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "node_modules/http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "node_modules/http-equiv-refresh": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-equiv-refresh/-/http-equiv-refresh-1.0.0.tgz", + "integrity": "sha1-jsU4hmBCvl8/evpzfRmNlL6xsHs=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/http-errors/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/http-parser-js": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", + "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==", + "dev": true + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "dev": true, + "dependencies": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "dependencies": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + }, + "engines": { + "node": ">=0.8", + "npm": ">=1.3.7" + } + }, + "node_modules/https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/humanize-duration": { + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/humanize-duration/-/humanize-duration-3.27.0.tgz", + "integrity": "sha512-qLo/08cNc3Tb0uD7jK0jAcU5cnqCM0n568918E7R2XhMr/+7F37p4EY062W/stg7tmzvknNn9b/1+UhVRzsYrQ==", + "dev": true + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", + "dev": true + }, + "node_modules/icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.14" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "node_modules/ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immediate": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", + "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==", + "dev": true + }, + "node_modules/import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "dev": true, + "dependencies": { + "import-from": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "dependencies": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-fresh/node_modules/caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "dependencies": { + "caller-callsite": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", + "dev": true, + "dependencies": { + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "dependencies": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-local/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-local/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-local/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/import-local/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "dev": true, + "dependencies": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "node_modules/ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-arguments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-bigint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "dependencies": { + "binary-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", + "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-browser/-/is-browser-2.1.0.tgz", + "integrity": "sha512-F5rTJxDQ2sW81fcfOR1GnCXT6sVJC104fCyfj+mjpwNEwaPYSn5fte5jiHmBg3DHsIoL/l8Kvw5VN5SsTRcRFQ==", + "dev": true + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "node_modules/is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "dependencies": { + "ci-info": "^2.0.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "dev": true, + "dependencies": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, + "node_modules/is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "dependencies": { + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-date-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", + "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-installed-globally": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", + "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "dev": true, + "dependencies": { + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-npm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", + "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", + "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "dependencies": { + "is-path-inside": "^2.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-in-cwd/node_modules/is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "dependencies": { + "path-is-inside": "^1.0.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-string": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", + "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/isbot": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/isbot/-/isbot-2.5.7.tgz", + "integrity": "sha512-8P+oGrRDvuCpDdovK9oD4skHmSXu56bsK17K2ovXrkW7Ic4H9Y4AqnUUqlXqZxcqQ2358kid9Rb+fbLH5yeeUw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "node_modules/javascript-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz", + "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==", + "dev": true + }, + "node_modules/joi": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.2.tgz", + "integrity": "sha512-Lm56PP+n0+Z2A2rfRvsfWVDXGEWjXxatPopkQ8qQ5mxCEhwHG+Ettgg5o98FFaxilOxozoa14cFhrE/hOzh/Nw==", + "dev": true, + "dependencies": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.0", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "node_modules/jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "node_modules/json3": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", + "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/jsonp/-/jsonp-0.2.1.tgz", + "integrity": "sha1-pltPoPEL2nGaBUQep7lMVfPhW64=", + "dev": true, + "dependencies": { + "debug": "^2.1.3" + } + }, + "node_modules/jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "node_modules/keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.0" + } + }, + "node_modules/khroma": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-1.4.1.tgz", + "integrity": "sha512-+GmxKvmiRuCcUYDgR7g5Ngo0JEDeOsGdNONdU2zsiBQaK4z19Y2NvXqfEDE0ZiIrg45GTZyAnPLVsLZZACYm3Q==", + "dev": true + }, + "node_modules/killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/last-call-webpack-plugin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", + "integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==", + "dev": true, + "dependencies": { + "lodash": "^4.17.5", + "webpack-sources": "^1.1.0" + } + }, + "node_modules/latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "dependencies": { + "package-json": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=", + "dev": true, + "engines": { + "node": "> 0.8" + } + }, + "node_modules/limited-request-queue": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/limited-request-queue/-/limited-request-queue-2.0.0.tgz", + "integrity": "sha1-FMfBILE4BgsZoqEDCrr2aTVyZQ0=", + "dev": true, + "dependencies": { + "is-browser": "^2.0.1", + "parse-domain": "~0.2.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/link-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/link-types/-/link-types-1.1.0.tgz", + "integrity": "sha1-r2XlnbUucMH/sYrEw8sFa/55aDA=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "dependencies": { + "uc.micro": "^1.0.1" + } + }, + "node_modules/load-script": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz", + "integrity": "sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ=", + "dev": true + }, + "node_modules/loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true, + "engines": { + "node": ">=4.3.0 <5.0.0 || >=5.10" + } + }, + "node_modules/loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "dependencies": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/loader-utils/node_modules/json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "node_modules/lodash.chunk": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz", + "integrity": "sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw=", + "dev": true + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, + "node_modules/lodash.defaultsdeep": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", + "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==", + "dev": true + }, + "node_modules/lodash.isempty": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", + "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=", + "dev": true + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=", + "dev": true + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/lodash.padstart": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", + "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=", + "dev": true + }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, + "node_modules/lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "dependencies": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "node_modules/lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "dependencies": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "node_modules/lodash.trimend": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/lodash.trimend/-/lodash.trimend-4.5.1.tgz", + "integrity": "sha1-EoBENyhrmMrYmWt5QU4RMAEUCC8=", + "dev": true + }, + "node_modules/lodash.trimstart": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/lodash.trimstart/-/lodash.trimstart-4.5.1.tgz", + "integrity": "sha1-j/TexTLYJIavWVc8OURZFOlEp/E=", + "dev": true + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "node_modules/loglevel": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", + "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==", + "dev": true, + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, + "node_modules/lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, + "node_modules/lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/luxon": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.0.tgz", + "integrity": "sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, + "node_modules/map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "dependencies": { + "object-visit": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/markdown-it": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", + "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==", + "dev": true, + "dependencies": { + "argparse": "^1.0.7", + "entities": "~1.1.1", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + }, + "bin": { + "markdown-it": "bin/markdown-it.js" + } + }, + "node_modules/markdown-it-anchor": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", + "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", + "dev": true, + "peerDependencies": { + "markdown-it": "*" + } + }, + "node_modules/markdown-it-chain": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-chain/-/markdown-it-chain-1.3.0.tgz", + "integrity": "sha512-XClV8I1TKy8L2qsT9iX3qiV+50ZtcInGXI80CA+DP62sMs7hXlyV/RM3hfwy5O3Ad0sJm9xIwQELgANfESo8mQ==", + "dev": true, + "dependencies": { + "webpack-chain": "^4.9.0" + }, + "engines": { + "node": ">=6.9" + }, + "peerDependencies": { + "markdown-it": ">=5.0.0" + } + }, + "node_modules/markdown-it-chain/node_modules/javascript-stringify": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-1.6.0.tgz", + "integrity": "sha1-FC0RHzpuPa6PSpr9d9RYVbWpzOM=", + "dev": true + }, + "node_modules/markdown-it-chain/node_modules/webpack-chain": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-4.12.1.tgz", + "integrity": "sha512-BCfKo2YkDe2ByqkEWe1Rw+zko4LsyS75LVr29C6xIrxAg9JHJ4pl8kaIZ396SUSNp6b4815dRZPSTAS8LlURRQ==", + "dev": true, + "dependencies": { + "deepmerge": "^1.5.2", + "javascript-stringify": "^1.6.0" + } + }, + "node_modules/markdown-it-container": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-container/-/markdown-it-container-2.0.0.tgz", + "integrity": "sha1-ABm0P9Au7+zi8ZYKKJX7qBpARpU=", + "dev": true + }, + "node_modules/markdown-it-emoji": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/markdown-it-emoji/-/markdown-it-emoji-1.4.0.tgz", + "integrity": "sha1-m+4OmpkKljupbfaYDE/dsF37Tcw=", + "dev": true + }, + "node_modules/markdown-it-footnote": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/markdown-it-footnote/-/markdown-it-footnote-3.0.3.tgz", + "integrity": "sha512-YZMSuCGVZAjzKMn+xqIco9d1cLGxbELHZ9do/TSYVzraooV8ypsppKNmUJ0fVH5ljkCInQAtFpm8Rb3eXSrt5w==", + "dev": true + }, + "node_modules/markdown-it-implicit-figures": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/markdown-it-implicit-figures/-/markdown-it-implicit-figures-0.10.0.tgz", + "integrity": "sha512-1TWr6+apyoJvRa4Z7eIolZdeajZCRBcc1ckVXon7XwdL8MfydIWsHnZOS5zRrpUNX5b0/O9giWcmuItSkleK5A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/markdown-it-table-of-contents": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/markdown-it-table-of-contents/-/markdown-it-table-of-contents-0.4.4.tgz", + "integrity": "sha512-TAIHTHPwa9+ltKvKPWulm/beozQU41Ab+FIefRaQV1NRnpzwcV9QOe6wXQS5WLivm5Q/nlo0rl6laGkMDZE7Gw==", + "dev": true, + "engines": { + "node": ">6.4.0" + } + }, + "node_modules/maybe-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/maybe-callback/-/maybe-callback-2.1.0.tgz", + "integrity": "sha1-ivoLp7aRp6sSPn8S9l4yu10fgkM=", + "dev": true + }, + "node_modules/md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "dev": true + }, + "node_modules/mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/medium-zoom": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/medium-zoom/-/medium-zoom-1.0.6.tgz", + "integrity": "sha512-UdiUWfvz9fZMg1pzf4dcuqA0W079o0mpqbTnOz5ip4VGYX96QjmbM+OgOU/0uOzAytxC0Ny4z+VcYQnhdifimg==", + "dev": true + }, + "node_modules/memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "dependencies": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "node_modules/merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/merge-source-map/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mermaid": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-8.12.1.tgz", + "integrity": "sha512-0UCcSF0FLoNcPBsRF4f9OIV32t41fV18//z8o3S+FDz2PbDA1CRGKdQF9IX84VP4Tv9kcgJI/oqJdcBEtB/GPA==", + "dev": true, + "dependencies": { + "@braintree/sanitize-url": "^3.1.0", + "d3": "^5.16.0", + "dagre": "^0.8.5", + "dagre-d3": "^0.6.4", + "dompurify": "2.3.1", + "graphlib": "^2.1.8", + "khroma": "^1.4.1", + "moment-mini": "^2.24.0", + "stylis": "^4.0.10" + } + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "dependencies": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "bin": { + "miller-rabin": "bin/miller-rabin" + } + }, + "node_modules/miller-rabin/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", + "dev": true, + "dependencies": { + "mime-db": "1.48.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "dev": true, + "dependencies": { + "dom-walk": "^0.1.0" + } + }, + "node_modules/mini-css-extract-plugin": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.6.0.tgz", + "integrity": "sha512-79q5P7YGI6rdnVyIAV4NXpBQJFWdkzJxCim3Kog4078fM0piAaFlwocqbejdWtLW1cEzCexPrh6EdyFsPgVdAw==", + "dev": true, + "dependencies": { + "loader-utils": "^1.1.0", + "normalize-url": "^2.0.1", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.4.0" + } + }, + "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "node_modules/minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "dependencies": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mississippi/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/mississippi/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "dependencies": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mixin-deep/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/moment-mini": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.24.0.tgz", + "integrity": "sha512-9ARkWHBs+6YJIvrIp0Ik5tyTTtP9PoV0Ssu2Ocq5y9v8+NOOpWiRshAp8c4rZVWTOe+157on/5G+zj5pwIQFEQ==", + "dev": true + }, + "node_modules/move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "dependencies": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "node_modules/multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "dependencies": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + }, + "bin": { + "multicast-dns": "cli.js" + } + }, + "node_modules/multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "node_modules/nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true, + "optional": true + }, + "node_modules/nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "dependencies": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nanomatch/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "node_modules/no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "dependencies": { + "lower-case": "^1.1.1" + } + }, + "node_modules/node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "dependencies": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + } + }, + "node_modules/node-libs-browser/node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/node-releases": { + "version": "1.1.73", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", + "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", + "dev": true + }, + "node_modules/nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + } + }, + "node_modules/nopter": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/nopter/-/nopter-0.3.0.tgz", + "integrity": "sha1-uWkOb6uPJWs35OfM0j4rOEUMxx8=", + "deprecated": "try optionator", + "dev": true, + "dependencies": { + "caller-path": "~0.1.0", + "camelcase": "^1.0.2", + "chalk": "~0.5.1", + "cli-table": "~0.3.1", + "eol": "~0.2.0", + "nopt": "^3.0.1", + "object-assign": "^2.0.0", + "splitargs": "~0.0.3" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/nopter/node_modules/ansi-regex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nopter/node_modules/ansi-styles": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nopter/node_modules/chalk": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "dev": true, + "dependencies": { + "ansi-styles": "^1.1.0", + "escape-string-regexp": "^1.0.0", + "has-ansi": "^0.1.0", + "strip-ansi": "^0.3.0", + "supports-color": "^0.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nopter/node_modules/has-ansi": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "dev": true, + "dependencies": { + "ansi-regex": "^0.2.0" + }, + "bin": { + "has-ansi": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nopter/node_modules/strip-ansi": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "dev": true, + "dependencies": { + "ansi-regex": "^0.2.1" + }, + "bin": { + "strip-ansi": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nopter/node_modules/supports-color": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "dev": true, + "bin": { + "supports-color": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "dev": true, + "dependencies": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E=", + "dev": true + }, + "node_modules/nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "dependencies": { + "boolbase": "~1.0.0" + } + }, + "node_modules/num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "node_modules/oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "dependencies": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-copy/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", + "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "dependencies": { + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.getownpropertydescriptors": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz", + "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object.values": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz", + "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "dev": true, + "bin": { + "opencollective-postinstall": "index.js" + } + }, + "node_modules/opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "dependencies": { + "is-wsl": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/opn/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/optimize-css-assets-webpack-plugin": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.8.tgz", + "integrity": "sha512-mgFS1JdOtEGzD8l+EuISqL57cKO+We9GcoiQEmdCWRqqck+FGNmYJtx9qfAPzEz+lRrlThWMuGDaRkI/yWNx/Q==", + "dev": true, + "dependencies": { + "cssnano": "^4.1.10", + "last-call-webpack-plugin": "^3.0.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "dev": true, + "dependencies": { + "url-parse": "^1.4.3" + } + }, + "node_modules/os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "node_modules/os-name": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-1.0.3.tgz", + "integrity": "sha1-GzefZINa98Wn9JizV8uVIVwVnt8=", + "dev": true, + "dependencies": { + "osx-release": "^1.0.0", + "win-release": "^1.0.0" + }, + "bin": { + "os-name": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/osx-release": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/osx-release/-/osx-release-1.1.0.tgz", + "integrity": "sha1-8heRGigTaUmvG/kwiyQeJzfTzWw=", + "dev": true, + "dependencies": { + "minimist": "^1.1.0" + }, + "bin": { + "osx-release": "cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "dependencies": { + "retry": "^0.12.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "dependencies": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/registry-auth-token": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "dev": true, + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/package-json/node_modules/registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "dependencies": { + "rc": "^1.2.8" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/package-json/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "node_modules/parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "dependencies": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "node_modules/param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dev": true, + "dependencies": { + "no-case": "^2.2.0" + } + }, + "node_modules/parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "dependencies": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "node_modules/parse-domain": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-0.2.2.tgz", + "integrity": "sha1-GImJseLnOYv/PE9P19yhV+tR+sE=", + "dev": true + }, + "node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/parse5": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "node_modules/path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", + "dev": true + }, + "node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/path-type/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "dependencies": { + "through": "~2.3" + } + }, + "node_modules/pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "dependencies": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true, + "optional": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "dependencies": { + "pinkie": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "dependencies": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "engines": { + "node": ">= 0.12.0" + } + }, + "node_modules/portfinder/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/portfinder/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss": { + "version": "7.0.36", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", + "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-calc": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.5.tgz", + "integrity": "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" + } + }, + "node_modules/postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-colormin/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-convert-values/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-load-config": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.2.tgz", + "integrity": "sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw==", + "dev": true, + "dependencies": { + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", + "dev": true, + "dependencies": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss-loader/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", + "dev": true, + "dependencies": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-merge-longhand/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-merge-rules/node_modules/postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-font-values/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", + "dev": true, + "dependencies": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-gradients/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", + "dev": true, + "dependencies": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-params/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "dev": true, + "dependencies": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-minify-selectors/node_modules/postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss-modules-local-by-default": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz", + "integrity": "sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0", + "postcss-value-parser": "^3.3.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss-modules-local-by-default/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "dev": true, + "dependencies": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss-modules-values": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz", + "integrity": "sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w==", + "dev": true, + "dependencies": { + "icss-replace-symbols": "^1.1.0", + "postcss": "^7.0.6" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", + "dev": true, + "dependencies": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-display-values/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", + "dev": true, + "dependencies": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-positions/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", + "dev": true, + "dependencies": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-repeat-style/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", + "dev": true, + "dependencies": { + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-string/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", + "dev": true, + "dependencies": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-timing-functions/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-unicode": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-unicode/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", + "dev": true, + "dependencies": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-url/node_modules/normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/postcss-normalize-url/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-normalize-whitespace/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", + "dev": true, + "dependencies": { + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-ordered-values/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", + "dev": true, + "dependencies": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-reduce-transforms/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-safe-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz", + "integrity": "sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g==", + "dev": true, + "dependencies": { + "postcss": "^7.0.26" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz", + "integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.3.tgz", + "integrity": "sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw==", + "dev": true, + "dependencies": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-svgo/node_modules/postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "node_modules/postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "dev": true, + "dependencies": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", + "dev": true + }, + "node_modules/postcss/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/postcss/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/prettier": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "dev": true, + "optional": true, + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/pretty-error": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz", + "integrity": "sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==", + "dev": true, + "dependencies": { + "lodash": "^4.17.20", + "renderkid": "^2.0.4" + } + }, + "node_modules/pretty-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", + "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/prismjs": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.24.0.tgz", + "integrity": "sha512-SqV5GRsNqnzCL8k5dfAjCNhUrF3pR0A9lTDSCUZeh/LIshheXJEaP0hwLz2t4XHivd2J/v2HR+gRnigzeKe3cQ==", + "dev": true + }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true, + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "node_modules/ps-tree": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", + "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", + "dev": true, + "dependencies": { + "event-stream": "=3.3.4" + }, + "bin": { + "ps-tree": "bin/ps-tree.js" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "node_modules/psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "node_modules/public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "dependencies": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "node_modules/public-encrypt/node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + }, + "node_modules/pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "dependencies": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + } + }, + "node_modules/pumpify/node_modules/pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "node_modules/pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "dependencies": { + "escape-goat": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true, + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "dev": true, + "dependencies": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/query-string/node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "dependencies": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "dependencies": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/reduce": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/reduce/-/reduce-1.0.2.tgz", + "integrity": "sha512-xX7Fxke/oHO5IfZSk77lvPa/7bjMh9BuCk4OOoX5XTXrM7s0Z+MkPfSDfz0q7r91BhhGSs8gii/VEN/7zhCPpQ==", + "dev": true, + "dependencies": { + "object-keys": "^1.1.0" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + }, + "node_modules/regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regex-not/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", + "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dev": true, + "dependencies": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "dependencies": { + "rc": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "dev": true + }, + "node_modules/regjsparser": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.9.tgz", + "integrity": "sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ==", + "dev": true, + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/remove-markdown": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/remove-markdown/-/remove-markdown-0.3.0.tgz", + "integrity": "sha1-XktmdJOpNXlyjz1S7MHbnKUF3Jg=", + "dev": true + }, + "node_modules/remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "node_modules/renderkid": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz", + "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==", + "dev": true, + "dependencies": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^3.0.1" + } + }, + "node_modules/renderkid/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/renderkid/node_modules/css-select": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", + "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^5.0.0", + "domhandler": "^4.2.0", + "domutils": "^2.6.0", + "nth-check": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/renderkid/node_modules/css-what": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", + "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/renderkid/node_modules/dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dev": true, + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/renderkid/node_modules/domutils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz", + "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==", + "dev": true, + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/nth-check": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz", + "integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/renderkid/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142", + "dev": true, + "dependencies": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/request/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "dependencies": { + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "deprecated": "https://github.com/lydell/resolve-url#deprecated", + "dev": true + }, + "node_modules/responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "dependencies": { + "lowercase-keys": "^1.0.0" + } + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", + "dev": true + }, + "node_modules/rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", + "dev": true + }, + "node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "dependencies": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "node_modules/robot-directives": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/robot-directives/-/robot-directives-0.3.0.tgz", + "integrity": "sha1-F0+x/8KpuXh3MB6HyJs5X0KdH2U=", + "dev": true, + "dependencies": { + "isbot": "^2.0.0", + "useragent": "^2.1.8" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/robots-txt-guard": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/robots-txt-guard/-/robots-txt-guard-0.1.1.tgz", + "integrity": "sha512-6+nGkE6c2dI9/dmhmNcoMKVwJxlA6sgN/XNo0rm6LLdA0hnj4YkpgrZdhMPl58gJkAqeiHlf4+8tJcLM1tv1Ew==", + "dev": true + }, + "node_modules/robots-txt-parse": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/robots-txt-parse/-/robots-txt-parse-0.0.4.tgz", + "integrity": "sha1-99HzI/eZIdfpxsS70lBI9umBDXE=", + "dev": true, + "dependencies": { + "bluebird": "^2.3.5", + "split": "^0.3.0", + "stream-combiner": "^0.2.1", + "through": "^2.3.4" + } + }, + "node_modules/run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "dependencies": { + "aproba": "^1.1.1" + } + }, + "node_modules/rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=", + "dev": true + }, + "node_modules/rxjs": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.3.0.tgz", + "integrity": "sha512-p2yuGIg9S1epc3vrjKf6iVb3RCaAYjYskkO+jHIaV0IjOPlJop4UnodOoFb2xeNwlguqLYvGw1b1McillYb5Gw==", + "dev": true, + "dependencies": { + "tslib": "~2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "dependencies": { + "ret": "~0.1.10" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "node_modules/schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "dependencies": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "node_modules/selfsigned": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz", + "integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==", + "dev": true, + "dependencies": { + "node-forge": "^0.10.0" + } + }, + "node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "dependencies": { + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/semver-diff/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "dependencies": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "node_modules/send/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/serve/-/serve-12.0.1.tgz", + "integrity": "sha512-CQ4ikLpxg/wmNM7yivulpS6fhjRiFG6OjmP8ty3/c1SBnSk23fpKmLAV4HboTA2KrZhkUPlDfjDhnRmAjQ5Phw==", + "dev": true, + "dependencies": { + "@zeit/schemas": "2.6.0", + "ajv": "6.12.6", + "arg": "2.0.0", + "boxen": "1.3.0", + "chalk": "2.4.1", + "clipboardy": "2.3.0", + "compression": "1.7.3", + "serve-handler": "6.1.3", + "update-check": "1.5.2" + }, + "bin": { + "serve": "bin/serve.js" + } + }, + "node_modules/serve-handler": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", + "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", + "dev": true, + "dependencies": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.0.4", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" + } + }, + "node_modules/serve-handler/node_modules/mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-handler/node_modules/mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "dependencies": { + "mime-db": "~1.33.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "dependencies": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-index/node_modules/http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "dependencies": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/serve-index/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/serve-index/node_modules/setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + }, + "node_modules/serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve/node_modules/chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "node_modules/set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "dependencies": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "node_modules/setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dev": true, + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + }, + "node_modules/sitemap": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-3.2.2.tgz", + "integrity": "sha512-TModL/WU4m2q/mQcrDgNANn0P4LwprM9MMvG4hu5zP4c6IIKs2YLTu6nXXnNr8ODW/WFtxKggiJ1EGn2W0GNmg==", + "dev": true, + "dependencies": { + "lodash.chunk": "^4.2.0", + "lodash.padstart": "^4.6.1", + "whatwg-url": "^7.0.0", + "xmlbuilder": "^13.0.0" + }, + "engines": { + "node": ">=6.0.0", + "npm": ">=4.0.0" + } + }, + "node_modules/slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/smoothscroll-polyfill": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/smoothscroll-polyfill/-/smoothscroll-polyfill-0.4.4.tgz", + "integrity": "sha512-TK5ZA9U5RqCwMpfoMq/l1mrH0JAR7y7KRvOBx0n2869aLxch+gT9GhN3yUfjiw+d/DiF1mKo14+hd62JyMmoBg==", + "dev": true + }, + "node_modules/snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "dependencies": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "dependencies": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-node/node_modules/define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "dependencies": { + "is-descriptor": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "dependencies": { + "kind-of": "^3.2.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon-util/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/snapdragon/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sockjs": { + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz", + "integrity": "sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==", + "dev": true, + "dependencies": { + "faye-websocket": "^0.11.3", + "uuid": "^3.4.0", + "websocket-driver": "^0.7.4" + } + }, + "node_modules/sockjs-client": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.1.tgz", + "integrity": "sha512-VnVAb663fosipI/m6pqRXakEOw7nvd7TUgdr3PlR/8V2I95QIdwT8L4nMxhyU8SmDBHYXU1TOElaKOmKLfYzeQ==", + "dev": true, + "dependencies": { + "debug": "^3.2.6", + "eventsource": "^1.0.7", + "faye-websocket": "^0.11.3", + "inherits": "^2.0.4", + "json3": "^3.3.3", + "url-parse": "^1.5.1" + } + }, + "node_modules/sockjs-client/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/sockjs-client/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/sockjs/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "dev": true, + "dependencies": { + "is-plain-obj": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "dependencies": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "dev": true + }, + "node_modules/spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "dependencies": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + } + }, + "node_modules/spdy-transport/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy-transport/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/spdy-transport/node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/spdy/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/spdy/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dev": true, + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "dependencies": { + "extend-shallow": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-string/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/splitargs": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/splitargs/-/splitargs-0.0.7.tgz", + "integrity": "sha1-/p965lc3GzOxDLgNoUPPgknPazs=", + "dev": true + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "node_modules/squarecrypto-vuepress-devkit-theme": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/squarecrypto-vuepress-devkit-theme/-/squarecrypto-vuepress-devkit-theme-0.1.10.tgz", + "integrity": "sha512-W6P3sHVD4m3f+AoYiEXaCmWn4Fcmw8Gmr4BeRDuu860AsHOHY1WxuRU5zJuBPFpCCWdzvEgiY6ct8ZdmAHlMnQ==", + "dev": true, + "dependencies": { + "@vuepress/plugin-back-to-top": "1.8.2", + "@vuepress/plugin-blog": "1.9.4", + "@vuepress/plugin-medium-zoom": "1.8.2", + "@vuepress/plugin-search": "1.8.2", + "@vuepress/theme-default": "1.8.2", + "lodash": "4.17.21", + "markdown-it-footnote": "3.0.3", + "markdown-it-implicit-figures": "0.10.0", + "vue-tabs-component": "1.5.0", + "vuepress-plugin-clean-urls": "1.1.2", + "vuepress-plugin-code-copy": "1.0.6", + "vuepress-plugin-mermaidjs": "^1.8.1", + "vuepress-plugin-seo": "0.1.4", + "vuepress-plugin-sitemap": "2.3.1", + "vuepress-plugin-tabs": "0.3.0" + } + }, + "node_modules/sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "dependencies": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + }, + "bin": { + "sshpk-conv": "bin/sshpk-conv", + "sshpk-sign": "bin/sshpk-sign", + "sshpk-verify": "bin/sshpk-verify" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "dependencies": { + "figgy-pudding": "^3.5.1" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "node_modules/stack-utils": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.5.tgz", + "integrity": "sha512-KZiTzuV3CnSnSvgMRrARVCj+Ht7rMbauGDK0LdVFRGyenwdylpajAp4Q0i6SX8rEmbTpMMf6ryq2gb8pPq2WgQ==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/start-server-and-test": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-1.14.0.tgz", + "integrity": "sha512-on5ELuxO2K0t8EmNj9MtVlFqwBMxfWOhu4U7uZD1xccVpFlOQKR93CSe0u98iQzfNxRyaNTb/CdadbNllplTsw==", + "dev": true, + "dependencies": { + "bluebird": "3.7.2", + "check-more-types": "2.24.0", + "debug": "4.3.2", + "execa": "5.1.1", + "lazy-ass": "1.6.0", + "ps-tree": "1.2.0", + "wait-on": "6.0.0" + }, + "bin": { + "server-test": "src/bin/start.js", + "start-server-and-test": "src/bin/start.js", + "start-test": "src/bin/start.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/start-server-and-test/node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "node_modules/start-server-and-test/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/start-server-and-test/node_modules/debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/start-server-and-test/node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/start-server-and-test/node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/start-server-and-test/node_modules/is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/start-server-and-test/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/start-server-and-test/node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/start-server-and-test/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/start-server-and-test/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/start-server-and-test/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/start-server-and-test/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "dependencies": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "dependencies": { + "is-descriptor": "^0.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "dependencies": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/static-extend/node_modules/kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/std-env": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-2.3.0.tgz", + "integrity": "sha512-4qT5B45+Kjef2Z6pE0BkskzsH0GO7GrND0wGlTM1ioUe3v0dGYx9ZJH0Aro/YyA8fqQ5EyIKDRjZojJYMFTflw==", + "dev": true, + "dependencies": { + "ci-info": "^3.0.0" + } + }, + "node_modules/std-env/node_modules/ci-info": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", + "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", + "dev": true + }, + "node_modules/stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "dependencies": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "node_modules/stream-combiner": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", + "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", + "dev": true, + "dependencies": { + "duplexer": "~0.1.1", + "through": "~2.3.4" + } + }, + "node_modules/stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "dependencies": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "node_modules/stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "dependencies": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + } + }, + "node_modules/stream-http/node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/stream-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-length/-/stream-length-1.0.2.tgz", + "integrity": "sha1-gnfzy+5JpNqrz9tOL0qbXp8snwA=", + "dev": true, + "dependencies": { + "bluebird": "^2.6.2" + } + }, + "node_modules/stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "node_modules/strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/striptags": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/striptags/-/striptags-3.1.1.tgz", + "integrity": "sha1-yMPn/db7S7OjKjt1LltePjgJPr0=", + "dev": true + }, + "node_modules/stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", + "dev": true, + "dependencies": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/stylehacks/node_modules/postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "dependencies": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stylis": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.10.tgz", + "integrity": "sha512-m3k+dk7QeJw660eIKRRn3xPF6uuvHs/FFzjX3HQ5ove0qYsiygoAhwn5a3IYKaZPo5LrYD0rfVmtv1gNY1uYwg==", + "dev": true + }, + "node_modules/stylus": { + "version": "0.54.8", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.8.tgz", + "integrity": "sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg==", + "dev": true, + "dependencies": { + "css-parse": "~2.0.0", + "debug": "~3.1.0", + "glob": "^7.1.6", + "mkdirp": "~1.0.4", + "safer-buffer": "^2.1.2", + "sax": "~1.2.4", + "semver": "^6.3.0", + "source-map": "^0.7.3" + }, + "bin": { + "stylus": "bin/stylus" + }, + "engines": { + "node": "*" + } + }, + "node_modules/stylus-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz", + "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==", + "dev": true, + "dependencies": { + "loader-utils": "^1.0.2", + "lodash.clonedeep": "^4.5.0", + "when": "~3.6.x" + }, + "peerDependencies": { + "stylus": ">=0.52.4" + } + }, + "node_modules/stylus/node_modules/debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/stylus/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stylus/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/stylus/node_modules/source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", + "dev": true + }, + "node_modules/svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "dev": true, + "dependencies": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "dependencies": { + "execa": "^0.7.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/term-size/node_modules/cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "dependencies": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "node_modules/term-size/node_modules/execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "dependencies": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/term-size/node_modules/get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "dependencies": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^4.0.0" + } + }, + "node_modules/terser-webpack-plugin/node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser-webpack-plugin/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser-webpack-plugin/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/terser-webpack-plugin/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser-webpack-plugin/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser-webpack-plugin/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser-webpack-plugin/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/terser-webpack-plugin/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/terser-webpack-plugin/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/terser/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "node_modules/through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "dependencies": { + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" + } + }, + "node_modules/through2-sink": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/through2-sink/-/through2-sink-1.0.0.tgz", + "integrity": "sha1-XxBruh1zMNrTy6XAqxhjkjJWw5k=", + "dev": true, + "dependencies": { + "through2": "~0.5.1", + "xtend": "~3.0.0" + } + }, + "node_modules/through2-spy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/through2-spy/-/through2-spy-1.2.0.tgz", + "integrity": "sha1-nIkcqcpA4eHkzzHhrFf5TMnSSMs=", + "dev": true, + "dependencies": { + "through2": "~0.5.1", + "xtend": "~3.0.0" + } + }, + "node_modules/through2/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "node_modules/through2/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "node_modules/through2/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "node_modules/thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "node_modules/timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "dependencies": { + "setimmediate": "^1.0.4" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "node_modules/to-factory": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-factory/-/to-factory-1.0.0.tgz", + "integrity": "sha1-hzivi9lxIK0dQEeXKtpVY7+UebE=", + "dev": true + }, + "node_modules/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "dependencies": { + "kind-of": "^3.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-object-path/node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "dependencies": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "dependencies": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "dependencies": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/to-regex/node_modules/is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "dependencies": { + "is-plain-object": "^2.0.4" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==", + "dev": true + }, + "node_modules/toposort": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", + "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", + "dev": true + }, + "node_modules/tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "dependencies": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tough-cookie/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/tr46/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + }, + "node_modules/tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "node_modules/typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "dependencies": { + "is-typedarray": "^1.0.0" + } + }, + "node_modules/uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "node_modules/uglify-js": { + "version": "3.4.10", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", + "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", + "dev": true, + "dependencies": { + "commander": "~2.19.0", + "source-map": "~0.6.1" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uglify-js/node_modules/commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + }, + "node_modules/uglify-js/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "dependencies": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "node_modules/uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "dev": true + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", + "dev": true + }, + "node_modules/unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "dependencies": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "dependencies": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-value/node_modules/isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "dependencies": { + "isarray": "1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/unset-value/node_modules/has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/update-check": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.2.tgz", + "integrity": "sha512-1TrmYLuLj/5ZovwUS7fFd1jMH3NnFDN1y1A8dboedIDt7zs/zJMo6TwwlhYKkSeEwzleeiSBV5/3c9ufAQWDaQ==", + "dev": true, + "dependencies": { + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0" + } + }, + "node_modules/update-notifier": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", + "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", + "dev": true, + "dependencies": { + "boxen": "^4.2.0", + "chalk": "^3.0.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.3.1", + "is-npm": "^4.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "pupa": "^2.0.1", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/yeoman/update-notifier?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "dev": true, + "dependencies": { + "string-width": "^3.0.0" + } + }, + "node_modules/update-notifier/node_modules/ansi-align/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/update-notifier/node_modules/ansi-align/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/update-notifier/node_modules/ansi-align/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/update-notifier/node_modules/ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-notifier/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/update-notifier/node_modules/boxen": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "dev": true, + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "cli-boxes": "^2.2.0", + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/update-notifier/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-notifier/node_modules/cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/update-notifier/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/update-notifier/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-notifier/node_modules/string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-notifier/node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/update-notifier/node_modules/string-width/node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-notifier/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-notifier/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-notifier/node_modules/term-size": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/update-notifier/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/update-notifier/node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "deprecated": "Please see https://github.com/lydell/urix#deprecated", + "dev": true + }, + "node_modules/url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "dependencies": { + "punycode": "1.3.2", + "querystring": "0.2.0" + } + }, + "node_modules/url-loader": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz", + "integrity": "sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==", + "dev": true, + "dependencies": { + "loader-utils": "^1.1.0", + "mime": "^2.0.3", + "schema-utils": "^1.0.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^3.0.0 || ^4.0.0" + } + }, + "node_modules/url-loader/node_modules/mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/url-loader/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/url-parse": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz", + "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==", + "dev": true, + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "node_modules/url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "dependencies": { + "prepend-http": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/url/node_modules/punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + }, + "node_modules/urlcache": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/urlcache/-/urlcache-0.7.0.tgz", + "integrity": "sha512-xOW4t6wJDT07+VunsHwePemyXXRidCSOZ/1RIILJi2XnB+81FA5H0MRvS63/7joTWjGLajcJJGvR5odpbkV6hw==", + "dev": true, + "dependencies": { + "urlobj": "0.0.11" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/urlobj": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/urlobj/-/urlobj-0.0.11.tgz", + "integrity": "sha512-Ncck0WWtuFBbZhSYwKjK1AU2V51V98P/KHUPkaEc+mFy4xkpAHFNyVQT+S5SgtsJAr94e4wiKUucJSfasV2kBw==", + "deprecated": "use universal-url, minurl, relateurl, url-relation", + "dev": true, + "dependencies": { + "is-object": "^1.0.1", + "is-string": "^1.0.4", + "object-assign": "^4.1.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/urlobj/node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/useragent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "dev": true, + "dependencies": { + "lru-cache": "4.1.x", + "tmp": "0.0.x" + } + }, + "node_modules/util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "dependencies": { + "inherits": "2.0.3" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/util/node_modules/inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "node_modules/utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vendors": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", + "dev": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "node_modules/vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "node_modules/vssue": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/vssue/-/vssue-1.4.8.tgz", + "integrity": "sha512-Stp0CxF65Uv658qgYUgYKEDiWM8wskUfKCOT9ISJwz/Qn58N050vYnFYClnUXG060ZQi1YQxkTCuJAw8ee3YlQ==", + "dev": true, + "dependencies": { + "@vssue/utils": "^1.4.7", + "github-markdown-css": "^3.0.1", + "vue": "^2.6.10", + "vue-i18n": "^8.11.2", + "vue-property-decorator": "^8.1.1" + } + }, + "node_modules/vue": { + "version": "2.6.14", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.14.tgz", + "integrity": "sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ==", + "dev": true + }, + "node_modules/vue-class-component": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/vue-class-component/-/vue-class-component-7.2.6.tgz", + "integrity": "sha512-+eaQXVrAm/LldalI272PpDe3+i4mPis0ORiMYxF6Ae4hyuCh15W8Idet7wPUEs4N4YptgFHGys4UrgNQOMyO6w==", + "dev": true, + "peerDependencies": { + "vue": "^2.0.0" + } + }, + "node_modules/vue-disqus": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/vue-disqus/-/vue-disqus-3.0.5.tgz", + "integrity": "sha512-T3Y68lXf5W2lYt6j4Y3kZ4opLPH0EAzqriy11MS4D4Q2+UN0tFuUXeYP1MxfvdyaCEboXSM6CUswxsULuNV70Q==", + "dev": true + }, + "node_modules/vue-hot-reload-api": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", + "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", + "dev": true + }, + "node_modules/vue-i18n": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.25.0.tgz", + "integrity": "sha512-ynhcL+PmTxuuSE1T10htiSXzjBozxYIE3ffbM1RfgAkVbr/v1SP+9Mi/7/uv8ZVV1yGuKjFAYp9BXq+X7op6MQ==", + "dev": true + }, + "node_modules/vue-loader": { + "version": "15.9.7", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.7.tgz", + "integrity": "sha512-qzlsbLV1HKEMf19IqCJqdNvFJRCI58WNbS6XbPqK13MrLz65es75w392MSQ5TsARAfIjUw+ATm3vlCXUJSOH9Q==", + "dev": true, + "dependencies": { + "@vue/component-compiler-utils": "^3.1.0", + "hash-sum": "^1.0.2", + "loader-utils": "^1.1.0", + "vue-hot-reload-api": "^2.3.0", + "vue-style-loader": "^4.1.0" + }, + "peerDependencies": { + "css-loader": "*", + "webpack": "^3.0.0 || ^4.1.0 || ^5.0.0-0" + }, + "peerDependenciesMeta": { + "cache-loader": { + "optional": true + }, + "vue-template-compiler": { + "optional": true + } + } + }, + "node_modules/vue-property-decorator": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/vue-property-decorator/-/vue-property-decorator-8.5.1.tgz", + "integrity": "sha512-O6OUN2OMsYTGPvgFtXeBU3jPnX5ffQ9V4I1WfxFQ6dqz6cOUbR3Usou7kgFpfiXDvV7dJQSFcJ5yUPgOtPPm1Q==", + "dev": true, + "dependencies": { + "vue-class-component": "^7.1.0" + }, + "peerDependencies": { + "vue": "*" + } + }, + "node_modules/vue-router": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.1.tgz", + "integrity": "sha512-RRQNLT8Mzr8z7eL4p7BtKvRaTSGdCbTy2+Mm5HTJvLGYSSeG9gDzNasJPP/yOYKLy+/cLG/ftrqq5fvkFwBJEw==", + "dev": true + }, + "node_modules/vue-server-renderer": { + "version": "2.6.14", + "resolved": "https://registry.npmjs.org/vue-server-renderer/-/vue-server-renderer-2.6.14.tgz", + "integrity": "sha512-HifYRa/LW7cKywg9gd4ZtvtRuBlstQBao5ZCWlg40fyB4OPoGfEXAzxb0emSLv4pBDOHYx0UjpqvxpiQFEuoLA==", + "dev": true, + "dependencies": { + "chalk": "^1.1.3", + "hash-sum": "^1.0.2", + "he": "^1.1.0", + "lodash.template": "^4.5.0", + "lodash.uniq": "^4.5.0", + "resolve": "^1.2.0", + "serialize-javascript": "^3.1.0", + "source-map": "0.5.6" + } + }, + "node_modules/vue-server-renderer/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vue-server-renderer/node_modules/ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vue-server-renderer/node_modules/chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "dependencies": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vue-server-renderer/node_modules/serialize-javascript": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", + "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/vue-server-renderer/node_modules/source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vue-server-renderer/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vue-server-renderer/node_modules/supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/vue-style-loader": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", + "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==", + "dev": true, + "dependencies": { + "hash-sum": "^1.0.2", + "loader-utils": "^1.0.2" + } + }, + "node_modules/vue-tabs-component": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/vue-tabs-component/-/vue-tabs-component-1.5.0.tgz", + "integrity": "sha512-ld4p+hv49Fimw+zv/7GQqMhbjAHjpbWF3UiJtmMaSnvLKbsB1ysfs9dQH0SZ8NvdYpqqKay/VLIqR9yXgse1Sg==", + "dev": true, + "peerDependencies": { + "vue": "^2.3.0" + } + }, + "node_modules/vue-template-compiler": { + "version": "2.6.14", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz", + "integrity": "sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g==", + "dev": true, + "dependencies": { + "de-indent": "^1.0.2", + "he": "^1.1.0" + } + }, + "node_modules/vue-template-es2015-compiler": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", + "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", + "dev": true + }, + "node_modules/vuejs-paginate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vuejs-paginate/-/vuejs-paginate-2.1.0.tgz", + "integrity": "sha512-gnwyXlmCiDOu9MLWxN5UJ4PGijKGNOMpHG8ujsrynCzTJljn/rp7Jq0WiDGDAMi5/u0AHuYIHhced+tUW4jblA==", + "dev": true + }, + "node_modules/vuepress": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/vuepress/-/vuepress-1.8.2.tgz", + "integrity": "sha512-BU1lUDwsA3ghf7a9ga4dsf0iTc++Z/l7BR1kUagHWVBHw7HNRgRDfAZBDDQXhllMILVToIxaTifpne9mSi94OA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@vuepress/core": "1.8.2", + "@vuepress/theme-default": "1.8.2", + "cac": "^6.5.6", + "envinfo": "^7.2.0", + "opencollective-postinstall": "^2.0.2", + "update-notifier": "^4.0.0" + }, + "bin": { + "vuepress": "cli.js" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/vuepress-html-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vuepress-html-webpack-plugin/-/vuepress-html-webpack-plugin-3.2.0.tgz", + "integrity": "sha512-BebAEl1BmWlro3+VyDhIOCY6Gef2MCBllEVAP3NUAtMguiyOwo/dClbwJ167WYmcxHJKLl7b0Chr9H7fpn1d0A==", + "dev": true, + "dependencies": { + "html-minifier": "^3.2.3", + "loader-utils": "^0.2.16", + "lodash": "^4.17.3", + "pretty-error": "^2.0.2", + "tapable": "^1.0.0", + "toposort": "^1.0.0", + "util.promisify": "1.0.0" + }, + "engines": { + "node": ">=6.9" + }, + "peerDependencies": { + "webpack": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0" + } + }, + "node_modules/vuepress-html-webpack-plugin/node_modules/big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/vuepress-html-webpack-plugin/node_modules/emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vuepress-html-webpack-plugin/node_modules/json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/vuepress-html-webpack-plugin/node_modules/loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "dependencies": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } + }, + "node_modules/vuepress-html-webpack-plugin/node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vuepress-html-webpack-plugin/node_modules/util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, + "node_modules/vuepress-plugin-clean-urls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vuepress-plugin-clean-urls/-/vuepress-plugin-clean-urls-1.1.2.tgz", + "integrity": "sha512-36r6XT9stybGSL9zHfFM6F+EBOF9rRDzGdNeias3AmU3AH5+DqsciMjRpHfecKXDKeVcc0PlNfG1Tf19CW5MzA==", + "dev": true + }, + "node_modules/vuepress-plugin-code-copy": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/vuepress-plugin-code-copy/-/vuepress-plugin-code-copy-1.0.6.tgz", + "integrity": "sha512-FiqwMtlb4rEsOI56O6sSkekcd3SlESxbkR2IaTIQxsMOMoalKfW5R9WlR1Pjm10v6jmU661Ex8MR11k9IzrNUg==", + "dev": true + }, + "node_modules/vuepress-plugin-container": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/vuepress-plugin-container/-/vuepress-plugin-container-2.1.5.tgz", + "integrity": "sha512-TQrDX/v+WHOihj3jpilVnjXu9RcTm6m8tzljNJwYhxnJUW0WWQ0hFLcDTqTBwgKIFdEiSxVOmYE+bJX/sq46MA==", + "dev": true, + "dependencies": { + "@vuepress/shared-utils": "^1.2.0", + "markdown-it-container": "^2.0.0" + } + }, + "node_modules/vuepress-plugin-disqus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/vuepress-plugin-disqus/-/vuepress-plugin-disqus-0.2.0.tgz", + "integrity": "sha512-kx+AeVzjJ9lx9bufLt1/X35V1VXfnQ1srkDMIzFKD9NyQ3eycsWQRcGO1dFe1HMrY3+7fTu+1/JeUEUEpGZ5tw==", + "dev": true, + "dependencies": { + "vue-disqus": "^3.0.5" + } + }, + "node_modules/vuepress-plugin-feed": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/vuepress-plugin-feed/-/vuepress-plugin-feed-0.1.9.tgz", + "integrity": "sha512-iOJkR7zPmJAX0TEVdxNsUT07xNQB6lZFpU7DqsYzO01FhaPkMOOVM5Vx5a/iOOuOggAeoI9H9yuah+cRmCImlw==", + "dev": true, + "dependencies": { + "feed": "2.0.4", + "lodash.defaultsdeep": "4.6.1", + "lodash.isempty": "4.4.0", + "lodash.trimend": "^4.5.1", + "lodash.trimstart": "^4.5.1", + "remove-markdown": "0.3.0", + "striptags": "3.1.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "vuepress": "1.x" + } + }, + "node_modules/vuepress-plugin-mailchimp": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/vuepress-plugin-mailchimp/-/vuepress-plugin-mailchimp-1.4.2.tgz", + "integrity": "sha512-4t5ZaKZXu5ZkwgE+WW//7CgXgz6DEhRefGrO5aql4PwapauNXlHKgQ2JMf9FRe5y5WHjNpDHYveEDNzISZmxJw==", + "dev": true, + "dependencies": { + "jsonp": "^0.2.1", + "query-string": "^6.9.0" + } + }, + "node_modules/vuepress-plugin-mailchimp/node_modules/query-string": { + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", + "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", + "dev": true, + "dependencies": { + "decode-uri-component": "^0.2.0", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vuepress-plugin-mailchimp/node_modules/strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/vuepress-plugin-mermaidjs": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/vuepress-plugin-mermaidjs/-/vuepress-plugin-mermaidjs-1.8.1.tgz", + "integrity": "sha512-gVnl2t2cbTd0ZWqikZzPPIjBvvcSKzAcuiON96Fi6RQo0QzIpjzXxuIp9bZ+tFUHn6UZp6hqqPtOdbsgcajilg==", + "dev": true, + "dependencies": { + "mermaid": "^8.8.3" + } + }, + "node_modules/vuepress-plugin-seo": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/vuepress-plugin-seo/-/vuepress-plugin-seo-0.1.4.tgz", + "integrity": "sha512-foNKrAAKihiC47bx0UXFzs/+BIFmnowTQsLVF/8pfsnsPDp8FXjkTGyjxyjOhbwj7ADPv32CdX3pEoYGnZ7OjA==", + "dev": true + }, + "node_modules/vuepress-plugin-sitemap": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/vuepress-plugin-sitemap/-/vuepress-plugin-sitemap-2.3.1.tgz", + "integrity": "sha512-n+8lbukhrKrsI9H/EX0EBgkE1pn85LAQFvQ5dIvrZP4Kz6JxPOPPNTQmZMhahQV1tXbLZQCEN7A1WZH4x+arJQ==", + "dev": true, + "dependencies": { + "sitemap": "^3.0.0" + }, + "bin": { + "vuepress-sitemap": "cli.js" + }, + "peerDependencies": { + "chalk": "^2.0.0", + "commander": "^2.0.0", + "esm": "^3.0.0" + } + }, + "node_modules/vuepress-plugin-smooth-scroll": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/vuepress-plugin-smooth-scroll/-/vuepress-plugin-smooth-scroll-0.0.3.tgz", + "integrity": "sha512-qsQkDftLVFLe8BiviIHaLV0Ea38YLZKKonDGsNQy1IE0wllFpFIEldWD8frWZtDFdx6b/O3KDMgVQ0qp5NjJCg==", + "dev": true, + "dependencies": { + "smoothscroll-polyfill": "^0.4.3" + } + }, + "node_modules/vuepress-plugin-tabs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/vuepress-plugin-tabs/-/vuepress-plugin-tabs-0.3.0.tgz", + "integrity": "sha512-jooDlcMdBqhXgIaF1awFSaOTM56mleP6bbCiGxyQxTZexfvCfDvZhNLGpyXqMQA50ZmNGmvLrK82YYb63k1jfA==", + "dev": true + }, + "node_modules/wait-on": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.0.tgz", + "integrity": "sha512-tnUJr9p5r+bEYXPUdRseolmz5XqJTTj98JgOsfBn7Oz2dxfE2g3zw1jE+Mo8lopM3j3et/Mq1yW7kKX6qw7RVw==", + "dev": true, + "dependencies": { + "axios": "^0.21.1", + "joi": "^17.4.0", + "lodash": "^4.17.21", + "minimist": "^1.2.5", + "rxjs": "^7.1.0" + }, + "bin": { + "wait-on": "bin/wait-on" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0" + }, + "optionalDependencies": { + "chokidar": "^3.4.1", + "watchpack-chokidar2": "^2.0.1" + } + }, + "node_modules/watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "dev": true, + "optional": true, + "dependencies": { + "chokidar": "^2.1.8" + } + }, + "node_modules/watchpack/node_modules/anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "optional": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/watchpack/node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/watchpack/node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "optional": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/watchpack/node_modules/chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "dev": true, + "optional": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/watchpack/node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "optional": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/watchpack/node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/watchpack/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "optional": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/watchpack/node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "optional": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/watchpack/node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "optional": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/watchpack/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "optional": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/watchpack/node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "optional": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "dependencies": { + "minimalistic-assert": "^1.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "node_modules/webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "dependencies": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + }, + "webpack-command": { + "optional": true + } + } + }, + "node_modules/webpack-chain": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.5.1.tgz", + "integrity": "sha512-7doO/SRtLu8q5WM0s7vPKPWX580qhi0/yBHkOxNkv50f6qB76Zy9o2wRTrrPULqYTvQlVHuvbA8v+G5ayuUDsA==", + "dev": true, + "dependencies": { + "deepmerge": "^1.5.2", + "javascript-stringify": "^2.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/webpack-dev-middleware": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", + "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", + "dev": true, + "dependencies": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/webpack-dev-middleware/node_modules/mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/webpack-dev-middleware/node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/webpack-dev-server": { + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz", + "integrity": "sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ==", + "dev": true, + "dependencies": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.3.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.8", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.26", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.8", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "sockjs-client": "^1.5.0", + "spdy": "^4.0.2", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "^13.3.2" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 6.11.5" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "dependencies": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/webpack-dev-server/node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/webpack-dev-server/node_modules/debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server/node_modules/debug/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "node_modules/webpack-dev-server/node_modules/is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/webpack-dev-server/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/webpack-dev-server/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/webpack-dev-server/node_modules/strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "dependencies": { + "ansi-regex": "^2.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack-dev-server/node_modules/supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "dependencies": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/webpack-log/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/webpack-merge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", + "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", + "dev": true, + "dependencies": { + "lodash": "^4.17.15" + } + }, + "node_modules/webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "dependencies": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + } + }, + "node_modules/webpack-sources/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webpack/node_modules/schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "dependencies": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/webpackbar": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-3.2.0.tgz", + "integrity": "sha512-PC4o+1c8gWWileUfwabe0gqptlXUDJd5E0zbpr2xHP1VSOVlZVPBZ8j6NCR8zM5zbKdxPhctHXahgpNK1qFDPw==", + "dev": true, + "dependencies": { + "ansi-escapes": "^4.1.0", + "chalk": "^2.4.1", + "consola": "^2.6.0", + "figures": "^3.0.0", + "pretty-time": "^1.1.0", + "std-env": "^2.2.1", + "text-table": "^0.2.0", + "wrap-ansi": "^5.1.0" + }, + "engines": { + "node": ">= 6.9.0" + }, + "peerDependencies": { + "webpack": "^3.0.0 || ^4.0.0" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/when": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz", + "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=", + "dev": true + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "node_modules/widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "dev": true, + "dependencies": { + "string-width": "^2.1.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/win-release": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz", + "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", + "dev": true, + "dependencies": { + "semver": "^5.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "dependencies": { + "errno": "~0.1.7" + } + }, + "node_modules/wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "dev": true, + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", + "dev": true + }, + "node_modules/xmlbuilder": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", + "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==", + "dev": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "node_modules/yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "dependencies": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + } + }, + "node_modules/yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + }, + "node_modules/yargs-parser/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/yargs/node_modules/string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "dependencies": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/zepto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zepto/-/zepto-1.2.0.tgz", + "integrity": "sha1-4Se9nmb9hGvl6rSME5SIL3wOT5g=", + "dev": true + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", + "integrity": "sha512-9pzDqyc6OLDaqe+zbACgFkb6fKMNG6CObKpnYXChRsvYGyEdc7CA2BaqeOM+vOtCS5ndmJicPJhKAwYRI6UfFw==", + "dev": true, + "requires": { + "@babel/highlight": "^7.14.5" + } + }, + "@babel/compat-data": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.5.tgz", + "integrity": "sha512-kixrYn4JwfAVPa0f2yfzc2AWti6WRRyO3XjWW5PJAvtE11qhSayrrcrEnee05KAtNaPC+EwehE8Qt1UedEVB8w==", + "dev": true + }, + "@babel/core": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.14.6.tgz", + "integrity": "sha512-gJnOEWSqTk96qG5BoIrl5bVtc23DCycmIePPYnamY9RboYdI4nFy5vAQMSl81O5K/W0sLDWfGysnOECC+KUUCA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.14.5", + "@babel/helper-compilation-targets": "^7.14.5", + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helpers": "^7.14.6", + "@babel/parser": "^7.14.6", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5", + "convert-source-map": "^1.7.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.1.2", + "semver": "^6.3.0", + "source-map": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.5.tgz", + "integrity": "sha512-y3rlP+/G25OIX3mYKKIOlQRcqj7YgrvHxOLbVmyLJ9bPmi5ttvUmpydVjcFjZphOktWuA7ovbx91ECloWTfjIA==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, + "@babel/helper-annotate-as-pure": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.14.5.tgz", + "integrity": "sha512-EivH9EgBIb+G8ij1B2jAwSH36WnGvkQSEC6CkX/6v6ZFlw5fVOHvsgGF4uiEHO2GzMvunZb6tDLQEQSdrdocrA==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.14.5.tgz", + "integrity": "sha512-YTA/Twn0vBXDVGJuAX6PwW7x5zQei1luDDo2Pl6q1qZ7hVNl0RZrhHCQG/ArGpR29Vl7ETiB8eJyrvpuRp300w==", + "dev": true, + "requires": { + "@babel/helper-explode-assignable-expression": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-compilation-targets": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.5.tgz", + "integrity": "sha512-v+QtZqXEiOnpO6EYvlImB6zCD2Lel06RzOPzmkz/D/XgQiUu3C/Jb1LOqSt/AIA34TYi/Q+KlT8vTQrgdxkbLw==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.14.5", + "@babel/helper-validator-option": "^7.14.5", + "browserslist": "^4.16.6", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/helper-create-class-features-plugin": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.6.tgz", + "integrity": "sha512-Z6gsfGofTxH/+LQXqYEK45kxmcensbzmk/oi8DmaQytlQCgqNZt9XQF8iqlI/SeXWVjaMNxvYvzaYw+kh42mDg==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-member-expression-to-functions": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5" + } + }, + "@babel/helper-create-regexp-features-plugin": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.14.5.tgz", + "integrity": "sha512-TLawwqpOErY2HhWbGJ2nZT5wSkR192QpN+nBg1THfBfftrlvOh+WbhrxXCH4q4xJ9Gl16BGPR/48JA+Ryiho/A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "regexpu-core": "^4.7.1" + } + }, + "@babel/helper-define-polyfill-provider": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.2.3.tgz", + "integrity": "sha512-RH3QDAfRMzj7+0Nqu5oqgO5q9mFtQEVvCRsi8qCEfzLR9p2BHfn5FzhSB2oj1fF7I2+DcTORkYaQ6aTR9Cofew==", + "dev": true, + "requires": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/helper-explode-assignable-expression": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.14.5.tgz", + "integrity": "sha512-Htb24gnGJdIGT4vnRKMdoXiOIlqOLmdiUYpAQ0mYfgVT/GDm8GOYhgi4GL+hMKrkiPRohO4ts34ELFsGAPQLDQ==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-function-name": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.5.tgz", + "integrity": "sha512-Gjna0AsXWfFvrAuX+VKcN/aNNWonizBj39yGwUzVDVTlMYJMK2Wp6xdpy72mfArFq5uK+NOuexfzZlzI1z9+AQ==", + "dev": true, + "requires": { + "@babel/helper-get-function-arity": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-get-function-arity": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.14.5.tgz", + "integrity": "sha512-I1Db4Shst5lewOM4V+ZKJzQ0JGGaZ6VY1jYvMghRjqs6DWgxLCIyFt30GlnKkfUeFLpJt2vzbMVEXVSXlIFYUg==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-hoist-variables": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.14.5.tgz", + "integrity": "sha512-R1PXiz31Uc0Vxy4OEOm07x0oSjKAdPPCh3tPivn/Eo8cvz6gveAeuyUUPB21Hoiif0uoPQSSdhIPS3352nvdyQ==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-member-expression-to-functions": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.14.5.tgz", + "integrity": "sha512-UxUeEYPrqH1Q/k0yRku1JE7dyfyehNwT6SVkMHvYvPDv4+uu627VXBckVj891BO8ruKBkiDoGnZf4qPDD8abDQ==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-module-imports": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.14.5.tgz", + "integrity": "sha512-SwrNHu5QWS84XlHwGYPDtCxcA0hrSlL2yhWYLgeOc0w7ccOl2qv4s/nARI0aYZW+bSwAL5CukeXA47B/1NKcnQ==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-module-transforms": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.14.5.tgz", + "integrity": "sha512-iXpX4KW8LVODuAieD7MzhNjmM6dzYY5tfRqT+R9HDXWl0jPn/djKmA+G9s/2C2T9zggw5tK1QNqZ70USfedOwA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-simple-access": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-optimise-call-expression": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.14.5.tgz", + "integrity": "sha512-IqiLIrODUOdnPU9/F8ib1Fx2ohlgDhxnIDU7OEVi+kAbEZcyiF7BLU8W6PfvPi9LzztjS7kcbzbmL7oG8kD6VA==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-plugin-utils": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz", + "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==", + "dev": true + }, + "@babel/helper-remap-async-to-generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.14.5.tgz", + "integrity": "sha512-rLQKdQU+HYlxBwQIj8dk4/0ENOUEhA/Z0l4hN8BexpvmSMN9oA9EagjnhnDpNsRdWCfjwa4mn/HyBXO9yhQP6A==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-wrap-function": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-replace-supers": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.5.tgz", + "integrity": "sha512-3i1Qe9/8x/hCHINujn+iuHy+mMRLoc77b2nI9TB0zjH1hvn9qGlXjWlggdwUcju36PkPCy/lpM7LLUdcTyH4Ow==", + "dev": true, + "requires": { + "@babel/helper-member-expression-to-functions": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-simple-access": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.14.5.tgz", + "integrity": "sha512-nfBN9xvmCt6nrMZjfhkl7i0oTV3yxR4/FztsbOASyTvVcoYd0TRHh7eMLdlEcCqobydC0LAF3LtC92Iwxo0wyw==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.14.5.tgz", + "integrity": "sha512-dmqZB7mrb94PZSAOYtr+ZN5qt5owZIAgqtoTuqiFbHFtxgEcmQlRJVI+bO++fciBunXtB6MK7HrzrfcAzIz2NQ==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-split-export-declaration": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.14.5.tgz", + "integrity": "sha512-hprxVPu6e5Kdp2puZUmvOGjaLv9TCe58E/Fl6hRq4YiVQxIcNvuq6uTM2r1mT/oPskuS9CgR+I94sqAYv0NGKA==", + "dev": true, + "requires": { + "@babel/types": "^7.14.5" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.5.tgz", + "integrity": "sha512-5lsetuxCLilmVGyiLEfoHBRX8UCFD+1m2x3Rj97WrW3V7H3u4RWRXA4evMjImCsin2J2YT0QaVDGf+z8ondbAg==", + "dev": true + }, + "@babel/helper-validator-option": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz", + "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==", + "dev": true + }, + "@babel/helper-wrap-function": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.14.5.tgz", + "integrity": "sha512-YEdjTCq+LNuNS1WfxsDCNpgXkJaIyqco6DAelTUjT4f2KIWC1nBcaCaSdHTBqQVLnTBexBcVcFhLSU1KnYuePQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.14.5", + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/helpers": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.14.6.tgz", + "integrity": "sha512-yesp1ENQBiLI+iYHSJdoZKUtRpfTlL1grDIX9NRlAVppljLw/4tTyYupIB7uIYmC3stW/imAv8EqaKaS/ibmeA==", + "dev": true, + "requires": { + "@babel/template": "^7.14.5", + "@babel/traverse": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/highlight": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.5.tgz", + "integrity": "sha512-qf9u2WFWVV0MppaL877j2dBtQIDgmidgjGk5VIMw3OadXvYaXn66U1BFlH2t4+t3i+8PhedppRv+i40ABzd+gg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "@babel/parser": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.6.tgz", + "integrity": "sha512-oG0ej7efjEXxb4UgE+klVx+3j4MVo+A2vCzm7OUN4CLo6WhQ+vSOD2yJ8m7B+DghObxtLxt3EfgMWpq+AsWehQ==", + "dev": true + }, + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.14.5.tgz", + "integrity": "sha512-ZoJS2XCKPBfTmL122iP6NM9dOg+d4lc9fFk3zxc8iDjvt8Pk4+TlsHSKhIPf6X+L5ORCdBzqMZDjL/WHj7WknQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", + "@babel/plugin-proposal-optional-chaining": "^7.14.5" + } + }, + "@babel/plugin-proposal-async-generator-functions": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.5.tgz", + "integrity": "sha512-tbD/CG3l43FIXxmu4a7RBe4zH7MLJ+S/lFowPFO7HetS2hyOZ/0nnnznegDuzFzfkyQYTxqdTH/hKmuBngaDAA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-remap-async-to-generator": "^7.14.5", + "@babel/plugin-syntax-async-generators": "^7.8.4" + } + }, + "@babel/plugin-proposal-class-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.14.5.tgz", + "integrity": "sha512-q/PLpv5Ko4dVc1LYMpCY7RVAAO4uk55qPwrIuJ5QJ8c6cVuAmhu7I/49JOppXL6gXf7ZHzpRVEUZdYoPLM04Gg==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-proposal-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.14.5.tgz", + "integrity": "sha512-KBAH5ksEnYHCegqseI5N9skTdxgJdmDoAOc0uXa+4QMYKeZD0w5IARh4FMlTNtaHhbB8v+KzMdTgxMMzsIy6Yg==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + } + }, + "@babel/plugin-proposal-decorators": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.14.5.tgz", + "integrity": "sha512-LYz5nvQcvYeRVjui1Ykn28i+3aUiXwQ/3MGoEy0InTaz1pJo/lAzmIDXX+BQny/oufgHzJ6vnEEiXQ8KZjEVFg==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-decorators": "^7.14.5" + } + }, + "@babel/plugin-proposal-dynamic-import": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.14.5.tgz", + "integrity": "sha512-ExjiNYc3HDN5PXJx+bwC50GIx/KKanX2HiggnIUAYedbARdImiCU4RhhHfdf0Kd7JNXGpsBBBCOm+bBVy3Gb0g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + } + }, + "@babel/plugin-proposal-export-namespace-from": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.14.5.tgz", + "integrity": "sha512-g5POA32bXPMmSBu5Dx/iZGLGnKmKPc5AiY7qfZgurzrCYgIztDlHFbznSNCoQuv57YQLnQfaDi7dxCtLDIdXdA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + } + }, + "@babel/plugin-proposal-json-strings": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.14.5.tgz", + "integrity": "sha512-NSq2fczJYKVRIsUJyNxrVUMhB27zb7N7pOFGQOhBKJrChbGcgEAqyZrmZswkPk18VMurEeJAaICbfm57vUeTbQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-json-strings": "^7.8.3" + } + }, + "@babel/plugin-proposal-logical-assignment-operators": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.14.5.tgz", + "integrity": "sha512-YGn2AvZAo9TwyhlLvCCWxD90Xq8xJ4aSgaX3G5D/8DW94L8aaT+dS5cSP+Z06+rCJERGSr9GxMBZ601xoc2taw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + } + }, + "@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.14.5.tgz", + "integrity": "sha512-gun/SOnMqjSb98Nkaq2rTKMwervfdAoz6NphdY0vTfuzMfryj+tDGb2n6UkDKwez+Y8PZDhE3D143v6Gepp4Hg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + } + }, + "@babel/plugin-proposal-numeric-separator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.14.5.tgz", + "integrity": "sha512-yiclALKe0vyZRZE0pS6RXgjUOt87GWv6FYa5zqj15PvhOGFO69R5DusPlgK/1K5dVnCtegTiWu9UaBSrLLJJBg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + } + }, + "@babel/plugin-proposal-object-rest-spread": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.5.tgz", + "integrity": "sha512-VzMyY6PWNPPT3pxc5hi9LloKNr4SSrVCg7Yr6aZpW4Ym07r7KqSU/QXYwjXLVxqwSv0t/XSXkFoKBPUkZ8vb2A==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.14.5", + "@babel/helper-compilation-targets": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.14.5" + } + }, + "@babel/plugin-proposal-optional-catch-binding": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.14.5.tgz", + "integrity": "sha512-3Oyiixm0ur7bzO5ybNcZFlmVsygSIQgdOa7cTfOYCMY+wEPAYhZAJxi3mixKFCTCKUhQXuCTtQ1MzrpL3WT8ZQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + } + }, + "@babel/plugin-proposal-optional-chaining": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.14.5.tgz", + "integrity": "sha512-ycz+VOzo2UbWNI1rQXxIuMOzrDdHGrI23fRiz/Si2R4kv2XZQ1BK8ccdHwehMKBlcH/joGW/tzrUmo67gbJHlQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + } + }, + "@babel/plugin-proposal-private-methods": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.14.5.tgz", + "integrity": "sha512-838DkdUA1u+QTCplatfq4B7+1lnDa/+QMI89x5WZHBcnNv+47N8QEj2k9I2MUU9xIv8XJ4XvPCviM/Dj7Uwt9g==", + "dev": true, + "requires": { + "@babel/helper-create-class-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-proposal-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-62EyfyA3WA0mZiF2e2IV9mc9Ghwxcg8YTu8BS4Wss4Y3PY725OmS9M0qLORbJwLqFtGh+jiE4wAmocK2CTUK2Q==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-create-class-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + } + }, + "@babel/plugin-proposal-unicode-property-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.14.5.tgz", + "integrity": "sha512-6axIeOU5LnY471KenAB9vI8I5j7NQ2d652hIYwVyRfgaZT5UpiqFKCuVXCDMSrU+3VFafnu2c5m3lrWIlr6A5Q==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.12.13" + } + }, + "@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-decorators": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.14.5.tgz", + "integrity": "sha512-c4sZMRWL4GSvP1EXy0woIP7m4jkVcEuG8R1TOZxPBPtp4FSM/kiPZub9UIs/Jrb5ZAOzvTUSGYrWsrSu1JvoPw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", + "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.3" + } + }, + "@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-jsx": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.14.5.tgz", + "integrity": "sha512-ohuFIsOMXJnbOMRfX7/w7LocdR6R7whhuRD4ax8IipLcLPlZGJKkBxgHp++U4N/vKyU16/YDQr2f5seajD3jIw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4" + } + }, + "@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.8.0" + } + }, + "@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-arrow-functions": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.14.5.tgz", + "integrity": "sha512-KOnO0l4+tD5IfOdi4x8C1XmEIRWUjNRV8wc6K2vz/3e8yAOoZZvsRXRRIF/yo/MAOFb4QjtAw9xSxMXbSMRy8A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-async-to-generator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.14.5.tgz", + "integrity": "sha512-szkbzQ0mNk0rpu76fzDdqSyPu0MuvpXgC+6rz5rpMb5OIRxdmHfQxrktL8CYolL2d8luMCZTR0DpIMIdL27IjA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-remap-async-to-generator": "^7.14.5" + } + }, + "@babel/plugin-transform-block-scoped-functions": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.14.5.tgz", + "integrity": "sha512-dtqWqdWZ5NqBX3KzsVCWfQI3A53Ft5pWFCT2eCVUftWZgjc5DpDponbIF1+c+7cSGk2wN0YK7HGL/ezfRbpKBQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-block-scoping": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.14.5.tgz", + "integrity": "sha512-LBYm4ZocNgoCqyxMLoOnwpsmQ18HWTQvql64t3GvMUzLQrNoV1BDG0lNftC8QKYERkZgCCT/7J5xWGObGAyHDw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-classes": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.14.5.tgz", + "integrity": "sha512-J4VxKAMykM06K/64z9rwiL6xnBHgB1+FVspqvlgCdwD1KUbQNfszeKVVOMh59w3sztHYIZDgnhOC4WbdEfHFDA==", + "dev": true, + "requires": { + "@babel/helper-annotate-as-pure": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-optimise-call-expression": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "globals": "^11.1.0" + } + }, + "@babel/plugin-transform-computed-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.14.5.tgz", + "integrity": "sha512-pWM+E4283UxaVzLb8UBXv4EIxMovU4zxT1OPnpHJcmnvyY9QbPPTKZfEj31EUvG3/EQRbYAGaYEUZ4yWOBC2xg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-destructuring": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.5.tgz", + "integrity": "sha512-wU9tYisEbRMxqDezKUqC9GleLycCRoUsai9ddlsq54r8QRLaeEhc+d+9DqCG+kV9W2GgQjTZESPTpn5bAFMDww==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-dotall-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.14.5.tgz", + "integrity": "sha512-loGlnBdj02MDsFaHhAIJzh7euK89lBrGIdM9EAtHFo6xKygCUGuuWe07o1oZVk287amtW1n0808sQM99aZt3gw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-duplicate-keys": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.14.5.tgz", + "integrity": "sha512-iJjbI53huKbPDAsJ8EmVmvCKeeq21bAze4fu9GBQtSLqfvzj2oRuHVx4ZkDwEhg1htQ+5OBZh/Ab0XDf5iBZ7A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-exponentiation-operator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.14.5.tgz", + "integrity": "sha512-jFazJhMBc9D27o9jDnIE5ZErI0R0m7PbKXVq77FFvqFbzvTMuv8jaAwLZ5PviOLSFttqKIW0/wxNSDbjLk0tYA==", + "dev": true, + "requires": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-for-of": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.14.5.tgz", + "integrity": "sha512-CfmqxSUZzBl0rSjpoQSFoR9UEj3HzbGuGNL21/iFTmjb5gFggJp3ph0xR1YBhexmLoKRHzgxuFvty2xdSt6gTA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-function-name": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.14.5.tgz", + "integrity": "sha512-vbO6kv0fIzZ1GpmGQuvbwwm+O4Cbm2NrPzwlup9+/3fdkuzo1YqOZcXw26+YUJB84Ja7j9yURWposEHLYwxUfQ==", + "dev": true, + "requires": { + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.14.5.tgz", + "integrity": "sha512-ql33+epql2F49bi8aHXxvLURHkxJbSmMKl9J5yHqg4PLtdE6Uc48CH1GS6TQvZ86eoB/ApZXwm7jlA+B3kra7A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-member-expression-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.14.5.tgz", + "integrity": "sha512-WkNXxH1VXVTKarWFqmso83xl+2V3Eo28YY5utIkbsmXoItO8Q3aZxN4BTS2k0hz9dGUloHK26mJMyQEYfkn/+Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-modules-amd": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.14.5.tgz", + "integrity": "sha512-3lpOU8Vxmp3roC4vzFpSdEpGUWSMsHFreTWOMMLzel2gNGfHE5UWIh/LN6ghHs2xurUp4jRFYMUIZhuFbody1g==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-commonjs": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.14.5.tgz", + "integrity": "sha512-en8GfBtgnydoao2PS+87mKyw62k02k7kJ9ltbKe0fXTHrQmG6QZZflYuGI1VVG7sVpx4E1n7KBpNlPb8m78J+A==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-simple-access": "^7.14.5", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-systemjs": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.14.5.tgz", + "integrity": "sha512-mNMQdvBEE5DcMQaL5LbzXFMANrQjd2W7FPzg34Y4yEz7dBgdaC+9B84dSO+/1Wba98zoDbInctCDo4JGxz1VYA==", + "dev": true, + "requires": { + "@babel/helper-hoist-variables": "^7.14.5", + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-validator-identifier": "^7.14.5", + "babel-plugin-dynamic-import-node": "^2.3.3" + } + }, + "@babel/plugin-transform-modules-umd": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.14.5.tgz", + "integrity": "sha512-RfPGoagSngC06LsGUYyM9QWSXZ8MysEjDJTAea1lqRjNECE3y0qIJF/qbvJxc4oA4s99HumIMdXOrd+TdKaAAA==", + "dev": true, + "requires": { + "@babel/helper-module-transforms": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.5.tgz", + "integrity": "sha512-+Xe5+6MWFo311U8SchgeX5c1+lJM+eZDBZgD+tvXu9VVQPXwwVzeManMMjYX6xw2HczngfOSZjoFYKwdeB/Jvw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5" + } + }, + "@babel/plugin-transform-new-target": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.14.5.tgz", + "integrity": "sha512-Nx054zovz6IIRWEB49RDRuXGI4Gy0GMgqG0cII9L3MxqgXz/+rgII+RU58qpo4g7tNEx1jG7rRVH4ihZoP4esQ==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-object-super": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.14.5.tgz", + "integrity": "sha512-MKfOBWzK0pZIrav9z/hkRqIk/2bTv9qvxHzPQc12RcVkMOzpIKnFCNYJip00ssKWYkd8Sf5g0Wr7pqJ+cmtuFg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-replace-supers": "^7.14.5" + } + }, + "@babel/plugin-transform-parameters": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.5.tgz", + "integrity": "sha512-Tl7LWdr6HUxTmzQtzuU14SqbgrSKmaR77M0OKyq4njZLQTPfOvzblNKyNkGwOfEFCEx7KeYHQHDI0P3F02IVkA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-property-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.14.5.tgz", + "integrity": "sha512-r1uilDthkgXW8Z1vJz2dKYLV1tuw2xsbrp3MrZmD99Wh9vsfKoob+JTgri5VUb/JqyKRXotlOtwgu4stIYCmnw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-regenerator": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.14.5.tgz", + "integrity": "sha512-NVIY1W3ITDP5xQl50NgTKlZ0GrotKtLna08/uGY6ErQt6VEQZXla86x/CTddm5gZdcr+5GSsvMeTmWA5Ii6pkg==", + "dev": true, + "requires": { + "regenerator-transform": "^0.14.2" + } + }, + "@babel/plugin-transform-reserved-words": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.14.5.tgz", + "integrity": "sha512-cv4F2rv1nD4qdexOGsRQXJrOcyb5CrgjUH9PKrrtyhSDBNWGxd0UIitjyJiWagS+EbUGjG++22mGH1Pub8D6Vg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-runtime": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.14.5.tgz", + "integrity": "sha512-fPMBhh1AV8ZyneiCIA+wYYUH1arzlXR1UMcApjvchDhfKxhy2r2lReJv8uHEyihi4IFIGlr1Pdx7S5fkESDQsg==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "babel-plugin-polyfill-corejs2": "^0.2.2", + "babel-plugin-polyfill-corejs3": "^0.2.2", + "babel-plugin-polyfill-regenerator": "^0.2.2", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/plugin-transform-shorthand-properties": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.14.5.tgz", + "integrity": "sha512-xLucks6T1VmGsTB+GWK5Pl9Jl5+nRXD1uoFdA5TSO6xtiNjtXTjKkmPdFXVLGlK5A2/or/wQMKfmQ2Y0XJfn5g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-spread": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.14.6.tgz", + "integrity": "sha512-Zr0x0YroFJku7n7+/HH3A2eIrGMjbmAIbJSVv0IZ+t3U2WUQUA64S/oeied2e+MaGSjmt4alzBCsK9E8gh+fag==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.14.5" + } + }, + "@babel/plugin-transform-sticky-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.14.5.tgz", + "integrity": "sha512-Z7F7GyvEMzIIbwnziAZmnSNpdijdr4dWt+FJNBnBLz5mwDFkqIXU9wmBcWWad3QeJF5hMTkRe4dAq2sUZiG+8A==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-template-literals": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.14.5.tgz", + "integrity": "sha512-22btZeURqiepOfuy/VkFr+zStqlujWaarpMErvay7goJS6BWwdd6BY9zQyDLDa4x2S3VugxFb162IZ4m/S/+Gg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-typeof-symbol": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.14.5.tgz", + "integrity": "sha512-lXzLD30ffCWseTbMQzrvDWqljvZlHkXU+CnseMhkMNqU1sASnCsz3tSzAaH3vCUXb9PHeUb90ZT1BdFTm1xxJw==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-unicode-escapes": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.14.5.tgz", + "integrity": "sha512-crTo4jATEOjxj7bt9lbYXcBAM3LZaUrbP2uUdxb6WIorLmjNKSpHfIybgY4B8SRpbf8tEVIWH3Vtm7ayCrKocA==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/plugin-transform-unicode-regex": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.14.5.tgz", + "integrity": "sha512-UygduJpC5kHeCiRw/xDVzC+wj8VaYSoKl5JNVmbP7MadpNinAm3SvZCxZ42H37KZBKztz46YC73i9yV34d0Tzw==", + "dev": true, + "requires": { + "@babel/helper-create-regexp-features-plugin": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5" + } + }, + "@babel/preset-env": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.5.tgz", + "integrity": "sha512-ci6TsS0bjrdPpWGnQ+m4f+JSSzDKlckqKIJJt9UZ/+g7Zz9k0N8lYU8IeLg/01o2h8LyNZDMLGgRLDTxpudLsA==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.14.5", + "@babel/helper-compilation-targets": "^7.14.5", + "@babel/helper-plugin-utils": "^7.14.5", + "@babel/helper-validator-option": "^7.14.5", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.14.5", + "@babel/plugin-proposal-async-generator-functions": "^7.14.5", + "@babel/plugin-proposal-class-properties": "^7.14.5", + "@babel/plugin-proposal-class-static-block": "^7.14.5", + "@babel/plugin-proposal-dynamic-import": "^7.14.5", + "@babel/plugin-proposal-export-namespace-from": "^7.14.5", + "@babel/plugin-proposal-json-strings": "^7.14.5", + "@babel/plugin-proposal-logical-assignment-operators": "^7.14.5", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5", + "@babel/plugin-proposal-numeric-separator": "^7.14.5", + "@babel/plugin-proposal-object-rest-spread": "^7.14.5", + "@babel/plugin-proposal-optional-catch-binding": "^7.14.5", + "@babel/plugin-proposal-optional-chaining": "^7.14.5", + "@babel/plugin-proposal-private-methods": "^7.14.5", + "@babel/plugin-proposal-private-property-in-object": "^7.14.5", + "@babel/plugin-proposal-unicode-property-regex": "^7.14.5", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-transform-arrow-functions": "^7.14.5", + "@babel/plugin-transform-async-to-generator": "^7.14.5", + "@babel/plugin-transform-block-scoped-functions": "^7.14.5", + "@babel/plugin-transform-block-scoping": "^7.14.5", + "@babel/plugin-transform-classes": "^7.14.5", + "@babel/plugin-transform-computed-properties": "^7.14.5", + "@babel/plugin-transform-destructuring": "^7.14.5", + "@babel/plugin-transform-dotall-regex": "^7.14.5", + "@babel/plugin-transform-duplicate-keys": "^7.14.5", + "@babel/plugin-transform-exponentiation-operator": "^7.14.5", + "@babel/plugin-transform-for-of": "^7.14.5", + "@babel/plugin-transform-function-name": "^7.14.5", + "@babel/plugin-transform-literals": "^7.14.5", + "@babel/plugin-transform-member-expression-literals": "^7.14.5", + "@babel/plugin-transform-modules-amd": "^7.14.5", + "@babel/plugin-transform-modules-commonjs": "^7.14.5", + "@babel/plugin-transform-modules-systemjs": "^7.14.5", + "@babel/plugin-transform-modules-umd": "^7.14.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.5", + "@babel/plugin-transform-new-target": "^7.14.5", + "@babel/plugin-transform-object-super": "^7.14.5", + "@babel/plugin-transform-parameters": "^7.14.5", + "@babel/plugin-transform-property-literals": "^7.14.5", + "@babel/plugin-transform-regenerator": "^7.14.5", + "@babel/plugin-transform-reserved-words": "^7.14.5", + "@babel/plugin-transform-shorthand-properties": "^7.14.5", + "@babel/plugin-transform-spread": "^7.14.5", + "@babel/plugin-transform-sticky-regex": "^7.14.5", + "@babel/plugin-transform-template-literals": "^7.14.5", + "@babel/plugin-transform-typeof-symbol": "^7.14.5", + "@babel/plugin-transform-unicode-escapes": "^7.14.5", + "@babel/plugin-transform-unicode-regex": "^7.14.5", + "@babel/preset-modules": "^0.1.4", + "@babel/types": "^7.14.5", + "babel-plugin-polyfill-corejs2": "^0.2.2", + "babel-plugin-polyfill-corejs3": "^0.2.2", + "babel-plugin-polyfill-regenerator": "^0.2.2", + "core-js-compat": "^3.14.0", + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@babel/preset-modules": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", + "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", + "@babel/plugin-transform-dotall-regex": "^7.4.4", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + } + }, + "@babel/runtime": { + "version": "7.14.6", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.14.6.tgz", + "integrity": "sha512-/PCB2uJ7oM44tz8YhC4Z/6PeOKXp4K588f+5M3clr1M4zbqztlo0XEfJ2LEzj/FgwfgGcIdl8n7YYjTCI0BYwg==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "@babel/template": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.14.5.tgz", + "integrity": "sha512-6Z3Po85sfxRGachLULUhOmvAaOo7xCvqGQtxINai2mEGPFm6pQ4z5QInFnUrRpfoSV60BnjyF5F3c+15fxFV1g==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5" + } + }, + "@babel/traverse": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.5.tgz", + "integrity": "sha512-G3BiS15vevepdmFqmUc9X+64y0viZYygubAMO8SvBmKARuF6CPSZtH4Ng9vi/lrWlZFGe3FWdXNy835akH8Glg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.14.5", + "@babel/generator": "^7.14.5", + "@babel/helper-function-name": "^7.14.5", + "@babel/helper-hoist-variables": "^7.14.5", + "@babel/helper-split-export-declaration": "^7.14.5", + "@babel/parser": "^7.14.5", + "@babel/types": "^7.14.5", + "debug": "^4.1.0", + "globals": "^11.1.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "@babel/types": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.5.tgz", + "integrity": "sha512-M/NzBpEL95I5Hh4dwhin5JlE7EzO5PHMAuzjxss3tiOBD46KfQvVedN/3jEPZvdRvtsK2222XfdHogNIttFgcg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.5", + "to-fast-properties": "^2.0.0" + } + }, + "@braintree/sanitize-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@braintree/sanitize-url/-/sanitize-url-3.1.0.tgz", + "integrity": "sha512-GcIY79elgB+azP74j8vqkiXz8xLFfIzbQJdlwOPisgbKT00tviJQuEghOXSMVxJ00HoYJbGswr4kcllUc4xCcg==", + "dev": true + }, + "@hapi/hoek": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.2.0.tgz", + "integrity": "sha512-sqKVVVOe5ivCaXDWivIJYVSaEgdQK9ul7a4Kity5Iw7u9+wBAPbX1RMSnLLmp7O4Vzj0WOWwMAJsTL00xwaNug==", + "dev": true + }, + "@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@mrmlnc/readdir-enhanced": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz", + "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==", + "dev": true, + "requires": { + "call-me-maybe": "^1.0.1", + "glob-to-regexp": "^0.3.0" + } + }, + "@nodelib/fs.stat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz", + "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==", + "dev": true + }, + "@sideway/address": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.2.tgz", + "integrity": "sha512-idTz8ibqWFrPU8kMirL0CoPH/A29XOzzAzpyN3zQ4kAWnzmNfFmRaoMNN6VI8ske5M73HZyhIaW4OuSFIdM4oA==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0" + } + }, + "@sideway/formula": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.0.tgz", + "integrity": "sha512-vHe7wZ4NOXVfkoRb8T5otiENVlT7a3IAiw7H5M2+GO+9CDgcVUUsX1zalAztCmwyOr2RUTGJdgB+ZvSVqmdHmg==", + "dev": true + }, + "@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "dev": true + }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==", + "dev": true + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "dev": true, + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@types/glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-SEYeGAIQIQX8NN6LDKprLjbrd5dARM5EXsd8GI/A5l0apYI1fGMWgPHSe4ZKL4eozlAyI+doUE9XbYS4xCkQ1w==", + "dev": true, + "requires": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "@types/json-schema": { + "version": "7.0.7", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.7.tgz", + "integrity": "sha512-cxWFQVseBm6O9Gbw1IWb8r6OS4OhSt3hPZLkFApLjM8TEXROBuQGLAH2i2gZpcXdLBIrpXuTDhH7Vbm1iXmNGA==", + "dev": true + }, + "@types/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-1z8k4wzFnNjVK/tlxvrWuK5WMt6mydWWP7+zvH5eFep4oj+UkrfiJTRtjCeBXNpwaA/FYqqtb4/QS4ianFpIRA==", + "dev": true + }, + "@types/node": { + "version": "15.12.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.2.tgz", + "integrity": "sha512-zjQ69G564OCIWIOHSXyQEEDpdpGl+G348RAKY0XXy9Z5kU9Vzv1GMNnkar/ZJ8dzXB3COzD9Mo9NtRZ4xfgUww==", + "dev": true + }, + "@types/q": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.4.tgz", + "integrity": "sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==", + "dev": true + }, + "@vssue/api-github-v3": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@vssue/api-github-v3/-/api-github-v3-1.4.7.tgz", + "integrity": "sha512-ukhOnzGQarmj606ZiYN9iCMyr3EJS3YEPdZXX+zBLVsuzjTL5ffLbbpXsEtPBh2XNt3Ig3XdzCvA9bVXhwy4mQ==", + "dev": true, + "requires": { + "@vssue/utils": "^1.4.7", + "axios": "^0.21.1" + } + }, + "@vssue/utils": { + "version": "1.4.7", + "resolved": "https://registry.npmjs.org/@vssue/utils/-/utils-1.4.7.tgz", + "integrity": "sha512-e94karP4szmSNT2L4bgIT+VGToBSY3bdlgmGcomcD2qCXTWDK4krSOYm8ES+BhHTcmCvzQYU/xenHR4tzrythA==", + "dev": true, + "requires": { + "date-fns": "^1.29.0", + "qs": "^6.6.0" + }, + "dependencies": { + "qs": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.10.1.tgz", + "integrity": "sha512-M528Hph6wsSVOBiYUnGf+K/7w0hNshs/duGsNXPUCLH5XAqjEtiPGwNONLV0tBH8NoGb0mvD5JubnUTrujKDTg==", + "dev": true, + "requires": { + "side-channel": "^1.0.4" + } + } + } + }, + "@vssue/vuepress-plugin-vssue": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/@vssue/vuepress-plugin-vssue/-/vuepress-plugin-vssue-1.4.8.tgz", + "integrity": "sha512-0QzegHl/Rx4/XgXswThIJi4Yk+b6AIaM450jX6p4RbOM6yOTzEKLTMduUo54Rvhq/NHNusu4Yy/w1iY8NTqBEg==", + "dev": true, + "requires": { + "vssue": "^1.4.8" + } + }, + "@vue/babel-helper-vue-jsx-merge-props": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.2.1.tgz", + "integrity": "sha512-QOi5OW45e2R20VygMSNhyQHvpdUwQZqGPc748JLGCYEy+yp8fNFNdbNIGAgZmi9e+2JHPd6i6idRuqivyicIkA==", + "dev": true + }, + "@vue/babel-helper-vue-transform-on": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.2.tgz", + "integrity": "sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==", + "dev": true + }, + "@vue/babel-plugin-jsx": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.0.6.tgz", + "integrity": "sha512-RzYsvBhzKUmY2YG6LoV+W5PnlnkInq0thh1AzCmewwctAgGN6e9UFon6ZrQQV1CO5G5PeME7MqpB+/vvGg0h4g==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.0.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.0.0", + "@babel/types": "^7.0.0", + "@vue/babel-helper-vue-transform-on": "^1.0.2", + "camelcase": "^6.0.0", + "html-tags": "^3.1.0", + "svg-tags": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", + "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==", + "dev": true + } + } + }, + "@vue/babel-plugin-transform-vue-jsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.2.1.tgz", + "integrity": "sha512-HJuqwACYehQwh1fNT8f4kyzqlNMpBuUK4rSiSES5D4QsYncv5fxFsLyrxFPG2ksO7t5WP+Vgix6tt6yKClwPzA==", + "dev": true, + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", + "html-tags": "^2.0.0", + "lodash.kebabcase": "^4.1.1", + "svg-tags": "^1.0.0" + }, + "dependencies": { + "html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", + "dev": true + } + } + }, + "@vue/babel-preset-app": { + "version": "4.5.13", + "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-4.5.13.tgz", + "integrity": "sha512-pM7CR3yXB6L8Gfn6EmX7FLNE3+V/15I3o33GkSNsWvgsMp6HVGXKkXgojrcfUUauyL1LZOdvTmu4enU2RePGHw==", + "dev": true, + "requires": { + "@babel/core": "^7.11.0", + "@babel/helper-compilation-targets": "^7.9.6", + "@babel/helper-module-imports": "^7.8.3", + "@babel/plugin-proposal-class-properties": "^7.8.3", + "@babel/plugin-proposal-decorators": "^7.8.3", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-jsx": "^7.8.3", + "@babel/plugin-transform-runtime": "^7.11.0", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.0", + "@vue/babel-plugin-jsx": "^1.0.3", + "@vue/babel-preset-jsx": "^1.2.4", + "babel-plugin-dynamic-import-node": "^2.3.3", + "core-js": "^3.6.5", + "core-js-compat": "^3.6.5", + "semver": "^6.1.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@vue/babel-preset-jsx": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@vue/babel-preset-jsx/-/babel-preset-jsx-1.2.4.tgz", + "integrity": "sha512-oRVnmN2a77bYDJzeGSt92AuHXbkIxbf/XXSE3klINnh9AXBmVS1DGa1f0d+dDYpLfsAKElMnqKTQfKn7obcL4w==", + "dev": true, + "requires": { + "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", + "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", + "@vue/babel-sugar-composition-api-inject-h": "^1.2.1", + "@vue/babel-sugar-composition-api-render-instance": "^1.2.4", + "@vue/babel-sugar-functional-vue": "^1.2.2", + "@vue/babel-sugar-inject-h": "^1.2.2", + "@vue/babel-sugar-v-model": "^1.2.3", + "@vue/babel-sugar-v-on": "^1.2.3" + } + }, + "@vue/babel-sugar-composition-api-inject-h": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-inject-h/-/babel-sugar-composition-api-inject-h-1.2.1.tgz", + "integrity": "sha512-4B3L5Z2G+7s+9Bwbf+zPIifkFNcKth7fQwekVbnOA3cr3Pq71q71goWr97sk4/yyzH8phfe5ODVzEjX7HU7ItQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7.2.0" + } + }, + "@vue/babel-sugar-composition-api-render-instance": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-render-instance/-/babel-sugar-composition-api-render-instance-1.2.4.tgz", + "integrity": "sha512-joha4PZznQMsxQYXtR3MnTgCASC9u3zt9KfBxIeuI5g2gscpTsSKRDzWQt4aqNIpx6cv8On7/m6zmmovlNsG7Q==", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7.2.0" + } + }, + "@vue/babel-sugar-functional-vue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.2.2.tgz", + "integrity": "sha512-JvbgGn1bjCLByIAU1VOoepHQ1vFsroSA/QkzdiSs657V79q6OwEWLCQtQnEXD/rLTA8rRit4rMOhFpbjRFm82w==", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7.2.0" + } + }, + "@vue/babel-sugar-inject-h": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.2.2.tgz", + "integrity": "sha512-y8vTo00oRkzQTgufeotjCLPAvlhnpSkcHFEp60+LJUwygGcd5Chrpn5480AQp/thrxVm8m2ifAk0LyFel9oCnw==", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7.2.0" + } + }, + "@vue/babel-sugar-v-model": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.2.3.tgz", + "integrity": "sha512-A2jxx87mySr/ulAsSSyYE8un6SIH0NWHiLaCWpodPCVOlQVODCaSpiR4+IMsmBr73haG+oeCuSvMOM+ttWUqRQ==", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1", + "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", + "camelcase": "^5.0.0", + "html-tags": "^2.0.0", + "svg-tags": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", + "dev": true + } + } + }, + "@vue/babel-sugar-v-on": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.2.3.tgz", + "integrity": "sha512-kt12VJdz/37D3N3eglBywV8GStKNUhNrsxChXIV+o0MwVXORYuhDTHJRKPgLJRb/EY3vM2aRFQdxJBp9CLikjw==", + "dev": true, + "requires": { + "@babel/plugin-syntax-jsx": "^7.2.0", + "@vue/babel-plugin-transform-vue-jsx": "^1.2.1", + "camelcase": "^5.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + } + } + }, + "@vue/component-compiler-utils": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.2.2.tgz", + "integrity": "sha512-rAYMLmgMuqJFWAOb3Awjqqv5X3Q3hVr4jH/kgrFJpiU0j3a90tnNBplqbj+snzrgZhC9W128z+dtgMifOiMfJg==", + "dev": true, + "requires": { + "consolidate": "^0.15.1", + "hash-sum": "^1.0.2", + "lru-cache": "^4.1.2", + "merge-source-map": "^1.1.0", + "postcss": "^7.0.36", + "postcss-selector-parser": "^6.0.2", + "prettier": "^1.18.2", + "source-map": "~0.6.1", + "vue-template-es2015-compiler": "^1.9.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "@vuepress/core": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/core/-/core-1.8.2.tgz", + "integrity": "sha512-lh9BLC06k9s0wxTuWtCkiNj49fkbW87enp0XSrFZHEoyDGSGndQjZmMMErcHc5Hx7nrW1nzc33sPH1NNtJl0hw==", + "dev": true, + "requires": { + "@babel/core": "^7.8.4", + "@vue/babel-preset-app": "^4.1.2", + "@vuepress/markdown": "1.8.2", + "@vuepress/markdown-loader": "1.8.2", + "@vuepress/plugin-last-updated": "1.8.2", + "@vuepress/plugin-register-components": "1.8.2", + "@vuepress/shared-utils": "1.8.2", + "autoprefixer": "^9.5.1", + "babel-loader": "^8.0.4", + "cache-loader": "^3.0.0", + "chokidar": "^2.0.3", + "connect-history-api-fallback": "^1.5.0", + "copy-webpack-plugin": "^5.0.2", + "core-js": "^3.6.4", + "cross-spawn": "^6.0.5", + "css-loader": "^2.1.1", + "file-loader": "^3.0.1", + "js-yaml": "^3.13.1", + "lru-cache": "^5.1.1", + "mini-css-extract-plugin": "0.6.0", + "optimize-css-assets-webpack-plugin": "^5.0.1", + "portfinder": "^1.0.13", + "postcss-loader": "^3.0.0", + "postcss-safe-parser": "^4.0.1", + "toml": "^3.0.0", + "url-loader": "^1.0.1", + "vue": "^2.6.10", + "vue-loader": "^15.7.1", + "vue-router": "^3.4.5", + "vue-server-renderer": "^2.6.10", + "vue-template-compiler": "^2.6.10", + "vuepress-html-webpack-plugin": "^3.2.0", + "vuepress-plugin-container": "^2.0.2", + "webpack": "^4.8.1", + "webpack-chain": "^6.0.0", + "webpack-dev-server": "^3.5.1", + "webpack-merge": "^4.1.2", + "webpackbar": "3.2.0" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@vuepress/markdown": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/markdown/-/markdown-1.8.2.tgz", + "integrity": "sha512-zznBHVqW+iBkznF/BO/GY9RFu53khyl0Ey0PnGqvwCJpRLNan6y5EXgYumtjw2GSYn5nDTTALYxtyNBdz64PKg==", + "dev": true, + "requires": { + "@vuepress/shared-utils": "1.8.2", + "markdown-it": "^8.4.1", + "markdown-it-anchor": "^5.0.2", + "markdown-it-chain": "^1.3.0", + "markdown-it-emoji": "^1.4.0", + "markdown-it-table-of-contents": "^0.4.0", + "prismjs": "^1.13.0" + } + }, + "@vuepress/markdown-loader": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/markdown-loader/-/markdown-loader-1.8.2.tgz", + "integrity": "sha512-mWzFXikCUcAN/chpKkqZpRYKdo0312hMv8cBea2hvrJYV6y4ODB066XKvXN8JwOcxuCjxWYJkhWGr+pXq1oTtw==", + "dev": true, + "requires": { + "@vuepress/markdown": "1.8.2", + "loader-utils": "^1.1.0", + "lru-cache": "^5.1.1" + }, + "dependencies": { + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "@vuepress/plugin-active-header-links": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-active-header-links/-/plugin-active-header-links-1.8.2.tgz", + "integrity": "sha512-JmXAQg8D7J8mcKe2Ue3BZ9dOCzJMJXP4Cnkkc/IrqfDg0ET0l96gYWZohCqlvRIWt4f0VPiFAO4FLYrW+hko+g==", + "dev": true, + "requires": { + "lodash.debounce": "^4.0.8" + } + }, + "@vuepress/plugin-back-to-top": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-back-to-top/-/plugin-back-to-top-1.8.2.tgz", + "integrity": "sha512-htAf2m8+6cGmYQexWerznGBY10y1E4TBfebYC3Y3wqNjFjvXUmRKcAG/u6Yxvey4OFkQUxbth2ilKi/GlIW8aQ==", + "dev": true, + "requires": { + "lodash.debounce": "^4.0.8" + } + }, + "@vuepress/plugin-blog": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-blog/-/plugin-blog-1.9.4.tgz", + "integrity": "sha512-7A4Y3mYrSOUKdzsTjeVOKt0XgZ0m1Iqq7BeZn7y9YeZfDcZ4Fx6UldsPfK2+THwtYwGzQ7Not3zO8djyk7z3ew==", + "dev": true, + "requires": { + "@vssue/api-github-v3": "^1.1.2", + "@vssue/vuepress-plugin-vssue": "^1.2.0", + "dayjs": "^1.10.3", + "vuejs-paginate": "^2.1.0", + "vuepress-plugin-disqus": "^0.2.0", + "vuepress-plugin-feed": "^0.1.8", + "vuepress-plugin-mailchimp": "^1.4.1", + "vuepress-plugin-sitemap": "^2.3.1" + } + }, + "@vuepress/plugin-last-updated": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-last-updated/-/plugin-last-updated-1.8.2.tgz", + "integrity": "sha512-pYIRZi52huO9b6HY3JQNPKNERCLzMHejjBRt9ekdnJ1xhLs4MmRvt37BoXjI/qzvXkYtr7nmGgnKThNBVRTZuA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.5" + } + }, + "@vuepress/plugin-medium-zoom": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-medium-zoom/-/plugin-medium-zoom-1.8.2.tgz", + "integrity": "sha512-Mljso/8E6IbNmIKmwKeC6FDfnhKY3fsOUSs5kEGzz3RQwd54eshqHAMRVwW4LZkYZHhwQXF8+qk7YqoMZB7jjg==", + "dev": true, + "requires": { + "medium-zoom": "^1.0.4" + } + }, + "@vuepress/plugin-nprogress": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-nprogress/-/plugin-nprogress-1.8.2.tgz", + "integrity": "sha512-3TOBee2NM3WLr1tdjDTGfrAMggjN+OlEPyKyv8FqThsVkDYhw48O3HwqlThp9KX7UbL3ExxIFBwWRFLC+kYrdw==", + "dev": true, + "requires": { + "nprogress": "^0.2.0" + } + }, + "@vuepress/plugin-register-components": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-register-components/-/plugin-register-components-1.8.2.tgz", + "integrity": "sha512-6SUq3nHFMEh9qKFnjA8QnrNxj0kLs7+Gspq1OBU8vtu0NQmSvLFZVaMV7pzT/9zN2nO5Pld5qhsUJv1g71MrEA==", + "dev": true, + "requires": { + "@vuepress/shared-utils": "1.8.2" + } + }, + "@vuepress/plugin-search": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/plugin-search/-/plugin-search-1.8.2.tgz", + "integrity": "sha512-JrSJr9o0Kar14lVtZ4wfw39pplxvvMh8vDBD9oW09a+6Zi/4bySPGdcdaqdqGW+OHSiZNvG+6uyfKSBBBqF6PA==", + "dev": true + }, + "@vuepress/shared-utils": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/shared-utils/-/shared-utils-1.8.2.tgz", + "integrity": "sha512-6kGubc7iBDWruEBUU7yR+sQ++SOhMuvKWvWeTZJKRZedthycdzYz7QVpua0FaZSAJm5/dIt8ymU4WQvxTtZgTQ==", + "dev": true, + "requires": { + "chalk": "^2.3.2", + "escape-html": "^1.0.3", + "fs-extra": "^7.0.1", + "globby": "^9.2.0", + "gray-matter": "^4.0.1", + "hash-sum": "^1.0.2", + "semver": "^6.0.0", + "toml": "^3.0.0", + "upath": "^1.1.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "@vuepress/theme-default": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@vuepress/theme-default/-/theme-default-1.8.2.tgz", + "integrity": "sha512-rE7M1rs3n2xp4a/GrweO8EGwqFn3EA5gnFWdVmVIHyr7C1nix+EqjpPQF1SVWNnIrDdQuCw38PqS+oND1K2vYw==", + "dev": true, + "requires": { + "@vuepress/plugin-active-header-links": "1.8.2", + "@vuepress/plugin-nprogress": "1.8.2", + "@vuepress/plugin-search": "1.8.2", + "docsearch.js": "^2.5.2", + "lodash": "^4.17.15", + "stylus": "^0.54.8", + "stylus-loader": "^3.0.2", + "vuepress-plugin-container": "^2.0.2", + "vuepress-plugin-smooth-scroll": "^0.0.3" + } + }, + "@webassemblyjs/ast": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz", + "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==", + "dev": true, + "requires": { + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0" + } + }, + "@webassemblyjs/floating-point-hex-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz", + "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==", + "dev": true + }, + "@webassemblyjs/helper-api-error": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz", + "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==", + "dev": true + }, + "@webassemblyjs/helper-buffer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz", + "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==", + "dev": true + }, + "@webassemblyjs/helper-code-frame": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz", + "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==", + "dev": true, + "requires": { + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/helper-fsm": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz", + "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==", + "dev": true + }, + "@webassemblyjs/helper-module-context": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz", + "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0" + } + }, + "@webassemblyjs/helper-wasm-bytecode": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", + "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==", + "dev": true + }, + "@webassemblyjs/helper-wasm-section": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz", + "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0" + } + }, + "@webassemblyjs/ieee754": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz", + "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==", + "dev": true, + "requires": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "@webassemblyjs/leb128": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz", + "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==", + "dev": true, + "requires": { + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/utf8": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz", + "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==", + "dev": true + }, + "@webassemblyjs/wasm-edit": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz", + "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/helper-wasm-section": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-opt": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "@webassemblyjs/wast-printer": "1.9.0" + } + }, + "@webassemblyjs/wasm-gen": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz", + "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wasm-opt": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz", + "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-buffer": "1.9.0", + "@webassemblyjs/wasm-gen": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0" + } + }, + "@webassemblyjs/wasm-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz", + "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-wasm-bytecode": "1.9.0", + "@webassemblyjs/ieee754": "1.9.0", + "@webassemblyjs/leb128": "1.9.0", + "@webassemblyjs/utf8": "1.9.0" + } + }, + "@webassemblyjs/wast-parser": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz", + "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/floating-point-hex-parser": "1.9.0", + "@webassemblyjs/helper-api-error": "1.9.0", + "@webassemblyjs/helper-code-frame": "1.9.0", + "@webassemblyjs/helper-fsm": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@webassemblyjs/wast-printer": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz", + "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/wast-parser": "1.9.0", + "@xtuc/long": "4.2.2" + } + }, + "@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true + }, + "@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true + }, + "@zeit/schemas": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.6.0.tgz", + "integrity": "sha512-uUrgZ8AxS+Lio0fZKAipJjAh415JyrOZowliZAzmnJSsf7piVL5w+G0+gFJ0KSu3QRhvui/7zuvpLz03YjXAhg==", + "dev": true + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "dev": true, + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz", + "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==", + "dev": true + }, + "agentkeepalive": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-2.2.0.tgz", + "integrity": "sha1-xdG9SxKQCPEWPyNvhuX66iAm4u8=", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ajv-errors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz", + "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==", + "dev": true, + "requires": {} + }, + "ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "requires": {} + }, + "algoliasearch": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-3.35.1.tgz", + "integrity": "sha512-K4yKVhaHkXfJ/xcUnil04xiSrB8B8yHZoFEhWNpXg23eiCnqvTZw1tn/SqvdsANlYHLJlKl0qi3I/Q2Sqo7LwQ==", + "dev": true, + "requires": { + "agentkeepalive": "^2.2.0", + "debug": "^2.6.9", + "envify": "^4.0.0", + "es6-promise": "^4.1.0", + "events": "^1.1.0", + "foreach": "^2.0.5", + "global": "^4.3.2", + "inherits": "^2.0.1", + "isarray": "^2.0.1", + "load-script": "^1.0.0", + "object-keys": "^1.0.11", + "querystring-es3": "^0.2.1", + "reduce": "^1.0.1", + "semver": "^5.1.0", + "tunnel-agent": "^0.6.0" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } + } + }, + "alphanum-sort": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", + "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", + "dev": true + }, + "ansi-align": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-2.0.0.tgz", + "integrity": "sha1-w2rsy6VjuJzrVW82kPCx2eNUf38=", + "dev": true, + "requires": { + "string-width": "^2.0.0" + } + }, + "ansi-colors": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz", + "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==", + "dev": true + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "requires": { + "type-fest": "^0.21.3" + } + }, + "ansi-html": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz", + "integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=", + "dev": true + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "dev": true + }, + "arch": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", + "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", + "dev": true + }, + "arg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arg/-/arg-2.0.0.tgz", + "integrity": "sha512-XxNTUzKnz1ctK3ZIcI2XUPlD96wbHP2nGqkPKpvk/HNRlPveYrXIVSTk9m3LcqOgDPg3B1nMvdV/K8wZd7PG4w==", + "dev": true + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "arr-diff": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", + "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", + "dev": true + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", + "dev": true + }, + "arr-union": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", + "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", + "dev": true + }, + "array-flatten": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", + "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", + "dev": true + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "array-unique": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", + "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "dev": true, + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "assert": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", + "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "dev": true, + "requires": { + "object-assign": "^4.1.1", + "util": "0.10.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", + "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE=", + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", + "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk=", + "dev": true, + "requires": { + "inherits": "2.0.1" + } + } + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", + "dev": true + }, + "assign-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", + "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", + "dev": true + }, + "async": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.3.tgz", + "integrity": "sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==", + "dev": true, + "requires": { + "lodash": "^4.17.14" + } + }, + "async-each": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", + "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", + "dev": true + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==", + "dev": true + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", + "dev": true + }, + "atob": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", + "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", + "dev": true + }, + "autocomplete.js": { + "version": "0.36.0", + "resolved": "https://registry.npmjs.org/autocomplete.js/-/autocomplete.js-0.36.0.tgz", + "integrity": "sha512-jEwUXnVMeCHHutUt10i/8ZiRaCb0Wo+ZyKxeGsYwBDtw6EJHqEeDrq4UwZRD8YBSvp3g6klP678il2eeiVXN2Q==", + "dev": true, + "requires": { + "immediate": "^3.2.3" + } + }, + "autoprefixer": { + "version": "9.8.6", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.6.tgz", + "integrity": "sha512-XrvP4VVHdRBCdX1S3WXVD8+RyG9qeb1D5Sn1DeLiG2xfSpzellk5k54xbUERJ3M5DggQxes39UGOTP8CFrEGbg==", + "dev": true, + "requires": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "colorette": "^1.2.1", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + } + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=", + "dev": true + }, + "aws4": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", + "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==", + "dev": true + }, + "axios": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz", + "integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==", + "dev": true, + "requires": { + "follow-redirects": "^1.10.0" + } + }, + "babel-loader": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.2.tgz", + "integrity": "sha512-JvTd0/D889PQBtUXJ2PXaKU/pjZDMtHA9V2ecm+eNRmmBCMR09a+fmpGTNwnJtFmFl5Ei7Vy47LjBb+L0wQ99g==", + "dev": true, + "requires": { + "find-cache-dir": "^3.3.1", + "loader-utils": "^1.4.0", + "make-dir": "^3.1.0", + "schema-utils": "^2.6.5" + } + }, + "babel-plugin-dynamic-import-node": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", + "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", + "dev": true, + "requires": { + "object.assign": "^4.1.0" + } + }, + "babel-plugin-polyfill-corejs2": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.2.2.tgz", + "integrity": "sha512-kISrENsJ0z5dNPq5eRvcctITNHYXWOA4DUZRFYCz3jYCcvTb/A546LIddmoGNMVYg2U38OyFeNosQwI9ENTqIQ==", + "dev": true, + "requires": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.2.2", + "semver": "^6.1.1" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "babel-plugin-polyfill-corejs3": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.2.3.tgz", + "integrity": "sha512-rCOFzEIJpJEAU14XCcV/erIf/wZQMmMT5l5vXOpL5uoznyOGfDIjPj6FVytMvtzaKSTSVKouOCTPJ5OMUZH30g==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.2.2", + "core-js-compat": "^3.14.0" + } + }, + "babel-plugin-polyfill-regenerator": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.2.2.tgz", + "integrity": "sha512-Goy5ghsc21HgPDFtzRkSirpZVW35meGoTmTOb2bxqdl60ghub4xOidgNTHaZfQ2FaxQsKmwvXtOAkcIS4SMBWg==", + "dev": true, + "requires": { + "@babel/helper-define-polyfill-provider": "^0.2.2" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", + "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", + "dev": true, + "requires": { + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + } + } + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true + }, + "batch": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", + "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY=", + "dev": true + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "dev": true, + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bhttp": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/bhttp/-/bhttp-1.2.8.tgz", + "integrity": "sha512-ZwEA5FKEUhc98EHRX+BkNmUOs48RTnglvfze2+p0HrMPwhQBtVw1aAYyylnCtRl6x6vltCkzGo2+twQ6LVfm6Q==", + "dev": true, + "requires": { + "bluebird": "^2.8.2", + "concat-stream": "^1.4.7", + "debug": "^2.1.1", + "dev-null": "^0.1.1", + "errors": "^0.2.0", + "extend": "^2.0.0", + "form-data2": "^1.0.0", + "form-fix-array": "^1.0.0", + "lodash.clonedeep": "^4.5.0", + "lodash.merge": "^4.6.2", + "stream-length": "^1.0.2", + "through2-sink": "^1.0.0", + "through2-spy": "^1.2.0", + "tough-cookie": "^2.3.1" + }, + "dependencies": { + "extend": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-2.0.2.tgz", + "integrity": "sha512-AgFD4VU+lVLP6vjnlNfF7OeInLTyeyckCNPEsuxz1vi786UuK/nk6ynPuhn/h+Ju9++TQyr5EpLRI14fc1QtTQ==", + "dev": true + } + } + }, + "big.js": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", + "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", + "dev": true + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true + }, + "bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "dev": true, + "optional": true, + "requires": { + "file-uri-to-path": "1.0.0" + } + }, + "bluebird": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz", + "integrity": "sha1-U0uQM8AiyVecVro7Plpcqvu2UOE=", + "dev": true + }, + "bn.js": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz", + "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw==", + "dev": true + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + } + } + }, + "bonjour": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz", + "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=", + "dev": true, + "requires": { + "array-flatten": "^2.1.0", + "deep-equal": "^1.0.1", + "dns-equal": "^1.0.0", + "dns-txt": "^2.0.2", + "multicast-dns": "^6.0.1", + "multicast-dns-service-types": "^1.1.0" + } + }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, + "boxen": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.3.0.tgz", + "integrity": "sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw==", + "dev": true, + "requires": { + "ansi-align": "^2.0.0", + "camelcase": "^4.0.0", + "chalk": "^2.0.1", + "cli-boxes": "^1.0.0", + "string-width": "^2.0.0", + "term-size": "^1.2.0", + "widest-line": "^2.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + } + }, + "broken-link-checker": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/broken-link-checker/-/broken-link-checker-0.7.8.tgz", + "integrity": "sha512-/zH4/nLMNKDeDH5nVuf/R6WYd0Yjnar1NpcdAO2+VlwjGKzJa6y42C03UO+imBSHwe6BefSkVi82fImE2Rb7yg==", + "dev": true, + "requires": { + "bhttp": "^1.2.1", + "calmcard": "~0.1.1", + "chalk": "^1.1.3", + "char-spinner": "^1.0.1", + "condense-whitespace": "^1.0.0", + "default-user-agent": "^1.0.0", + "errno": "~0.1.4", + "extend": "^3.0.0", + "http-equiv-refresh": "^1.0.0", + "humanize-duration": "^3.9.1", + "is-stream": "^1.0.1", + "is-string": "^1.0.4", + "limited-request-queue": "^2.0.0", + "link-types": "^1.1.0", + "maybe-callback": "^2.1.0", + "nopter": "~0.3.0", + "parse5": "^3.0.2", + "robot-directives": "~0.3.0", + "robots-txt-guard": "~0.1.0", + "robots-txt-parse": "~0.0.4", + "urlcache": "~0.7.0", + "urlobj": "0.0.11" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "brorand": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", + "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8=", + "dev": true + }, + "browserify-aes": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", + "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==", + "dev": true, + "requires": { + "buffer-xor": "^1.0.3", + "cipher-base": "^1.0.0", + "create-hash": "^1.1.0", + "evp_bytestokey": "^1.0.3", + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "browserify-cipher": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz", + "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==", + "dev": true, + "requires": { + "browserify-aes": "^1.0.4", + "browserify-des": "^1.0.0", + "evp_bytestokey": "^1.0.0" + } + }, + "browserify-des": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz", + "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "des.js": "^1.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "browserify-rsa": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz", + "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==", + "dev": true, + "requires": { + "bn.js": "^5.0.0", + "randombytes": "^2.0.1" + } + }, + "browserify-sign": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", + "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "dev": true, + "requires": { + "bn.js": "^5.1.1", + "browserify-rsa": "^4.0.1", + "create-hash": "^1.2.0", + "create-hmac": "^1.1.7", + "elliptic": "^6.5.3", + "inherits": "^2.0.4", + "parse-asn1": "^5.1.5", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "browserify-zlib": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz", + "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==", + "dev": true, + "requires": { + "pako": "~1.0.5" + } + }, + "browserslist": { + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", + "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", + "dev": true, + "requires": { + "caniuse-lite": "^1.0.30001219", + "colorette": "^1.2.2", + "electron-to-chromium": "^1.3.723", + "escalade": "^3.1.1", + "node-releases": "^1.1.71" + } + }, + "buffer": { + "version": "4.9.2", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz", + "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==", + "dev": true, + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4", + "isarray": "^1.0.0" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-indexof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz", + "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==", + "dev": true + }, + "buffer-json": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-json/-/buffer-json-2.0.0.tgz", + "integrity": "sha512-+jjPFVqyfF1esi9fvfUs3NqM0pH1ziZ36VP4hmA/y/Ssfo/5w5xHKfTw9BwQjoJ1w/oVtpLomqwUHKdefGyuHw==", + "dev": true + }, + "buffer-xor": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz", + "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk=", + "dev": true + }, + "builtin-status-codes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz", + "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", + "dev": true + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=", + "dev": true + }, + "cac": { + "version": "6.7.3", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.3.tgz", + "integrity": "sha512-ECVqVZh74qgSuZG9YOt2OJPI3wGcf+EwwuF/XIOYqZBD0KZYLtgPWqFPxmDPQ6joxI1nOlvVgRV6VT53Ooyocg==", + "dev": true + }, + "cacache": { + "version": "12.0.4", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz", + "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==", + "dev": true, + "requires": { + "bluebird": "^3.5.5", + "chownr": "^1.1.1", + "figgy-pudding": "^3.5.1", + "glob": "^7.1.4", + "graceful-fs": "^4.1.15", + "infer-owner": "^1.0.3", + "lru-cache": "^5.1.1", + "mississippi": "^3.0.0", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "promise-inflight": "^1.0.1", + "rimraf": "^2.6.3", + "ssri": "^6.0.1", + "unique-filename": "^1.1.1", + "y18n": "^4.0.0" + }, + "dependencies": { + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "requires": { + "yallist": "^3.0.2" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + } + } + }, + "cache-base": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", + "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", + "dev": true, + "requires": { + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" + } + }, + "cache-loader": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/cache-loader/-/cache-loader-3.0.1.tgz", + "integrity": "sha512-HzJIvGiGqYsFUrMjAJNDbVZoG7qQA+vy9AIoKs7s9DscNfki0I589mf2w6/tW+kkFH3zyiknoWV5Jdynu6b/zw==", + "dev": true, + "requires": { + "buffer-json": "^2.0.0", + "find-cache-dir": "^2.1.0", + "loader-utils": "^1.2.3", + "mkdirp": "^0.5.1", + "neo-async": "^2.6.1", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "dev": true, + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "dev": true + }, + "normalize-url": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.1.tgz", + "integrity": "sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==", + "dev": true + } + } + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "call-me-maybe": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz", + "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms=", + "dev": true + }, + "caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ=", + "dev": true, + "requires": { + "callsites": "^2.0.0" + }, + "dependencies": { + "callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA=", + "dev": true + } + } + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "^0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "calmcard": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/calmcard/-/calmcard-0.1.1.tgz", + "integrity": "sha1-NawrZkkrDtOa0GqJOg/25hEk5Ek=", + "dev": true + }, + "camel-case": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz", + "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M=", + "dev": true, + "requires": { + "no-case": "^2.2.0", + "upper-case": "^1.1.1" + } + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=", + "dev": true + }, + "caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "caniuse-lite": { + "version": "1.0.30001237", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001237.tgz", + "integrity": "sha512-pDHgRndit6p1NR2GhzMbQ6CkRrp4VKuSsqbcLeOQppYPKOYkKT/6ZvZDvKJUqcmtyWIAHuZq3SVS2vc1egCZzw==", + "dev": true + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", + "dev": true + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "char-spinner": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/char-spinner/-/char-spinner-1.0.1.tgz", + "integrity": "sha1-5upnvSR+EHESmDt6sEee02KAAIE=", + "dev": true + }, + "check-more-types": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", + "integrity": "sha1-FCD/sQ/URNz8ebQ4kbv//TKoRgA=", + "dev": true + }, + "chokidar": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", + "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", + "dev": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "fsevents": "^1.2.7", + "glob-parent": "^3.1.0", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true + }, + "chrome-trace-event": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", + "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", + "dev": true + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "cipher-base": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz", + "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "class-utils": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", + "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "clean-css": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", + "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==", + "dev": true, + "requires": { + "source-map": "~0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cli-boxes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz", + "integrity": "sha1-T6kXw+WclKAEzWH47lCdplFocUM=", + "dev": true + }, + "cli-table": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.6.tgz", + "integrity": "sha512-ZkNZbnZjKERTY5NwC2SeMeLeifSPq/pubeRoTpdr3WchLlnZg6hEgvHkK5zL7KNFdd9PmHN8lxrENUwI3cE8vQ==", + "dev": true, + "requires": { + "colors": "1.0.3" + } + }, + "clipboardy": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", + "integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==", + "dev": true, + "requires": { + "arch": "^2.1.1", + "execa": "^1.0.0", + "is-wsl": "^2.1.1" + } + }, + "cliui": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", + "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", + "dev": true, + "requires": { + "string-width": "^3.1.0", + "strip-ansi": "^5.2.0", + "wrap-ansi": "^5.1.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "coa": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz", + "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==", + "dev": true, + "requires": { + "@types/q": "^1.5.1", + "chalk": "^2.4.1", + "q": "^1.1.2" + } + }, + "collection-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", + "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", + "dev": true, + "requires": { + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" + } + }, + "color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/color/-/color-3.1.3.tgz", + "integrity": "sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==", + "dev": true, + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.4" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "color-string": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.5.tgz", + "integrity": "sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==", + "dev": true, + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colorette": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", + "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", + "dev": true + }, + "colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=", + "dev": true + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dev": true, + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "combined-stream2": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/combined-stream2/-/combined-stream2-1.1.2.tgz", + "integrity": "sha1-9uFLegFWZvjHsKH6xQYkAWSsNXA=", + "dev": true, + "requires": { + "bluebird": "^2.8.1", + "debug": "^2.1.1", + "stream-length": "^1.0.1" + } + }, + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", + "dev": true + }, + "component-emitter": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", + "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", + "dev": true + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "dev": true, + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.3.tgz", + "integrity": "sha512-HSjyBG5N1Nnz7tF2+O7A9XUhyjru71/fwgNb7oIsEVHR0WShfs2tIS/EySLgiTe98aOK18YDlMXpzjCXY/n9mg==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.14", + "debug": "2.6.9", + "on-headers": "~1.0.1", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "condense-whitespace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/condense-whitespace/-/condense-whitespace-1.0.0.tgz", + "integrity": "sha1-g3bZjvAo5sss0kaOKM5CxcZasak=", + "dev": true + }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + } + }, + "connect-history-api-fallback": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz", + "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==", + "dev": true + }, + "consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", + "dev": true + }, + "console-browserify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz", + "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==", + "dev": true + }, + "consolidate": { + "version": "0.15.1", + "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz", + "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==", + "dev": true, + "requires": { + "bluebird": "^3.1.1" + }, + "dependencies": { + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + } + } + }, + "constants-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz", + "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=", + "dev": true + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=", + "dev": true + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==", + "dev": true + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=", + "dev": true + }, + "copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "copy-descriptor": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", + "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", + "dev": true + }, + "copy-webpack-plugin": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.1.2.tgz", + "integrity": "sha512-Uh7crJAco3AjBvgAy9Z75CjK8IG+gxaErro71THQ+vv/bl4HaQcpkexAY8KVW/T6D2W2IRr+couF/knIRkZMIQ==", + "dev": true, + "requires": { + "cacache": "^12.0.3", + "find-cache-dir": "^2.1.0", + "glob-parent": "^3.1.0", + "globby": "^7.1.1", + "is-glob": "^4.0.1", + "loader-utils": "^1.2.3", + "minimatch": "^3.0.4", + "normalize-path": "^3.0.0", + "p-limit": "^2.2.1", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "globby": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz", + "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "dir-glob": "^2.0.0", + "glob": "^7.1.2", + "ignore": "^3.3.5", + "pify": "^3.0.0", + "slash": "^1.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "ignore": { + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "slash": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz", + "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU=", + "dev": true + } + } + }, + "core-js": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.14.0.tgz", + "integrity": "sha512-3s+ed8er9ahK+zJpp9ZtuVcDoFzHNiZsPbNAAE4KXgrRHbjSqqNN6xGSXq6bq7TZIbKj4NLrLb6bJ5i+vSVjHA==", + "dev": true + }, + "core-js-compat": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.14.0.tgz", + "integrity": "sha512-R4NS2eupxtiJU+VwgkF9WTpnSfZW4pogwKHd8bclWU2sp93Pr5S1uYJI84cMOubJRou7bcfL0vmwtLslWN5p3A==", + "dev": true, + "requires": { + "browserslist": "^4.16.6", + "semver": "7.0.0" + }, + "dependencies": { + "semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true + } + } + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", + "dev": true + }, + "cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "dev": true, + "requires": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + } + }, + "create-ecdh": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz", + "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "elliptic": "^6.5.3" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "create-hash": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz", + "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.1", + "inherits": "^2.0.1", + "md5.js": "^1.3.4", + "ripemd160": "^2.0.1", + "sha.js": "^2.4.0" + } + }, + "create-hmac": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz", + "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==", + "dev": true, + "requires": { + "cipher-base": "^1.0.3", + "create-hash": "^1.1.0", + "inherits": "^2.0.1", + "ripemd160": "^2.0.0", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "requires": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + } + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true + }, + "css": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/css/-/css-2.2.4.tgz", + "integrity": "sha512-oUnjmWpy0niI3x/mPL8dVEI1l7MnG3+HHyRPHf+YFSbK+svOhXpmSOcDURUh2aOCgl2grzrOPt1nHLuCVFULLw==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "source-map": "^0.6.1", + "source-map-resolve": "^0.5.2", + "urix": "^0.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-color-names": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", + "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", + "dev": true + }, + "css-declaration-sorter": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz", + "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==", + "dev": true, + "requires": { + "postcss": "^7.0.1", + "timsort": "^0.3.0" + } + }, + "css-loader": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-2.1.1.tgz", + "integrity": "sha512-OcKJU/lt232vl1P9EEDamhoO9iKY3tIjY5GU+XDLblAykTdgs6Ux9P1hTHve8nFKy5KPpOXOsVI/hIwi3841+w==", + "dev": true, + "requires": { + "camelcase": "^5.2.0", + "icss-utils": "^4.1.0", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.14", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^2.0.6", + "postcss-modules-scope": "^2.1.0", + "postcss-modules-values": "^2.0.0", + "postcss-value-parser": "^3.3.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "css-parse": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-2.0.0.tgz", + "integrity": "sha1-pGjuZnwW2BzPBcWMONKpfHgNv9Q=", + "dev": true, + "requires": { + "css": "^2.0.0" + } + }, + "css-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz", + "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^3.2.1", + "domutils": "^1.7.0", + "nth-check": "^1.0.2" + } + }, + "css-select-base-adapter": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", + "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==", + "dev": true + }, + "css-tree": { + "version": "1.0.0-alpha.37", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", + "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==", + "dev": true, + "requires": { + "mdn-data": "2.0.4", + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "css-what": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz", + "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==", + "dev": true + }, + "cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true + }, + "cssnano": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.11.tgz", + "integrity": "sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "cssnano-preset-default": "^4.0.8", + "is-resolvable": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "cssnano-preset-default": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz", + "integrity": "sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ==", + "dev": true, + "requires": { + "css-declaration-sorter": "^4.0.1", + "cssnano-util-raw-cache": "^4.0.1", + "postcss": "^7.0.0", + "postcss-calc": "^7.0.1", + "postcss-colormin": "^4.0.3", + "postcss-convert-values": "^4.0.1", + "postcss-discard-comments": "^4.0.2", + "postcss-discard-duplicates": "^4.0.2", + "postcss-discard-empty": "^4.0.1", + "postcss-discard-overridden": "^4.0.1", + "postcss-merge-longhand": "^4.0.11", + "postcss-merge-rules": "^4.0.3", + "postcss-minify-font-values": "^4.0.2", + "postcss-minify-gradients": "^4.0.2", + "postcss-minify-params": "^4.0.2", + "postcss-minify-selectors": "^4.0.2", + "postcss-normalize-charset": "^4.0.1", + "postcss-normalize-display-values": "^4.0.2", + "postcss-normalize-positions": "^4.0.2", + "postcss-normalize-repeat-style": "^4.0.2", + "postcss-normalize-string": "^4.0.2", + "postcss-normalize-timing-functions": "^4.0.2", + "postcss-normalize-unicode": "^4.0.1", + "postcss-normalize-url": "^4.0.1", + "postcss-normalize-whitespace": "^4.0.2", + "postcss-ordered-values": "^4.1.2", + "postcss-reduce-initial": "^4.0.3", + "postcss-reduce-transforms": "^4.0.2", + "postcss-svgo": "^4.0.3", + "postcss-unique-selectors": "^4.0.1" + } + }, + "cssnano-util-get-arguments": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz", + "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8=", + "dev": true + }, + "cssnano-util-get-match": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz", + "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0=", + "dev": true + }, + "cssnano-util-raw-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz", + "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "cssnano-util-same-parent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz", + "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==", + "dev": true + }, + "csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dev": true, + "requires": { + "css-tree": "^1.1.2" + }, + "dependencies": { + "css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dev": true, + "requires": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + } + }, + "mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "cyclist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz", + "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk=", + "dev": true + }, + "d3": { + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/d3/-/d3-5.16.0.tgz", + "integrity": "sha512-4PL5hHaHwX4m7Zr1UapXW23apo6pexCgdetdJ5kTmADpG/7T9Gkxw0M0tf/pjoB63ezCCm0u5UaFYy2aMt0Mcw==", + "dev": true, + "requires": { + "d3-array": "1", + "d3-axis": "1", + "d3-brush": "1", + "d3-chord": "1", + "d3-collection": "1", + "d3-color": "1", + "d3-contour": "1", + "d3-dispatch": "1", + "d3-drag": "1", + "d3-dsv": "1", + "d3-ease": "1", + "d3-fetch": "1", + "d3-force": "1", + "d3-format": "1", + "d3-geo": "1", + "d3-hierarchy": "1", + "d3-interpolate": "1", + "d3-path": "1", + "d3-polygon": "1", + "d3-quadtree": "1", + "d3-random": "1", + "d3-scale": "2", + "d3-scale-chromatic": "1", + "d3-selection": "1", + "d3-shape": "1", + "d3-time": "1", + "d3-time-format": "2", + "d3-timer": "1", + "d3-transition": "1", + "d3-voronoi": "1", + "d3-zoom": "1" + } + }, + "d3-array": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz", + "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==", + "dev": true + }, + "d3-axis": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/d3-axis/-/d3-axis-1.0.12.tgz", + "integrity": "sha512-ejINPfPSNdGFKEOAtnBtdkpr24c4d4jsei6Lg98mxf424ivoDP2956/5HDpIAtmHo85lqT4pruy+zEgvRUBqaQ==", + "dev": true + }, + "d3-brush": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/d3-brush/-/d3-brush-1.1.6.tgz", + "integrity": "sha512-7RW+w7HfMCPyZLifTz/UnJmI5kdkXtpCbombUSs8xniAyo0vIbrDzDwUJB6eJOgl9u5DQOt2TQlYumxzD1SvYA==", + "dev": true, + "requires": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, + "d3-chord": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-chord/-/d3-chord-1.0.6.tgz", + "integrity": "sha512-JXA2Dro1Fxw9rJe33Uv+Ckr5IrAa74TlfDEhE/jfLOaXegMQFQTAgAw9WnZL8+HxVBRXaRGCkrNU7pJeylRIuA==", + "dev": true, + "requires": { + "d3-array": "1", + "d3-path": "1" + } + }, + "d3-collection": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz", + "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==", + "dev": true + }, + "d3-color": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.1.tgz", + "integrity": "sha512-p2sTHSLCJI2QKunbGb7ocOh7DgTAn8IrLx21QRc/BSnodXM4sv6aLQlnfpvehFMLZEfBc6g9pH9SWQccFYfJ9Q==", + "dev": true + }, + "d3-contour": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/d3-contour/-/d3-contour-1.3.2.tgz", + "integrity": "sha512-hoPp4K/rJCu0ladiH6zmJUEz6+u3lgR+GSm/QdM2BBvDraU39Vr7YdDCicJcxP1z8i9B/2dJLgDC1NcvlF8WCg==", + "dev": true, + "requires": { + "d3-array": "^1.1.1" + } + }, + "d3-dispatch": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz", + "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==", + "dev": true + }, + "d3-drag": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.5.tgz", + "integrity": "sha512-rD1ohlkKQwMZYkQlYVCrSFxsWPzI97+W+PaEIBNTMxRuxz9RF0Hi5nJWHGVJ3Om9d2fRTe1yOBINJyy/ahV95w==", + "dev": true, + "requires": { + "d3-dispatch": "1", + "d3-selection": "1" + } + }, + "d3-dsv": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz", + "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==", + "dev": true, + "requires": { + "commander": "2", + "iconv-lite": "0.4", + "rw": "1" + } + }, + "d3-ease": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.7.tgz", + "integrity": "sha512-lx14ZPYkhNx0s/2HX5sLFUI3mbasHjSSpwO/KaaNACweVwxUruKyWVcb293wMv1RqTPZyZ8kSZ2NogUZNcLOFQ==", + "dev": true + }, + "d3-fetch": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/d3-fetch/-/d3-fetch-1.2.0.tgz", + "integrity": "sha512-yC78NBVcd2zFAyR/HnUiBS7Lf6inSCoWcSxFfw8FYL7ydiqe80SazNwoffcqOfs95XaLo7yebsmQqDKSsXUtvA==", + "dev": true, + "requires": { + "d3-dsv": "1" + } + }, + "d3-force": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz", + "integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==", + "dev": true, + "requires": { + "d3-collection": "1", + "d3-dispatch": "1", + "d3-quadtree": "1", + "d3-timer": "1" + } + }, + "d3-format": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz", + "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==", + "dev": true + }, + "d3-geo": { + "version": "1.12.1", + "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz", + "integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==", + "dev": true, + "requires": { + "d3-array": "1" + } + }, + "d3-hierarchy": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz", + "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==", + "dev": true + }, + "d3-interpolate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.4.0.tgz", + "integrity": "sha512-V9znK0zc3jOPV4VD2zZn0sDhZU3WAE2bmlxdIwwQPPzPjvyLkd8B3JUVdS1IDUFDkWZ72c9qnv1GK2ZagTZ8EA==", + "dev": true, + "requires": { + "d3-color": "1" + } + }, + "d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==", + "dev": true + }, + "d3-polygon": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/d3-polygon/-/d3-polygon-1.0.6.tgz", + "integrity": "sha512-k+RF7WvI08PC8reEoXa/w2nSg5AUMTi+peBD9cmFc+0ixHfbs4QmxxkarVal1IkVkgxVuk9JSHhJURHiyHKAuQ==", + "dev": true + }, + "d3-quadtree": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz", + "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==", + "dev": true + }, + "d3-random": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/d3-random/-/d3-random-1.1.2.tgz", + "integrity": "sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ==", + "dev": true + }, + "d3-scale": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-2.2.2.tgz", + "integrity": "sha512-LbeEvGgIb8UMcAa0EATLNX0lelKWGYDQiPdHj+gLblGVhGLyNbaCn3EvrJf0A3Y/uOOU5aD6MTh5ZFCdEwGiCw==", + "dev": true, + "requires": { + "d3-array": "^1.2.0", + "d3-collection": "1", + "d3-format": "1", + "d3-interpolate": "1", + "d3-time": "1", + "d3-time-format": "2" + } + }, + "d3-scale-chromatic": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-1.5.0.tgz", + "integrity": "sha512-ACcL46DYImpRFMBcpk9HhtIyC7bTBR4fNOPxwVSl0LfulDAwyiHyPOTqcDG1+t5d4P9W7t/2NAuWu59aKko/cg==", + "dev": true, + "requires": { + "d3-color": "1", + "d3-interpolate": "1" + } + }, + "d3-selection": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz", + "integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg==", + "dev": true + }, + "d3-shape": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz", + "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==", + "dev": true, + "requires": { + "d3-path": "1" + } + }, + "d3-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz", + "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==", + "dev": true + }, + "d3-time-format": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz", + "integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==", + "dev": true, + "requires": { + "d3-time": "1" + } + }, + "d3-timer": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz", + "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==", + "dev": true + }, + "d3-transition": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.3.2.tgz", + "integrity": "sha512-sc0gRU4PFqZ47lPVHloMn9tlPcv8jxgOQg+0zjhfZXMQuvppjG6YuwdMBE0TuqCZjeJkLecku/l9R0JPcRhaDA==", + "dev": true, + "requires": { + "d3-color": "1", + "d3-dispatch": "1", + "d3-ease": "1", + "d3-interpolate": "1", + "d3-selection": "^1.1.0", + "d3-timer": "1" + } + }, + "d3-voronoi": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/d3-voronoi/-/d3-voronoi-1.1.4.tgz", + "integrity": "sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==", + "dev": true + }, + "d3-zoom": { + "version": "1.8.3", + "resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz", + "integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==", + "dev": true, + "requires": { + "d3-dispatch": "1", + "d3-drag": "1", + "d3-interpolate": "1", + "d3-selection": "1", + "d3-transition": "1" + } + }, + "dagre": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", + "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", + "dev": true, + "requires": { + "graphlib": "^2.1.8", + "lodash": "^4.17.15" + } + }, + "dagre-d3": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/dagre-d3/-/dagre-d3-0.6.4.tgz", + "integrity": "sha512-e/6jXeCP7/ptlAM48clmX4xTZc5Ek6T6kagS7Oz2HrYSdqcLZFLqpAfh7ldbZRFfxCZVyh61NEPR08UQRVxJzQ==", + "dev": true, + "requires": { + "d3": "^5.14", + "dagre": "^0.8.5", + "graphlib": "^2.1.8", + "lodash": "^4.17.15" + } + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "date-fns": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-1.30.1.tgz", + "integrity": "sha512-hBSVCvSmWC+QypYObzwGOd9wqdDpOt+0wl0KbU+R+uuZBS1jN8VsD1ss3irQDknRj5NvxiTF6oj/nDRnN/UQNw==", + "dev": true + }, + "dayjs": { + "version": "1.10.6", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.6.tgz", + "integrity": "sha512-AztC/IOW4L1Q41A86phW5Thhcrco3xuAA+YX/BLpLWWjRcTj5TOt/QImBLmCKlrF7u7k47arTnOyL6GnbG8Hvw==", + "dev": true + }, + "de-indent": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz", + "integrity": "sha1-sgOOhG3DO6pXlhKNCAS0VbjB4h0=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decode-uri-component": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", + "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", + "dev": true + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "dev": true, + "requires": { + "mimic-response": "^1.0.0" + } + }, + "deep-equal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", + "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "dev": true, + "requires": { + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.1", + "is-regex": "^1.0.4", + "object-is": "^1.0.1", + "object-keys": "^1.1.1", + "regexp.prototype.flags": "^1.2.0" + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, + "deepmerge": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", + "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==", + "dev": true + }, + "default-gateway": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz", + "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==", + "dev": true, + "requires": { + "execa": "^1.0.0", + "ip-regex": "^2.1.0" + } + }, + "default-user-agent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/default-user-agent/-/default-user-agent-1.0.0.tgz", + "integrity": "sha1-FsRu/cq6PtxF8k8r1IaLAbfCrcY=", + "dev": true, + "requires": { + "os-name": "~1.0.3" + } + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", + "dev": true + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "dev": true, + "requires": { + "object-keys": "^1.0.12" + } + }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" + } + }, + "del": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz", + "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "globby": "^6.1.0", + "is-path-cwd": "^2.0.0", + "is-path-in-cwd": "^2.0.0", + "p-map": "^2.0.0", + "pify": "^4.0.1", + "rimraf": "^2.6.3" + }, + "dependencies": { + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + } + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "dev": true + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=", + "dev": true + }, + "des.js": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", + "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0" + } + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=", + "dev": true + }, + "detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "dev": true + }, + "dev-null": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dev-null/-/dev-null-0.1.1.tgz", + "integrity": "sha1-WiBc48Ky73e2I41roXnrdMag6Bg=", + "dev": true + }, + "diffie-hellman": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", + "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "miller-rabin": "^4.0.0", + "randombytes": "^2.0.0" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "dir-glob": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz", + "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==", + "dev": true, + "requires": { + "path-type": "^3.0.0" + } + }, + "dns-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz", + "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0=", + "dev": true + }, + "dns-packet": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz", + "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==", + "dev": true, + "requires": { + "ip": "^1.1.0", + "safe-buffer": "^5.0.1" + } + }, + "dns-txt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz", + "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=", + "dev": true, + "requires": { + "buffer-indexof": "^1.0.0" + } + }, + "docsearch.js": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/docsearch.js/-/docsearch.js-2.6.3.tgz", + "integrity": "sha512-GN+MBozuyz664ycpZY0ecdQE0ND/LSgJKhTLA0/v3arIS3S1Rpf2OJz6A35ReMsm91V5apcmzr5/kM84cvUg+A==", + "dev": true, + "requires": { + "algoliasearch": "^3.24.5", + "autocomplete.js": "0.36.0", + "hogan.js": "^3.0.2", + "request": "^2.87.0", + "stack-utils": "^1.0.1", + "to-factory": "^1.0.0", + "zepto": "^1.2.0" + } + }, + "dom-converter": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", + "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==", + "dev": true, + "requires": { + "utila": "~0.4" + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + } + } + }, + "dom-walk": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz", + "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==", + "dev": true + }, + "domain-browser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz", + "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==", + "dev": true + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==", + "dev": true + }, + "domhandler": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.2.0.tgz", + "integrity": "sha512-zk7sgt970kzPks2Bf+dwT/PLzghLnsivb9CcxkvR8Mzr66Olr0Ofd8neSbglHJHaHa2MadfoSdNlKYAaafmWfA==", + "dev": true, + "requires": { + "domelementtype": "^2.2.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true + } + } + }, + "dompurify": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.3.1.tgz", + "integrity": "sha512-xGWt+NHAQS+4tpgbOAI08yxW0Pr256Gu/FNE2frZVTbgrBUn8M7tz7/ktS/LZ2MHeGqz6topj0/xY+y8R5FBFw==", + "dev": true + }, + "domutils": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz", + "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==", + "dev": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "dev": true + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", + "dev": true + }, + "duplexify": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz", + "integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + } + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "dev": true, + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=", + "dev": true + }, + "electron-to-chromium": { + "version": "1.3.752", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.752.tgz", + "integrity": "sha512-2Tg+7jSl3oPxgsBsWKh5H83QazTkmWG/cnNwJplmyZc7KcN61+I10oUgaXSVk/NwfvN3BdkKDR4FYuRBQQ2v0A==", + "dev": true + }, + "elliptic": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "dev": true, + "requires": { + "bn.js": "^4.11.9", + "brorand": "^1.1.0", + "hash.js": "^1.0.0", + "hmac-drbg": "^1.0.1", + "inherits": "^2.0.4", + "minimalistic-assert": "^1.0.1", + "minimalistic-crypto-utils": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", + "dev": true + }, + "emojis-list": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", + "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", + "dev": true + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=", + "dev": true + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "enhanced-resolve": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz", + "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "memory-fs": "^0.5.0", + "tapable": "^1.0.0" + }, + "dependencies": { + "memory-fs": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz", + "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + } + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==", + "dev": true + }, + "envify": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/envify/-/envify-4.1.0.tgz", + "integrity": "sha512-IKRVVoAYr4pIx4yIWNsz9mOsboxlNXiu7TNBnem/K/uTHdkyzXWDzHCK7UTolqBbgaBz0tQHsD3YNls0uIIjiw==", + "dev": true, + "requires": { + "esprima": "^4.0.0", + "through": "~2.3.4" + } + }, + "envinfo": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", + "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", + "dev": true + }, + "eol": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eol/-/eol-0.2.0.tgz", + "integrity": "sha1-L22whqJDpG4+Xb0OE0Ncfr6/Cd0=", + "dev": true + }, + "errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "requires": { + "prr": "~1.0.1" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "errors": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/errors/-/errors-0.2.0.tgz", + "integrity": "sha1-D1Hoidqj4RsZ5xhtEfEEqmbrJAM=", + "dev": true + }, + "es-abstract": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.3.tgz", + "integrity": "sha512-nQIr12dxV7SSxE6r6f1l3DtAeEYdsGpps13dR0TwJg1S8gyp4ZPgy3FZcHBgbiQqnoqSTb+oC+kO4UQ0C/J8vw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.2", + "is-callable": "^1.2.3", + "is-negative-zero": "^2.0.1", + "is-regex": "^1.1.3", + "is-string": "^1.0.6", + "object-inspect": "^1.10.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.2", + "string.prototype.trimend": "^1.0.4", + "string.prototype.trimstart": "^1.0.4", + "unbox-primitive": "^1.0.1" + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "es6-promise": { + "version": "4.2.8", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz", + "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==", + "dev": true + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==", + "dev": true + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "eslint-scope": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz", + "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.2.0.tgz", + "integrity": "sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=", + "dev": true + }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "dev": true, + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + }, + "dependencies": { + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "dev": true, + "requires": { + "duplexer": "~0.1.1" + } + } + } + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "dev": true + }, + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=", + "dev": true + }, + "eventsource": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.0.tgz", + "integrity": "sha512-VSJjT5oCNrFvCS6igjzPAt5hBzQ2qPBFIbJ03zLI9SE0mxwZpMw6BfJrbFHm1a141AavMEB8JHmBhWAd66PfCg==", + "dev": true, + "requires": { + "original": "^1.0.0" + } + }, + "evp_bytestokey": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz", + "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==", + "dev": true, + "requires": { + "md5.js": "^1.3.4", + "safe-buffer": "^5.1.1" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dev": true, + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "expand-brackets": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", + "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", + "dev": true, + "requires": { + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "dev": true, + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=", + "dev": true + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "dev": true, + "requires": { + "safe-buffer": "5.1.2" + } + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=", + "dev": true + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", + "dev": true + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + }, + "extglob": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", + "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", + "dev": true, + "requires": { + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", + "dev": true + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-glob": { + "version": "2.2.7", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz", + "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==", + "dev": true, + "requires": { + "@mrmlnc/readdir-enhanced": "^2.2.1", + "@nodelib/fs.stat": "^1.1.2", + "glob-parent": "^3.1.0", + "is-glob": "^4.0.0", + "merge2": "^1.2.3", + "micromatch": "^3.1.10" + } + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-url-parser": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", + "integrity": "sha1-9K8+qfNNiicc9YrSs3WfQx8LMY0=", + "dev": true, + "requires": { + "punycode": "^1.3.2" + } + }, + "faye-websocket": { + "version": "0.11.4", + "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz", + "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==", + "dev": true, + "requires": { + "websocket-driver": ">=0.5.1" + } + }, + "feed": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/feed/-/feed-2.0.4.tgz", + "integrity": "sha512-sWatfulDP6d18qVaWcu34qmq9ml6UeN6nHSBJpNZ2muBqxjPAdT375whPYAHP+gqLfyabtYU5qf2Dv4nqtlp0w==", + "dev": true, + "requires": { + "luxon": "^1.3.3", + "xml": "^1.0.1" + } + }, + "figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "dev": true + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-loader": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-3.0.1.tgz", + "integrity": "sha512-4sNIOXgtH/9WZq4NvlfU3Opn5ynUsqBwSLyM+I7UOwdGigTBYfVVQEwe/msZNX/j4pCJTIM14Fsw66Svo1oVrw==", + "dev": true, + "requires": { + "loader-utils": "^1.0.2", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "dev": true, + "optional": true + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + } + }, + "filter-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/filter-obj/-/filter-obj-1.1.0.tgz", + "integrity": "sha1-mzERErxsYSehbgFsbF1/GeCAXFs=", + "dev": true + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "dev": true, + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "find-cache-dir": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", + "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^3.0.2", + "pkg-dir": "^4.1.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "flush-write-stream": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz", + "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "readable-stream": "^2.3.6" + } + }, + "follow-redirects": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", + "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==", + "dev": true + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", + "dev": true + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", + "dev": true + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "dev": true, + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "form-data2": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/form-data2/-/form-data2-1.0.4.tgz", + "integrity": "sha512-buz4C3F6/7Vpdxt7dNU/tSfjQO/5z9Pyjfb43VhlVvSos5zVhCcMuW9sF1yJ2FdxZRCD2sWQ9WhqUiYLt+AUVQ==", + "dev": true, + "requires": { + "bluebird": "^2.8.2", + "combined-stream2": "^1.0.2", + "debug": "^2.1.1", + "mime": "^1.3.4", + "uuid": "^2.0.1" + } + }, + "form-fix-array": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/form-fix-array/-/form-fix-array-1.0.0.tgz", + "integrity": "sha1-oTR6R+UxF6t7zb8+Lz7JHGZ2m8g=", + "dev": true + }, + "forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "dev": true + }, + "fragment-cache": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", + "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", + "dev": true, + "requires": { + "map-cache": "^0.2.2" + } + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=", + "dev": true + }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", + "dev": true + }, + "from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" + } + }, + "fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "fsevents": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", + "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", + "dev": true, + "optional": true, + "requires": { + "bindings": "^1.5.0", + "nan": "^2.12.1" + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + }, + "get-value": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", + "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", + "dev": true + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0" + } + }, + "github-markdown-css": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/github-markdown-css/-/github-markdown-css-3.0.1.tgz", + "integrity": "sha512-9G5CIPsHoyk5ObDsb/H4KTi23J8KE1oDd4KYU51qwqeM+lKWAiO7abpSgCkyWswgmSKBiuE7/4f8xUz7f2qAiQ==", + "dev": true + }, + "glob": { + "version": "7.1.7", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", + "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-parent": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", + "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", + "dev": true, + "requires": { + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" + }, + "dependencies": { + "is-glob": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", + "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", + "dev": true, + "requires": { + "is-extglob": "^2.1.0" + } + } + } + }, + "glob-to-regexp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz", + "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs=", + "dev": true + }, + "global": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz", + "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==", + "dev": true, + "requires": { + "min-document": "^2.19.0", + "process": "^0.11.10" + } + }, + "global-dirs": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.1.0.tgz", + "integrity": "sha512-MG6kdOUh/xBnyo9cJFeIKkLEc1AyFq42QTU4XiX51i2NEdxLxLWXIjEjmqKeSuKR7pAZjTqUVoT2b2huxVLgYQ==", + "dev": true, + "requires": { + "ini": "1.3.7" + }, + "dependencies": { + "ini": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.7.tgz", + "integrity": "sha512-iKpRpXP+CrP2jyrxvg1kMUpXDyRUFDWurxbnVT1vQPx+Wz9uCYsMIqYuSBLV+PAaZG/d7kRLKRFc9oDMsH+mFQ==", + "dev": true + } + } + }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, + "globby": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz", + "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==", + "dev": true, + "requires": { + "@types/glob": "^7.1.1", + "array-union": "^1.0.2", + "dir-glob": "^2.2.2", + "fast-glob": "^2.2.6", + "glob": "^7.1.3", + "ignore": "^4.0.3", + "pify": "^4.0.1", + "slash": "^2.0.0" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "dev": true, + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "graphlib": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", + "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "gray-matter": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/gray-matter/-/gray-matter-4.0.3.tgz", + "integrity": "sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==", + "dev": true, + "requires": { + "js-yaml": "^3.13.1", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + } + }, + "handle-thing": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", + "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=", + "dev": true + }, + "har-validator": { + "version": "5.1.5", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz", + "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==", + "dev": true, + "requires": { + "ajv": "^6.12.3", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + } + } + }, + "has-bigints": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz", + "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "has-symbols": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz", + "integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw==", + "dev": true + }, + "has-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", + "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", + "dev": true, + "requires": { + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "has-values": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", + "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "kind-of": "^4.0.0" + }, + "dependencies": { + "kind-of": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", + "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==", + "dev": true + }, + "hash-base": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.1.0.tgz", + "integrity": "sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==", + "dev": true, + "requires": { + "inherits": "^2.0.4", + "readable-stream": "^3.6.0", + "safe-buffer": "^5.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } + } + }, + "hash-sum": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz", + "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=", + "dev": true + }, + "hash.js": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", + "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "minimalistic-assert": "^1.0.1" + } + }, + "he": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", + "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", + "dev": true + }, + "hex-color-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz", + "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==", + "dev": true + }, + "hmac-drbg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", + "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=", + "dev": true, + "requires": { + "hash.js": "^1.0.3", + "minimalistic-assert": "^1.0.0", + "minimalistic-crypto-utils": "^1.0.1" + } + }, + "hogan.js": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz", + "integrity": "sha1-TNnhq9QpQUbnZ55B14mHMrAse/0=", + "dev": true, + "requires": { + "mkdirp": "0.3.0", + "nopt": "1.0.10" + }, + "dependencies": { + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "dev": true, + "requires": { + "abbrev": "1" + } + } + } + }, + "hpack.js": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", + "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI=", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "obuf": "^1.0.0", + "readable-stream": "^2.0.1", + "wbuf": "^1.1.0" + } + }, + "hsl-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz", + "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4=", + "dev": true + }, + "hsla-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz", + "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg=", + "dev": true + }, + "html-entities": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz", + "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==", + "dev": true + }, + "html-minifier": { + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz", + "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==", + "dev": true, + "requires": { + "camel-case": "3.0.x", + "clean-css": "4.2.x", + "commander": "2.17.x", + "he": "1.2.x", + "param-case": "2.1.x", + "relateurl": "0.2.x", + "uglify-js": "3.4.x" + }, + "dependencies": { + "commander": { + "version": "2.17.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz", + "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg==", + "dev": true + } + } + }, + "html-tags": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz", + "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==", + "dev": true + }, + "htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" + }, + "dependencies": { + "dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true + }, + "domutils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz", + "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + } + } + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==", + "dev": true + }, + "http-deceiver": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz", + "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc=", + "dev": true + }, + "http-equiv-refresh": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/http-equiv-refresh/-/http-equiv-refresh-1.0.0.tgz", + "integrity": "sha1-jsU4hmBCvl8/evpzfRmNlL6xsHs=", + "dev": true + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "http-parser-js": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.3.tgz", + "integrity": "sha512-t7hjvef/5HEK7RWTdUzVUhl8zkEu+LlaE0IYzdMuvbSDipxBRpOn4Uhw8ZyECEa808iVT8XCjzo6xmYt4CiLZg==", + "dev": true + }, + "http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "requires": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + } + }, + "http-proxy-middleware": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz", + "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==", + "dev": true, + "requires": { + "http-proxy": "^1.17.0", + "is-glob": "^4.0.0", + "lodash": "^4.17.11", + "micromatch": "^3.1.10" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "https-browserify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz", + "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM=", + "dev": true + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "humanize-duration": { + "version": "3.27.0", + "resolved": "https://registry.npmjs.org/humanize-duration/-/humanize-duration-3.27.0.tgz", + "integrity": "sha512-qLo/08cNc3Tb0uD7jK0jAcU5cnqCM0n568918E7R2XhMr/+7F37p4EY062W/stg7tmzvknNn9b/1+UhVRzsYrQ==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=", + "dev": true + }, + "icss-utils": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", + "dev": true, + "requires": { + "postcss": "^7.0.14" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true + }, + "iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE=", + "dev": true + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "immediate": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/immediate/-/immediate-3.3.0.tgz", + "integrity": "sha512-HR7EVodfFUdQCTIeySw+WDRFJlPcLOJbXfwwZ7Oom6tjsvZ3bOkCDJHehQC3nxJrv7+f9XecwazynjU8e4Vw3Q==", + "dev": true + }, + "import-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", + "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk=", + "dev": true, + "requires": { + "import-from": "^2.1.0" + } + }, + "import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY=", + "dev": true, + "requires": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "dependencies": { + "caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ=", + "dev": true, + "requires": { + "caller-callsite": "^2.0.0" + } + } + } + }, + "import-from": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz", + "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=", + "dev": true + }, + "import-local": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz", + "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==", + "dev": true, + "requires": { + "pkg-dir": "^3.0.0", + "resolve-cwd": "^2.0.0" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + } + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc=", + "dev": true + }, + "infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "internal-ip": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", + "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==", + "dev": true, + "requires": { + "default-gateway": "^4.2.0", + "ipaddr.js": "^1.9.0" + } + }, + "ip": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", + "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "dev": true + }, + "ip-regex": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz", + "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk=", + "dev": true + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "dev": true + }, + "is-absolute-url": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", + "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", + "dev": true + }, + "is-accessor-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", + "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-arguments": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz", + "integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==", + "dev": true, + "requires": { + "call-bind": "^1.0.0" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-bigint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.2.tgz", + "integrity": "sha512-0JV5+SOCQkIdzjBK9buARcV804Ddu7A0Qet6sHi3FimE9ne6m4BGQZfRn+NZiXbBk4F4XmHfDZIipLj9pX8dSA==", + "dev": true + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-boolean-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.1.tgz", + "integrity": "sha512-bXdQWkECBUIAcCkeH1unwJLIpZYaa5VvuygSyS/c2lf719mTKZDU5UdDRlpd01UjADgmW8RfqaP+mRaVPdr/Ng==", + "dev": true, + "requires": { + "call-bind": "^1.0.2" + } + }, + "is-browser": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-browser/-/is-browser-2.1.0.tgz", + "integrity": "sha512-F5rTJxDQ2sW81fcfOR1GnCXT6sVJC104fCyfj+mjpwNEwaPYSn5fte5jiHmBg3DHsIoL/l8Kvw5VN5SsTRcRFQ==", + "dev": true + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true + }, + "is-callable": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.3.tgz", + "integrity": "sha512-J1DcMe8UYTBSrKezuIUTUwjXsho29693unXM2YhJUTR2txK/eG47bvNa/wipPFmZFgr/N6f1GA66dv0mEyTIyQ==", + "dev": true + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "dev": true, + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-color-stop": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", + "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U=", + "dev": true, + "requires": { + "css-color-names": "^0.0.4", + "hex-color-regex": "^1.1.0", + "hsl-regex": "^1.0.0", + "hsla-regex": "^1.0.0", + "rgb-regex": "^1.0.1", + "rgba-regex": "^1.0.0" + } + }, + "is-core-module": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.4.0.tgz", + "integrity": "sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-data-descriptor": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", + "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", + "dev": true, + "requires": { + "kind-of": "^6.0.0" + } + }, + "is-date-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.4.tgz", + "integrity": "sha512-/b4ZVsG7Z5XVtIxs/h9W8nvfLgSAyKYdtGWQLbqy6jA1icmgjf8WCoTKgeS4wy5tYaPePouzFMANbnj94c2Z+A==", + "dev": true + }, + "is-descriptor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", + "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" + } + }, + "is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", + "dev": true + }, + "is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true + }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-installed-globally": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", + "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "dev": true, + "requires": { + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + } + }, + "is-negative-zero": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz", + "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==", + "dev": true + }, + "is-npm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", + "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==", + "dev": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-number-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.5.tgz", + "integrity": "sha512-RU0lI/n95pMoUKu9v1BZP5MBcZuNSVJkMkAG2dJqC4z2GlkGUNeH68SuHuBKBD/XFe+LHZ+f9BKkLET60Niedw==", + "dev": true + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-object/-/is-object-1.0.2.tgz", + "integrity": "sha512-2rRIahhZr2UWb45fIOuvZGpFtz0TyOZLf32KxBbSoUCeZR495zCKlWUKKUByk3geS2eAs7ZAABt0Y/Rx0GiQGA==", + "dev": true + }, + "is-path-cwd": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", + "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", + "dev": true + }, + "is-path-in-cwd": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz", + "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==", + "dev": true, + "requires": { + "is-path-inside": "^2.1.0" + }, + "dependencies": { + "is-path-inside": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz", + "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==", + "dev": true, + "requires": { + "path-is-inside": "^1.0.2" + } + } + } + }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "is-regex": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.3.tgz", + "integrity": "sha512-qSVXFz28HM7y+IWX6vLCsexdlvzT1PJNFSBuaQLQ5o0IEw8UDYW6/2+eCMVyIsbM8CNLX2a/QWmSpyxYEHY7CQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "has-symbols": "^1.0.2" + } + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true + }, + "is-string": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.6.tgz", + "integrity": "sha512-2gdzbKUuqtQ3lYNrUTQYoClPhm7oQu4UdpSZMp1/DGgkHBT8E2Z1l0yMdb6D4zNAxwDiMv8MdulKROJGNl0Q0w==", + "dev": true + }, + "is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dev": true, + "requires": { + "has-symbols": "^1.0.2" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isbot": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/isbot/-/isbot-2.5.7.tgz", + "integrity": "sha512-8P+oGrRDvuCpDdovK9oD4skHmSXu56bsK17K2ovXrkW7Ic4H9Y4AqnUUqlXqZxcqQ2358kid9Rb+fbLH5yeeUw==", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", + "dev": true + }, + "javascript-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz", + "integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==", + "dev": true + }, + "joi": { + "version": "17.4.2", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.4.2.tgz", + "integrity": "sha512-Lm56PP+n0+Z2A2rfRvsfWVDXGEWjXxatPopkQ8qQ5mxCEhwHG+Ettgg5o98FFaxilOxozoa14cFhrE/hOzh/Nw==", + "dev": true, + "requires": { + "@hapi/hoek": "^9.0.0", + "@hapi/topo": "^5.0.0", + "@sideway/address": "^4.1.0", + "@sideway/formula": "^3.0.0", + "@sideway/pinpoint": "^2.0.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", + "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", + "dev": true + }, + "jsesc": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", + "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", + "dev": true + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=", + "dev": true + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "json3": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz", + "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==", + "dev": true + }, + "json5": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/jsonp/-/jsonp-0.2.1.tgz", + "integrity": "sha1-pltPoPEL2nGaBUQep7lMVfPhW64=", + "dev": true, + "requires": { + "debug": "^2.1.3" + } + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "dev": true, + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "dev": true, + "requires": { + "json-buffer": "3.0.0" + } + }, + "khroma": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/khroma/-/khroma-1.4.1.tgz", + "integrity": "sha512-+GmxKvmiRuCcUYDgR7g5Ngo0JEDeOsGdNONdU2zsiBQaK4z19Y2NvXqfEDE0ZiIrg45GTZyAnPLVsLZZACYm3Q==", + "dev": true + }, + "killable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", + "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==", + "dev": true + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "last-call-webpack-plugin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz", + "integrity": "sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w==", + "dev": true, + "requires": { + "lodash": "^4.17.5", + "webpack-sources": "^1.1.0" + } + }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "dev": true, + "requires": { + "package-json": "^6.3.0" + } + }, + "lazy-ass": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", + "integrity": "sha1-eZllXoZGwX8In90YfRUNMyTVRRM=", + "dev": true + }, + "limited-request-queue": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/limited-request-queue/-/limited-request-queue-2.0.0.tgz", + "integrity": "sha1-FMfBILE4BgsZoqEDCrr2aTVyZQ0=", + "dev": true, + "requires": { + "is-browser": "^2.0.1", + "parse-domain": "~0.2.0" + } + }, + "link-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/link-types/-/link-types-1.1.0.tgz", + "integrity": "sha1-r2XlnbUucMH/sYrEw8sFa/55aDA=", + "dev": true + }, + "linkify-it": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-2.2.0.tgz", + "integrity": "sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==", + "dev": true, + "requires": { + "uc.micro": "^1.0.1" + } + }, + "load-script": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz", + "integrity": "sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ=", + "dev": true + }, + "loader-runner": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz", + "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==", + "dev": true + }, + "loader-utils": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz", + "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==", + "dev": true, + "requires": { + "big.js": "^5.2.2", + "emojis-list": "^3.0.0", + "json5": "^1.0.1" + }, + "dependencies": { + "json5": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz", + "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==", + "dev": true, + "requires": { + "minimist": "^1.2.0" + } + } + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash._reinterpolate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz", + "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", + "dev": true + }, + "lodash.chunk": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.chunk/-/lodash.chunk-4.2.0.tgz", + "integrity": "sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw=", + "dev": true + }, + "lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", + "dev": true + }, + "lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=", + "dev": true + }, + "lodash.defaultsdeep": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", + "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==", + "dev": true + }, + "lodash.isempty": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.isempty/-/lodash.isempty-4.4.0.tgz", + "integrity": "sha1-b4bL7di+TsmHvpqvM8loTbGzHn4=", + "dev": true + }, + "lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY=", + "dev": true + }, + "lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4=", + "dev": true + }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "lodash.padstart": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padstart/-/lodash.padstart-4.6.1.tgz", + "integrity": "sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs=", + "dev": true + }, + "lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=", + "dev": true + }, + "lodash.template": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-4.5.0.tgz", + "integrity": "sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0", + "lodash.templatesettings": "^4.0.0" + } + }, + "lodash.templatesettings": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz", + "integrity": "sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ==", + "dev": true, + "requires": { + "lodash._reinterpolate": "^3.0.0" + } + }, + "lodash.trimend": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/lodash.trimend/-/lodash.trimend-4.5.1.tgz", + "integrity": "sha1-EoBENyhrmMrYmWt5QU4RMAEUCC8=", + "dev": true + }, + "lodash.trimstart": { + "version": "4.5.1", + "resolved": "https://registry.npmjs.org/lodash.trimstart/-/lodash.trimstart-4.5.1.tgz", + "integrity": "sha1-j/TexTLYJIavWVc8OURZFOlEp/E=", + "dev": true + }, + "lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M=", + "dev": true + }, + "loglevel": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.7.1.tgz", + "integrity": "sha512-Hesni4s5UkWkwCGJMQGAh71PaLUmKFM60dHvq0zi/vDhhrzuk+4GgNbTXJ12YYQJn6ZKBDNIjYcuQGKudvqrIw==", + "dev": true + }, + "lower-case": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz", + "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw=", + "dev": true + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "luxon": { + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-1.28.0.tgz", + "integrity": "sha512-TfTiyvZhwBYM/7QdAVDh+7dBTBA29v4ik0Ce9zda3Mnf8on1S5KJI8P2jKFZ8+5C0jhmr0KwJEO/Wdpm0VeWJQ==", + "dev": true + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", + "dev": true + }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=", + "dev": true + }, + "map-visit": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", + "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", + "dev": true, + "requires": { + "object-visit": "^1.0.0" + } + }, + "markdown-it": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-8.4.2.tgz", + "integrity": "sha512-GcRz3AWTqSUphY3vsUqQSFMbgR38a4Lh3GWlHRh/7MRwz8mcu9n2IO7HOh+bXHrR9kOPDl5RNCaEsrneb+xhHQ==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "entities": "~1.1.1", + "linkify-it": "^2.0.0", + "mdurl": "^1.0.1", + "uc.micro": "^1.0.5" + } + }, + "markdown-it-anchor": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-anchor/-/markdown-it-anchor-5.3.0.tgz", + "integrity": "sha512-/V1MnLL/rgJ3jkMWo84UR+K+jF1cxNG1a+KwqeXqTIJ+jtA8aWSHuigx8lTzauiIjBDbwF3NcWQMotd0Dm39jA==", + "dev": true, + "requires": {} + }, + "markdown-it-chain": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/markdown-it-chain/-/markdown-it-chain-1.3.0.tgz", + "integrity": "sha512-XClV8I1TKy8L2qsT9iX3qiV+50ZtcInGXI80CA+DP62sMs7hXlyV/RM3hfwy5O3Ad0sJm9xIwQELgANfESo8mQ==", + "dev": true, + "requires": { + "webpack-chain": "^4.9.0" + }, + "dependencies": { + "javascript-stringify": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-1.6.0.tgz", + "integrity": "sha1-FC0RHzpuPa6PSpr9d9RYVbWpzOM=", + "dev": true + }, + "webpack-chain": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-4.12.1.tgz", + "integrity": "sha512-BCfKo2YkDe2ByqkEWe1Rw+zko4LsyS75LVr29C6xIrxAg9JHJ4pl8kaIZ396SUSNp6b4815dRZPSTAS8LlURRQ==", + "dev": true, + "requires": { + "deepmerge": "^1.5.2", + "javascript-stringify": "^1.6.0" + } + } + } + }, + "markdown-it-container": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/markdown-it-container/-/markdown-it-container-2.0.0.tgz", + "integrity": "sha1-ABm0P9Au7+zi8ZYKKJX7qBpARpU=", + "dev": true + }, + "markdown-it-emoji": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/markdown-it-emoji/-/markdown-it-emoji-1.4.0.tgz", + "integrity": "sha1-m+4OmpkKljupbfaYDE/dsF37Tcw=", + "dev": true + }, + "markdown-it-footnote": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/markdown-it-footnote/-/markdown-it-footnote-3.0.3.tgz", + "integrity": "sha512-YZMSuCGVZAjzKMn+xqIco9d1cLGxbELHZ9do/TSYVzraooV8ypsppKNmUJ0fVH5ljkCInQAtFpm8Rb3eXSrt5w==", + "dev": true + }, + "markdown-it-implicit-figures": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/markdown-it-implicit-figures/-/markdown-it-implicit-figures-0.10.0.tgz", + "integrity": "sha512-1TWr6+apyoJvRa4Z7eIolZdeajZCRBcc1ckVXon7XwdL8MfydIWsHnZOS5zRrpUNX5b0/O9giWcmuItSkleK5A==", + "dev": true + }, + "markdown-it-table-of-contents": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/markdown-it-table-of-contents/-/markdown-it-table-of-contents-0.4.4.tgz", + "integrity": "sha512-TAIHTHPwa9+ltKvKPWulm/beozQU41Ab+FIefRaQV1NRnpzwcV9QOe6wXQS5WLivm5Q/nlo0rl6laGkMDZE7Gw==", + "dev": true + }, + "maybe-callback": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/maybe-callback/-/maybe-callback-2.1.0.tgz", + "integrity": "sha1-ivoLp7aRp6sSPn8S9l4yu10fgkM=", + "dev": true + }, + "md5.js": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", + "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1", + "safe-buffer": "^5.1.2" + } + }, + "mdn-data": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz", + "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==", + "dev": true + }, + "mdurl": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz", + "integrity": "sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4=", + "dev": true + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=", + "dev": true + }, + "medium-zoom": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/medium-zoom/-/medium-zoom-1.0.6.tgz", + "integrity": "sha512-UdiUWfvz9fZMg1pzf4dcuqA0W079o0mpqbTnOz5ip4VGYX96QjmbM+OgOU/0uOzAytxC0Ny4z+VcYQnhdifimg==", + "dev": true + }, + "memory-fs": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz", + "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI=", + "dev": true, + "requires": { + "errno": "^0.1.3", + "readable-stream": "^2.0.1" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=", + "dev": true + }, + "merge-source-map": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz", + "integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==", + "dev": true, + "requires": { + "source-map": "^0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "mermaid": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-8.12.1.tgz", + "integrity": "sha512-0UCcSF0FLoNcPBsRF4f9OIV32t41fV18//z8o3S+FDz2PbDA1CRGKdQF9IX84VP4Tv9kcgJI/oqJdcBEtB/GPA==", + "dev": true, + "requires": { + "@braintree/sanitize-url": "^3.1.0", + "d3": "^5.16.0", + "dagre": "^0.8.5", + "dagre-d3": "^0.6.4", + "dompurify": "2.3.1", + "graphlib": "^2.1.8", + "khroma": "^1.4.1", + "moment-mini": "^2.24.0", + "stylis": "^4.0.10" + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=", + "dev": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "miller-rabin": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz", + "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==", + "dev": true, + "requires": { + "bn.js": "^4.0.0", + "brorand": "^1.0.1" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true + }, + "mime-db": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", + "dev": true, + "requires": { + "mime-db": "1.48.0" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "dev": true + }, + "min-document": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", + "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=", + "dev": true, + "requires": { + "dom-walk": "^0.1.0" + } + }, + "mini-css-extract-plugin": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.6.0.tgz", + "integrity": "sha512-79q5P7YGI6rdnVyIAV4NXpBQJFWdkzJxCim3Kog4078fM0piAaFlwocqbejdWtLW1cEzCexPrh6EdyFsPgVdAw==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "normalize-url": "^2.0.1", + "schema-utils": "^1.0.0", + "webpack-sources": "^1.1.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", + "dev": true + }, + "minimalistic-crypto-utils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", + "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "mississippi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz", + "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==", + "dev": true, + "requires": { + "concat-stream": "^1.5.0", + "duplexify": "^3.4.2", + "end-of-stream": "^1.1.0", + "flush-write-stream": "^1.0.0", + "from2": "^2.1.0", + "parallel-transform": "^1.1.0", + "pump": "^3.0.0", + "pumpify": "^1.3.3", + "stream-each": "^1.1.0", + "through2": "^2.0.0" + }, + "dependencies": { + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, + "mixin-deep": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", + "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", + "dev": true, + "requires": { + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "dev": true, + "requires": { + "minimist": "^1.2.5" + } + }, + "moment-mini": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment-mini/-/moment-mini-2.24.0.tgz", + "integrity": "sha512-9ARkWHBs+6YJIvrIp0Ik5tyTTtP9PoV0Ssu2Ocq5y9v8+NOOpWiRshAp8c4rZVWTOe+157on/5G+zj5pwIQFEQ==", + "dev": true + }, + "move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I=", + "dev": true, + "requires": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true + }, + "multicast-dns": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz", + "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==", + "dev": true, + "requires": { + "dns-packet": "^1.3.1", + "thunky": "^1.0.2" + } + }, + "multicast-dns-service-types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", + "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE=", + "dev": true + }, + "nan": { + "version": "2.14.2", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", + "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==", + "dev": true, + "optional": true + }, + "nanomatch": { + "version": "1.2.13", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", + "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", + "dev": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "dev": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "no-case": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz", + "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==", + "dev": true, + "requires": { + "lower-case": "^1.1.1" + } + }, + "node-forge": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", + "dev": true + }, + "node-libs-browser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", + "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==", + "dev": true, + "requires": { + "assert": "^1.1.1", + "browserify-zlib": "^0.2.0", + "buffer": "^4.3.0", + "console-browserify": "^1.1.0", + "constants-browserify": "^1.0.0", + "crypto-browserify": "^3.11.0", + "domain-browser": "^1.1.1", + "events": "^3.0.0", + "https-browserify": "^1.0.0", + "os-browserify": "^0.3.0", + "path-browserify": "0.0.1", + "process": "^0.11.10", + "punycode": "^1.2.4", + "querystring-es3": "^0.2.0", + "readable-stream": "^2.3.3", + "stream-browserify": "^2.0.1", + "stream-http": "^2.7.2", + "string_decoder": "^1.0.0", + "timers-browserify": "^2.0.4", + "tty-browserify": "0.0.0", + "url": "^0.11.0", + "util": "^0.11.0", + "vm-browserify": "^1.0.1" + }, + "dependencies": { + "events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true + } + } + }, + "node-releases": { + "version": "1.1.73", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", + "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", + "dev": true + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, + "requires": { + "abbrev": "1" + } + }, + "nopter": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/nopter/-/nopter-0.3.0.tgz", + "integrity": "sha1-uWkOb6uPJWs35OfM0j4rOEUMxx8=", + "dev": true, + "requires": { + "caller-path": "~0.1.0", + "camelcase": "^1.0.2", + "chalk": "~0.5.1", + "cli-table": "~0.3.1", + "eol": "~0.2.0", + "nopt": "^3.0.1", + "object-assign": "^2.0.0", + "splitargs": "~0.0.3" + }, + "dependencies": { + "ansi-regex": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-0.2.1.tgz", + "integrity": "sha1-DY6UaWej2BQ/k+JOKYUl/BsiNfk=", + "dev": true + }, + "ansi-styles": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-1.1.0.tgz", + "integrity": "sha1-6uy/Zs1waIJ2Cy9GkVgrj1XXp94=", + "dev": true + }, + "chalk": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-0.5.1.tgz", + "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", + "dev": true, + "requires": { + "ansi-styles": "^1.1.0", + "escape-string-regexp": "^1.0.0", + "has-ansi": "^0.1.0", + "strip-ansi": "^0.3.0", + "supports-color": "^0.2.0" + } + }, + "has-ansi": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-0.1.0.tgz", + "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", + "dev": true, + "requires": { + "ansi-regex": "^0.2.0" + } + }, + "strip-ansi": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-0.3.0.tgz", + "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", + "dev": true, + "requires": { + "ansi-regex": "^0.2.1" + } + }, + "supports-color": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-0.2.0.tgz", + "integrity": "sha1-2S3iaU6z9nMjlz1649i1W0wiGQo=", + "dev": true + } + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true + }, + "normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", + "dev": true + }, + "normalize-url": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-2.0.1.tgz", + "integrity": "sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw==", + "dev": true, + "requires": { + "prepend-http": "^2.0.0", + "query-string": "^5.0.1", + "sort-keys": "^2.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha1-y480xTIT2JVyP8urkH6UIq28r7E=", + "dev": true + }, + "nth-check": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", + "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==", + "dev": true, + "requires": { + "boolbase": "~1.0.0" + } + }, + "num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4=", + "dev": true + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "object-copy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", + "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", + "dev": true, + "requires": { + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + }, + "dependencies": { + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "object-inspect": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.10.3.tgz", + "integrity": "sha512-e5mCJlSH7poANfC8z8S9s9S2IN5/4Zb3aZ33f5s8YqoazCFzNLloLU8r5VCG+G7WoqLvAAZoVMcy3tp/3X0Plw==", + "dev": true + }, + "object-is": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", + "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true + }, + "object-visit": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", + "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", + "dev": true, + "requires": { + "isobject": "^3.0.0" + } + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.getownpropertydescriptors": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.2.tgz", + "integrity": "sha512-WtxeKSzfBjlzL+F9b7M7hewDzMwy+C8NRssHd1YrNlzHzIDrXcXiNOMrezdAEM4UXixgV+vvnyBeN7Rygl2ttQ==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.2" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "dev": true, + "requires": { + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz", + "integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3", + "es-abstract": "^1.18.2" + } + }, + "obuf": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", + "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==", + "dev": true + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "dev": true, + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "dev": true + }, + "opn": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz", + "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==", + "dev": true, + "requires": { + "is-wsl": "^1.1.0" + }, + "dependencies": { + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + } + } + }, + "optimize-css-assets-webpack-plugin": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.8.tgz", + "integrity": "sha512-mgFS1JdOtEGzD8l+EuISqL57cKO+We9GcoiQEmdCWRqqck+FGNmYJtx9qfAPzEz+lRrlThWMuGDaRkI/yWNx/Q==", + "dev": true, + "requires": { + "cssnano": "^4.1.10", + "last-call-webpack-plugin": "^3.0.0" + } + }, + "original": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/original/-/original-1.0.2.tgz", + "integrity": "sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg==", + "dev": true, + "requires": { + "url-parse": "^1.4.3" + } + }, + "os-browserify": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz", + "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc=", + "dev": true + }, + "os-name": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/os-name/-/os-name-1.0.3.tgz", + "integrity": "sha1-GzefZINa98Wn9JizV8uVIVwVnt8=", + "dev": true, + "requires": { + "osx-release": "^1.0.0", + "win-release": "^1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "osx-release": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/osx-release/-/osx-release-1.1.0.tgz", + "integrity": "sha1-8heRGigTaUmvG/kwiyQeJzfTzWw=", + "dev": true, + "requires": { + "minimist": "^1.1.0" + } + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==", + "dev": true + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-map": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz", + "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==", + "dev": true + }, + "p-retry": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz", + "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==", + "dev": true, + "requires": { + "retry": "^0.12.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "dev": true, + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "registry-auth-token": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.2.1.tgz", + "integrity": "sha512-6gkSb4U6aWJB4SF2ZvLb76yCBjcvufXBqvvEx1HbmKPkutswjW1xNVRY0+daljIYRbogN7O0etYSlbiaEQyMyw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "dev": true, + "requires": { + "rc": "^1.2.8" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true + }, + "parallel-transform": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz", + "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==", + "dev": true, + "requires": { + "cyclist": "^1.0.1", + "inherits": "^2.0.3", + "readable-stream": "^2.1.5" + } + }, + "param-case": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz", + "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc=", + "dev": true, + "requires": { + "no-case": "^2.2.0" + } + }, + "parse-asn1": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", + "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "dev": true, + "requires": { + "asn1.js": "^5.2.0", + "browserify-aes": "^1.0.0", + "evp_bytestokey": "^1.0.0", + "pbkdf2": "^3.0.3", + "safe-buffer": "^5.1.1" + } + }, + "parse-domain": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/parse-domain/-/parse-domain-0.2.2.tgz", + "integrity": "sha1-GImJseLnOYv/PE9P19yhV+tR+sE=", + "dev": true + }, + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "parse5": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-3.0.3.tgz", + "integrity": "sha512-rgO9Zg5LLLkfJF9E6CCmXlSE4UVceloys8JrFqCcHloC3usd/kJCyPDwH2SOlzix2j3xaP9sUX3e8+kvkuleAA==", + "dev": true, + "requires": { + "@types/node": "*" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true + }, + "pascalcase": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", + "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", + "dev": true + }, + "path-browserify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz", + "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==", + "dev": true + }, + "path-dirname": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", + "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-to-regexp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-2.2.1.tgz", + "integrity": "sha512-gu9bD6Ta5bwGrrU8muHzVOBFFREpp2iRkVfhBJahwJ6p6Xw20SjT0MxLnwkjOibQmGSYhiUnf2FLe7k+jcFmGQ==", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "dev": true, + "requires": { + "through": "~2.3" + } + }, + "pbkdf2": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz", + "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==", + "dev": true, + "requires": { + "create-hash": "^1.1.2", + "create-hmac": "^1.1.4", + "ripemd160": "^2.0.1", + "safe-buffer": "^5.0.1", + "sha.js": "^2.4.8" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", + "dev": true + }, + "picomatch": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz", + "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==", + "dev": true, + "optional": true + }, + "pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "portfinder": { + "version": "1.0.28", + "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz", + "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==", + "dev": true, + "requires": { + "async": "^2.6.2", + "debug": "^3.1.1", + "mkdirp": "^0.5.5" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "posix-character-classes": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", + "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", + "dev": true + }, + "postcss": { + "version": "7.0.36", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz", + "integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "source-map": "^0.6.1", + "supports-color": "^6.1.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "postcss-calc": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.5.tgz", + "integrity": "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==", + "dev": true, + "requires": { + "postcss": "^7.0.27", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.2" + } + }, + "postcss-colormin": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz", + "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "color": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-convert-values": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz", + "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-discard-comments": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz", + "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-duplicates": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz", + "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-empty": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz", + "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-discard-overridden": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz", + "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-load-config": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.2.tgz", + "integrity": "sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw==", + "dev": true, + "requires": { + "cosmiconfig": "^5.0.0", + "import-cwd": "^2.0.0" + } + }, + "postcss-loader": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz", + "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "postcss": "^7.0.0", + "postcss-load-config": "^2.0.0", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "postcss-merge-longhand": { + "version": "4.0.11", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz", + "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==", + "dev": true, + "requires": { + "css-color-names": "0.0.4", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "stylehacks": "^4.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-merge-rules": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz", + "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "cssnano-util-same-parent": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0", + "vendors": "^1.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-minify-font-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz", + "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-minify-gradients": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz", + "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "is-color-stop": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-minify-params": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz", + "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "browserslist": "^4.0.0", + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "uniqs": "^2.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-minify-selectors": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz", + "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "postcss-modules-extract-imports": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", + "dev": true, + "requires": { + "postcss": "^7.0.5" + } + }, + "postcss-modules-local-by-default": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-2.0.6.tgz", + "integrity": "sha512-oLUV5YNkeIBa0yQl7EYnxMgy4N6noxmiwZStaEJUSe2xPMcdNc8WmBQuQCx18H5psYbVxz8zoHk0RAAYZXP9gA==", + "dev": true, + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0", + "postcss-value-parser": "^3.3.1" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-modules-scope": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", + "dev": true, + "requires": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" + } + }, + "postcss-modules-values": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-2.0.0.tgz", + "integrity": "sha512-Ki7JZa7ff1N3EIMlPnGTZfUMe69FFwiQPnVSXC9mnn3jozCRBYIxiZd44yJOV2AmabOo4qFf8s0dC/+lweG7+w==", + "dev": true, + "requires": { + "icss-replace-symbols": "^1.1.0", + "postcss": "^7.0.6" + } + }, + "postcss-normalize-charset": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", + "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==", + "dev": true, + "requires": { + "postcss": "^7.0.0" + } + }, + "postcss-normalize-display-values": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz", + "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-positions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz", + "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-repeat-style": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz", + "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-string": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz", + "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==", + "dev": true, + "requires": { + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-timing-functions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz", + "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-unicode": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz", + "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-url": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz", + "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==", + "dev": true, + "requires": { + "is-absolute-url": "^2.0.0", + "normalize-url": "^3.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "normalize-url": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz", + "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", + "dev": true + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-normalize-whitespace": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz", + "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-ordered-values": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz", + "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==", + "dev": true, + "requires": { + "cssnano-util-get-arguments": "^4.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-reduce-initial": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz", + "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "caniuse-api": "^3.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0" + } + }, + "postcss-reduce-transforms": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz", + "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==", + "dev": true, + "requires": { + "cssnano-util-get-match": "^4.0.0", + "has": "^1.0.0", + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-safe-parser": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-4.0.2.tgz", + "integrity": "sha512-Uw6ekxSWNLCPesSv/cmqf2bY/77z11O7jZGPax3ycZMFU/oi2DMH9i89AdHc1tRwFg/arFoEwX0IS3LCUxJh1g==", + "dev": true, + "requires": { + "postcss": "^7.0.26" + } + }, + "postcss-selector-parser": { + "version": "6.0.6", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz", + "integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==", + "dev": true, + "requires": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + } + }, + "postcss-svgo": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.3.tgz", + "integrity": "sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw==", + "dev": true, + "requires": { + "postcss": "^7.0.0", + "postcss-value-parser": "^3.0.0", + "svgo": "^1.0.0" + }, + "dependencies": { + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + } + } + }, + "postcss-unique-selectors": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz", + "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==", + "dev": true, + "requires": { + "alphanum-sort": "^1.0.0", + "postcss": "^7.0.0", + "uniqs": "^2.0.0" + } + }, + "postcss-value-parser": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.1.0.tgz", + "integrity": "sha512-97DXOFbQJhk71ne5/Mt6cOu6yxsSfM0QGQyl0L25Gca4yGWEGJaig7l7gbCX623VqTBNGLRLaVUCnNkcedlRSQ==", + "dev": true + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=", + "dev": true + }, + "prettier": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", + "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", + "dev": true, + "optional": true + }, + "pretty-error": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz", + "integrity": "sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==", + "dev": true, + "requires": { + "lodash": "^4.17.20", + "renderkid": "^2.0.4" + } + }, + "pretty-time": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/pretty-time/-/pretty-time-1.1.0.tgz", + "integrity": "sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA==", + "dev": true + }, + "prismjs": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.24.0.tgz", + "integrity": "sha512-SqV5GRsNqnzCL8k5dfAjCNhUrF3pR0A9lTDSCUZeh/LIshheXJEaP0hwLz2t4XHivd2J/v2HR+gRnigzeKe3cQ==", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", + "dev": true + }, + "proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "dev": true, + "requires": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + } + }, + "prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY=", + "dev": true + }, + "ps-tree": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", + "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", + "dev": true, + "requires": { + "event-stream": "=3.3.4" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=", + "dev": true + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==", + "dev": true + }, + "public-encrypt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz", + "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==", + "dev": true, + "requires": { + "bn.js": "^4.1.0", + "browserify-rsa": "^4.0.0", + "create-hash": "^1.1.0", + "parse-asn1": "^5.0.0", + "randombytes": "^2.0.1", + "safe-buffer": "^5.1.2" + }, + "dependencies": { + "bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", + "dev": true + } + } + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "pumpify": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz", + "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==", + "dev": true, + "requires": { + "duplexify": "^3.6.0", + "inherits": "^2.0.3", + "pump": "^2.0.0" + }, + "dependencies": { + "pump": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz", + "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + } + } + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + }, + "pupa": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.1.1.tgz", + "integrity": "sha512-l1jNAspIBSFqbT+y+5FosojNpVpF94nlI+wDUpqP9enwOTfHx9f0gh5nB96vl+6yTpsJsypeNrwfzPrKuHB41A==", + "dev": true, + "requires": { + "escape-goat": "^2.0.0" + } + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", + "dev": true + }, + "query-string": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-5.1.1.tgz", + "integrity": "sha512-gjWOsm2SoGlgLEdAGt7a6slVOk9mGiXmPFMqrEhLQ68rhQuBnpfs3+EmlvqKyxnCo9/PPlF+9MtY02S1aFg+Jw==", + "dev": true, + "requires": { + "decode-uri-component": "^0.2.0", + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=", + "dev": true + }, + "querystring-es3": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", + "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM=", + "dev": true + }, + "querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "dev": true + }, + "randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "requires": { + "safe-buffer": "^5.1.0" + } + }, + "randomfill": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz", + "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==", + "dev": true, + "requires": { + "randombytes": "^2.0.5", + "safe-buffer": "^5.1.0" + } + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=", + "dev": true + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "dev": true, + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "dependencies": { + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==", + "dev": true + } + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "reduce": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/reduce/-/reduce-1.0.2.tgz", + "integrity": "sha512-xX7Fxke/oHO5IfZSk77lvPa/7bjMh9BuCk4OOoX5XTXrM7s0Z+MkPfSDfz0q7r91BhhGSs8gii/VEN/7zhCPpQ==", + "dev": true, + "requires": { + "object-keys": "^1.1.0" + } + }, + "regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "regenerate-unicode-properties": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", + "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", + "dev": true, + "requires": { + "regenerate": "^1.4.0" + } + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==", + "dev": true + }, + "regenerator-transform": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", + "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", + "dev": true, + "requires": { + "@babel/runtime": "^7.8.4" + } + }, + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "regexp.prototype.flags": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz", + "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "regexpu-core": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", + "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.2.0", + "regjsgen": "^0.5.1", + "regjsparser": "^0.6.4", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.2.0" + } + }, + "registry-auth-token": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-3.3.2.tgz", + "integrity": "sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ==", + "dev": true, + "requires": { + "rc": "^1.1.6", + "safe-buffer": "^5.0.1" + } + }, + "registry-url": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-3.1.0.tgz", + "integrity": "sha1-PU74cPc93h138M+aOBQyRE4XSUI=", + "dev": true, + "requires": { + "rc": "^1.0.1" + } + }, + "regjsgen": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", + "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", + "dev": true + }, + "regjsparser": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.9.tgz", + "integrity": "sha512-ZqbNRz1SNjLAiYuwY0zoXW8Ne675IX5q+YHioAGbCw4X96Mjl2+dcX9B2ciaeyYjViDAfvIjFpQjJgLttTEERQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + }, + "dependencies": { + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + } + } + }, + "relateurl": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz", + "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk=", + "dev": true + }, + "remove-markdown": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/remove-markdown/-/remove-markdown-0.3.0.tgz", + "integrity": "sha1-XktmdJOpNXlyjz1S7MHbnKUF3Jg=", + "dev": true + }, + "remove-trailing-separator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", + "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", + "dev": true + }, + "renderkid": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz", + "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==", + "dev": true, + "requires": { + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "css-select": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz", + "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==", + "dev": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "^5.0.0", + "domhandler": "^4.2.0", + "domutils": "^2.6.0", + "nth-check": "^2.0.0" + } + }, + "css-what": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.0.1.tgz", + "integrity": "sha512-FYDTSHb/7KXsWICVsxdmiExPjCfRC4qRFBdVwv7Ax9hMnvMmEjP9RfxTEZ3qPZGmADDn2vAKSo9UcN1jKVYscg==", + "dev": true + }, + "dom-serializer": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz", + "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==", + "dev": true, + "requires": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + } + }, + "domelementtype": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz", + "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==", + "dev": true + }, + "domutils": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.7.0.tgz", + "integrity": "sha512-8eaHa17IwJUPAiB+SoTYBo5mCdeMgdcAoXJ59m6DT1vw+5iLS3gNoqYaRowaBKtGVrOF1Jz4yDTgYKLK2kvfJg==", + "dev": true, + "requires": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + } + }, + "entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "dev": true + }, + "nth-check": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.0.tgz", + "integrity": "sha512-i4sc/Kj8htBrAiH1viZ0TgU8Y5XqCaV/FziYK6TBczxmeKm3AEFWqqF3195yKudrarqy7Zu80Ra5dobFjn9X/Q==", + "dev": true, + "requires": { + "boolbase": "^1.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } + } + }, + "repeat-element": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz", + "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==", + "dev": true + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "dev": true, + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "dev": true + }, + "requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=", + "dev": true + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "resolve-cwd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz", + "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo=", + "dev": true, + "requires": { + "resolve-from": "^3.0.0" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "resolve-url": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", + "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", + "dev": true + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "dev": true, + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true + }, + "retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", + "dev": true + }, + "rgb-regex": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz", + "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE=", + "dev": true + }, + "rgba-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz", + "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM=", + "dev": true + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "ripemd160": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz", + "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==", + "dev": true, + "requires": { + "hash-base": "^3.0.0", + "inherits": "^2.0.1" + } + }, + "robot-directives": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/robot-directives/-/robot-directives-0.3.0.tgz", + "integrity": "sha1-F0+x/8KpuXh3MB6HyJs5X0KdH2U=", + "dev": true, + "requires": { + "isbot": "^2.0.0", + "useragent": "^2.1.8" + } + }, + "robots-txt-guard": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/robots-txt-guard/-/robots-txt-guard-0.1.1.tgz", + "integrity": "sha512-6+nGkE6c2dI9/dmhmNcoMKVwJxlA6sgN/XNo0rm6LLdA0hnj4YkpgrZdhMPl58gJkAqeiHlf4+8tJcLM1tv1Ew==", + "dev": true + }, + "robots-txt-parse": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/robots-txt-parse/-/robots-txt-parse-0.0.4.tgz", + "integrity": "sha1-99HzI/eZIdfpxsS70lBI9umBDXE=", + "dev": true, + "requires": { + "bluebird": "^2.3.5", + "split": "^0.3.0", + "stream-combiner": "^0.2.1", + "through": "^2.3.4" + } + }, + "run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec=", + "dev": true, + "requires": { + "aproba": "^1.1.1" + } + }, + "rw": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", + "integrity": "sha1-P4Yt+pGrdmsUiF700BEkv9oHT7Q=", + "dev": true + }, + "rxjs": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.3.0.tgz", + "integrity": "sha512-p2yuGIg9S1epc3vrjKf6iVb3RCaAYjYskkO+jHIaV0IjOPlJop4UnodOoFb2xeNwlguqLYvGw1b1McillYb5Gw==", + "dev": true, + "requires": { + "tslib": "~2.1.0" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "~0.1.10" + } + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "dev": true + }, + "schema-utils": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz", + "integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.5", + "ajv": "^6.12.4", + "ajv-keywords": "^3.5.2" + } + }, + "section-matter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + } + }, + "select-hose": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", + "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo=", + "dev": true + }, + "selfsigned": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz", + "integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==", + "dev": true, + "requires": { + "node-forge": "^0.10.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "dev": true, + "requires": { + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "dev": true, + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + } + } + }, + "serialize-javascript": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz", + "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "serve": { + "version": "12.0.1", + "resolved": "https://registry.npmjs.org/serve/-/serve-12.0.1.tgz", + "integrity": "sha512-CQ4ikLpxg/wmNM7yivulpS6fhjRiFG6OjmP8ty3/c1SBnSk23fpKmLAV4HboTA2KrZhkUPlDfjDhnRmAjQ5Phw==", + "dev": true, + "requires": { + "@zeit/schemas": "2.6.0", + "ajv": "6.12.6", + "arg": "2.0.0", + "boxen": "1.3.0", + "chalk": "2.4.1", + "clipboardy": "2.3.0", + "compression": "1.7.3", + "serve-handler": "6.1.3", + "update-check": "1.5.2" + }, + "dependencies": { + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + } + } + }, + "serve-handler": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/serve-handler/-/serve-handler-6.1.3.tgz", + "integrity": "sha512-FosMqFBNrLyeiIDvP1zgO6YoTzFYHxLDEIavhlmQ+knB2Z7l1t+kGLHkZIDN7UVWqQAmKI3D20A6F6jo3nDd4w==", + "dev": true, + "requires": { + "bytes": "3.0.0", + "content-disposition": "0.5.2", + "fast-url-parser": "1.1.3", + "mime-types": "2.1.18", + "minimatch": "3.0.4", + "path-is-inside": "1.0.2", + "path-to-regexp": "2.2.1", + "range-parser": "1.2.0" + }, + "dependencies": { + "mime-db": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.33.0.tgz", + "integrity": "sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ==", + "dev": true + }, + "mime-types": { + "version": "2.1.18", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.18.tgz", + "integrity": "sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ==", + "dev": true, + "requires": { + "mime-db": "~1.33.0" + } + } + } + }, + "serve-index": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz", + "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk=", + "dev": true, + "requires": { + "accepts": "~1.3.4", + "batch": "0.6.1", + "debug": "2.6.9", + "escape-html": "~1.0.3", + "http-errors": "~1.6.2", + "mime-types": "~2.1.17", + "parseurl": "~1.3.2" + }, + "dependencies": { + "http-errors": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "dev": true, + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==", + "dev": true + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "dev": true, + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", + "dev": true + }, + "set-value": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", + "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" + } + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==", + "dev": true + }, + "sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true + }, + "side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dev": true, + "requires": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + } + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "dev": true, + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==", + "dev": true + } + } + }, + "sitemap": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-3.2.2.tgz", + "integrity": "sha512-TModL/WU4m2q/mQcrDgNANn0P4LwprM9MMvG4hu5zP4c6IIKs2YLTu6nXXnNr8ODW/WFtxKggiJ1EGn2W0GNmg==", + "dev": true, + "requires": { + "lodash.chunk": "^4.2.0", + "lodash.padstart": "^4.6.1", + "whatwg-url": "^7.0.0", + "xmlbuilder": "^13.0.0" + } + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + }, + "smoothscroll-polyfill": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/smoothscroll-polyfill/-/smoothscroll-polyfill-0.4.4.tgz", + "integrity": "sha512-TK5ZA9U5RqCwMpfoMq/l1mrH0JAR7y7KRvOBx0n2869aLxch+gT9GhN3yUfjiw+d/DiF1mKo14+hd62JyMmoBg==", + "dev": true + }, + "snapdragon": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", + "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", + "dev": true, + "requires": { + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "snapdragon-node": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", + "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", + "dev": true, + "requires": { + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "^1.0.0" + } + } + } + }, + "snapdragon-util": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", + "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", + "dev": true, + "requires": { + "kind-of": "^3.2.0" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "sockjs": { + "version": "0.3.21", + "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.21.tgz", + "integrity": "sha512-DhbPFGpxjc6Z3I+uX07Id5ZO2XwYsWOrYjaSeieES78cq+JaJvVe5q/m1uvjIQhXinhIeCFRH6JgXe+mvVMyXw==", + "dev": true, + "requires": { + "faye-websocket": "^0.11.3", + "uuid": "^3.4.0", + "websocket-driver": "^0.7.4" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } + } + }, + "sockjs-client": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.1.tgz", + "integrity": "sha512-VnVAb663fosipI/m6pqRXakEOw7nvd7TUgdr3PlR/8V2I95QIdwT8L4nMxhyU8SmDBHYXU1TOElaKOmKLfYzeQ==", + "dev": true, + "requires": { + "debug": "^3.2.6", + "eventsource": "^1.0.7", + "faye-websocket": "^0.11.3", + "inherits": "^2.0.4", + "json3": "^3.3.3", + "url-parse": "^1.5.1" + }, + "dependencies": { + "debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + } + } + }, + "sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg=", + "dev": true, + "requires": { + "is-plain-obj": "^1.0.0" + } + }, + "source-list-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", + "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", + "dev": true + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true + }, + "source-map-resolve": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", + "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", + "dev": true, + "requires": { + "atob": "^2.1.2", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" + } + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "source-map-url": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz", + "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==", + "dev": true + }, + "spdy": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz", + "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "handle-thing": "^2.0.0", + "http-deceiver": "^1.2.7", + "select-hose": "^2.0.0", + "spdy-transport": "^3.0.0" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "spdy-transport": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz", + "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==", + "dev": true, + "requires": { + "debug": "^4.1.0", + "detect-node": "^2.0.4", + "hpack.js": "^2.1.6", + "obuf": "^1.1.2", + "readable-stream": "^3.0.6", + "wbuf": "^1.7.3" + }, + "dependencies": { + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "dev": true, + "requires": { + "through": "2" + } + }, + "split-on-first": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz", + "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw==", + "dev": true + }, + "split-string": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", + "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", + "dev": true, + "requires": { + "extend-shallow": "^3.0.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "splitargs": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/splitargs/-/splitargs-0.0.7.tgz", + "integrity": "sha1-/p965lc3GzOxDLgNoUPPgknPazs=", + "dev": true + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "squarecrypto-vuepress-devkit-theme": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/squarecrypto-vuepress-devkit-theme/-/squarecrypto-vuepress-devkit-theme-0.1.10.tgz", + "integrity": "sha512-W6P3sHVD4m3f+AoYiEXaCmWn4Fcmw8Gmr4BeRDuu860AsHOHY1WxuRU5zJuBPFpCCWdzvEgiY6ct8ZdmAHlMnQ==", + "dev": true, + "requires": { + "@vuepress/plugin-back-to-top": "1.8.2", + "@vuepress/plugin-blog": "1.9.4", + "@vuepress/plugin-medium-zoom": "1.8.2", + "@vuepress/plugin-search": "1.8.2", + "@vuepress/theme-default": "1.8.2", + "lodash": "4.17.21", + "markdown-it-footnote": "3.0.3", + "markdown-it-implicit-figures": "0.10.0", + "vue-tabs-component": "1.5.0", + "vuepress-plugin-clean-urls": "1.1.2", + "vuepress-plugin-code-copy": "1.0.6", + "vuepress-plugin-mermaidjs": "^1.8.1", + "vuepress-plugin-seo": "0.1.4", + "vuepress-plugin-sitemap": "2.3.1", + "vuepress-plugin-tabs": "0.3.0" + } + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "dev": true, + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "ssri": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz", + "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==", + "dev": true, + "requires": { + "figgy-pudding": "^3.5.1" + } + }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true + }, + "stack-utils": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.5.tgz", + "integrity": "sha512-KZiTzuV3CnSnSvgMRrARVCj+Ht7rMbauGDK0LdVFRGyenwdylpajAp4Q0i6SX8rEmbTpMMf6ryq2gb8pPq2WgQ==", + "dev": true, + "requires": { + "escape-string-regexp": "^2.0.0" + }, + "dependencies": { + "escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true + } + } + }, + "start-server-and-test": { + "version": "1.14.0", + "resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-1.14.0.tgz", + "integrity": "sha512-on5ELuxO2K0t8EmNj9MtVlFqwBMxfWOhu4U7uZD1xccVpFlOQKR93CSe0u98iQzfNxRyaNTb/CdadbNllplTsw==", + "dev": true, + "requires": { + "bluebird": "3.7.2", + "check-more-types": "2.24.0", + "debug": "4.3.2", + "execa": "5.1.1", + "lazy-ass": "1.6.0", + "ps-tree": "1.2.0", + "wait-on": "6.0.0" + }, + "dependencies": { + "bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "debug": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.2.tgz", + "integrity": "sha512-mOp8wKcvj7XxC78zLgw/ZA+6TSgkoE2C/ienthhRD298T7UNwAg9diBpLRxC0mOezLl4B0xV7M0cCO6P/O0Xhw==", + "dev": true, + "requires": { + "ms": "2.1.2" + } + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "static-extend": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", + "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", + "dev": true, + "requires": { + "define-property": "^0.2.5", + "object-copy": "^0.1.0" + }, + "dependencies": { + "define-property": { + "version": "0.2.5", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", + "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", + "dev": true, + "requires": { + "is-descriptor": "^0.1.0" + } + }, + "is-accessor-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", + "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-data-descriptor": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", + "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=", + "dev": true + }, + "std-env": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-2.3.0.tgz", + "integrity": "sha512-4qT5B45+Kjef2Z6pE0BkskzsH0GO7GrND0wGlTM1ioUe3v0dGYx9ZJH0Aro/YyA8fqQ5EyIKDRjZojJYMFTflw==", + "dev": true, + "requires": { + "ci-info": "^3.0.0" + }, + "dependencies": { + "ci-info": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.2.0.tgz", + "integrity": "sha512-dVqRX7fLUm8J6FgHJ418XuIgDLZDkYcDFTeL6TA2gt5WlIZUQrrH6EZrNClwT/H0FateUsZkGIOPRrLbP+PR9A==", + "dev": true + } + } + }, + "stream-browserify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz", + "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==", + "dev": true, + "requires": { + "inherits": "~2.0.1", + "readable-stream": "^2.0.2" + } + }, + "stream-combiner": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", + "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", + "dev": true, + "requires": { + "duplexer": "~0.1.1", + "through": "~2.3.4" + } + }, + "stream-each": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz", + "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==", + "dev": true, + "requires": { + "end-of-stream": "^1.1.0", + "stream-shift": "^1.0.0" + } + }, + "stream-http": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz", + "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==", + "dev": true, + "requires": { + "builtin-status-codes": "^3.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.3.6", + "to-arraybuffer": "^1.0.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + } + } + }, + "stream-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/stream-length/-/stream-length-1.0.2.tgz", + "integrity": "sha1-gnfzy+5JpNqrz9tOL0qbXp8snwA=", + "dev": true, + "requires": { + "bluebird": "^2.6.2" + } + }, + "stream-shift": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz", + "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ==", + "dev": true + }, + "strict-uri-encode": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", + "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "string.prototype.trimend": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz", + "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "string.prototype.trimstart": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz", + "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==", + "dev": true, + "requires": { + "call-bind": "^1.0.2", + "define-properties": "^1.1.3" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=", + "dev": true + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "striptags": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/striptags/-/striptags-3.1.1.tgz", + "integrity": "sha1-yMPn/db7S7OjKjt1LltePjgJPr0=", + "dev": true + }, + "stylehacks": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", + "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==", + "dev": true, + "requires": { + "browserslist": "^4.0.0", + "postcss": "^7.0.0", + "postcss-selector-parser": "^3.0.0" + }, + "dependencies": { + "postcss-selector-parser": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz", + "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==", + "dev": true, + "requires": { + "dot-prop": "^5.2.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + } + } + } + }, + "stylis": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.0.10.tgz", + "integrity": "sha512-m3k+dk7QeJw660eIKRRn3xPF6uuvHs/FFzjX3HQ5ove0qYsiygoAhwn5a3IYKaZPo5LrYD0rfVmtv1gNY1uYwg==", + "dev": true + }, + "stylus": { + "version": "0.54.8", + "resolved": "https://registry.npmjs.org/stylus/-/stylus-0.54.8.tgz", + "integrity": "sha512-vr54Or4BZ7pJafo2mpf0ZcwA74rpuYCZbxrHBsH8kbcXOwSfvBFwsRfpGO5OD5fhG5HDCFW737PKaawI7OqEAg==", + "dev": true, + "requires": { + "css-parse": "~2.0.0", + "debug": "~3.1.0", + "glob": "^7.1.6", + "mkdirp": "~1.0.4", + "safer-buffer": "^2.1.2", + "sax": "~1.2.4", + "semver": "^6.3.0", + "source-map": "^0.7.3" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + } + } + }, + "stylus-loader": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/stylus-loader/-/stylus-loader-3.0.2.tgz", + "integrity": "sha512-+VomPdZ6a0razP+zinir61yZgpw2NfljeSsdUF5kJuEzlo3khXhY19Fn6l8QQz1GRJGtMCo8nG5C04ePyV7SUA==", + "dev": true, + "requires": { + "loader-utils": "^1.0.2", + "lodash.clonedeep": "^4.5.0", + "when": "~3.6.x" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", + "dev": true + }, + "svgo": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz", + "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "coa": "^2.0.2", + "css-select": "^2.0.0", + "css-select-base-adapter": "^0.1.1", + "css-tree": "1.0.0-alpha.37", + "csso": "^4.0.2", + "js-yaml": "^3.13.1", + "mkdirp": "~0.5.1", + "object.values": "^1.1.0", + "sax": "~1.2.4", + "stable": "^0.1.8", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + } + }, + "tapable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz", + "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==", + "dev": true + }, + "term-size": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", + "integrity": "sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk=", + "dev": true, + "requires": { + "execa": "^0.7.0" + }, + "dependencies": { + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true + } + } + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "terser-webpack-plugin": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz", + "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==", + "dev": true, + "requires": { + "cacache": "^12.0.2", + "find-cache-dir": "^2.1.0", + "is-wsl": "^1.1.0", + "schema-utils": "^1.0.0", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.1.2", + "webpack-sources": "^1.4.0", + "worker-farm": "^1.7.0" + }, + "dependencies": { + "find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "dev": true, + "requires": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + } + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0=", + "dev": true + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "requires": { + "pify": "^4.0.1", + "semver": "^5.6.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "dev": true, + "requires": { + "find-up": "^3.0.0" + } + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.5.1.tgz", + "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", + "dev": true, + "requires": { + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, + "through2-sink": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/through2-sink/-/through2-sink-1.0.0.tgz", + "integrity": "sha1-XxBruh1zMNrTy6XAqxhjkjJWw5k=", + "dev": true, + "requires": { + "through2": "~0.5.1", + "xtend": "~3.0.0" + } + }, + "through2-spy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/through2-spy/-/through2-spy-1.2.0.tgz", + "integrity": "sha1-nIkcqcpA4eHkzzHhrFf5TMnSSMs=", + "dev": true, + "requires": { + "through2": "~0.5.1", + "xtend": "~3.0.0" + } + }, + "thunky": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", + "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", + "dev": true + }, + "timers-browserify": { + "version": "2.0.12", + "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz", + "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==", + "dev": true, + "requires": { + "setimmediate": "^1.0.4" + } + }, + "timsort": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", + "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=", + "dev": true + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-arraybuffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", + "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M=", + "dev": true + }, + "to-factory": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-factory/-/to-factory-1.0.0.tgz", + "integrity": "sha1-hzivi9lxIK0dQEeXKtpVY7+UebE=", + "dev": true + }, + "to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", + "dev": true + }, + "to-object-path": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", + "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", + "dev": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==", + "dev": true + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "^2.0.4" + } + } + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==", + "dev": true + }, + "toml": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/toml/-/toml-3.0.0.tgz", + "integrity": "sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==", + "dev": true + }, + "toposort": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz", + "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk=", + "dev": true + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "dev": true, + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, + "tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk=", + "dev": true, + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true + }, + "tty-browserify": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz", + "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY=", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "dev": true, + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", + "dev": true + }, + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "dev": true, + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "dev": true, + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "uc.micro": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-1.0.6.tgz", + "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==", + "dev": true + }, + "uglify-js": { + "version": "3.4.10", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz", + "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==", + "dev": true, + "requires": { + "commander": "~2.19.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "unbox-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz", + "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1", + "has-bigints": "^1.0.1", + "has-symbols": "^1.0.2", + "which-boxed-primitive": "^1.0.2" + } + }, + "unicode-canonical-property-names-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", + "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", + "dev": true + }, + "unicode-match-property-ecmascript": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", + "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", + "dev": true, + "requires": { + "unicode-canonical-property-names-ecmascript": "^1.0.4", + "unicode-property-aliases-ecmascript": "^1.0.4" + } + }, + "unicode-match-property-value-ecmascript": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", + "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", + "dev": true + }, + "unicode-property-aliases-ecmascript": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", + "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", + "dev": true + }, + "union-value": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", + "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", + "dev": true, + "requires": { + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^2.0.1" + } + }, + "uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8=", + "dev": true + }, + "uniqs": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz", + "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI=", + "dev": true + }, + "unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "dev": true, + "requires": { + "unique-slug": "^2.0.0" + } + }, + "unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", + "dev": true + }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", + "dev": true + }, + "unset-value": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", + "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", + "dev": true, + "requires": { + "has-value": "^0.3.1", + "isobject": "^3.0.0" + }, + "dependencies": { + "has-value": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", + "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", + "dev": true, + "requires": { + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" + }, + "dependencies": { + "isobject": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", + "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, + "requires": { + "isarray": "1.0.0" + } + } + } + }, + "has-values": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", + "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", + "dev": true + } + } + }, + "upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true + }, + "update-check": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/update-check/-/update-check-1.5.2.tgz", + "integrity": "sha512-1TrmYLuLj/5ZovwUS7fFd1jMH3NnFDN1y1A8dboedIDt7zs/zJMo6TwwlhYKkSeEwzleeiSBV5/3c9ufAQWDaQ==", + "dev": true, + "requires": { + "registry-auth-token": "3.3.2", + "registry-url": "3.1.0" + } + }, + "update-notifier": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.3.tgz", + "integrity": "sha512-Yld6Z0RyCYGB6ckIjffGOSOmHXj1gMeE7aROz4MG+XMkmixBX4jUngrGXNYz7wPKBmtoD4MnBa2Anu7RSKht/A==", + "dev": true, + "requires": { + "boxen": "^4.2.0", + "chalk": "^3.0.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.3.1", + "is-npm": "^4.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "pupa": "^2.0.1", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "dev": true, + "requires": { + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "boxen": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "dev": true, + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "cli-boxes": "^2.2.0", + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cli-boxes": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.1.tgz", + "integrity": "sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw==", + "dev": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "string-width": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.2.tgz", + "integrity": "sha512-XBJbT3N4JhVumXE0eoLU9DCjcaF92KLNqTmFCnG1pf8duUxFGwtP6AD6nkjw9a3IdiRtL3E2w3JDiE/xi3vOeA==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + } + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "term-size": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.1.tgz", + "integrity": "sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==", + "dev": true + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dev": true, + "requires": { + "string-width": "^4.0.0" + } + } + } + }, + "upper-case": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz", + "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg=", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, + "urix": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", + "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", + "dev": true + }, + "url": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", + "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE=", + "dev": true, + "requires": { + "punycode": "1.3.2", + "querystring": "0.2.0" + }, + "dependencies": { + "punycode": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", + "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0=", + "dev": true + } + } + }, + "url-loader": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-1.1.2.tgz", + "integrity": "sha512-dXHkKmw8FhPqu8asTc1puBfe3TehOCo2+RmOOev5suNCIYBcT626kxiWg1NBVkwc4rO8BGa7gP70W7VXuqHrjg==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "mime": "^2.0.3", + "schema-utils": "^1.0.0" + }, + "dependencies": { + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "url-parse": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz", + "integrity": "sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ==", + "dev": true, + "requires": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "dev": true, + "requires": { + "prepend-http": "^2.0.0" + } + }, + "urlcache": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/urlcache/-/urlcache-0.7.0.tgz", + "integrity": "sha512-xOW4t6wJDT07+VunsHwePemyXXRidCSOZ/1RIILJi2XnB+81FA5H0MRvS63/7joTWjGLajcJJGvR5odpbkV6hw==", + "dev": true, + "requires": { + "urlobj": "0.0.11" + } + }, + "urlobj": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/urlobj/-/urlobj-0.0.11.tgz", + "integrity": "sha512-Ncck0WWtuFBbZhSYwKjK1AU2V51V98P/KHUPkaEc+mFy4xkpAHFNyVQT+S5SgtsJAr94e4wiKUucJSfasV2kBw==", + "dev": true, + "requires": { + "is-object": "^1.0.1", + "is-string": "^1.0.4", + "object-assign": "^4.1.1" + }, + "dependencies": { + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + } + } + }, + "use": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", + "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", + "dev": true + }, + "useragent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/useragent/-/useragent-2.3.0.tgz", + "integrity": "sha512-4AoH4pxuSvHCjqLO04sU6U/uE65BYza8l/KKBS0b0hnUPWi+cQ2BpeTEwejCSx9SPV5/U03nniDTrWx5NrmKdw==", + "dev": true, + "requires": { + "lru-cache": "4.1.x", + "tmp": "0.0.x" + } + }, + "util": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz", + "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==", + "dev": true, + "requires": { + "inherits": "2.0.3" + }, + "dependencies": { + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + } + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "util.promisify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.1.tgz", + "integrity": "sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==", + "dev": true, + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.2", + "has-symbols": "^1.0.1", + "object.getownpropertydescriptors": "^2.1.0" + } + }, + "utila": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz", + "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw=", + "dev": true + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=", + "dev": true + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=", + "dev": true + }, + "vendors": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz", + "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==", + "dev": true + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "dev": true, + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "vm-browserify": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz", + "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==", + "dev": true + }, + "vssue": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/vssue/-/vssue-1.4.8.tgz", + "integrity": "sha512-Stp0CxF65Uv658qgYUgYKEDiWM8wskUfKCOT9ISJwz/Qn58N050vYnFYClnUXG060ZQi1YQxkTCuJAw8ee3YlQ==", + "dev": true, + "requires": { + "@vssue/utils": "^1.4.7", + "github-markdown-css": "^3.0.1", + "vue": "^2.6.10", + "vue-i18n": "^8.11.2", + "vue-property-decorator": "^8.1.1" + } + }, + "vue": { + "version": "2.6.14", + "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.14.tgz", + "integrity": "sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ==", + "dev": true + }, + "vue-class-component": { + "version": "7.2.6", + "resolved": "https://registry.npmjs.org/vue-class-component/-/vue-class-component-7.2.6.tgz", + "integrity": "sha512-+eaQXVrAm/LldalI272PpDe3+i4mPis0ORiMYxF6Ae4hyuCh15W8Idet7wPUEs4N4YptgFHGys4UrgNQOMyO6w==", + "dev": true, + "requires": {} + }, + "vue-disqus": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/vue-disqus/-/vue-disqus-3.0.5.tgz", + "integrity": "sha512-T3Y68lXf5W2lYt6j4Y3kZ4opLPH0EAzqriy11MS4D4Q2+UN0tFuUXeYP1MxfvdyaCEboXSM6CUswxsULuNV70Q==", + "dev": true + }, + "vue-hot-reload-api": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz", + "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", + "dev": true + }, + "vue-i18n": { + "version": "8.25.0", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-8.25.0.tgz", + "integrity": "sha512-ynhcL+PmTxuuSE1T10htiSXzjBozxYIE3ffbM1RfgAkVbr/v1SP+9Mi/7/uv8ZVV1yGuKjFAYp9BXq+X7op6MQ==", + "dev": true + }, + "vue-loader": { + "version": "15.9.7", + "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.7.tgz", + "integrity": "sha512-qzlsbLV1HKEMf19IqCJqdNvFJRCI58WNbS6XbPqK13MrLz65es75w392MSQ5TsARAfIjUw+ATm3vlCXUJSOH9Q==", + "dev": true, + "requires": { + "@vue/component-compiler-utils": "^3.1.0", + "hash-sum": "^1.0.2", + "loader-utils": "^1.1.0", + "vue-hot-reload-api": "^2.3.0", + "vue-style-loader": "^4.1.0" + } + }, + "vue-property-decorator": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/vue-property-decorator/-/vue-property-decorator-8.5.1.tgz", + "integrity": "sha512-O6OUN2OMsYTGPvgFtXeBU3jPnX5ffQ9V4I1WfxFQ6dqz6cOUbR3Usou7kgFpfiXDvV7dJQSFcJ5yUPgOtPPm1Q==", + "dev": true, + "requires": { + "vue-class-component": "^7.1.0" + } + }, + "vue-router": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.1.tgz", + "integrity": "sha512-RRQNLT8Mzr8z7eL4p7BtKvRaTSGdCbTy2+Mm5HTJvLGYSSeG9gDzNasJPP/yOYKLy+/cLG/ftrqq5fvkFwBJEw==", + "dev": true + }, + "vue-server-renderer": { + "version": "2.6.14", + "resolved": "https://registry.npmjs.org/vue-server-renderer/-/vue-server-renderer-2.6.14.tgz", + "integrity": "sha512-HifYRa/LW7cKywg9gd4ZtvtRuBlstQBao5ZCWlg40fyB4OPoGfEXAzxb0emSLv4pBDOHYx0UjpqvxpiQFEuoLA==", + "dev": true, + "requires": { + "chalk": "^1.1.3", + "hash-sum": "^1.0.2", + "he": "^1.1.0", + "lodash.template": "^4.5.0", + "lodash.uniq": "^4.5.0", + "resolve": "^1.2.0", + "serialize-javascript": "^3.1.0", + "source-map": "0.5.6" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "serialize-javascript": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", + "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", + "dev": true, + "requires": { + "randombytes": "^2.1.0" + } + }, + "source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha1-dc449SvwczxafwwRjYEzSiu19BI=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "vue-style-loader": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz", + "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==", + "dev": true, + "requires": { + "hash-sum": "^1.0.2", + "loader-utils": "^1.0.2" + } + }, + "vue-tabs-component": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/vue-tabs-component/-/vue-tabs-component-1.5.0.tgz", + "integrity": "sha512-ld4p+hv49Fimw+zv/7GQqMhbjAHjpbWF3UiJtmMaSnvLKbsB1ysfs9dQH0SZ8NvdYpqqKay/VLIqR9yXgse1Sg==", + "dev": true, + "requires": {} + }, + "vue-template-compiler": { + "version": "2.6.14", + "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.14.tgz", + "integrity": "sha512-ODQS1SyMbjKoO1JBJZojSw6FE4qnh9rIpUZn2EUT86FKizx9uH5z6uXiIrm4/Nb/gwxTi/o17ZDEGWAXHvtC7g==", + "dev": true, + "requires": { + "de-indent": "^1.0.2", + "he": "^1.1.0" + } + }, + "vue-template-es2015-compiler": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz", + "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==", + "dev": true + }, + "vuejs-paginate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/vuejs-paginate/-/vuejs-paginate-2.1.0.tgz", + "integrity": "sha512-gnwyXlmCiDOu9MLWxN5UJ4PGijKGNOMpHG8ujsrynCzTJljn/rp7Jq0WiDGDAMi5/u0AHuYIHhced+tUW4jblA==", + "dev": true + }, + "vuepress": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/vuepress/-/vuepress-1.8.2.tgz", + "integrity": "sha512-BU1lUDwsA3ghf7a9ga4dsf0iTc++Z/l7BR1kUagHWVBHw7HNRgRDfAZBDDQXhllMILVToIxaTifpne9mSi94OA==", + "dev": true, + "requires": { + "@vuepress/core": "1.8.2", + "@vuepress/theme-default": "1.8.2", + "cac": "^6.5.6", + "envinfo": "^7.2.0", + "opencollective-postinstall": "^2.0.2", + "update-notifier": "^4.0.0" + } + }, + "vuepress-html-webpack-plugin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/vuepress-html-webpack-plugin/-/vuepress-html-webpack-plugin-3.2.0.tgz", + "integrity": "sha512-BebAEl1BmWlro3+VyDhIOCY6Gef2MCBllEVAP3NUAtMguiyOwo/dClbwJ167WYmcxHJKLl7b0Chr9H7fpn1d0A==", + "dev": true, + "requires": { + "html-minifier": "^3.2.3", + "loader-utils": "^0.2.16", + "lodash": "^4.17.3", + "pretty-error": "^2.0.2", + "tapable": "^1.0.0", + "toposort": "^1.0.0", + "util.promisify": "1.0.0" + }, + "dependencies": { + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==", + "dev": true + }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=", + "dev": true + }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=", + "dev": true + }, + "loader-utils": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz", + "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g=", + "dev": true, + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0", + "object-assign": "^4.0.1" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true + }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + } + } + }, + "vuepress-plugin-clean-urls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vuepress-plugin-clean-urls/-/vuepress-plugin-clean-urls-1.1.2.tgz", + "integrity": "sha512-36r6XT9stybGSL9zHfFM6F+EBOF9rRDzGdNeias3AmU3AH5+DqsciMjRpHfecKXDKeVcc0PlNfG1Tf19CW5MzA==", + "dev": true + }, + "vuepress-plugin-code-copy": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/vuepress-plugin-code-copy/-/vuepress-plugin-code-copy-1.0.6.tgz", + "integrity": "sha512-FiqwMtlb4rEsOI56O6sSkekcd3SlESxbkR2IaTIQxsMOMoalKfW5R9WlR1Pjm10v6jmU661Ex8MR11k9IzrNUg==", + "dev": true + }, + "vuepress-plugin-container": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/vuepress-plugin-container/-/vuepress-plugin-container-2.1.5.tgz", + "integrity": "sha512-TQrDX/v+WHOihj3jpilVnjXu9RcTm6m8tzljNJwYhxnJUW0WWQ0hFLcDTqTBwgKIFdEiSxVOmYE+bJX/sq46MA==", + "dev": true, + "requires": { + "@vuepress/shared-utils": "^1.2.0", + "markdown-it-container": "^2.0.0" + } + }, + "vuepress-plugin-disqus": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/vuepress-plugin-disqus/-/vuepress-plugin-disqus-0.2.0.tgz", + "integrity": "sha512-kx+AeVzjJ9lx9bufLt1/X35V1VXfnQ1srkDMIzFKD9NyQ3eycsWQRcGO1dFe1HMrY3+7fTu+1/JeUEUEpGZ5tw==", + "dev": true, + "requires": { + "vue-disqus": "^3.0.5" + } + }, + "vuepress-plugin-feed": { + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/vuepress-plugin-feed/-/vuepress-plugin-feed-0.1.9.tgz", + "integrity": "sha512-iOJkR7zPmJAX0TEVdxNsUT07xNQB6lZFpU7DqsYzO01FhaPkMOOVM5Vx5a/iOOuOggAeoI9H9yuah+cRmCImlw==", + "dev": true, + "requires": { + "feed": "2.0.4", + "lodash.defaultsdeep": "4.6.1", + "lodash.isempty": "4.4.0", + "lodash.trimend": "^4.5.1", + "lodash.trimstart": "^4.5.1", + "remove-markdown": "0.3.0", + "striptags": "3.1.1" + } + }, + "vuepress-plugin-mailchimp": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/vuepress-plugin-mailchimp/-/vuepress-plugin-mailchimp-1.4.2.tgz", + "integrity": "sha512-4t5ZaKZXu5ZkwgE+WW//7CgXgz6DEhRefGrO5aql4PwapauNXlHKgQ2JMf9FRe5y5WHjNpDHYveEDNzISZmxJw==", + "dev": true, + "requires": { + "jsonp": "^0.2.1", + "query-string": "^6.9.0" + }, + "dependencies": { + "query-string": { + "version": "6.14.1", + "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.14.1.tgz", + "integrity": "sha512-XDxAeVmpfu1/6IjyT/gXHOl+S0vQ9owggJ30hhWKdHAsNPOcasn5o9BW0eejZqL2e4vMjhAxoW3jVHcD6mbcYw==", + "dev": true, + "requires": { + "decode-uri-component": "^0.2.0", + "filter-obj": "^1.1.0", + "split-on-first": "^1.0.0", + "strict-uri-encode": "^2.0.0" + } + }, + "strict-uri-encode": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz", + "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY=", + "dev": true + } + } + }, + "vuepress-plugin-mermaidjs": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/vuepress-plugin-mermaidjs/-/vuepress-plugin-mermaidjs-1.8.1.tgz", + "integrity": "sha512-gVnl2t2cbTd0ZWqikZzPPIjBvvcSKzAcuiON96Fi6RQo0QzIpjzXxuIp9bZ+tFUHn6UZp6hqqPtOdbsgcajilg==", + "dev": true, + "requires": { + "mermaid": "^8.8.3" + } + }, + "vuepress-plugin-seo": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/vuepress-plugin-seo/-/vuepress-plugin-seo-0.1.4.tgz", + "integrity": "sha512-foNKrAAKihiC47bx0UXFzs/+BIFmnowTQsLVF/8pfsnsPDp8FXjkTGyjxyjOhbwj7ADPv32CdX3pEoYGnZ7OjA==", + "dev": true + }, + "vuepress-plugin-sitemap": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/vuepress-plugin-sitemap/-/vuepress-plugin-sitemap-2.3.1.tgz", + "integrity": "sha512-n+8lbukhrKrsI9H/EX0EBgkE1pn85LAQFvQ5dIvrZP4Kz6JxPOPPNTQmZMhahQV1tXbLZQCEN7A1WZH4x+arJQ==", + "dev": true, + "requires": { + "sitemap": "^3.0.0" + } + }, + "vuepress-plugin-smooth-scroll": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/vuepress-plugin-smooth-scroll/-/vuepress-plugin-smooth-scroll-0.0.3.tgz", + "integrity": "sha512-qsQkDftLVFLe8BiviIHaLV0Ea38YLZKKonDGsNQy1IE0wllFpFIEldWD8frWZtDFdx6b/O3KDMgVQ0qp5NjJCg==", + "dev": true, + "requires": { + "smoothscroll-polyfill": "^0.4.3" + } + }, + "vuepress-plugin-tabs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/vuepress-plugin-tabs/-/vuepress-plugin-tabs-0.3.0.tgz", + "integrity": "sha512-jooDlcMdBqhXgIaF1awFSaOTM56mleP6bbCiGxyQxTZexfvCfDvZhNLGpyXqMQA50ZmNGmvLrK82YYb63k1jfA==", + "dev": true + }, + "wait-on": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-6.0.0.tgz", + "integrity": "sha512-tnUJr9p5r+bEYXPUdRseolmz5XqJTTj98JgOsfBn7Oz2dxfE2g3zw1jE+Mo8lopM3j3et/Mq1yW7kKX6qw7RVw==", + "dev": true, + "requires": { + "axios": "^0.21.1", + "joi": "^17.4.0", + "lodash": "^4.17.21", + "minimist": "^1.2.5", + "rxjs": "^7.1.0" + } + }, + "watchpack": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz", + "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==", + "dev": true, + "requires": { + "chokidar": "^3.4.1", + "graceful-fs": "^4.1.2", + "neo-async": "^2.5.0", + "watchpack-chokidar2": "^2.0.1" + }, + "dependencies": { + "anymatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", + "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==", + "dev": true, + "optional": true, + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "optional": true + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "optional": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "chokidar": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz", + "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "fsevents": "~2.3.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "optional": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "optional": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "optional": true + }, + "readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "optional": true, + "requires": { + "picomatch": "^2.2.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "optional": true, + "requires": { + "is-number": "^7.0.0" + } + } + } + }, + "watchpack-chokidar2": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz", + "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==", + "dev": true, + "optional": true, + "requires": { + "chokidar": "^2.1.8" + } + }, + "wbuf": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz", + "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==", + "dev": true, + "requires": { + "minimalistic-assert": "^1.0.0" + } + }, + "webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true + }, + "webpack": { + "version": "4.46.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz", + "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==", + "dev": true, + "requires": { + "@webassemblyjs/ast": "1.9.0", + "@webassemblyjs/helper-module-context": "1.9.0", + "@webassemblyjs/wasm-edit": "1.9.0", + "@webassemblyjs/wasm-parser": "1.9.0", + "acorn": "^6.4.1", + "ajv": "^6.10.2", + "ajv-keywords": "^3.4.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^4.5.0", + "eslint-scope": "^4.0.3", + "json-parse-better-errors": "^1.0.2", + "loader-runner": "^2.4.0", + "loader-utils": "^1.2.3", + "memory-fs": "^0.4.1", + "micromatch": "^3.1.10", + "mkdirp": "^0.5.3", + "neo-async": "^2.6.1", + "node-libs-browser": "^2.2.1", + "schema-utils": "^1.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^1.4.3", + "watchpack": "^1.7.4", + "webpack-sources": "^1.4.1" + }, + "dependencies": { + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + } + } + }, + "webpack-chain": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.5.1.tgz", + "integrity": "sha512-7doO/SRtLu8q5WM0s7vPKPWX580qhi0/yBHkOxNkv50f6qB76Zy9o2wRTrrPULqYTvQlVHuvbA8v+G5ayuUDsA==", + "dev": true, + "requires": { + "deepmerge": "^1.5.2", + "javascript-stringify": "^2.0.1" + } + }, + "webpack-dev-middleware": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz", + "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==", + "dev": true, + "requires": { + "memory-fs": "^0.4.1", + "mime": "^2.4.4", + "mkdirp": "^0.5.1", + "range-parser": "^1.2.1", + "webpack-log": "^2.0.0" + }, + "dependencies": { + "mime": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.5.2.tgz", + "integrity": "sha512-tqkh47FzKeCPD2PUiPB6pkbMzsCasjxAfC62/Wap5qrUWcb+sFasXUC5I3gYM5iBM8v/Qpn4UK0x+j0iHyFPDg==", + "dev": true + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true + } + } + }, + "webpack-dev-server": { + "version": "3.11.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.2.tgz", + "integrity": "sha512-A80BkuHRQfCiNtGBS1EMf2ChTUs0x+B3wGDFmOeT4rmJOHhHTCH2naNxIHhmkr0/UillP4U3yeIyv1pNp+QDLQ==", + "dev": true, + "requires": { + "ansi-html": "0.0.7", + "bonjour": "^3.5.0", + "chokidar": "^2.1.8", + "compression": "^1.7.4", + "connect-history-api-fallback": "^1.6.0", + "debug": "^4.1.1", + "del": "^4.1.1", + "express": "^4.17.1", + "html-entities": "^1.3.1", + "http-proxy-middleware": "0.19.1", + "import-local": "^2.0.0", + "internal-ip": "^4.3.0", + "ip": "^1.1.5", + "is-absolute-url": "^3.0.3", + "killable": "^1.0.1", + "loglevel": "^1.6.8", + "opn": "^5.5.0", + "p-retry": "^3.0.1", + "portfinder": "^1.0.26", + "schema-utils": "^1.0.0", + "selfsigned": "^1.10.8", + "semver": "^6.3.0", + "serve-index": "^1.9.1", + "sockjs": "^0.3.21", + "sockjs-client": "^1.5.0", + "spdy": "^4.0.2", + "strip-ansi": "^3.0.1", + "supports-color": "^6.1.0", + "url": "^0.11.0", + "webpack-dev-middleware": "^3.7.2", + "webpack-log": "^2.0.0", + "ws": "^6.2.1", + "yargs": "^13.3.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "dev": true, + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "debug": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", + "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", + "dev": true, + "requires": { + "ms": "2.1.2" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "dev": true + } + } + }, + "is-absolute-url": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz", + "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz", + "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "webpack-log": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz", + "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==", + "dev": true, + "requires": { + "ansi-colors": "^3.0.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "dev": true + } + } + }, + "webpack-merge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz", + "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==", + "dev": true, + "requires": { + "lodash": "^4.17.15" + } + }, + "webpack-sources": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", + "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", + "dev": true, + "requires": { + "source-list-map": "^2.0.0", + "source-map": "~0.6.1" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "webpackbar": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/webpackbar/-/webpackbar-3.2.0.tgz", + "integrity": "sha512-PC4o+1c8gWWileUfwabe0gqptlXUDJd5E0zbpr2xHP1VSOVlZVPBZ8j6NCR8zM5zbKdxPhctHXahgpNK1qFDPw==", + "dev": true, + "requires": { + "ansi-escapes": "^4.1.0", + "chalk": "^2.4.1", + "consola": "^2.6.0", + "figures": "^3.0.0", + "pretty-time": "^1.1.0", + "std-env": "^2.2.1", + "text-table": "^0.2.0", + "wrap-ansi": "^5.1.0" + } + }, + "websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dev": true, + "requires": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + } + }, + "websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "dev": true + }, + "whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "requires": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "when": { + "version": "3.6.4", + "resolved": "https://registry.npmjs.org/when/-/when-3.6.4.tgz", + "integrity": "sha1-RztRfsFZ4rhQBUl6E5g/CVQS404=", + "dev": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "requires": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "widest-line": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-2.0.1.tgz", + "integrity": "sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA==", + "dev": true, + "requires": { + "string-width": "^2.1.1" + } + }, + "win-release": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/win-release/-/win-release-1.1.1.tgz", + "integrity": "sha1-X6VeAr58qTTt/BJmVjLoSbcuUgk=", + "dev": true, + "requires": { + "semver": "^5.0.1" + } + }, + "worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dev": true, + "requires": { + "errno": "~0.1.7" + } + }, + "wrap-ansi": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", + "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.0", + "string-width": "^3.0.0", + "strip-ansi": "^5.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "ws": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.2.tgz", + "integrity": "sha512-zmhltoSR8u1cnDsD43TX59mzoMZsLKqUweyYBAIvTngR3shc0W6aOZylZmq/7hqyVxPdi+5Ud2QInblgyE72fw==", + "dev": true, + "requires": { + "async-limiter": "~1.0.0" + } + }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "dev": true + }, + "xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha1-eLpyAgApxbyHuKgaPPzXS0ovweU=", + "dev": true + }, + "xmlbuilder": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", + "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==", + "dev": true + }, + "xtend": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-3.0.0.tgz", + "integrity": "sha1-XM50B7r2Qsunvs2laBEcST9ZZlo=", + "dev": true + }, + "y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "dev": true + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=", + "dev": true + }, + "yargs": { + "version": "13.3.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", + "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", + "dev": true, + "requires": { + "cliui": "^5.0.0", + "find-up": "^3.0.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^3.0.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^13.1.2" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "dev": true, + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "yargs-parser": { + "version": "13.1.2", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", + "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "dependencies": { + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + } + } + }, + "zepto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/zepto/-/zepto-1.2.0.tgz", + "integrity": "sha1-4Se9nmb9hGvl6rSME5SIL3wOT5g=", + "dev": true + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000000..792ef76f56 --- /dev/null +++ b/package.json @@ -0,0 +1,38 @@ +{ + "name": "bitcoindevkit.org", + "version": "1.0.0", + "description": "Bitcoin Dev Kit Documentation", + "author": "Bitcoin Dev Kit", + "license": "MIT", + "bugs": "https://github.com/bitcoindevkit/bitcoindevkit.org/issues", + "homepage": "https://bitcoindevkit.org", + "repository": { + "type": "git", + "url": "git+https://github.com/bitcoindevkit/bitcoindevkit.org.git" + }, + "keywords": [ + "bitcoin", + "bdk", + "documentation" + ], + "config": { + "dist": "docs/.vuepress/dist", + "port": "8080", + "linkcheck": "blc -ro --filter-level 2 --requests 1 --exclude edit/master --exclude issues/new" + }, + "scripts": { + "prestart": "rm -rf $npm_package_config_dist", + "start": "NODE_ENV=development vuepress dev docs -p $npm_package_config_port", + "build": "NODE_ENV=production vuepress build docs", + "linkcheck": "start-server-and-test linkcheck:serve $npm_package_config_port linkcheck:local", + "linkcheck:serve": "serve -p $npm_package_config_port $npm_package_config_dist", + "linkcheck:local": "$npm_package_config_linkcheck http://localhost:$npm_package_config_port" + }, + "devDependencies": { + "broken-link-checker": "0.7.8", + "serve": "12.0.1", + "squarecrypto-vuepress-devkit-theme": "0.1.10", + "start-server-and-test": "1.14.0", + "vuepress": "1.8.2" + } +} diff --git a/publish_to_ghpages.sh b/publish_to_ghpages.sh deleted file mode 100755 index ac370bedba..0000000000 --- a/publish_to_ghpages.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh -# https://gohugo.io/hosting-and-deployment/hosting-on-github/ - -if [ "`git status -s`" ] -then - echo "The working directory is dirty. Please commit any pending changes." - exit 1; -fi - -echo "Deleting old publication" -rm -rf public -mkdir public -git worktree prune -rm -rf .git/worktrees/public/ - -echo "Checking out gh-pages branch into public" -git worktree add -B gh-pages public origin/gh-pages - -echo "Removing existing files" -rm -rf public/* - -echo "Generating site" -hugo - -echo "Updating gh-pages branch" -cd public && git add --all && git commit -m "Publishing to gh-pages (publish.sh)" - -#echo "Pushing to github" -#git push origin gh-pages - diff --git a/static/CNAME b/static/CNAME deleted file mode 100644 index cddb241d5e..0000000000 --- a/static/CNAME +++ /dev/null @@ -1 +0,0 @@ -bitcoindevkit.org \ No newline at end of file diff --git a/static/badge/bitcoin-dev-kit.svg b/static/badge/bitcoin-dev-kit.svg deleted file mode 100644 index 818d8f4603..0000000000 --- a/static/badge/bitcoin-dev-kit.svg +++ /dev/null @@ -1 +0,0 @@ -Bitcoin Dev KitBitcoin Dev Kit \ No newline at end of file diff --git a/static/bdk-cli/playground/1.playground.js b/static/bdk-cli/playground/1.playground.js deleted file mode 100644 index b72c6096f4..0000000000 --- a/static/bdk-cli/playground/1.playground.js +++ /dev/null @@ -1,19 +0,0 @@ -(window.webpackJsonp=window.webpackJsonp||[]).push([[1],[,,,function(t,e,o){var i,n,s;n=[o(7)],void 0===(s="function"==typeof(i=function(t){ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -"use strict";return t.setLocale=function(e){t.Msg=t.Msg||{},Object.keys(e).forEach((function(o){t.Msg[o]=e[o]}))},t})?i.apply(e,n):i)||(t.exports=s)},function(t,e,o){var i,n,s;n=[o(6)],void 0===(s="function"==typeof(i=function(t){ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -"use strict";return t})?i.apply(e,n):i)||(t.exports=s)},function(t,e){var o;o=function(){return this}();try{o=o||new Function("return this")()}catch(t){"object"==typeof window&&(o=window)}t.exports=o},function(t,e,o){var i,n,s;n=[o(3),o(8),o(9),o(10)],void 0===(s="function"==typeof(i=function(t,e,o,i){ -/** - * @license - * Copyright 2019 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ -"use strict";return t.setLocale(e),t.Blocks=t.Blocks||{},Object.keys(o).forEach((function(e){t.Blocks[e]=o[e]})),t.JavaScript=i,t})?i.apply(e,n):i)||(t.exports=s)},function(t,e,o){(function(o){var i,n,s;n=[],void 0===(s="function"==typeof(i=function(){"use strict";var t={constants:{},LINE_MODE_MULTIPLIER:40,PAGE_MODE_MULTIPLIER:125,DRAG_RADIUS:5,FLYOUT_DRAG_RADIUS:10,SNAP_RADIUS:28};return t.CONNECTING_SNAP_RADIUS=t.SNAP_RADIUS,t.CURRENT_CONNECTION_PREFERENCE=8,t.BUMP_DELAY=250,t.BUMP_RANDOMNESS=10,t.COLLAPSE_CHARS=30,t.LONGPRESS=750,t.SOUND_LIMIT=100,t.DRAG_STACK=!0,t.HSV_SATURATION=.45,t.HSV_VALUE=.65,t.SPRITE={width:96,height:124,url:"sprites.png"},t.INPUT_VALUE=1,t.OUTPUT_VALUE=2,t.NEXT_STATEMENT=3,t.PREVIOUS_STATEMENT=4,t.DUMMY_INPUT=5,t.ALIGN_LEFT=-1,t.ALIGN_CENTRE=0,t.ALIGN_RIGHT=1,t.DRAG_NONE=0,t.DRAG_STICKY=1,t.DRAG_BEGIN=1,t.DRAG_FREE=2,t.OPPOSITE_TYPE=[],t.OPPOSITE_TYPE[t.INPUT_VALUE]=t.OUTPUT_VALUE,t.OPPOSITE_TYPE[t.OUTPUT_VALUE]=t.INPUT_VALUE,t.OPPOSITE_TYPE[t.NEXT_STATEMENT]=t.PREVIOUS_STATEMENT,t.OPPOSITE_TYPE[t.PREVIOUS_STATEMENT]=t.NEXT_STATEMENT,t.TOOLBOX_AT_TOP=0,t.TOOLBOX_AT_BOTTOM=1,t.TOOLBOX_AT_LEFT=2,t.TOOLBOX_AT_RIGHT=3,t.DELETE_AREA_NONE=null,t.DELETE_AREA_TRASH=1,t.DELETE_AREA_TOOLBOX=2,t.VARIABLE_CATEGORY_NAME="VARIABLE",t.VARIABLE_DYNAMIC_CATEGORY_NAME="VARIABLE_DYNAMIC",t.PROCEDURE_CATEGORY_NAME="PROCEDURE",t.RENAME_VARIABLE_ID="RENAME_VARIABLE_ID",t.DELETE_VARIABLE_ID="DELETE_VARIABLE_ID",t.utils={},t.utils.global=function(){return"object"==typeof self?self:"object"==typeof window?window:"object"==typeof o?o:this}(),t.Msg={},t.utils.global.Blockly||(t.utils.global.Blockly={}),t.utils.global.Blockly.Msg||(t.utils.global.Blockly.Msg=t.Msg),t.utils.colour={},t.utils.colour.parse=function(e){e=String(e).toLowerCase().trim();var o=t.utils.colour.names[e];if(o)return o;if(o="#"==(o="0x"==e.substring(0,2)?"#"+e.substring(2):e)[0]?o:"#"+o,/^#[0-9a-f]{6}$/.test(o))return o;if(/^#[0-9a-f]{3}$/.test(o))return["#",o[1],o[1],o[2],o[2],o[3],o[3]].join("");var i=e.match(/^(?:rgb)?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/);return i&&(e=Number(i[1]),o=Number(i[2]),i=Number(i[3]),0<=e&&256>e&&0<=o&&256>o&&0<=i&&256>i)?t.utils.colour.rgbToHex(e,o,i):null},t.utils.colour.rgbToHex=function(t,e,o){return e=t<<16|e<<8|o,16>t?"#"+(16777216|e).toString(16).substr(1):"#"+e.toString(16)},t.utils.colour.hexToRgb=function(e){return(e=t.utils.colour.parse(e))?[(e=parseInt(e.substr(1),16))>>16,e>>8&255,255&e]:[0,0,0]},t.utils.colour.hsvToHex=function(e,o,i){var n=0,s=0,r=0;if(0==o)r=s=n=i;else{var a=Math.floor(e/60),l=e/60-a;e=i*(1-o);var c=i*(1-o*l);switch(o=i*(1-o*(1-l)),a){case 1:n=c,s=i,r=e;break;case 2:n=e,s=i,r=o;break;case 3:n=e,s=c,r=i;break;case 4:n=o,s=e,r=i;break;case 5:n=i,s=e,r=c;break;case 6:case 0:n=i,s=o,r=e}}return t.utils.colour.rgbToHex(Math.floor(n),Math.floor(s),Math.floor(r))},t.utils.colour.blend=function(e,o,i){return(e=t.utils.colour.parse(e))&&(o=t.utils.colour.parse(o))?(e=t.utils.colour.hexToRgb(e),o=t.utils.colour.hexToRgb(o),t.utils.colour.rgbToHex(Math.round(o[0]+i*(e[0]-o[0])),Math.round(o[1]+i*(e[1]-o[1])),Math.round(o[2]+i*(e[2]-o[2])))):null},t.utils.colour.names={aqua:"#00ffff",black:"#000000",blue:"#0000ff",fuchsia:"#ff00ff",gray:"#808080",green:"#008000",lime:"#00ff00",maroon:"#800000",navy:"#000080",olive:"#808000",purple:"#800080",red:"#ff0000",silver:"#c0c0c0",teal:"#008080",white:"#ffffff",yellow:"#ffff00"},t.utils.Coordinate=function(t,e){this.x=t,this.y=e},t.utils.Coordinate.equals=function(t,e){return t==e||!(!t||!e)&&t.x==e.x&&t.y==e.y},t.utils.Coordinate.distance=function(t,e){var o=t.x-e.x;return t=t.y-e.y,Math.sqrt(o*o+t*t)},t.utils.Coordinate.magnitude=function(t){return Math.sqrt(t.x*t.x+t.y*t.y)},t.utils.Coordinate.difference=function(e,o){return new t.utils.Coordinate(e.x-o.x,e.y-o.y)},t.utils.Coordinate.sum=function(e,o){return new t.utils.Coordinate(e.x+o.x,e.y+o.y)},t.utils.Coordinate.prototype.scale=function(t){return this.x*=t,this.y*=t,this},t.utils.Coordinate.prototype.translate=function(t,e){return this.x+=t,this.y+=e,this},t.utils.string={},t.utils.string.startsWith=function(t,e){return 0==t.lastIndexOf(e,0)},t.utils.string.shortestStringLength=function(t){return t.length?t.reduce((function(t,e){return t.lengtho&&(o=i[n].length);n=-1/0;var s=1;do{var r=n,a=e;e=[];var l=i.length/s,c=1;for(n=0;nr);return a},t.utils.string.wrapScore_=function(t,e,o){for(var i=[0],n=[],s=0;ss&&(s=l,n=a)}return n?t.utils.string.wrapMutate_(e,n,i):o},t.utils.string.wrapToText_=function(t,e){for(var o=[],i=0;i=l?(s=2,r=l,(l=e.join(""))&&i.push(l),e.length=0):"{"==l?s=3:(e.push("%",l),s=0):2==s?"0"<=l&&"9">=l?r+=l:(i.push(parseInt(r,10)),a--,s=0):3==s&&(""==l?(e.splice(0,0,"%{"),a--,s=0):"}"!=l?e.push(l):(s=e.join(""),/[A-Z]\w*/i.test(s)?(l=s.toUpperCase(),(l=t.utils.string.startsWith(l,"BKY_")?l.substring(4):null)&&l in t.Msg?"string"==typeof(s=t.Msg[l])?Array.prototype.push.apply(i,t.utils.tokenizeInterpolation_(s,o)):o?i.push(String(s)):i.push(s):i.push("%{"+s+"}")):i.push("%{"+s+"}"),s=e.length=0))}for((l=e.join(""))&&i.push(l),o=[],a=e.length=0;ai;i++)o[i]=t.utils.genUid.soup_.charAt(Math.random()*e);return o.join("")},t.utils.genUid.soup_="!#$%()*+,-./:;=?@[]^_`{|}~ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",t.utils.is3dSupported=function(){if(void 0!==t.utils.is3dSupported.cached_)return t.utils.is3dSupported.cached_;if(!t.utils.global.getComputedStyle)return!1;var e=document.createElement("p"),o="none",i={webkitTransform:"-webkit-transform",OTransform:"-o-transform",msTransform:"-ms-transform",MozTransform:"-moz-transform",transform:"transform"};for(var n in document.body.insertBefore(e,null),i)if(void 0!==e.style[n]){if(e.style[n]="translate3d(1px,1px,1px)",!(o=t.utils.global.getComputedStyle(e)))return document.body.removeChild(e),!1;o=o.getPropertyValue(i[n])}return document.body.removeChild(e),t.utils.is3dSupported.cached_="none"!==o,t.utils.is3dSupported.cached_},t.utils.runAfterPageLoad=function(t){if("object"!=typeof document)throw Error("Blockly.utils.runAfterPageLoad() requires browser document.");if("complete"==document.readyState)t();else var e=setInterval((function(){"complete"==document.readyState&&(clearInterval(e),t())}),10)},t.utils.getViewportBBox=function(){var e=t.utils.style.getViewportPageOffset();return{right:document.documentElement.clientWidth+e.x,bottom:document.documentElement.clientHeight+e.y,top:e.y,left:e.x}},t.utils.arrayRemove=function(t,e){return-1!=(e=t.indexOf(e))&&(t.splice(e,1),!0)},t.utils.getDocumentScroll=function(){var e=document.documentElement,o=window;return t.utils.userAgent.IE&&o.pageYOffset!=e.scrollTop?new t.utils.Coordinate(e.scrollLeft,e.scrollTop):new t.utils.Coordinate(o.pageXOffset||e.scrollLeft,o.pageYOffset||e.scrollTop)},t.utils.getBlockTypeCounts=function(t,e){var o=Object.create(null),i=t.getDescendants(!0);for(e&&(t=t.getNextBlock())&&(t=i.indexOf(t),i.splice(t,i.length-t)),t=0;e=i[t];t++)o[e.type]?o[e.type]++:o[e.type]=1;return o},t.utils.screenToWsCoordinates=function(e,o){var i=o.x;o=o.y;var n=e.getInjectionDiv().getBoundingClientRect();return i=new t.utils.Coordinate(i-n.left,o-n.top),o=e.getOriginOffsetInPixels(),t.utils.Coordinate.difference(i,o).scale(1/e.scale)},t.utils.parseBlockColour=function(e){var o="string"==typeof e?t.utils.replaceMessageReferences(e):e,i=Number(o);if(!isNaN(i)&&0<=i&&360>=i)return{hue:i,hex:t.utils.colour.hsvToHex(i,t.HSV_SATURATION,255*t.HSV_VALUE)};if(i=t.utils.colour.parse(o))return{hue:null,hex:i};throw i='Invalid colour: "'+o+'"',e!=o&&(i+=' (from "'+e+'")'),Error(i)},t.Events={},t.Events.group_="",t.Events.recordUndo=!0,t.Events.disabled_=0,t.Events.CREATE="create",t.Events.BLOCK_CREATE=t.Events.CREATE,t.Events.DELETE="delete",t.Events.BLOCK_DELETE=t.Events.DELETE,t.Events.CHANGE="change",t.Events.BLOCK_CHANGE=t.Events.CHANGE,t.Events.MOVE="move",t.Events.BLOCK_MOVE=t.Events.MOVE,t.Events.VAR_CREATE="var_create",t.Events.VAR_DELETE="var_delete",t.Events.VAR_RENAME="var_rename",t.Events.UI="ui",t.Events.COMMENT_CREATE="comment_create",t.Events.COMMENT_DELETE="comment_delete",t.Events.COMMENT_CHANGE="comment_change",t.Events.COMMENT_MOVE="comment_move",t.Events.FINISHED_LOADING="finished_loading",t.Events.BUMP_EVENTS=[t.Events.BLOCK_CREATE,t.Events.BLOCK_MOVE,t.Events.COMMENT_CREATE,t.Events.COMMENT_MOVE],t.Events.FIRE_QUEUE_=[],t.Events.fire=function(e){t.Events.isEnabled()&&(t.Events.FIRE_QUEUE_.length||setTimeout(t.Events.fireNow_,0),t.Events.FIRE_QUEUE_.push(e))},t.Events.fireNow_=function(){for(var e,o=t.Events.filter(t.Events.FIRE_QUEUE_,!0),i=t.Events.FIRE_QUEUE_.length=0;e=o[i];i++)if(e.workspaceId){var n=t.Workspace.getById(e.workspaceId);n&&n.fireChangeListener(e)}},t.Events.filter=function(e,o){e=e.slice(),o||e.reverse();for(var i,n=[],s=Object.create(null),r=0;i=e[r];r++)if(!i.isNull()){var a=[i.type,i.blockId,i.workspaceId].join(" "),l=s[a],c=l?l.event:null;l?i.type==t.Events.MOVE&&l.index==r-1?(c.newParentId=i.newParentId,c.newInputName=i.newInputName,c.newCoordinate=i.newCoordinate,l.index=r):i.type==t.Events.CHANGE&&i.element==c.element&&i.name==c.name?c.newValue=i.newValue:(i.type!=t.Events.UI||"click"!=i.element||"commentOpen"!=c.element&&"mutatorOpen"!=c.element&&"warningOpen"!=c.element)&&(s[a]={event:i,index:1},n.push(i)):(s[a]={event:i,index:r},n.push(i))}for(e=n.filter((function(t){return!t.isNull()})),o||e.reverse(),r=1;i=e[r];r++)i.type==t.Events.CHANGE&&"mutation"==i.element&&e.unshift(e.splice(r,1)[0]);return e},t.Events.clearPendingUndo=function(){for(var e,o=0;e=t.Events.FIRE_QUEUE_[o];o++)e.recordUndo=!1},t.Events.disable=function(){t.Events.disabled_++},t.Events.enable=function(){t.Events.disabled_--},t.Events.isEnabled=function(){return 0==t.Events.disabled_},t.Events.getGroup=function(){return t.Events.group_},t.Events.setGroup=function(e){t.Events.group_="boolean"==typeof e?e?t.utils.genUid():"":e},t.Events.getDescendantIds=function(t){var e=[];t=t.getDescendants(!1);for(var o,i=0;o=t[i];i++)e[i]=o.id;return e},t.Events.fromJson=function(e,o){switch(e.type){case t.Events.CREATE:var i=new t.Events.Create(null);break;case t.Events.DELETE:i=new t.Events.Delete(null);break;case t.Events.CHANGE:i=new t.Events.Change(null,"","","","");break;case t.Events.MOVE:i=new t.Events.Move(null);break;case t.Events.VAR_CREATE:i=new t.Events.VarCreate(null);break;case t.Events.VAR_DELETE:i=new t.Events.VarDelete(null);break;case t.Events.VAR_RENAME:i=new t.Events.VarRename(null,"");break;case t.Events.UI:i=new t.Events.Ui(null,"","","");break;case t.Events.COMMENT_CREATE:i=new t.Events.CommentCreate(null);break;case t.Events.COMMENT_CHANGE:i=new t.Events.CommentChange(null,"","");break;case t.Events.COMMENT_MOVE:i=new t.Events.CommentMove(null);break;case t.Events.COMMENT_DELETE:i=new t.Events.CommentDelete(null);break;case t.Events.FINISHED_LOADING:i=new t.Events.FinishedLoading(o);break;default:throw Error("Unknown event type.")}return i.fromJson(e),i.workspaceId=o.id,i},t.Events.disableOrphans=function(e){if((e.type==t.Events.MOVE||e.type==t.Events.CREATE)&&e.workspaceId){var o=t.Workspace.getById(e.workspaceId);if(e=o.getBlockById(e.blockId)){var i=e.getParent();if(i&&i.isEnabled())for(o=e.getDescendants(!1),e=0;i=o[e];e++)i.setEnabled(!0);else if((e.outputConnection||e.previousConnection)&&!o.isDragging())do{e.setEnabled(!1),e=e.getNextBlock()}while(e)}}},t.Events.Abstract=function(){this.workspaceId=void 0,this.group=t.Events.getGroup(),this.recordUndo=t.Events.recordUndo},t.Events.Abstract.prototype.toJson=function(){var t={type:this.type};return this.group&&(t.group=this.group),t},t.Events.Abstract.prototype.fromJson=function(t){this.group=t.group},t.Events.Abstract.prototype.isNull=function(){return!1},t.Events.Abstract.prototype.run=function(t){},t.Events.Abstract.prototype.getEventWorkspace_=function(){if(this.workspaceId)var e=t.Workspace.getById(this.workspaceId);if(!e)throw Error("Workspace is null. Event must have been generated from real Blockly events.");return e},t.utils.object={},t.utils.object.inherits=function(t,e){t.superClass_=e.prototype,t.prototype=Object.create(e.prototype),t.prototype.constructor=t},t.utils.object.mixin=function(t,e){for(var o in e)t[o]=e[o]},t.utils.object.deepMerge=function(e,o){for(var i in o)e[i]="object"==typeof o[i]?t.utils.object.deepMerge(e[i]||Object.create(null),o[i]):o[i];return e},t.utils.object.values=function(t){return Object.values?Object.values(t):Object.keys(t).map((function(e){return t[e]}))},t.Events.Ui=function(e,o,i,n){t.Events.Ui.superClass_.constructor.call(this),this.blockId=e?e.id:null,this.workspaceId=e?e.workspace.id:void 0,this.element=o,this.oldValue=i,this.newValue=n,this.recordUndo=!1},t.utils.object.inherits(t.Events.Ui,t.Events.Abstract),t.Events.Ui.prototype.type=t.Events.UI,t.Events.Ui.prototype.toJson=function(){var e=t.Events.Ui.superClass_.toJson.call(this);return e.element=this.element,void 0!==this.newValue&&(e.newValue=this.newValue),this.blockId&&(e.blockId=this.blockId),e},t.Events.Ui.prototype.fromJson=function(e){t.Events.Ui.superClass_.fromJson.call(this,e),this.element=e.element,this.newValue=e.newValue,this.blockId=e.blockId},t.utils.dom={},t.utils.dom.SVG_NS="http://www.w3.org/2000/svg",t.utils.dom.HTML_NS="http://www.w3.org/1999/xhtml",t.utils.dom.XLINK_NS="http://www.w3.org/1999/xlink",t.utils.dom.Node={ELEMENT_NODE:1,TEXT_NODE:3,COMMENT_NODE:8,DOCUMENT_POSITION_CONTAINED_BY:16},t.utils.dom.cacheWidths_=null,t.utils.dom.cacheReference_=0,t.utils.dom.canvasContext_=null,t.utils.dom.createSvgElement=function(e,o,i){for(var n in e=document.createElementNS(t.utils.dom.SVG_NS,e),o)e.setAttribute(n,o[n]);return document.body.runtimeStyle&&(e.runtimeStyle=e.currentStyle=e.style),i&&i.appendChild(e),e},t.utils.dom.addClass=function(t,e){var o=t.getAttribute("class")||"";return-1==(" "+o+" ").indexOf(" "+e+" ")&&(o&&(o+=" "),t.setAttribute("class",o+e),!0)},t.utils.dom.removeClass=function(t,e){var o=t.getAttribute("class");if(-1==(" "+o+" ").indexOf(" "+e+" "))return!1;o=o.split(/\s+/);for(var i=0;io||o>this.getChildCount())throw Error(t.Component.Error.CHILD_INDEX_OUT_OF_BOUNDS);if(this.childIndex_[e.getId()]=e,e.getParent()==this){var n=this.children_.indexOf(e);-1>>/g,e),(e=document.createElement("style")).id="blockly-common-style",i=document.createTextNode(i),e.appendChild(i),document.head.insertBefore(e,document.head.firstChild))}},t.Css.setCursor=function(t){console.warn("Deprecated call to Blockly.Css.setCursor. See https://github.com/google/blockly/issues/981 for context")},t.Css.CONTENT=[".blocklySvg {","background-color: #fff;","outline: none;","overflow: hidden;","position: absolute;","display: block;","}",".blocklyWidgetDiv {","display: none;","position: absolute;","z-index: 99999;","}",".injectionDiv {","height: 100%;","position: relative;","overflow: hidden;","touch-action: none;","}",".blocklyNonSelectable {","user-select: none;","-ms-user-select: none;","-webkit-user-select: none;","}",".blocklyWsDragSurface {","display: none;","position: absolute;","top: 0;","left: 0;","}",".blocklyWsDragSurface.blocklyOverflowVisible {","overflow: visible;","}",".blocklyBlockDragSurface {","display: none;","position: absolute;","top: 0;","left: 0;","right: 0;","bottom: 0;","overflow: visible !important;","z-index: 50;","}",".blocklyBlockCanvas.blocklyCanvasTransitioning,",".blocklyBubbleCanvas.blocklyCanvasTransitioning {","transition: transform .5s;","}",".blocklyTooltipDiv {","background-color: #ffffc7;","border: 1px solid #ddc;","box-shadow: 4px 4px 20px 1px rgba(0,0,0,.15);","color: #000;","display: none;","font-family: sans-serif;","font-size: 9pt;","opacity: .9;","padding: 2px;","position: absolute;","z-index: 100000;","}",".blocklyDropDownDiv {","position: absolute;","left: 0;","top: 0;","z-index: 1000;","display: none;","border: 1px solid;","border-color: #dadce0;","background-color: #fff;","border-radius: 2px;","padding: 4px;","box-shadow: 0px 0px 3px 1px rgba(0,0,0,.3);","}",".blocklyDropDownDiv.focused {","box-shadow: 0px 0px 6px 1px rgba(0,0,0,.3);","}",".blocklyDropDownContent {","max-height: 300px;","overflow: auto;","overflow-x: hidden;","}",".blocklyDropDownArrow {","position: absolute;","left: 0;","top: 0;","width: 16px;","height: 16px;","z-index: -1;","background-color: inherit;","border-color: inherit;","}",".blocklyDropDownButton {","display: inline-block;","float: left;","padding: 0;","margin: 4px;","border-radius: 4px;","outline: none;","border: 1px solid;","transition: box-shadow .1s;","cursor: pointer;","}",".blocklyArrowTop {","border-top: 1px solid;","border-left: 1px solid;","border-top-left-radius: 4px;","border-color: inherit;","}",".blocklyArrowBottom {","border-bottom: 1px solid;","border-right: 1px solid;","border-bottom-right-radius: 4px;","border-color: inherit;","}",".blocklyResizeSE {","cursor: se-resize;","fill: #aaa;","}",".blocklyResizeSW {","cursor: sw-resize;","fill: #aaa;","}",".blocklyResizeLine {","stroke: #515A5A;","stroke-width: 1;","}",".blocklyHighlightedConnectionPath {","fill: none;","stroke: #fc3;","stroke-width: 4px;","}",".blocklyPathLight {","fill: none;","stroke-linecap: round;","stroke-width: 1;","}",".blocklySelected>.blocklyPathLight {","display: none;","}",".blocklyDraggable {",'cursor: url("<<>>/handopen.cur"), auto;',"cursor: grab;","cursor: -webkit-grab;","}",".blocklyDragging {",'cursor: url("<<>>/handclosed.cur"), auto;',"cursor: grabbing;","cursor: -webkit-grabbing;","}",".blocklyDraggable:active {",'cursor: url("<<>>/handclosed.cur"), auto;',"cursor: grabbing;","cursor: -webkit-grabbing;","}",".blocklyBlockDragSurface .blocklyDraggable {",'cursor: url("<<>>/handclosed.cur"), auto;',"cursor: grabbing;","cursor: -webkit-grabbing;","}",".blocklyDragging.blocklyDraggingDelete {",'cursor: url("<<>>/handdelete.cur"), auto;',"}",".blocklyDragging>.blocklyPath,",".blocklyDragging>.blocklyPathLight {","fill-opacity: .8;","stroke-opacity: .8;","}",".blocklyDragging>.blocklyPathDark {","display: none;","}",".blocklyDisabled>.blocklyPath {","fill-opacity: .5;","stroke-opacity: .5;","}",".blocklyDisabled>.blocklyPathLight,",".blocklyDisabled>.blocklyPathDark {","display: none;","}",".blocklyInsertionMarker>.blocklyPath,",".blocklyInsertionMarker>.blocklyPathLight,",".blocklyInsertionMarker>.blocklyPathDark {","fill-opacity: .2;","stroke: none","}",".blocklyMultilineText {","font-family: monospace;","}",".blocklyNonEditableText>text {","pointer-events: none;","}",".blocklyFlyout {","position: absolute;","z-index: 20;","}",".blocklyText text {","cursor: default;","}",".blocklySvg text, .blocklyBlockDragSurface text {","user-select: none;","-ms-user-select: none;","-webkit-user-select: none;","cursor: inherit;","}",".blocklyHidden {","display: none;","}",".blocklyFieldDropdown:not(.blocklyHidden) {","display: block;","}",".blocklyIconGroup {","cursor: default;","}",".blocklyIconGroup:not(:hover),",".blocklyIconGroupReadonly {","opacity: .6;","}",".blocklyIconShape {","fill: #00f;","stroke: #fff;","stroke-width: 1px;","}",".blocklyIconSymbol {","fill: #fff;","}",".blocklyMinimalBody {","margin: 0;","padding: 0;","}",".blocklyHtmlInput {","border: none;","border-radius: 4px;","height: 100%;","margin: 0;","outline: none;","padding: 0;","width: 100%;","text-align: center;","display: block;","box-sizing: border-box;","}",".blocklyHtmlInput::-ms-clear {","display: none;","}",".blocklyMainBackground {","stroke-width: 1;","stroke: #c6c6c6;","}",".blocklyMutatorBackground {","fill: #fff;","stroke: #ddd;","stroke-width: 1;","}",".blocklyFlyoutBackground {","fill: #ddd;","fill-opacity: .8;","}",".blocklyMainWorkspaceScrollbar {","z-index: 20;","}",".blocklyFlyoutScrollbar {","z-index: 30;","}",".blocklyScrollbarHorizontal, .blocklyScrollbarVertical {","position: absolute;","outline: none;","}",".blocklyScrollbarBackground {","opacity: 0;","}",".blocklyScrollbarHandle {","fill: #ccc;","}",".blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,",".blocklyScrollbarHandle:hover {","fill: #bbb;","}",".blocklyFlyout .blocklyScrollbarHandle {","fill: #bbb;","}",".blocklyFlyout .blocklyScrollbarBackground:hover+.blocklyScrollbarHandle,",".blocklyFlyout .blocklyScrollbarHandle:hover {","fill: #aaa;","}",".blocklyInvalidInput {","background: #faa;","}",".blocklyContextMenu {","border-radius: 4px;","max-height: 100%;","}",".blocklyDropdownMenu {","border-radius: 2px;","padding: 0 !important;","}",".blocklyWidgetDiv .blocklyDropdownMenu .goog-menuitem,",".blocklyDropDownDiv .blocklyDropdownMenu .goog-menuitem {","padding-left: 28px;","}",".blocklyWidgetDiv .blocklyDropdownMenu .goog-menuitem.goog-menuitem-rtl,",".blocklyDropDownDiv .blocklyDropdownMenu .goog-menuitem.goog-menuitem-rtl {","padding-left: 5px;","padding-right: 28px;","}",".blocklyVerticalMarker {","stroke-width: 3px;","fill: rgba(255,255,255,.5);","pointer-events: none","}",".blocklyWidgetDiv .goog-option-selected .goog-menuitem-checkbox,",".blocklyWidgetDiv .goog-option-selected .goog-menuitem-icon,",".blocklyDropDownDiv .goog-option-selected .goog-menuitem-checkbox,",".blocklyDropDownDiv .goog-option-selected .goog-menuitem-icon {","background: url(<<>>/sprites.png) no-repeat -48px -16px;","}",".blocklyWidgetDiv .goog-menu {","background: #fff;","border-color: transparent;","border-style: solid;","border-width: 1px;","cursor: default;","font: normal 13px Arial, sans-serif;","margin: 0;","outline: none;","padding: 4px 0;","position: absolute;","overflow-y: auto;","overflow-x: hidden;","max-height: 100%;","z-index: 20000;","box-shadow: 0px 0px 3px 1px rgba(0,0,0,.3);","}",".blocklyWidgetDiv .goog-menu.focused {","box-shadow: 0px 0px 6px 1px rgba(0,0,0,.3);","}",".blocklyDropDownDiv .goog-menu {","cursor: default;",'font: normal 13px "Helvetica Neue", Helvetica, sans-serif;',"outline: none;","z-index: 20000;","}",".blocklyWidgetDiv .goog-menuitem,",".blocklyDropDownDiv .goog-menuitem {","color: #000;","font: normal 13px Arial, sans-serif;","list-style: none;","margin: 0;","min-width: 7em;","border: none;","padding: 6px 15px;","white-space: nowrap;","cursor: pointer;","}",".blocklyWidgetDiv .goog-menu-nocheckbox .goog-menuitem,",".blocklyWidgetDiv .goog-menu-noicon .goog-menuitem,",".blocklyDropDownDiv .goog-menu-nocheckbox .goog-menuitem,",".blocklyDropDownDiv .goog-menu-noicon .goog-menuitem {","padding-left: 12px;","}",".blocklyWidgetDiv .goog-menuitem-content,",".blocklyDropDownDiv .goog-menuitem-content {","font-family: Arial, sans-serif;","font-size: 13px;","}",".blocklyWidgetDiv .goog-menuitem-content {","color: #000;","}",".blocklyDropDownDiv .goog-menuitem-content {","color: #000;","}",".blocklyWidgetDiv .goog-menuitem-disabled,",".blocklyDropDownDiv .goog-menuitem-disabled {","cursor: inherit;","}",".blocklyWidgetDiv .goog-menuitem-disabled .goog-menuitem-content,",".blocklyDropDownDiv .goog-menuitem-disabled .goog-menuitem-content {","color: #ccc !important;","}",".blocklyWidgetDiv .goog-menuitem-disabled .goog-menuitem-icon,",".blocklyDropDownDiv .goog-menuitem-disabled .goog-menuitem-icon {","opacity: .3;","filter: alpha(opacity=30);","}",".blocklyWidgetDiv .goog-menuitem-highlight ,",".blocklyDropDownDiv .goog-menuitem-highlight {","background-color: rgba(0,0,0,.1);","}",".blocklyWidgetDiv .goog-menuitem-checkbox,",".blocklyWidgetDiv .goog-menuitem-icon,",".blocklyDropDownDiv .goog-menuitem-checkbox,",".blocklyDropDownDiv .goog-menuitem-icon {","background-repeat: no-repeat;","height: 16px;","left: 6px;","position: absolute;","right: auto;","vertical-align: middle;","width: 16px;","}",".blocklyWidgetDiv .goog-menuitem-rtl .goog-menuitem-checkbox,",".blocklyWidgetDiv .goog-menuitem-rtl .goog-menuitem-icon,",".blocklyDropDownDiv .goog-menuitem-rtl .goog-menuitem-checkbox,",".blocklyDropDownDiv .goog-menuitem-rtl .goog-menuitem-icon {","left: auto;","right: 6px;","}",".blocklyWidgetDiv .goog-option-selected .goog-menuitem-checkbox,",".blocklyWidgetDiv .goog-option-selected .goog-menuitem-icon,",".blocklyDropDownDiv .goog-option-selected .goog-menuitem-checkbox,",".blocklyDropDownDiv .goog-option-selected .goog-menuitem-icon {","position: static;","float: left;","margin-left: -24px;","}",".blocklyWidgetDiv .goog-menuitem-rtl .goog-menuitem-checkbox,",".blocklyWidgetDiv .goog-menuitem-rtl .goog-menuitem-icon,",".blocklyDropDownDiv .goog-menuitem-rtl .goog-menuitem-checkbox,",".blocklyDropDownDiv .goog-menuitem-rtl .goog-menuitem-icon {","float: right;","margin-right: -24px;","}",".blocklyComputeCanvas {","position: absolute;","width: 0;","height: 0;","}",".blocklyNoPointerEvents {","pointer-events: none;","}"],t.utils.math={},t.utils.math.toRadians=function(t){return t*Math.PI/180},t.utils.math.toDegrees=function(t){return 180*t/Math.PI},t.utils.math.clamp=function(t,e,o){if(os.top?t.DropDownDiv.getPositionAboveMetrics_(i,n,s,r):o+r.heightdocument.documentElement.clientTop?t.DropDownDiv.getPositionAboveMetrics_(i,n,s,r):t.DropDownDiv.getPositionTopOfPageMetrics_(e,s,r)},t.DropDownDiv.getPositionBelowMetrics_=function(e,o,i,n){return{initialX:(e=t.DropDownDiv.getPositionX(e,i.left,i.right,n.width)).divX,initialY:o,finalX:e.divX,finalY:o+t.DropDownDiv.PADDING_Y,arrowX:e.arrowX,arrowY:-(t.DropDownDiv.ARROW_SIZE/2+t.DropDownDiv.BORDER_SIZE),arrowAtTop:!0,arrowVisible:!0}},t.DropDownDiv.getPositionAboveMetrics_=function(e,o,i,n){return{initialX:(e=t.DropDownDiv.getPositionX(e,i.left,i.right,n.width)).divX,initialY:o-n.height,finalX:e.divX,finalY:o-n.height-t.DropDownDiv.PADDING_Y,arrowX:e.arrowX,arrowY:n.height-2*t.DropDownDiv.BORDER_SIZE-t.DropDownDiv.ARROW_SIZE/2,arrowAtTop:!1,arrowVisible:!0}},t.DropDownDiv.getPositionTopOfPageMetrics_=function(e,o,i){return{initialX:(e=t.DropDownDiv.getPositionX(e,o.left,o.right,i.width)).divX,initialY:0,finalX:e.divX,finalY:0,arrowVisible:!1}},t.DropDownDiv.getPositionX=function(e,o,i,n){var s=e;return e=t.utils.math.clamp(o,e-n/2,i-n),s-=t.DropDownDiv.ARROW_SIZE/2,o=t.DropDownDiv.ARROW_HORIZONTAL_PADDING,{arrowX:n=t.utils.math.clamp(o,s-e,n-o-t.DropDownDiv.ARROW_SIZE),divX:e}},t.DropDownDiv.isVisible=function(){return!!t.DropDownDiv.owner_},t.DropDownDiv.hideIfOwner=function(e,o){return t.DropDownDiv.owner_===e&&(o?t.DropDownDiv.hideWithoutAnimation():t.DropDownDiv.hide(),!0)},t.DropDownDiv.hide=function(){var e=t.DropDownDiv.DIV_;e.style.transform="translate(0, 0)",e.style.opacity=0,t.DropDownDiv.animateOutTimer_=setTimeout((function(){t.DropDownDiv.hideWithoutAnimation()}),1e3*t.DropDownDiv.ANIMATION_TIME),t.DropDownDiv.onHide_&&(t.DropDownDiv.onHide_(),t.DropDownDiv.onHide_=null)},t.DropDownDiv.hideWithoutAnimation=function(){if(t.DropDownDiv.isVisible()){t.DropDownDiv.animateOutTimer_&&clearTimeout(t.DropDownDiv.animateOutTimer_);var e=t.DropDownDiv.DIV_;e.style.transform="",e.style.left="",e.style.top="",e.style.opacity=0,e.style.display="none",e.style.backgroundColor="",e.style.borderColor="",t.DropDownDiv.onHide_&&(t.DropDownDiv.onHide_(),t.DropDownDiv.onHide_=null),t.DropDownDiv.clearContent(),t.DropDownDiv.owner_=null,t.DropDownDiv.rendererClassName_&&(t.utils.dom.removeClass(e,t.DropDownDiv.rendererClassName_),t.DropDownDiv.rendererClassName_=""),t.DropDownDiv.themeClassName_&&(t.utils.dom.removeClass(e,t.DropDownDiv.themeClassName_),t.DropDownDiv.themeClassName_=""),t.getMainWorkspace().markFocused()}},t.DropDownDiv.positionInternal_=function(e,o,i,n){(e=t.DropDownDiv.getPositionMetrics_(e,o,i,n)).arrowVisible?(t.DropDownDiv.arrow_.style.display="",t.DropDownDiv.arrow_.style.transform="translate("+e.arrowX+"px,"+e.arrowY+"px) rotate(45deg)",t.DropDownDiv.arrow_.setAttribute("class",e.arrowAtTop?"blocklyDropDownArrow blocklyArrowTop":"blocklyDropDownArrow blocklyArrowBottom")):t.DropDownDiv.arrow_.style.display="none",o=Math.floor(e.initialX),i=Math.floor(e.initialY),n=Math.floor(e.finalX);var s=Math.floor(e.finalY),r=t.DropDownDiv.DIV_;return r.style.left=o+"px",r.style.top=i+"px",r.style.display="block",r.style.opacity=1,r.style.transform="translate("+(n-o)+"px,"+(s-i)+"px)",e.arrowAtTop},t.DropDownDiv.repositionForWindowResize=function(){if(t.DropDownDiv.owner_){var e=t.DropDownDiv.owner_,o=t.DropDownDiv.owner_.getSourceBlock();o=(e=t.DropDownDiv.positionToField_?t.DropDownDiv.getScaledBboxOfField_(e):t.DropDownDiv.getScaledBboxOfBlock_(o)).left+(e.right-e.left)/2,t.DropDownDiv.positionInternal_(o,e.bottom,o,e.top)}else t.DropDownDiv.hide()},t.Grid=function(t,e){this.gridPattern_=t,this.spacing_=e.spacing,this.length_=e.length,this.line2_=(this.line1_=t.firstChild)&&this.line1_.nextSibling,this.snapToGrid_=e.snap},t.Grid.prototype.scale_=1,t.Grid.prototype.dispose=function(){this.gridPattern_=null},t.Grid.prototype.shouldSnap=function(){return this.snapToGrid_},t.Grid.prototype.getSpacing=function(){return this.spacing_},t.Grid.prototype.getPatternId=function(){return this.gridPattern_.id},t.Grid.prototype.update=function(t){this.scale_=t;var e=this.spacing_*t||100;this.gridPattern_.setAttribute("width",e),this.gridPattern_.setAttribute("height",e);var o=(e=Math.floor(this.spacing_/2)+.5)-this.length_/2,i=e+this.length_/2;e*=t,o*=t,i*=t,this.setLineAttributes_(this.line1_,t,o,i,e,e),this.setLineAttributes_(this.line2_,t,e,e,o,i)},t.Grid.prototype.setLineAttributes_=function(t,e,o,i,n,s){t&&(t.setAttribute("stroke-width",e),t.setAttribute("x1",o),t.setAttribute("y1",n),t.setAttribute("x2",i),t.setAttribute("y2",s))},t.Grid.prototype.moveTo=function(e,o){this.gridPattern_.setAttribute("x",e),this.gridPattern_.setAttribute("y",o),(t.utils.userAgent.IE||t.utils.userAgent.EDGE)&&this.update(this.scale_)},t.Grid.createDom=function(e,o,i){return e=t.utils.dom.createSvgElement("pattern",{id:"blocklyGridPattern"+e,patternUnits:"userSpaceOnUse"},i),0e.indexOf(o))throw Error(o+" is not a valid modifier key.")},t.user.keyMap.createSerializedKey=function(e,o){var i="",n=t.utils.object.values(t.user.keyMap.modifierKeys);t.user.keyMap.checkModifiers_(o,n);for(var s,r=0;s=n[r];r++)-1");o.domToMutation(n)}t.Events.fire(new t.Events.Change(o,"mutation",null,i,e));break;default:console.warn("Unknown change type: "+this.element)}else console.warn("Can't change non-existent block: "+this.blockId)},t.Events.Create=function(e){e&&(t.Events.Create.superClass_.constructor.call(this,e),this.xml=e.workspace.rendered?t.Xml.blockToDomWithXY(e):t.Xml.blockToDom(e),this.ids=t.Events.getDescendantIds(e))},t.utils.object.inherits(t.Events.Create,t.Events.BlockBase),t.Events.BlockCreate=t.Events.Create,t.Events.Create.prototype.type=t.Events.CREATE,t.Events.Create.prototype.toJson=function(){var e=t.Events.Create.superClass_.toJson.call(this);return e.xml=t.Xml.domToText(this.xml),e.ids=this.ids,e},t.Events.Create.prototype.fromJson=function(e){t.Events.Create.superClass_.fromJson.call(this,e),this.xml=t.Xml.textToDom(e.xml),this.ids=e.ids},t.Events.Create.prototype.run=function(e){var o=this.getEventWorkspace_();if(e)(e=t.utils.xml.createElement("xml")).appendChild(this.xml),t.Xml.domToWorkspace(e,o);else{e=0;for(var i;i=this.ids[e];e++){var n=o.getBlockById(i);n?n.dispose(!1):i==this.blockId&&console.warn("Can't uncreate non-existent block: "+i)}}},t.Events.Delete=function(e){if(e){if(e.getParent())throw Error("Connected blocks cannot be deleted.");t.Events.Delete.superClass_.constructor.call(this,e),this.oldXml=e.workspace.rendered?t.Xml.blockToDomWithXY(e):t.Xml.blockToDom(e),this.ids=t.Events.getDescendantIds(e)}},t.utils.object.inherits(t.Events.Delete,t.Events.BlockBase),t.Events.BlockDelete=t.Events.Delete,t.Events.Delete.prototype.type=t.Events.DELETE,t.Events.Delete.prototype.toJson=function(){var e=t.Events.Delete.superClass_.toJson.call(this);return e.ids=this.ids,e},t.Events.Delete.prototype.fromJson=function(e){t.Events.Delete.superClass_.fromJson.call(this,e),this.ids=e.ids},t.Events.Delete.prototype.run=function(e){var o=this.getEventWorkspace_();if(e){e=0;for(var i;i=this.ids[e];e++){var n=o.getBlockById(i);n?n.dispose(!1):i==this.blockId&&console.warn("Can't delete non-existent block: "+i)}}else(e=t.utils.xml.createElement("xml")).appendChild(this.oldXml),t.Xml.domToWorkspace(e,o)},t.Events.Move=function(e){e&&(t.Events.Move.superClass_.constructor.call(this,e),e=this.currentLocation_(),this.oldParentId=e.parentId,this.oldInputName=e.inputName,this.oldCoordinate=e.coordinate)},t.utils.object.inherits(t.Events.Move,t.Events.BlockBase),t.Events.BlockMove=t.Events.Move,t.Events.Move.prototype.type=t.Events.MOVE,t.Events.Move.prototype.toJson=function(){var e=t.Events.Move.superClass_.toJson.call(this);return this.newParentId&&(e.newParentId=this.newParentId),this.newInputName&&(e.newInputName=this.newInputName),this.newCoordinate&&(e.newCoordinate=Math.round(this.newCoordinate.x)+","+Math.round(this.newCoordinate.y)),e},t.Events.Move.prototype.fromJson=function(e){t.Events.Move.superClass_.fromJson.call(this,e),this.newParentId=e.newParentId,this.newInputName=e.newInputName,e.newCoordinate&&(e=e.newCoordinate.split(","),this.newCoordinate=new t.utils.Coordinate(Number(e[0]),Number(e[1])))},t.Events.Move.prototype.recordNew=function(){var t=this.currentLocation_();this.newParentId=t.parentId,this.newInputName=t.inputName,this.newCoordinate=t.coordinate},t.Events.Move.prototype.currentLocation_=function(){var t=this.getEventWorkspace_().getBlockById(this.blockId),e={},o=t.getParent();return o?(e.parentId=o.id,(t=o.getInputWithBlock(t))&&(e.inputName=t.name)):e.coordinate=t.getRelativeToSurfaceXY(),e},t.Events.Move.prototype.isNull=function(){return this.oldParentId==this.newParentId&&this.oldInputName==this.newInputName&&t.utils.Coordinate.equals(this.oldCoordinate,this.newCoordinate)},t.Events.Move.prototype.run=function(e){var o=this.getEventWorkspace_(),i=o.getBlockById(this.blockId);if(i){var n=e?this.newParentId:this.oldParentId,s=e?this.newInputName:this.oldInputName;e=e?this.newCoordinate:this.oldCoordinate;var r=null;if(n&&!(r=o.getBlockById(n)))return void console.warn("Can't connect to non-existent block: "+n);if(i.getParent()&&i.unplug(),e)s=i.getRelativeToSurfaceXY(),i.moveBy(e.x-s.x,e.y-s.y);else{if(i=i.outputConnection||i.previousConnection,s){if(o=r.getInput(s))var a=o.connection}else i.type==t.PREVIOUS_STATEMENT&&(a=r.nextConnection);a?i.connect(a):console.warn("Can't connect to non-existent input: "+s)}}else console.warn("Can't move non-existent block: "+this.blockId)},t.Events.FinishedLoading=function(e){this.workspaceId=e.id,this.group=t.Events.getGroup(),this.recordUndo=!1},t.utils.object.inherits(t.Events.FinishedLoading,t.Events.Ui),t.Events.FinishedLoading.prototype.type=t.Events.FINISHED_LOADING,t.Events.FinishedLoading.prototype.toJson=function(){var t={type:this.type};return this.group&&(t.group=this.group),this.workspaceId&&(t.workspaceId=this.workspaceId),t},t.Events.FinishedLoading.prototype.fromJson=function(t){this.workspaceId=t.workspaceId,this.group=t.group},t.Events.VarBase=function(e){t.Events.VarBase.superClass_.constructor.call(this),this.varId=e.getId(),this.workspaceId=e.workspace.id},t.utils.object.inherits(t.Events.VarBase,t.Events.Abstract),t.Events.VarBase.prototype.toJson=function(){var e=t.Events.VarBase.superClass_.toJson.call(this);return e.varId=this.varId,e},t.Events.VarBase.prototype.fromJson=function(e){t.Events.VarBase.superClass_.toJson.call(this),this.varId=e.varId},t.Events.VarCreate=function(e){e&&(t.Events.VarCreate.superClass_.constructor.call(this,e),this.varType=e.type,this.varName=e.name)},t.utils.object.inherits(t.Events.VarCreate,t.Events.VarBase),t.Events.VarCreate.prototype.type=t.Events.VAR_CREATE,t.Events.VarCreate.prototype.toJson=function(){var e=t.Events.VarCreate.superClass_.toJson.call(this);return e.varType=this.varType,e.varName=this.varName,e},t.Events.VarCreate.prototype.fromJson=function(e){t.Events.VarCreate.superClass_.fromJson.call(this,e),this.varType=e.varType,this.varName=e.varName},t.Events.VarCreate.prototype.run=function(t){var e=this.getEventWorkspace_();t?e.createVariable(this.varName,this.varType,this.varId):e.deleteVariableById(this.varId)},t.Events.VarDelete=function(e){e&&(t.Events.VarDelete.superClass_.constructor.call(this,e),this.varType=e.type,this.varName=e.name)},t.utils.object.inherits(t.Events.VarDelete,t.Events.VarBase),t.Events.VarDelete.prototype.type=t.Events.VAR_DELETE,t.Events.VarDelete.prototype.toJson=function(){var e=t.Events.VarDelete.superClass_.toJson.call(this);return e.varType=this.varType,e.varName=this.varName,e},t.Events.VarDelete.prototype.fromJson=function(e){t.Events.VarDelete.superClass_.fromJson.call(this,e),this.varType=e.varType,this.varName=e.varName},t.Events.VarDelete.prototype.run=function(t){var e=this.getEventWorkspace_();t?e.deleteVariableById(this.varId):e.createVariable(this.varName,this.varType,this.varId)},t.Events.VarRename=function(e,o){e&&(t.Events.VarRename.superClass_.constructor.call(this,e),this.oldName=e.name,this.newName=o)},t.utils.object.inherits(t.Events.VarRename,t.Events.VarBase),t.Events.VarRename.prototype.type=t.Events.VAR_RENAME,t.Events.VarRename.prototype.toJson=function(){var e=t.Events.VarRename.superClass_.toJson.call(this);return e.oldName=this.oldName,e.newName=this.newName,e},t.Events.VarRename.prototype.fromJson=function(e){t.Events.VarRename.superClass_.fromJson.call(this,e),this.oldName=e.oldName,this.newName=e.newName},t.Events.VarRename.prototype.run=function(t){var e=this.getEventWorkspace_();t?e.renameVariableById(this.varId,this.newName):e.renameVariableById(this.varId,this.oldName)},t.Xml={},t.Xml.workspaceToDom=function(e,o){var i=t.utils.xml.createElement("xml"),n=t.Xml.variablesToDom(t.Variables.allUsedVarModels(e));n.hasChildNodes()&&i.appendChild(n);var s,r=e.getTopComments(!0);for(n=0;s=r[n];n++)i.appendChild(s.toXmlWithXY(o));for(e=e.getTopBlocks(!0),n=0;r=e[n];n++)i.appendChild(t.Xml.blockToDomWithXY(r,o));return i},t.Xml.variablesToDom=function(e){for(var o,i=t.utils.xml.createElement("variables"),n=0;o=e[n];n++){var s=t.utils.xml.createElement("variable");s.appendChild(t.utils.xml.createTextNode(o.name)),o.type&&s.setAttribute("type",o.type),s.id=o.getId(),i.appendChild(s)}return i},t.Xml.blockToDomWithXY=function(e,o){var i;e.workspace.RTL&&(i=e.workspace.getWidth()),o=t.Xml.blockToDom(e,o);var n=e.getRelativeToSurfaceXY();return o.setAttribute("x",Math.round(e.workspace.RTL?i-n.x:n.x)),o.setAttribute("y",Math.round(n.y)),o},t.Xml.fieldToDom_=function(e){if(e.isSerializable()){var o=t.utils.xml.createElement("field");return o.setAttribute("name",e.name||""),e.toXml(o)}return null},t.Xml.allFieldsToDom_=function(e,o){for(var i,n=0;i=e.inputList[n];n++)for(var s,r=0;s=i.fieldRow[r];r++)(s=t.Xml.fieldToDom_(s))&&o.appendChild(s)},t.Xml.blockToDom=function(e,o){var i=t.utils.xml.createElement(e.isShadow()?"shadow":"block");if(i.setAttribute("type",e.type),o||i.setAttribute("id",e.id),e.mutationToDom){var n=e.mutationToDom();n&&(n.hasChildNodes()||n.hasAttributes())&&i.appendChild(n)}if(t.Xml.allFieldsToDom_(e,i),n=e.getCommentText()){var s=e.commentModel.size,r=e.commentModel.pinned,a=t.utils.xml.createElement("comment");a.appendChild(t.utils.xml.createTextNode(n)),a.setAttribute("pinned",r),a.setAttribute("h",s.height),a.setAttribute("w",s.width),i.appendChild(a)}for(e.data&&((n=t.utils.xml.createElement("data")).appendChild(t.utils.xml.createTextNode(e.data)),i.appendChild(n)),s=0;r=e.inputList[s];s++){var l;if(a=!0,r.type!=t.DUMMY_INPUT){var c=r.connection.targetBlock();r.type==t.INPUT_VALUE?l=t.utils.xml.createElement("value"):r.type==t.NEXT_STATEMENT&&(l=t.utils.xml.createElement("statement")),!(n=r.connection.getShadowDom())||c&&c.isShadow()||l.appendChild(t.Xml.cloneShadow_(n,o)),c&&(l.appendChild(t.Xml.blockToDom(c,o)),a=!1),l.setAttribute("name",r.name),a||i.appendChild(l)}}return null!=e.inputsInline&&e.inputsInline!=e.inputsInlineDefault&&i.setAttribute("inline",e.inputsInline),e.isCollapsed()&&i.setAttribute("collapsed",!0),e.isEnabled()||i.setAttribute("disabled",!0),e.isDeletable()||e.isShadow()||i.setAttribute("deletable",!1),e.isMovable()||e.isShadow()||i.setAttribute("movable",!1),e.isEditable()||i.setAttribute("editable",!1),(s=e.getNextBlock())&&((l=t.utils.xml.createElement("next")).appendChild(t.Xml.blockToDom(s,o)),i.appendChild(l)),!(n=e.nextConnection&&e.nextConnection.getShadowDom())||s&&s.isShadow()||l.appendChild(t.Xml.cloneShadow_(n,o)),i},t.Xml.cloneShadow_=function(e,o){for(var i,n=e=e.cloneNode(!0);n;)if(o&&"shadow"==n.nodeName&&n.removeAttribute("id"),n.firstChild)n=n.firstChild;else{for(;n&&!n.nextSibling;)i=n,n=n.parentNode,i.nodeType==t.utils.dom.Node.TEXT_NODE&&""==i.data.trim()&&n.firstChild!=i&&t.utils.dom.removeNode(i);n&&(i=n,n=n.nextSibling,i.nodeType==t.utils.dom.Node.TEXT_NODE&&""==i.data.trim()&&t.utils.dom.removeNode(i))}return e},t.Xml.domToText=function(e){e=t.utils.xml.domToText(e);var o=/(<[^/](?:[^>]*[^/])?>[^<]*)\n([^<]*<\/)/;do{var i=e;e=e.replace(o,"$1 $2")}while(e!=i);return e.replace(/<(\w+)([^<]*)\/>/g,"<$1$2>")},t.Xml.domToPrettyText=function(e){e=t.Xml.domToText(e).split("<");for(var o="",i=1;i"!=n.slice(-2)&&(o+=" ")}return(e=(e=e.join("\n")).replace(/(<(\w+)\b[^>]*>[^\n]*)\n *<\/\2>/g,"$1")).replace(/^\n/,"")},t.Xml.textToDom=function(e){var o=t.utils.xml.textToDomDocument(e);if(!o||!o.documentElement||o.getElementsByTagName("parsererror").length)throw Error("textToDom was unable to parse: "+e);return o.documentElement},t.Xml.clearWorkspaceAndLoadFromXml=function(e,o){return o.setResizesEnabled(!1),o.clear(),e=t.Xml.domToWorkspace(e,o),o.setResizesEnabled(!0),e},t.Xml.domToWorkspace=function(e,o){if(e instanceof t.Workspace){var i=e;e=o,o=i,console.warn("Deprecated call to Blockly.Xml.domToWorkspace, swap the arguments.")}var n;o.RTL&&(n=o.getWidth()),i=[],t.utils.dom.startTextWidthCache();var s=t.Events.getGroup();s||t.Events.setGroup(!0),o.setResizesEnabled&&o.setResizesEnabled(!1);var r=!0;try{for(var a,l=0;a=e.childNodes[l];l++){var c=a.nodeName.toLowerCase(),h=a;if("block"==c||"shadow"==c&&!t.Events.recordUndo){var u=t.Xml.domToBlock(h,o);i.push(u.id);var p=h.hasAttribute("x")?parseInt(h.getAttribute("x"),10):10,_=h.hasAttribute("y")?parseInt(h.getAttribute("y"),10):10;isNaN(p)||isNaN(_)||u.moveBy(o.RTL?n-p:p,_),r=!1}else{if("shadow"==c)throw TypeError("Shadow block cannot be a top-level block.");if("comment"==c)o.rendered?t.WorkspaceCommentSvg?t.WorkspaceCommentSvg.fromXml(h,o,n):console.warn("Missing require for Blockly.WorkspaceCommentSvg, ignoring workspace comment."):t.WorkspaceComment?t.WorkspaceComment.fromXml(h,o):console.warn("Missing require for Blockly.WorkspaceComment, ignoring workspace comment.");else if("variables"==c){if(!r)throw Error("'variables' tag must exist once before block and shadow tag elements in the workspace XML, but it was found in another location.");t.Xml.domToVariables(h,o),r=!1}}}}finally{s||t.Events.setGroup(!1),t.utils.dom.stopTextWidthCache()}return o.setResizesEnabled&&o.setResizesEnabled(!0),t.Events.fire(new t.Events.FinishedLoading(o)),i},t.Xml.appendDomToWorkspace=function(e,o){var i;if(o.hasOwnProperty("scale")&&(i=o.getBlocksBoundingBox()),e=t.Xml.domToWorkspace(e,o),i&&i.top!=i.bottom){var n=i.bottom,s=o.RTL?i.right:i.left,r=1/0,a=-1/0,l=1/0;for(i=0;ia&&(a=c.x)}for(n=n-l+10,s=o.RTL?s-a:s-r,i=0;i document.")}else e=null;return e},t.Touch={},t.Touch.TOUCH_ENABLED="ontouchstart"in t.utils.global||!!(t.utils.global.document&&document.documentElement&&"ontouchstart"in document.documentElement)||!(!t.utils.global.navigator||!t.utils.global.navigator.maxTouchPoints&&!t.utils.global.navigator.msMaxTouchPoints),t.Touch.touchIdentifier_=null,t.Touch.TOUCH_MAP={},t.utils.global.PointerEvent?t.Touch.TOUCH_MAP={mousedown:["pointerdown"],mouseenter:["pointerenter"],mouseleave:["pointerleave"],mousemove:["pointermove"],mouseout:["pointerout"],mouseover:["pointerover"],mouseup:["pointerup","pointercancel"],touchend:["pointerup"],touchcancel:["pointercancel"]}:t.Touch.TOUCH_ENABLED&&(t.Touch.TOUCH_MAP={mousedown:["touchstart"],mousemove:["touchmove"],mouseup:["touchend","touchcancel"]}),t.longPid_=0,t.longStart=function(e,o){t.longStop_(),e.changedTouches&&1!=e.changedTouches.length||(t.longPid_=setTimeout((function(){e.changedTouches&&(e.button=2,e.clientX=e.changedTouches[0].clientX,e.clientY=e.changedTouches[0].clientY),o&&o.handleRightClick(e)}),t.LONGPRESS))},t.longStop_=function(){t.longPid_&&(clearTimeout(t.longPid_),t.longPid_=0)},t.Touch.clearTouchIdentifier=function(){t.Touch.touchIdentifier_=null},t.Touch.shouldHandleEvent=function(e){return!t.Touch.isMouseOrTouchEvent(e)||t.Touch.checkTouchIdentifier(e)},t.Touch.getTouchIdentifierFromEvent=function(t){return null!=t.pointerId?t.pointerId:t.changedTouches&&t.changedTouches[0]&&void 0!==t.changedTouches[0].identifier&&null!==t.changedTouches[0].identifier?t.changedTouches[0].identifier:"mouse"},t.Touch.checkTouchIdentifier=function(e){var o=t.Touch.getTouchIdentifierFromEvent(e);return void 0!==t.Touch.touchIdentifier_&&null!==t.Touch.touchIdentifier_?t.Touch.touchIdentifier_==o:("mousedown"==e.type||"touchstart"==e.type||"pointerdown"==e.type)&&(t.Touch.touchIdentifier_=o,!0)},t.Touch.setClientFromTouch=function(e){if(t.utils.string.startsWith(e.type,"touch")){var o=e.changedTouches[0];e.clientX=o.clientX,e.clientY=o.clientY}},t.Touch.isMouseOrTouchEvent=function(e){return t.utils.string.startsWith(e.type,"touch")||t.utils.string.startsWith(e.type,"mouse")||t.utils.string.startsWith(e.type,"pointer")},t.Touch.isTouchEvent=function(e){return t.utils.string.startsWith(e.type,"touch")||t.utils.string.startsWith(e.type,"pointer")},t.Touch.splitEventByTouches=function(t){var e=[];if(t.changedTouches)for(var o=0;o=i+this.handleLength_&&(n+=s),this.setHandlePosition(this.constrainHandle_(n)),this.onScroll_(),e.stopPropagation(),e.preventDefault()}},t.Scrollbar.prototype.onMouseDownHandle_=function(e){this.workspace_.markFocused(),this.cleanUp_(),t.utils.isRightButton(e)?e.stopPropagation():(this.startDragHandle=this.handlePosition_,this.workspace_.setupDragSurface(),this.startDragMouse_=this.horizontal_?e.clientX:e.clientY,t.Scrollbar.onMouseUpWrapper_=t.bindEventWithChecks_(document,"mouseup",this,this.onMouseUpHandle_),t.Scrollbar.onMouseMoveWrapper_=t.bindEventWithChecks_(document,"mousemove",this,this.onMouseMoveHandle_),e.stopPropagation(),e.preventDefault())},t.Scrollbar.prototype.onMouseMoveHandle_=function(t){this.setHandlePosition(this.constrainHandle_(this.startDragHandle+((this.horizontal_?t.clientX:t.clientY)-this.startDragMouse_))),this.onScroll_()},t.Scrollbar.prototype.onMouseUpHandle_=function(){this.workspace_.resetDragSurface(),t.Touch.clearTouchIdentifier(),this.cleanUp_()},t.Scrollbar.prototype.cleanUp_=function(){t.hideChaff(!0),t.Scrollbar.onMouseUpWrapper_&&(t.unbindEvent_(t.Scrollbar.onMouseUpWrapper_),t.Scrollbar.onMouseUpWrapper_=null),t.Scrollbar.onMouseMoveWrapper_&&(t.unbindEvent_(t.Scrollbar.onMouseMoveWrapper_),t.Scrollbar.onMouseMoveWrapper_=null)},t.Scrollbar.prototype.constrainHandle_=function(t){return 0>=t||isNaN(t)||this.scrollViewSize_t.Tooltip.RADIUS_OK&&t.Tooltip.hide()}else t.Tooltip.poisonedElement_!=t.Tooltip.element_&&(clearTimeout(t.Tooltip.showPid_),t.Tooltip.lastX_=e.pageX,t.Tooltip.lastY_=e.pageY,t.Tooltip.showPid_=setTimeout(t.Tooltip.show_,t.Tooltip.HOVER_MS))},t.Tooltip.dispose=function(){t.Tooltip.element_=null,t.Tooltip.poisonedElement_=null,t.Tooltip.hide()},t.Tooltip.hide=function(){t.Tooltip.visible&&(t.Tooltip.visible=!1,t.Tooltip.DIV&&(t.Tooltip.DIV.style.display="none")),t.Tooltip.showPid_&&clearTimeout(t.Tooltip.showPid_)},t.Tooltip.block=function(){t.Tooltip.hide(),t.Tooltip.blocked_=!0},t.Tooltip.unblock=function(){t.Tooltip.blocked_=!1},t.Tooltip.show_=function(){if(!t.Tooltip.blocked_&&(t.Tooltip.poisonedElement_=t.Tooltip.element_,t.Tooltip.DIV)){t.Tooltip.DIV.textContent="";for(var e=t.Tooltip.element_.tooltip;"function"==typeof e;)e=e();e=(e=t.utils.string.wrap(e,t.Tooltip.LIMIT)).split("\n");for(var o=0;oi+window.scrollY&&(s-=t.Tooltip.DIV.offsetHeight+2*t.Tooltip.OFFSET_Y),e?n=Math.max(t.Tooltip.MARGINS-window.scrollX,n):n+t.Tooltip.DIV.offsetWidth>o+window.scrollX-2*t.Tooltip.MARGINS&&(n=o-t.Tooltip.DIV.offsetWidth-2*t.Tooltip.MARGINS),t.Tooltip.DIV.style.top=s+"px",t.Tooltip.DIV.style.left=n+"px"}},t.WorkspaceDragSurfaceSvg=function(t){this.container_=t,this.createDom()},t.WorkspaceDragSurfaceSvg.prototype.SVG_=null,t.WorkspaceDragSurfaceSvg.prototype.dragGroup_=null,t.WorkspaceDragSurfaceSvg.prototype.container_=null,t.WorkspaceDragSurfaceSvg.prototype.createDom=function(){this.SVG_||(this.SVG_=t.utils.dom.createSvgElement("svg",{xmlns:t.utils.dom.SVG_NS,"xmlns:html":t.utils.dom.HTML_NS,"xmlns:xlink":t.utils.dom.XLINK_NS,version:"1.1",class:"blocklyWsDragSurface blocklyOverflowVisible"},null),this.container_.appendChild(this.SVG_))},t.WorkspaceDragSurfaceSvg.prototype.translateSurface=function(e,o){e=e.toFixed(0),o=o.toFixed(0),this.SVG_.style.display="block",t.utils.dom.setCssTransform(this.SVG_,"translate3d("+e+"px, "+o+"px, 0px)")},t.WorkspaceDragSurfaceSvg.prototype.getSurfaceTranslation=function(){return t.utils.getRelativeXY(this.SVG_)},t.WorkspaceDragSurfaceSvg.prototype.clearAndHide=function(e){if(!e)throw Error("Couldn't clear and hide the drag surface: missing new surface.");var o=this.SVG_.childNodes[0],i=this.SVG_.childNodes[1];if(!(o&&i&&t.utils.dom.hasClass(o,"blocklyBlockCanvas")&&t.utils.dom.hasClass(i,"blocklyBubbleCanvas")))throw Error("Couldn't clear and hide the drag surface. A node was missing.");if(null!=this.previousSibling_?t.utils.dom.insertAfter(o,this.previousSibling_):e.insertBefore(o,e.firstChild),t.utils.dom.insertAfter(i,o),this.SVG_.style.display="none",this.SVG_.childNodes.length)throw Error("Drag surface was not cleared.");t.utils.dom.setCssTransform(this.SVG_,""),this.previousSibling_=null},t.WorkspaceDragSurfaceSvg.prototype.setContentsAndShow=function(t,e,o,i,n,s){if(this.SVG_.childNodes.length)throw Error("Already dragging a block.");this.previousSibling_=o,t.setAttribute("transform","translate(0, 0) scale("+s+")"),e.setAttribute("transform","translate(0, 0) scale("+s+")"),this.SVG_.setAttribute("width",i),this.SVG_.setAttribute("height",n),this.SVG_.appendChild(t),this.SVG_.appendChild(e),this.SVG_.style.display="block"},t.ASTNode=function(e,o,i){if(!o)throw Error("Cannot create a node without a location.");this.type_=e,this.isConnection_=t.ASTNode.isConnectionType_(e),this.location_=o,this.processParams_(i||null)},t.ASTNode.types={FIELD:"field",BLOCK:"block",INPUT:"input",OUTPUT:"output",NEXT:"next",PREVIOUS:"previous",STACK:"stack",WORKSPACE:"workspace"},t.ASTNode.NAVIGATE_ALL_FIELDS=!1,t.ASTNode.DEFAULT_OFFSET_Y=-20,t.ASTNode.isConnectionType_=function(e){switch(e){case t.ASTNode.types.PREVIOUS:case t.ASTNode.types.NEXT:case t.ASTNode.types.INPUT:case t.ASTNode.types.OUTPUT:return!0}return!1},t.ASTNode.createFieldNode=function(e){return e?new t.ASTNode(t.ASTNode.types.FIELD,e):null},t.ASTNode.createConnectionNode=function(e){return e?e.type==t.INPUT_VALUE||e.type==t.NEXT_STATEMENT&&e.getParentInput()?t.ASTNode.createInputNode(e.getParentInput()):e.type==t.NEXT_STATEMENT?new t.ASTNode(t.ASTNode.types.NEXT,e):e.type==t.OUTPUT_VALUE?new t.ASTNode(t.ASTNode.types.OUTPUT,e):e.type==t.PREVIOUS_STATEMENT?new t.ASTNode(t.ASTNode.types.PREVIOUS,e):null:null},t.ASTNode.createInputNode=function(e){return e&&e.connection?new t.ASTNode(t.ASTNode.types.INPUT,e.connection):null},t.ASTNode.createBlockNode=function(e){return e?new t.ASTNode(t.ASTNode.types.BLOCK,e):null},t.ASTNode.createStackNode=function(e){return e?new t.ASTNode(t.ASTNode.types.STACK,e):null},t.ASTNode.createWorkspaceNode=function(e,o){return o&&e?new t.ASTNode(t.ASTNode.types.WORKSPACE,e,{wsCoordinate:o}):null},t.ASTNode.prototype.processParams_=function(t){t&&t.wsCoordinate&&(this.wsCoordinate_=t.wsCoordinate)},t.ASTNode.prototype.getLocation=function(){return this.location_},t.ASTNode.prototype.getType=function(){return this.type_},t.ASTNode.prototype.getWsCoordinate=function(){return this.wsCoordinate_},t.ASTNode.prototype.isConnection=function(){return this.isConnection_},t.ASTNode.prototype.findNextForInput_=function(){var e,o=this.location_.getParentInput(),i=o.getSourceBlock();for(o=i.inputList.indexOf(o)+1;e=i.inputList[o];o++){for(var n,s=e.fieldRow,r=0;n=s[r];r++)if(n.isClickable()||t.ASTNode.NAVIGATE_ALL_FIELDS)return t.ASTNode.createFieldNode(n);if(e.connection)return t.ASTNode.createInputNode(e)}return null},t.ASTNode.prototype.findNextForField_=function(){var e=this.location_,o=e.getParentInput(),i=e.getSourceBlock(),n=i.inputList.indexOf(o);for(e=o.fieldRow.indexOf(e)+1;o=i.inputList[n];n++){for(var s=o.fieldRow;ei)){var n=o.getSvgXY(e.getSvgRoot());e.outputConnection?(n.x+=(e.RTL?3:-3)*i,n.y+=13*i):e.previousConnection&&(n.x+=(e.RTL?-23:23)*i,n.y+=3*i),e=t.utils.dom.createSvgElement("circle",{cx:n.x,cy:n.y,r:0,fill:"none",stroke:"#888","stroke-width":10},o.getParentSvg()),t.blockAnimations.connectionUiStep_(e,new Date,i)}},t.blockAnimations.connectionUiStep_=function(e,o,i){var n=(new Date-o)/150;1e.workspace.scale)){var o=e.getHeightWidth().height;o=Math.atan(10/o)/Math.PI*180,e.RTL||(o*=-1),t.blockAnimations.disconnectUiStep_(e.getSvgRoot(),o,new Date)}},t.blockAnimations.disconnectUiStep_=function(e,o,i){var n=(new Date-i)/200;1o-t.CURRENT_CONNECTION_PREFERENCE)):!this.localConnection_&&!this.closestConnection_||(console.error("Only one of localConnection_ and closestConnection_ was set."),console.error("Returning true from shouldUpdatePreviews, but it's not clear why."),!0):!(!this.localConnection_||!this.closestConnection_)},t.InsertionMarkerManager.prototype.getCandidate_=function(t){for(var e=this.getStartRadius_(),o=null,i=null,n=0;nthis.remainingCapacityOfType(e))return!1;o+=t[e]}return!(o>this.remainingCapacity())},t.Workspace.prototype.hasBlockLimits=function(){return 1/0!=this.options.maxBlocks||!!this.options.maxInstances},t.Workspace.prototype.undo=function(e){var o=e?this.redoStack_:this.undoStack_,i=e?this.undoStack_:this.redoStack_,n=o.pop();if(n){for(var s=[n];o.length&&n.group&&n.group==o[o.length-1].group;)s.push(o.pop());for(o=0;n=s[o];o++)i.push(n);s=t.Events.filter(s,e),t.Events.recordUndo=!1;try{for(o=0;n=s[o];o++)n.run(e)}finally{t.Events.recordUndo=!0}}},t.Workspace.prototype.clearUndo=function(){this.undoStack_.length=0,this.redoStack_.length=0,t.Events.clearPendingUndo()},t.Workspace.prototype.addChangeListener=function(t){return this.listeners_.push(t),t},t.Workspace.prototype.removeChangeListener=function(e){t.utils.arrayRemove(this.listeners_,e)},t.Workspace.prototype.fireChangeListener=function(t){if(t.recordUndo)for(this.undoStack_.push(t),this.redoStack_.length=0;this.undoStack_.length>this.MAX_UNDO&&0<=this.MAX_UNDO;)this.undoStack_.shift();for(var e,o=0;e=this.listeners_[o];o++)e(t)},t.Workspace.prototype.getBlockById=function(t){return this.blockDB_[t]||null},t.Workspace.prototype.setBlockById=function(t,e){this.blockDB_[t]=e},t.Workspace.prototype.removeBlockById=function(t){delete this.blockDB_[t]},t.Workspace.prototype.getCommentById=function(t){return this.commentDB_[t]||null},t.Workspace.prototype.allInputsFilled=function(t){for(var e,o=this.getTopBlocks(!1),i=0;e=o[i];i++)if(!e.allInputsFilled(t))return!1;return!0},t.Workspace.prototype.getPotentialVariableMap=function(){return this.potentialVariableMap_},t.Workspace.prototype.createPotentialVariableMap=function(){this.potentialVariableMap_=new t.VariableMap(this)},t.Workspace.prototype.getVariableMap=function(){return this.variableMap_},t.Workspace.prototype.setVariableMap=function(t){this.variableMap_=t},t.Workspace.WorkspaceDB_=Object.create(null),t.Workspace.getById=function(e){return t.Workspace.WorkspaceDB_[e]||null},t.Workspace.getAll=function(){var e,o=[];for(e in t.Workspace.WorkspaceDB_)o.push(t.Workspace.WorkspaceDB_[e]);return o},t.Bubble=function(e,o,i,n,s,r){this.workspace_=e,this.content_=o,this.shape_=i,this.onMouseDownResizeWrapper_=this.onMouseDownBubbleWrapper_=this.moveCallback_=this.resizeCallback_=null,this.disposed=!1,i=t.Bubble.ARROW_ANGLE,this.workspace_.RTL&&(i=-i),this.arrow_radians_=t.utils.math.toRadians(i),e.getBubbleCanvas().appendChild(this.createDom_(o,!(!s||!r))),this.setAnchorLocation(n),s&&r||(s=(e=this.content_.getBBox()).width+2*t.Bubble.BORDER_WIDTH,r=e.height+2*t.Bubble.BORDER_WIDTH),this.setBubbleSize(s,r),this.positionBubble_(),this.renderArrow_(),this.rendered_=!0},t.Bubble.BORDER_WIDTH=6,t.Bubble.ARROW_THICKNESS=5,t.Bubble.ARROW_ANGLE=20,t.Bubble.ARROW_BEND=4,t.Bubble.ANCHOR_RADIUS=8,t.Bubble.onMouseUpWrapper_=null,t.Bubble.onMouseMoveWrapper_=null,t.Bubble.unbindDragEvents_=function(){t.Bubble.onMouseUpWrapper_&&(t.unbindEvent_(t.Bubble.onMouseUpWrapper_),t.Bubble.onMouseUpWrapper_=null),t.Bubble.onMouseMoveWrapper_&&(t.unbindEvent_(t.Bubble.onMouseMoveWrapper_),t.Bubble.onMouseMoveWrapper_=null)},t.Bubble.bubbleMouseUp_=function(e){t.Touch.clearTouchIdentifier(),t.Bubble.unbindDragEvents_()},t.Bubble.prototype.rendered_=!1,t.Bubble.prototype.anchorXY_=null,t.Bubble.prototype.relativeLeft_=0,t.Bubble.prototype.relativeTop_=0,t.Bubble.prototype.width_=0,t.Bubble.prototype.height_=0,t.Bubble.prototype.autoLayout_=!0,t.Bubble.prototype.createDom_=function(e,o){this.bubbleGroup_=t.utils.dom.createSvgElement("g",{},null);var i={filter:"url(#"+this.workspace_.getRenderer().getConstants().embossFilterId+")"};return t.utils.userAgent.JAVA_FX&&(i={}),i=t.utils.dom.createSvgElement("g",i,this.bubbleGroup_),this.bubbleArrow_=t.utils.dom.createSvgElement("path",{},i),this.bubbleBack_=t.utils.dom.createSvgElement("rect",{class:"blocklyDraggable",x:0,y:0,rx:t.Bubble.BORDER_WIDTH,ry:t.Bubble.BORDER_WIDTH},i),o?(this.resizeGroup_=t.utils.dom.createSvgElement("g",{class:this.workspace_.RTL?"blocklyResizeSW":"blocklyResizeSE"},this.bubbleGroup_),o=2*t.Bubble.BORDER_WIDTH,t.utils.dom.createSvgElement("polygon",{points:"0,x x,x x,0".replace(/x/g,o.toString())},this.resizeGroup_),t.utils.dom.createSvgElement("line",{class:"blocklyResizeLine",x1:o/3,y1:o-1,x2:o-1,y2:o/3},this.resizeGroup_),t.utils.dom.createSvgElement("line",{class:"blocklyResizeLine",x1:2*o/3,y1:o-1,x2:o-1,y2:2*o/3},this.resizeGroup_)):this.resizeGroup_=null,this.workspace_.options.readOnly||(this.onMouseDownBubbleWrapper_=t.bindEventWithChecks_(this.bubbleBack_,"mousedown",this,this.bubbleMouseDown_),this.resizeGroup_&&(this.onMouseDownResizeWrapper_=t.bindEventWithChecks_(this.resizeGroup_,"mousedown",this,this.resizeMouseDown_))),this.bubbleGroup_.appendChild(e),this.bubbleGroup_},t.Bubble.prototype.getSvgRoot=function(){return this.bubbleGroup_},t.Bubble.prototype.setSvgId=function(t){this.bubbleGroup_.dataset&&(this.bubbleGroup_.dataset.blockId=t)},t.Bubble.prototype.bubbleMouseDown_=function(t){var e=this.workspace_.getGesture(t);e&&e.handleBubbleStart(t,this)},t.Bubble.prototype.showContextMenu=function(t){},t.Bubble.prototype.isDeletable=function(){return!1},t.Bubble.prototype.resizeMouseDown_=function(e){this.promote(),t.Bubble.unbindDragEvents_(),t.utils.isRightButton(e)||(this.workspace_.startDrag(e,new t.utils.Coordinate(this.workspace_.RTL?-this.width_:this.width_,this.height_)),t.Bubble.onMouseUpWrapper_=t.bindEventWithChecks_(document,"mouseup",this,t.Bubble.bubbleMouseUp_),t.Bubble.onMouseMoveWrapper_=t.bindEventWithChecks_(document,"mousemove",this,this.resizeMouseMove_),t.hideChaff()),e.stopPropagation()},t.Bubble.prototype.resizeMouseMove_=function(t){this.autoLayout_=!1,t=this.workspace_.moveDrag(t),this.setBubbleSize(this.workspace_.RTL?-t.x:t.x,t.y),this.workspace_.RTL&&this.positionBubble_()},t.Bubble.prototype.registerResizeEvent=function(t){this.resizeCallback_=t},t.Bubble.prototype.registerMoveEvent=function(t){this.moveCallback_=t},t.Bubble.prototype.promote=function(){var t=this.bubbleGroup_.parentNode;return t.lastChild!==this.bubbleGroup_&&(t.appendChild(this.bubbleGroup_),!0)},t.Bubble.prototype.setAnchorLocation=function(t){this.anchorXY_=t,this.rendered_&&this.positionBubble_()},t.Bubble.prototype.layoutBubble_=function(){var t=this.workspace_.getMetrics();t.viewLeft/=this.workspace_.scale,t.viewWidth/=this.workspace_.scale,t.viewTop/=this.workspace_.scale,t.viewHeight/=this.workspace_.scale;var e=this.getOptimalRelativeLeft_(t),o=this.getOptimalRelativeTop_(t),i=this.shape_.getBBox(),n={x:e,y:-this.height_-this.workspace_.getRenderer().getConstants().MIN_BLOCK_HEIGHT},s={x:-this.width_-30,y:o};o={x:i.width,y:o};var r={x:e,y:i.height};e=i.widthe.viewWidth)return o;if(this.workspace_.RTL)var i=this.anchorXY_.x-o,n=i-this.width_,s=e.viewLeft+e.viewWidth,r=e.viewLeft+t.Scrollbar.scrollbarThickness/this.workspace_.scale;else i=(n=o+this.anchorXY_.x)+this.width_,r=e.viewLeft,s=e.viewLeft+e.viewWidth-t.Scrollbar.scrollbarThickness/this.workspace_.scale;return this.workspace_.RTL?ns&&(o=-(s-this.anchorXY_.x)):ns&&(o=s-this.anchorXY_.x-this.width_),o},t.Bubble.prototype.getOptimalRelativeTop_=function(e){var o=-this.height_/4;if(this.height_>e.viewHeight)return o;var i=this.anchorXY_.y+o,n=i+this.height_,s=e.viewTop;e=e.viewTop+e.viewHeight-t.Scrollbar.scrollbarThickness/this.workspace_.scale;var r=this.anchorXY_.y;return ie&&(o=e-r-this.height_),o},t.Bubble.prototype.positionBubble_=function(){var t=this.anchorXY_.x;t=this.workspace_.RTL?t-(this.relativeLeft_+this.width_):t+this.relativeLeft_,this.moveTo(t,this.relativeTop_+this.anchorXY_.y)},t.Bubble.prototype.moveTo=function(t,e){this.bubbleGroup_.setAttribute("transform","translate("+t+","+e+")")},t.Bubble.prototype.setDragging=function(t){!t&&this.moveCallback_&&this.moveCallback_()},t.Bubble.prototype.getBubbleSize=function(){return new t.utils.Size(this.width_,this.height_)},t.Bubble.prototype.setBubbleSize=function(e,o){var i=2*t.Bubble.BORDER_WIDTH;e=Math.max(e,i+45),o=Math.max(o,i+20),this.width_=e,this.height_=o,this.bubbleBack_.setAttribute("width",e),this.bubbleBack_.setAttribute("height",o),this.resizeGroup_&&(this.workspace_.RTL?this.resizeGroup_.setAttribute("transform","translate("+2*t.Bubble.BORDER_WIDTH+","+(o-i)+") scale(-1 1)"):this.resizeGroup_.setAttribute("transform","translate("+(e-i)+","+(o-i)+")")),this.autoLayout_&&this.layoutBubble_(),this.positionBubble_(),this.renderArrow_(),this.resizeCallback_&&this.resizeCallback_()},t.Bubble.prototype.renderArrow_=function(){var e=[],o=this.width_/2,i=this.height_/2,n=-this.relativeLeft_,s=-this.relativeTop_;if(o==n&&i==s)e.push("M "+o+","+i);else{s-=i,n-=o,this.workspace_.RTL&&(n*=-1);var r=Math.sqrt(s*s+n*n),a=Math.acos(n/r);0>s&&(a=2*Math.PI-a);var l=a+Math.PI/2;l>2*Math.PI&&(l-=2*Math.PI);var c=Math.sin(l),h=Math.cos(l),u=this.getBubbleSize();l=(u.width+u.height)/t.Bubble.ARROW_THICKNESS,l=Math.min(l,u.width,u.height)/4,n=o+(u=1-t.Bubble.ANCHOR_RADIUS/r)*n,s=i+u*s,u=o+l*h;var p=i+l*c;o-=l*h,i-=l*c,(c=a+this.arrow_radians_)>2*Math.PI&&(c-=2*Math.PI),a=Math.sin(c)*r/t.Bubble.ARROW_BEND,r=Math.cos(c)*r/t.Bubble.ARROW_BEND,e.push("M"+u+","+p),e.push("C"+(u+r)+","+(p+a)+" "+n+","+s+" "+n+","+s),e.push("C"+n+","+s+" "+(o+r)+","+(i+a)+" "+o+","+i)}e.push("z"),this.bubbleArrow_.setAttribute("d",e.join(" "))},t.Bubble.prototype.setColour=function(t){this.bubbleBack_.setAttribute("fill",t),this.bubbleArrow_.setAttribute("fill",t)},t.Bubble.prototype.dispose=function(){this.onMouseDownBubbleWrapper_&&t.unbindEvent_(this.onMouseDownBubbleWrapper_),this.onMouseDownResizeWrapper_&&t.unbindEvent_(this.onMouseDownResizeWrapper_),t.Bubble.unbindDragEvents_(),t.utils.dom.removeNode(this.bubbleGroup_),this.disposed=!0},t.Bubble.prototype.moveDuringDrag=function(t,e){t?t.translateSurface(e.x,e.y):this.moveTo(e.x,e.y),this.relativeLeft_=this.workspace_.RTL?this.anchorXY_.x-e.x-this.width_:e.x-this.anchorXY_.x,this.relativeTop_=e.y-this.anchorXY_.y,this.renderArrow_()},t.Bubble.prototype.getRelativeToSurfaceXY=function(){return new t.utils.Coordinate(this.workspace_.RTL?-this.relativeLeft_+this.anchorXY_.x-this.width_:this.anchorXY_.x+this.relativeLeft_,this.anchorXY_.y+this.relativeTop_)},t.Bubble.prototype.setAutoLayout=function(t){this.autoLayout_=t},t.Events.CommentBase=function(e){this.commentId=e.id,this.workspaceId=e.workspace.id,this.group=t.Events.getGroup(),this.recordUndo=t.Events.recordUndo},t.utils.object.inherits(t.Events.CommentBase,t.Events.Abstract),t.Events.CommentBase.prototype.toJson=function(){var e=t.Events.CommentBase.superClass_.toJson.call(this);return this.commentId&&(e.commentId=this.commentId),e},t.Events.CommentBase.prototype.fromJson=function(e){t.Events.CommentBase.superClass_.fromJson.call(this,e),this.commentId=e.commentId},t.Events.CommentChange=function(e,o,i){e&&(t.Events.CommentChange.superClass_.constructor.call(this,e),this.oldContents_=o,this.newContents_=i)},t.utils.object.inherits(t.Events.CommentChange,t.Events.CommentBase),t.Events.CommentChange.prototype.type=t.Events.COMMENT_CHANGE,t.Events.CommentChange.prototype.toJson=function(){var e=t.Events.CommentChange.superClass_.toJson.call(this);return e.newContents=this.newContents_,e},t.Events.CommentChange.prototype.fromJson=function(e){t.Events.CommentChange.superClass_.fromJson.call(this,e),this.newContents_=e.newValue},t.Events.CommentChange.prototype.isNull=function(){return this.oldContents_==this.newContents_},t.Events.CommentChange.prototype.run=function(t){var e=this.getEventWorkspace_().getCommentById(this.commentId);e?e.setContent(t?this.newContents_:this.oldContents_):console.warn("Can't change non-existent comment: "+this.commentId)},t.Events.CommentCreate=function(e){e&&(t.Events.CommentCreate.superClass_.constructor.call(this,e),this.xml=e.toXmlWithXY())},t.utils.object.inherits(t.Events.CommentCreate,t.Events.CommentBase),t.Events.CommentCreate.prototype.type=t.Events.COMMENT_CREATE,t.Events.CommentCreate.prototype.toJson=function(){var e=t.Events.CommentCreate.superClass_.toJson.call(this);return e.xml=t.Xml.domToText(this.xml),e},t.Events.CommentCreate.prototype.fromJson=function(e){t.Events.CommentCreate.superClass_.fromJson.call(this,e),this.xml=t.Xml.textToDom(e.xml)},t.Events.CommentCreate.prototype.run=function(e){t.Events.CommentCreateDeleteHelper(this,e)},t.Events.CommentCreateDeleteHelper=function(e,o){var i=e.getEventWorkspace_();o?((o=t.utils.xml.createElement("xml")).appendChild(e.xml),t.Xml.domToWorkspace(o,i)):(i=i.getCommentById(e.commentId))?i.dispose(!1,!1):console.warn("Can't uncreate non-existent comment: "+e.commentId)},t.Events.CommentDelete=function(e){e&&(t.Events.CommentDelete.superClass_.constructor.call(this,e),this.xml=e.toXmlWithXY())},t.utils.object.inherits(t.Events.CommentDelete,t.Events.CommentBase),t.Events.CommentDelete.prototype.type=t.Events.COMMENT_DELETE,t.Events.CommentDelete.prototype.toJson=function(){return t.Events.CommentDelete.superClass_.toJson.call(this)},t.Events.CommentDelete.prototype.fromJson=function(e){t.Events.CommentDelete.superClass_.fromJson.call(this,e)},t.Events.CommentDelete.prototype.run=function(e){t.Events.CommentCreateDeleteHelper(this,!e)},t.Events.CommentMove=function(e){e&&(t.Events.CommentMove.superClass_.constructor.call(this,e),this.comment_=e,this.oldCoordinate_=e.getXY(),this.newCoordinate_=null)},t.utils.object.inherits(t.Events.CommentMove,t.Events.CommentBase),t.Events.CommentMove.prototype.recordNew=function(){if(!this.comment_)throw Error("Tried to record the new position of a comment on the same event twice.");this.newCoordinate_=this.comment_.getXY(),this.comment_=null},t.Events.CommentMove.prototype.type=t.Events.COMMENT_MOVE,t.Events.CommentMove.prototype.setOldCoordinate=function(t){this.oldCoordinate_=t},t.Events.CommentMove.prototype.toJson=function(){var e=t.Events.CommentMove.superClass_.toJson.call(this);return this.newCoordinate_&&(e.newCoordinate=Math.round(this.newCoordinate_.x)+","+Math.round(this.newCoordinate_.y)),e},t.Events.CommentMove.prototype.fromJson=function(e){t.Events.CommentMove.superClass_.fromJson.call(this,e),e.newCoordinate&&(e=e.newCoordinate.split(","),this.newCoordinate_=new t.utils.Coordinate(Number(e[0]),Number(e[1])))},t.Events.CommentMove.prototype.isNull=function(){return t.utils.Coordinate.equals(this.oldCoordinate_,this.newCoordinate_)},t.Events.CommentMove.prototype.run=function(t){var e=this.getEventWorkspace_().getCommentById(this.commentId);if(e){t=t?this.newCoordinate_:this.oldCoordinate_;var o=e.getXY();e.moveBy(t.x-o.x,t.y-o.y)}else console.warn("Can't move non-existent comment: "+this.commentId)},t.BubbleDragger=function(e,o){this.draggingBubble_=e,this.workspace_=o,this.deleteArea_=null,this.wouldDeleteBubble_=!1,this.startXY_=this.draggingBubble_.getRelativeToSurfaceXY(),this.dragSurface_=t.utils.is3dSupported()&&o.getBlockDragSurface()?o.getBlockDragSurface():null},t.BubbleDragger.prototype.dispose=function(){this.dragSurface_=this.workspace_=this.draggingBubble_=null},t.BubbleDragger.prototype.startBubbleDrag=function(){t.Events.getGroup()||t.Events.setGroup(!0),this.workspace_.setResizesEnabled(!1),this.draggingBubble_.setAutoLayout(!1),this.dragSurface_&&this.moveToDragSurface_(),this.draggingBubble_.setDragging&&this.draggingBubble_.setDragging(!0);var e=this.workspace_.getToolbox();if(e){var o=this.draggingBubble_.isDeletable()?"blocklyToolboxDelete":"blocklyToolboxGrab";e.addStyle(o)}},t.BubbleDragger.prototype.dragBubble=function(e,o){o=this.pixelsToWorkspaceUnits_(o),o=t.utils.Coordinate.sum(this.startXY_,o),this.draggingBubble_.moveDuringDrag(this.dragSurface_,o),this.draggingBubble_.isDeletable()&&(this.deleteArea_=this.workspace_.isDeleteArea(e),this.updateCursorDuringBubbleDrag_())},t.BubbleDragger.prototype.maybeDeleteBubble_=function(){var t=this.workspace_.trashcan;return this.wouldDeleteBubble_?(t&&setTimeout(t.close.bind(t),100),this.fireMoveEvent_(),this.draggingBubble_.dispose(!1,!0)):t&&t.close(),this.wouldDeleteBubble_},t.BubbleDragger.prototype.updateCursorDuringBubbleDrag_=function(){this.wouldDeleteBubble_=this.deleteArea_!=t.DELETE_AREA_NONE;var e=this.workspace_.trashcan;this.wouldDeleteBubble_?(this.draggingBubble_.setDeleteStyle(!0),this.deleteArea_==t.DELETE_AREA_TRASH&&e&&e.setOpen(!0)):(this.draggingBubble_.setDeleteStyle(!1),e&&e.setOpen(!1))},t.BubbleDragger.prototype.endBubbleDrag=function(e,o){this.dragBubble(e,o),e=this.pixelsToWorkspaceUnits_(o),e=t.utils.Coordinate.sum(this.startXY_,e),this.draggingBubble_.moveTo(e.x,e.y),this.maybeDeleteBubble_()||(this.dragSurface_&&this.dragSurface_.clearAndHide(this.workspace_.getBubbleCanvas()),this.draggingBubble_.setDragging&&this.draggingBubble_.setDragging(!1),this.fireMoveEvent_()),this.workspace_.setResizesEnabled(!0),this.workspace_.getToolbox()&&(e=this.draggingBubble_.isDeletable()?"blocklyToolboxDelete":"blocklyToolboxGrab",this.workspace_.getToolbox().removeStyle(e)),t.Events.setGroup(!1)},t.BubbleDragger.prototype.fireMoveEvent_=function(){if(this.draggingBubble_.isComment){var e=new t.Events.CommentMove(this.draggingBubble_);e.setOldCoordinate(this.startXY_),e.recordNew(),t.Events.fire(e)}},t.BubbleDragger.prototype.pixelsToWorkspaceUnits_=function(e){return e=new t.utils.Coordinate(e.x/this.workspace_.scale,e.y/this.workspace_.scale),this.workspace_.isMutator&&e.scale(1/this.workspace_.options.parentWorkspace.scale),e},t.BubbleDragger.prototype.moveToDragSurface_=function(){this.draggingBubble_.moveTo(0,0),this.dragSurface_.translateSurface(this.startXY_.x,this.startXY_.y),this.dragSurface_.setBlocksAndShow(this.draggingBubble_.getSvgRoot())},t.WorkspaceDragger=function(e){this.workspace_=e,this.startScrollXY_=new t.utils.Coordinate(e.scrollX,e.scrollY)},t.WorkspaceDragger.prototype.dispose=function(){this.workspace_=null},t.WorkspaceDragger.prototype.startDrag=function(){t.selected&&t.selected.unselect(),this.workspace_.setupDragSurface()},t.WorkspaceDragger.prototype.endDrag=function(t){this.drag(t),this.workspace_.resetDragSurface()},t.WorkspaceDragger.prototype.drag=function(e){e=t.utils.Coordinate.sum(this.startScrollXY_,e),this.workspace_.scroll(e.x,e.y)},t.FlyoutDragger=function(e){t.FlyoutDragger.superClass_.constructor.call(this,e.getWorkspace()),this.scrollbar_=e.scrollbar_,this.horizontalLayout_=e.horizontalLayout_},t.utils.object.inherits(t.FlyoutDragger,t.WorkspaceDragger),t.FlyoutDragger.prototype.drag=function(e){e=t.utils.Coordinate.sum(this.startScrollXY_,e),this.horizontalLayout_?this.scrollbar_.set(-e.x):this.scrollbar_.set(-e.y)},t.Action=function(t,e){this.name=t,this.desc=e},t.navigation={},t.navigation.loggingCallback=null,t.navigation.STATE_FLYOUT=1,t.navigation.STATE_WS=2,t.navigation.STATE_TOOLBOX=3,t.navigation.WS_MOVE_DISTANCE=40,t.navigation.currentState_=t.navigation.STATE_WS,t.navigation.actionNames={PREVIOUS:"previous",NEXT:"next",IN:"in",OUT:"out",INSERT:"insert",MARK:"mark",DISCONNECT:"disconnect",TOOLBOX:"toolbox",EXIT:"exit",TOGGLE_KEYBOARD_NAV:"toggle_keyboard_nav",MOVE_WS_CURSOR_UP:"move workspace cursor up",MOVE_WS_CURSOR_DOWN:"move workspace cursor down",MOVE_WS_CURSOR_LEFT:"move workspace cursor left",MOVE_WS_CURSOR_RIGHT:"move workspace cursor right"},t.navigation.MARKER_NAME="local_marker_1",t.navigation.getMarker=function(){return t.getMainWorkspace().getMarker(t.navigation.MARKER_NAME)},t.navigation.focusToolbox_=function(){var e=t.getMainWorkspace().getToolbox();e&&(t.navigation.currentState_=t.navigation.STATE_TOOLBOX,t.navigation.resetFlyout_(!1),t.navigation.getMarker().getCurNode()||t.navigation.markAtCursor_(),e.selectFirstCategory())},t.navigation.focusFlyout_=function(){t.navigation.currentState_=t.navigation.STATE_FLYOUT;var e=t.getMainWorkspace(),o=e.getToolbox();e=o?o.flyout_:e.getFlyout(),t.navigation.getMarker().getCurNode()||t.navigation.markAtCursor_(),e&&e.getWorkspace()&&0<(e=e.getWorkspace().getTopBlocks(!0)).length&&(e=e[0],e=t.ASTNode.createStackNode(e),t.navigation.getFlyoutCursor_().setCurNode(e))},t.navigation.focusWorkspace_=function(){t.hideChaff();var e=t.getMainWorkspace(),o=e.getCursor(),i=!!e.getToolbox(),n=e.getTopBlocks(!0);t.navigation.resetFlyout_(i),t.navigation.currentState_=t.navigation.STATE_WS,0(this.flyout_?t.FLYOUT_DRAG_RADIUS:t.DRAG_RADIUS))},t.Gesture.prototype.updateIsDraggingFromFlyout_=function(){return!(!this.targetBlock_||!this.flyout_.isBlockCreatable_(this.targetBlock_)||this.flyout_.isScrollable()&&!this.flyout_.isDragTowardWorkspace(this.currentDragDeltaXY_)||(this.startWorkspace_=this.flyout_.targetWorkspace_,this.startWorkspace_.updateScreenCalculationsIfScrolled(),t.Events.getGroup()||t.Events.setGroup(!0),this.startBlock_=null,this.targetBlock_=this.flyout_.createBlock(this.targetBlock_),this.targetBlock_.select(),0))},t.Gesture.prototype.updateIsDraggingBubble_=function(){return!!this.startBubble_&&(this.isDraggingBubble_=!0,this.startDraggingBubble_(),!0)},t.Gesture.prototype.updateIsDraggingBlock_=function(){return!!this.targetBlock_&&(this.flyout_?this.isDraggingBlock_=this.updateIsDraggingFromFlyout_():this.targetBlock_.isMovable()&&(this.isDraggingBlock_=!0),!!this.isDraggingBlock_&&(this.startDraggingBlock_(),!0))},t.Gesture.prototype.updateIsDraggingWorkspace_=function(){(this.flyout_?this.flyout_.isScrollable():this.startWorkspace_&&this.startWorkspace_.isDraggable())&&(this.workspaceDragger_=this.flyout_?new t.FlyoutDragger(this.flyout_):new t.WorkspaceDragger(this.startWorkspace_),this.isDraggingWorkspace_=!0,this.workspaceDragger_.startDrag())},t.Gesture.prototype.updateIsDragging_=function(){if(this.calledUpdateIsDragging_)throw Error("updateIsDragging_ should only be called once per gesture.");this.calledUpdateIsDragging_=!0,this.updateIsDraggingBubble_()||this.updateIsDraggingBlock_()||this.updateIsDraggingWorkspace_()},t.Gesture.prototype.startDraggingBlock_=function(){this.blockDragger_=new t.BlockDragger(this.targetBlock_,this.startWorkspace_),this.blockDragger_.startBlockDrag(this.currentDragDeltaXY_,this.healStack_),this.blockDragger_.dragBlock(this.mostRecentEvent_,this.currentDragDeltaXY_)},t.Gesture.prototype.startDraggingBubble_=function(){this.bubbleDragger_=new t.BubbleDragger(this.startBubble_,this.startWorkspace_),this.bubbleDragger_.startBubbleDrag(),this.bubbleDragger_.dragBubble(this.mostRecentEvent_,this.currentDragDeltaXY_)},t.Gesture.prototype.doStart=function(e){t.utils.isTargetInput(e)?this.cancel():(this.hasStarted_=!0,t.blockAnimations.disconnectUiStop(),this.startWorkspace_.updateScreenCalculationsIfScrolled(),this.startWorkspace_.isMutator&&this.startWorkspace_.resize(),t.hideChaff(!!this.flyout_),this.startWorkspace_.markFocused(),this.mostRecentEvent_=e,t.Tooltip.block(),this.targetBlock_&&(!this.targetBlock_.isInFlyout&&e.shiftKey&&this.targetBlock_.workspace.keyboardAccessibilityMode?this.creatorWorkspace_.getCursor().setCurNode(t.navigation.getTopNode(this.targetBlock_)):this.targetBlock_.select()),t.utils.isRightButton(e)?this.handleRightClick(e):("touchstart"!=e.type.toLowerCase()&&"pointerdown"!=e.type.toLowerCase()||"mouse"==e.pointerType||t.longStart(e,this),this.mouseDownXY_=new t.utils.Coordinate(e.clientX,e.clientY),this.healStack_=e.altKey||e.ctrlKey||e.metaKey,this.bindMouseEvents(e)))},t.Gesture.prototype.bindMouseEvents=function(e){this.onMoveWrapper_=t.bindEventWithChecks_(document,"mousemove",null,this.handleMove.bind(this)),this.onUpWrapper_=t.bindEventWithChecks_(document,"mouseup",null,this.handleUp.bind(this)),e.preventDefault(),e.stopPropagation()},t.Gesture.prototype.handleMove=function(t){this.updateFromEvent_(t),this.isDraggingWorkspace_?this.workspaceDragger_.drag(this.currentDragDeltaXY_):this.isDraggingBlock_?this.blockDragger_.dragBlock(this.mostRecentEvent_,this.currentDragDeltaXY_):this.isDraggingBubble_&&this.bubbleDragger_.dragBubble(this.mostRecentEvent_,this.currentDragDeltaXY_),t.preventDefault(),t.stopPropagation()},t.Gesture.prototype.handleUp=function(e){this.updateFromEvent_(e),t.longStop_(),this.isEnding_?console.log("Trying to end a gesture recursively."):(this.isEnding_=!0,this.isDraggingBubble_?this.bubbleDragger_.endBubbleDrag(e,this.currentDragDeltaXY_):this.isDraggingBlock_?this.blockDragger_.endBlockDrag(e,this.currentDragDeltaXY_):this.isDraggingWorkspace_?this.workspaceDragger_.endDrag(this.currentDragDeltaXY_):this.isBubbleClick_()?this.doBubbleClick_():this.isFieldClick_()?this.doFieldClick_():this.isBlockClick_()?this.doBlockClick_():this.isWorkspaceClick_()&&this.doWorkspaceClick_(e),e.preventDefault(),e.stopPropagation(),this.dispose())},t.Gesture.prototype.cancel=function(){this.isEnding_||(t.longStop_(),this.isDraggingBubble_?this.bubbleDragger_.endBubbleDrag(this.mostRecentEvent_,this.currentDragDeltaXY_):this.isDraggingBlock_?this.blockDragger_.endBlockDrag(this.mostRecentEvent_,this.currentDragDeltaXY_):this.isDraggingWorkspace_&&this.workspaceDragger_.endDrag(this.currentDragDeltaXY_),this.dispose())},t.Gesture.prototype.handleRightClick=function(e){this.targetBlock_?(this.bringBlockToFront_(),t.hideChaff(!!this.flyout_),this.targetBlock_.showContextMenu(e)):this.startBubble_?this.startBubble_.showContextMenu(e):this.startWorkspace_&&!this.flyout_&&(t.hideChaff(),this.startWorkspace_.showContextMenu(e)),e.preventDefault(),e.stopPropagation(),this.dispose()},t.Gesture.prototype.handleWsStart=function(e,o){if(this.hasStarted_)throw Error("Tried to call gesture.handleWsStart, but the gesture had already been started.");this.setStartWorkspace_(o),this.mostRecentEvent_=e,this.doStart(e),this.startWorkspace_.keyboardAccessibilityMode&&t.navigation.setState(t.navigation.STATE_WS)},t.Gesture.prototype.handleFlyoutStart=function(t,e){if(this.hasStarted_)throw Error("Tried to call gesture.handleFlyoutStart, but the gesture had already been started.");this.setStartFlyout_(e),this.handleWsStart(t,e.getWorkspace())},t.Gesture.prototype.handleBlockStart=function(t,e){if(this.hasStarted_)throw Error("Tried to call gesture.handleBlockStart, but the gesture had already been started.");this.setStartBlock(e),this.mostRecentEvent_=t},t.Gesture.prototype.handleBubbleStart=function(t,e){if(this.hasStarted_)throw Error("Tried to call gesture.handleBubbleStart, but the gesture had already been started.");this.setStartBubble(e),this.mostRecentEvent_=t},t.Gesture.prototype.doBubbleClick_=function(){this.startBubble_.setFocus&&this.startBubble_.setFocus(),this.startBubble_.select&&this.startBubble_.select()},t.Gesture.prototype.doFieldClick_=function(){this.startField_.showEditor(this.mostRecentEvent_),this.bringBlockToFront_()},t.Gesture.prototype.doBlockClick_=function(){this.flyout_&&this.flyout_.autoClose?this.targetBlock_.isEnabled()&&(t.Events.getGroup()||t.Events.setGroup(!0),this.flyout_.createBlock(this.targetBlock_).scheduleSnapAndBump()):t.Events.fire(new t.Events.Ui(this.startBlock_,"click",void 0,void 0)),this.bringBlockToFront_(),t.Events.setGroup(!1)},t.Gesture.prototype.doWorkspaceClick_=function(e){var o=this.creatorWorkspace_;e.shiftKey&&o.keyboardAccessibilityMode?(e=new t.utils.Coordinate(e.clientX,e.clientY),e=t.utils.screenToWsCoordinates(o,e),e=t.ASTNode.createWorkspaceNode(o,e),o.getCursor().setCurNode(e)):t.selected&&t.selected.unselect()},t.Gesture.prototype.bringBlockToFront_=function(){this.targetBlock_&&!this.flyout_&&this.targetBlock_.bringToFront()},t.Gesture.prototype.setStartField=function(t){if(this.hasStarted_)throw Error("Tried to call gesture.setStartField, but the gesture had already been started.");this.startField_||(this.startField_=t)},t.Gesture.prototype.setStartBubble=function(t){this.startBubble_||(this.startBubble_=t)},t.Gesture.prototype.setStartBlock=function(t){this.startBlock_||this.startBubble_||(this.startBlock_=t,t.isInFlyout&&t!=t.getRootBlock()?this.setTargetBlock_(t.getRootBlock()):this.setTargetBlock_(t))},t.Gesture.prototype.setTargetBlock_=function(t){t.isShadow()?this.setTargetBlock_(t.getParent()):this.targetBlock_=t},t.Gesture.prototype.setStartWorkspace_=function(t){this.startWorkspace_||(this.startWorkspace_=t)},t.Gesture.prototype.setStartFlyout_=function(t){this.flyout_||(this.flyout_=t)},t.Gesture.prototype.isBubbleClick_=function(){return!!this.startBubble_&&!this.hasExceededDragRadius_},t.Gesture.prototype.isBlockClick_=function(){return!!this.startBlock_&&!this.hasExceededDragRadius_&&!this.isFieldClick_()},t.Gesture.prototype.isFieldClick_=function(){return!!this.startField_&&this.startField_.isClickable()&&!this.hasExceededDragRadius_&&(!this.flyout_||!this.flyout_.autoClose)},t.Gesture.prototype.isWorkspaceClick_=function(){return!(this.startBlock_||this.startBubble_||this.startField_||this.hasExceededDragRadius_)},t.Gesture.prototype.isDragging=function(){return this.isDraggingWorkspace_||this.isDraggingBlock_||this.isDraggingBubble_},t.Gesture.prototype.hasStarted=function(){return this.hasStarted_},t.Gesture.prototype.getInsertionMarkers=function(){return this.blockDragger_?this.blockDragger_.getInsertionMarkers():[]},t.Gesture.inProgress=function(){for(var e,o=t.Workspace.getAll(),i=0;e=o[i];i++)if(e.currentGesture_)return!0;return!1},t.Field=function(e,o,i){this.tooltip_=this.validator_=this.value_=null,this.size_=new t.utils.Size(0,0),this.constants_=this.mouseDownWrapper_=this.textContent_=this.textElement_=this.borderRect_=this.fieldGroup_=this.markerSvg_=this.cursorSvg_=null,i&&this.configure_(i),this.setValue(e),o&&this.setValidator(o)},t.Field.prototype.name=void 0,t.Field.prototype.disposed=!1,t.Field.prototype.maxDisplayLength=50,t.Field.prototype.sourceBlock_=null,t.Field.prototype.isDirty_=!0,t.Field.prototype.visible_=!0,t.Field.prototype.clickTarget_=null,t.Field.NBSP=" ",t.Field.prototype.EDITABLE=!0,t.Field.prototype.SERIALIZABLE=!1,t.Field.prototype.configure_=function(e){var o=e.tooltip;"string"==typeof o&&(o=t.utils.replaceMessageReferences(e.tooltip)),o&&this.setTooltip(o)},t.Field.prototype.setSourceBlock=function(t){if(this.sourceBlock_)throw Error("Field already bound to a block.");this.sourceBlock_=t},t.Field.prototype.getConstants=function(){return!this.constants_&&this.sourceBlock_&&this.sourceBlock_.workspace&&this.sourceBlock_.workspace.rendered&&(this.constants_=this.sourceBlock_.workspace.getRenderer().getConstants()),this.constants_},t.Field.prototype.getSourceBlock=function(){return this.sourceBlock_},t.Field.prototype.init=function(){this.fieldGroup_||(this.fieldGroup_=t.utils.dom.createSvgElement("g",{},null),this.isVisible()||(this.fieldGroup_.style.display="none"),this.sourceBlock_.getSvgRoot().appendChild(this.fieldGroup_),this.initView(),this.updateEditable(),this.setTooltip(this.tooltip_),this.bindEvents_(),this.initModel())},t.Field.prototype.initView=function(){this.createBorderRect_(),this.createTextElement_()},t.Field.prototype.initModel=function(){},t.Field.prototype.createBorderRect_=function(){this.borderRect_=t.utils.dom.createSvgElement("rect",{rx:this.getConstants().FIELD_BORDER_RECT_RADIUS,ry:this.getConstants().FIELD_BORDER_RECT_RADIUS,x:0,y:0,height:this.size_.height,width:this.size_.width,class:"blocklyFieldRect"},this.fieldGroup_)},t.Field.prototype.createTextElement_=function(){this.textElement_=t.utils.dom.createSvgElement("text",{class:"blocklyText"},this.fieldGroup_),this.getConstants().FIELD_TEXT_BASELINE_CENTER&&this.textElement_.setAttribute("dominant-baseline","central"),this.textContent_=document.createTextNode(""),this.textElement_.appendChild(this.textContent_)},t.Field.prototype.bindEvents_=function(){t.Tooltip.bindMouseEvents(this.getClickTarget_()),this.mouseDownWrapper_=t.bindEventWithChecks_(this.getClickTarget_(),"mousedown",this,this.onMouseDown_)},t.Field.prototype.fromXml=function(t){this.setValue(t.textContent)},t.Field.prototype.toXml=function(t){return t.textContent=this.getValue(),t},t.Field.prototype.dispose=function(){t.DropDownDiv.hideIfOwner(this),t.WidgetDiv.hideIfOwner(this),t.Tooltip.unbindMouseEvents(this.getClickTarget_()),this.mouseDownWrapper_&&t.unbindEvent_(this.mouseDownWrapper_),t.utils.dom.removeNode(this.fieldGroup_),this.disposed=!0},t.Field.prototype.updateEditable=function(){var e=this.fieldGroup_;this.EDITABLE&&e&&(this.sourceBlock_.isEditable()?(t.utils.dom.addClass(e,"blocklyEditableText"),t.utils.dom.removeClass(e,"blocklyNonEditableText"),e.style.cursor=this.CURSOR):(t.utils.dom.addClass(e,"blocklyNonEditableText"),t.utils.dom.removeClass(e,"blocklyEditableText"),e.style.cursor=""))},t.Field.prototype.isClickable=function(){return!!this.sourceBlock_&&this.sourceBlock_.isEditable()&&!!this.showEditor_&&"function"==typeof this.showEditor_},t.Field.prototype.isCurrentlyEditable=function(){return this.EDITABLE&&!!this.sourceBlock_&&this.sourceBlock_.isEditable()},t.Field.prototype.isSerializable=function(){var t=!1;return this.name&&(this.SERIALIZABLE?t=!0:this.EDITABLE&&(console.warn("Detected an editable field that was not serializable. Please define SERIALIZABLE property as true on all editable custom fields. Proceeding with serialization."),t=!0)),t},t.Field.prototype.isVisible=function(){return this.visible_},t.Field.prototype.setVisible=function(t){if(this.visible_!=t){this.visible_=t;var e=this.getSvgRoot();e&&(e.style.display=t?"block":"none")}},t.Field.prototype.setValidator=function(t){this.validator_=t},t.Field.prototype.getValidator=function(){return this.validator_},t.Field.prototype.classValidator=function(t){return t},t.Field.prototype.callValidator=function(t){var e=this.classValidator(t);if(null===e)return null;if(void 0!==e&&(t=e),e=this.getValidator()){if(null===(e=e.call(this,t)))return null;void 0!==e&&(t=e)}return t},t.Field.prototype.getSvgRoot=function(){return this.fieldGroup_},t.Field.prototype.applyColour=function(){},t.Field.prototype.render_=function(){this.textContent_&&(this.textContent_.nodeValue=this.getDisplayText_()),this.updateSize_()},t.Field.prototype.showEditor=function(t){this.isClickable()&&this.showEditor_(t)},t.Field.prototype.updateWidth=function(){console.warn("Deprecated call to updateWidth, call Blockly.Field.updateSize_ to force an update to the size of the field, or Blockly.utils.dom.getTextWidth() to check the size of the field."),this.updateSize_()},t.Field.prototype.updateSize_=function(e){var o=this.getConstants(),i=2*(e=null!=e?e:this.borderRect_?this.getConstants().FIELD_BORDER_RECT_X_PADDING:0),n=o.FIELD_TEXT_HEIGHT,s=0;this.textElement_&&(i+=s=t.utils.dom.getFastTextWidth(this.textElement_,o.FIELD_TEXT_FONTSIZE,o.FIELD_TEXT_FONTWEIGHT,o.FIELD_TEXT_FONTFAMILY)),this.borderRect_&&(n=Math.max(n,o.FIELD_BORDER_RECT_HEIGHT)),this.size_.height=n,this.size_.width=i,this.positionTextElement_(e,s),this.positionBorderRect_()},t.Field.prototype.positionTextElement_=function(t,e){if(this.textElement_){var o=this.getConstants(),i=this.size_.height/2;this.textElement_.setAttribute("x",this.sourceBlock_.RTL?this.size_.width-e-t:t),this.textElement_.setAttribute("y",o.FIELD_TEXT_BASELINE_CENTER?i:i-o.FIELD_TEXT_HEIGHT/2+o.FIELD_TEXT_BASELINE)}},t.Field.prototype.positionBorderRect_=function(){this.borderRect_&&(this.borderRect_.setAttribute("width",this.size_.width),this.borderRect_.setAttribute("height",this.size_.height),this.borderRect_.setAttribute("rx",this.getConstants().FIELD_BORDER_RECT_RADIUS),this.borderRect_.setAttribute("ry",this.getConstants().FIELD_BORDER_RECT_RADIUS))},t.Field.prototype.getSize=function(){return this.isVisible()?(this.isDirty_?(this.render_(),this.isDirty_=!1):this.visible_&&0==this.size_.width&&(console.warn("Deprecated use of setting size_.width to 0 to rerender a field. Set field.isDirty_ to true instead."),this.render_()),this.size_):new t.utils.Size(0,0)},t.Field.prototype.getScaledBBox=function(){if(this.borderRect_)e=this.borderRect_.getBoundingClientRect(),i=t.utils.style.getPageOffset(this.borderRect_),n=e.width,e=e.height;else{var e=this.sourceBlock_.getHeightWidth(),o=this.sourceBlock_.workspace.scale,i=this.getAbsoluteXY_(),n=e.width*o;e=e.height*o,t.utils.userAgent.GECKO?(i.x+=1.5*o,i.y+=1.5*o):t.utils.userAgent.EDGE||t.utils.userAgent.IE||(i.x-=.5*o,i.y-=.5*o),n+=1*o,e+=1*o}return{top:i.y,bottom:i.y+e,left:i.x,right:i.x+n}},t.Field.prototype.getDisplayText_=function(){var e=this.getText();return e?(e.length>this.maxDisplayLength&&(e=e.substring(0,this.maxDisplayLength-2)+"…"),e=e.replace(/\s/g,t.Field.NBSP),this.sourceBlock_&&this.sourceBlock_.RTL&&(e+="‏"),e):t.Field.NBSP},t.Field.prototype.getText=function(){if(this.getText_){var t=this.getText_.call(this);if(null!==t)return String(t)}return String(this.getValue())},t.Field.prototype.setText=function(t){throw Error("setText method is deprecated")},t.Field.prototype.markDirty=function(){this.isDirty_=!0,this.constants_=null},t.Field.prototype.forceRerender=function(){this.isDirty_=!0,this.sourceBlock_&&this.sourceBlock_.rendered&&(this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours(),this.updateMarkers_())},t.Field.prototype.setValue=function(e){if(null!==e){var o=this.doClassValidation_(e);if(!((e=this.processValidation_(e,o))instanceof Error)){if((o=this.getValidator())&&(o=o.call(this,e),(e=this.processValidation_(e,o))instanceof Error))return;(o=this.getValue())!==e&&(this.sourceBlock_&&t.Events.isEnabled()&&t.Events.fire(new t.Events.BlockChange(this.sourceBlock_,"field",this.name||null,o,e)),this.doValueUpdate_(e),this.isDirty_&&this.forceRerender())}}},t.Field.prototype.processValidation_=function(t,e){return null===e?(this.doValueInvalid_(t),this.isDirty_&&this.forceRerender(),Error()):(void 0!==e&&(t=e),t)},t.Field.prototype.getValue=function(){return this.value_},t.Field.prototype.doClassValidation_=function(t){return null==t?null:t=this.classValidator(t)},t.Field.prototype.doValueUpdate_=function(t){this.value_=t,this.isDirty_=!0},t.Field.prototype.doValueInvalid_=function(t){},t.Field.prototype.onMouseDown_=function(t){this.sourceBlock_&&this.sourceBlock_.workspace&&(t=this.sourceBlock_.workspace.getGesture(t))&&t.setStartField(this)},t.Field.prototype.setTooltip=function(t){var e=this.getClickTarget_();e?e.tooltip=t||""===t?t:this.sourceBlock_:this.tooltip_=t},t.Field.prototype.getClickTarget_=function(){return this.clickTarget_||this.getSvgRoot()},t.Field.prototype.getAbsoluteXY_=function(){return t.utils.style.getPageOffset(this.getClickTarget_())},t.Field.prototype.referencesVariables=function(){return!1},t.Field.prototype.getParentInput=function(){for(var t=null,e=this.sourceBlock_,o=e.inputList,i=0;ie||e>this.fieldRow.length)throw Error("index "+e+" out of bounds.");return o||""==o&&i?("string"==typeof o&&(o=new t.FieldLabel(o)),o.setSourceBlock(this.sourceBlock_),this.sourceBlock_.rendered&&o.init(),o.name=i,o.prefixField&&(e=this.insertFieldAt(e,o.prefixField)),this.fieldRow.splice(e,0,o),++e,o.suffixField&&(e=this.insertFieldAt(e,o.suffixField)),this.sourceBlock_.rendered&&(this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours()),e):e},t.Input.prototype.removeField=function(t){for(var e,o=0;e=this.fieldRow[o];o++)if(e.name===t)return e.dispose(),this.fieldRow.splice(o,1),void(this.sourceBlock_.rendered&&(this.sourceBlock_.render(),this.sourceBlock_.bumpNeighbours()));throw Error('Field "%s" not found.',t)},t.Input.prototype.isVisible=function(){return this.visible_},t.Input.prototype.setVisible=function(t){var e=[];if(this.visible_==t)return e;for(var o,i=(this.visible_=t)?"block":"none",n=0;o=this.fieldRow[n];n++)o.setVisible(t);return this.connection&&(t?e=this.connection.startTrackingAll():this.connection.stopTrackingAll(),n=this.connection.targetBlock())&&(n.getSvgRoot().style.display=i,t||(n.rendered=!1)),e},t.Input.prototype.markDirty=function(){for(var t,e=0;t=this.fieldRow[e];e++)t.markDirty()},t.Input.prototype.setCheck=function(t){if(!this.connection)throw Error("This input does not have a connection.");return this.connection.setCheck(t),this},t.Input.prototype.setAlign=function(t){return this.align=t,this.sourceBlock_.rendered&&this.sourceBlock_.render(),this},t.Input.prototype.init=function(){if(this.sourceBlock_.workspace.rendered)for(var t=0;tt&&(o=o.substring(0,t-3)+"..."),o},t.Block.prototype.appendValueInput=function(e){return this.appendInput_(t.INPUT_VALUE,e)},t.Block.prototype.appendStatementInput=function(e){return this.appendInput_(t.NEXT_STATEMENT,e)},t.Block.prototype.appendDummyInput=function(e){return this.appendInput_(t.DUMMY_INPUT,e||"")},t.Block.prototype.jsonInit=function(e){var o=e.type?'Block "'+e.type+'": ':"";if(e.output&&e.previousStatement)throw Error(o+"Must not have both an output and a previousStatement.");if(e.style&&e.style.hat&&(this.hat=e.style.hat,e.style=null),e.style&&e.colour)throw Error(o+"Must not have both a colour and a style.");e.style?this.jsonInitStyle_(e,o):this.jsonInitColour_(e,o);for(var i=0;void 0!==e["message"+i];)this.interpolate_(e["message"+i],e["args"+i]||[],e["lastDummyAlign"+i],o),i++;if(void 0!==e.inputsInline&&this.setInputsInline(e.inputsInline),void 0!==e.output&&this.setOutput(!0,e.output),void 0!==e.outputShape&&this.setOutputShape(e.outputShape),void 0!==e.previousStatement&&this.setPreviousStatement(!0,e.previousStatement),void 0!==e.nextStatement&&this.setNextStatement(!0,e.nextStatement),void 0!==e.tooltip&&(i=e.tooltip,i=t.utils.replaceMessageReferences(i),this.setTooltip(i)),void 0!==e.enableContextMenu&&(i=e.enableContextMenu,this.contextMenu=!!i),void 0!==e.helpUrl&&(i=e.helpUrl,i=t.utils.replaceMessageReferences(i),this.setHelpUrl(i)),"string"==typeof e.extensions&&(console.warn(o+"JSON attribute 'extensions' should be an array of strings. Found raw string in JSON for '"+e.type+"' block."),e.extensions=[e.extensions]),void 0!==e.mutator&&t.Extensions.apply(e.mutator,this,!0),Array.isArray(e.extensions))for(e=e.extensions,o=0;o=c||c>o.length)throw Error('Block "'+this.type+'": Message index %'+c+" out of range.");if(r[c])throw Error('Block "'+this.type+'": Message index %'+c+" duplicated.");r[c]=!0,a++,e.push(o[c-1])}else(c=c.trim())&&e.push(c)}if(a!=o.length)throw Error('Block "'+this.type+'": Message does not reference all '+o.length+" arg(s).");for(e.length&&("string"==typeof e[e.length-1]||t.utils.string.startsWith(e[e.length-1].type,"field_"))&&(l={type:"input_dummy"},i&&(l.align=i),e.push(l)),i={LEFT:t.ALIGN_LEFT,RIGHT:t.ALIGN_RIGHT,CENTRE:t.ALIGN_CENTRE,CENTER:t.ALIGN_CENTRE},o=[],l=0;l=this.inputList.length)throw RangeError("Input index "+t+" out of bounds.");if(e>this.inputList.length)throw RangeError("Reference input "+e+" out of bounds.");var o=this.inputList[t];this.inputList.splice(t,1),t--t?e-1:t}),this.highlightedIndex_)},t.Menu.prototype.highlightHelper=function(t,e){e=0>e?-1:e;var o=this.getChildCount();e=t.call(this,e,o);for(var i=0;i<=o;){var n=this.getChildAt(e);if(n&&this.canHighlightItem(n))return this.setHighlightedIndex(e),!0;i++,e=t.call(this,e,o)}return!1},t.Menu.prototype.canHighlightItem=function(t){return t.isEnabled()},t.Menu.prototype.handleMouseOver_=function(t){(t=this.getMenuItem(t.target))&&(t.isEnabled()?this.getHighlighted()!==t&&(this.unhighlightCurrent(),this.setHighlighted(t)):this.unhighlightCurrent())},t.Menu.prototype.handleClick_=function(e){var o=this.openingCoords;if(this.openingCoords=null,o&&"number"==typeof e.clientX){var i=new t.utils.Coordinate(e.clientX,e.clientY);if(1>t.utils.Coordinate.distance(o,i))return}(o=this.getMenuItem(e.target))&&o.handleClick(e)&&e.preventDefault()},t.Menu.prototype.handleMouseEnter_=function(t){this.focus()},t.Menu.prototype.handleMouseLeave_=function(t){this.getElement()&&(this.blur(),this.clearHighlighted())},t.Menu.prototype.handleKeyEvent=function(t){return!(0==this.getChildCount()||!this.handleKeyEventInternal(t)||(t.preventDefault(),t.stopPropagation(),0))},t.Menu.prototype.handleKeyEventInternal=function(e){var o=this.getHighlighted();if(o&&"function"==typeof o.handleKeyEvent&&o.handleKeyEvent(e))return!0;if(e.shiftKey||e.ctrlKey||e.metaKey||e.altKey)return!1;switch(e.keyCode){case t.utils.KeyCodes.ENTER:o&&o.performActionInternal(e);break;case t.utils.KeyCodes.UP:this.highlightPrevious();break;case t.utils.KeyCodes.DOWN:this.highlightNext();break;default:return!1}return!0},t.MenuItem=function(e,o){t.Component.call(this),this.setContentInternal(e),this.setValue(o),this.enabled_=!0},t.utils.object.inherits(t.MenuItem,t.Component),t.MenuItem.prototype.createDom=function(){var e=document.createElement("div");e.id=this.getId(),this.setElementInternal(e),e.className="goog-menuitem goog-option "+(this.enabled_?"":"goog-menuitem-disabled ")+(this.checked_?"goog-option-selected ":"")+(this.rightToLeft_?"goog-menuitem-rtl ":"");var o=this.getContentWrapperDom();e.appendChild(o);var i=this.getCheckboxDom();i&&o.appendChild(i),o.appendChild(this.getContentDom()),t.utils.aria.setRole(e,this.roleName_||(this.checkable_?t.utils.aria.Role.MENUITEMCHECKBOX:t.utils.aria.Role.MENUITEM)),t.utils.aria.setState(e,t.utils.aria.State.SELECTED,this.checkable_&&this.checked_||!1)},t.MenuItem.prototype.getCheckboxDom=function(){if(!this.checkable_)return null;var t=document.createElement("div");return t.className="goog-menuitem-checkbox",t},t.MenuItem.prototype.getContentDom=function(){var t=this.content_;return"string"==typeof t&&(t=document.createTextNode(t)),t},t.MenuItem.prototype.getContentWrapperDom=function(){var t=document.createElement("div");return t.className="goog-menuitem-content",t},t.MenuItem.prototype.setContentInternal=function(t){this.content_=t},t.MenuItem.prototype.setValue=function(t){this.value_=t},t.MenuItem.prototype.getValue=function(){return this.value_},t.MenuItem.prototype.setRole=function(t){this.roleName_=t},t.MenuItem.prototype.setCheckable=function(t){this.checkable_=t},t.MenuItem.prototype.setChecked=function(e){if(this.checkable_){this.checked_=e;var o=this.getElement();o&&this.isEnabled()&&(e?(t.utils.dom.addClass(o,"goog-option-selected"),t.utils.aria.setState(o,t.utils.aria.State.SELECTED,!0)):(t.utils.dom.removeClass(o,"goog-option-selected"),t.utils.aria.setState(o,t.utils.aria.State.SELECTED,!1)))}},t.MenuItem.prototype.setHighlighted=function(e){this.highlight_=e;var o=this.getElement();o&&this.isEnabled()&&(e?t.utils.dom.addClass(o,"goog-menuitem-highlight"):t.utils.dom.removeClass(o,"goog-menuitem-highlight"))},t.MenuItem.prototype.isEnabled=function(){return this.enabled_},t.MenuItem.prototype.setEnabled=function(e){this.enabled_=e,(e=this.getElement())&&(this.enabled_?t.utils.dom.removeClass(e,"goog-menuitem-disabled"):t.utils.dom.addClass(e,"goog-menuitem-disabled"))},t.MenuItem.prototype.handleClick=function(t){this.isEnabled()&&(this.setHighlighted(!0),this.performActionInternal())},t.MenuItem.prototype.performActionInternal=function(){this.checkable_&&this.setChecked(!this.checked_),this.actionHandler_&&this.actionHandler_.call(this.actionHandlerObj_,this)},t.MenuItem.prototype.onAction=function(t,e){this.actionHandler_=t,this.actionHandlerObj_=e},t.utils.uiMenu={},t.utils.uiMenu.getSize=function(e){e=e.getElement();var o=t.utils.style.getSize(e);return o.height=e.scrollHeight,o},t.utils.uiMenu.adjustBBoxesForRTL=function(t,e,o){e.left+=o.width,e.right+=o.width,t.left+=o.width,t.right+=o.width},t.ContextMenu={},t.ContextMenu.currentBlock=null,t.ContextMenu.eventWrapper_=null,t.ContextMenu.show=function(e,o,i){if(t.WidgetDiv.show(t.ContextMenu,i,null),o.length){var n=t.ContextMenu.populate_(o,i);t.ContextMenu.position_(n,e,i),setTimeout((function(){n.getElement().focus()}),1),t.ContextMenu.currentBlock=null}else t.ContextMenu.hide()},t.ContextMenu.populate_=function(e,o){var i=new t.Menu;i.setRightToLeft(o);for(var n,s=0;n=e[s];s++){var r=new t.MenuItem(n.text);r.setRightToLeft(o),i.addChild(r,!0),r.setEnabled(n.enabled),n.enabled&&r.onAction((function(){t.ContextMenu.hide(),this.callback()}),n)}return i},t.ContextMenu.position_=function(e,o,i){var n=t.utils.getViewportBBox();o={top:o.clientY+n.top,bottom:o.clientY+n.top,left:o.clientX+n.left,right:o.clientX+n.left},t.ContextMenu.createWidget_(e);var s=t.utils.uiMenu.getSize(e);i&&t.utils.uiMenu.adjustBBoxesForRTL(n,o,s),t.WidgetDiv.positionWithAnchor(n,o,s,i),e.getElement().focus()},t.ContextMenu.createWidget_=function(e){e.render(t.WidgetDiv.DIV);var o=e.getElement();t.utils.dom.addClass(o,"blocklyContextMenu"),t.bindEventWithChecks_(o,"contextmenu",null,t.utils.noEvent),e.focus()},t.ContextMenu.hide=function(){t.WidgetDiv.hideIfOwner(t.ContextMenu),t.ContextMenu.currentBlock=null,t.ContextMenu.eventWrapper_&&(t.unbindEvent_(t.ContextMenu.eventWrapper_),t.ContextMenu.eventWrapper_=null)},t.ContextMenu.callbackFactory=function(e,o){return function(){t.Events.disable();try{var i=t.Xml.domToBlock(o,e.workspace),n=e.getRelativeToSurfaceXY();n.x=e.RTL?n.x-t.SNAP_RADIUS:n.x+t.SNAP_RADIUS,n.y+=2*t.SNAP_RADIUS,i.moveBy(n.x,n.y)}finally{t.Events.enable()}t.Events.isEnabled()&&!i.isShadow()&&t.Events.fire(new t.Events.BlockCreate(i)),i.select()}},t.ContextMenu.blockDeleteOption=function(e){var o=e.getDescendants(!1).length,i=e.getNextBlock();return i&&(o-=i.getDescendants(!1).length),{text:1==o?t.Msg.DELETE_BLOCK:t.Msg.DELETE_X_BLOCKS.replace("%1",String(o)),enabled:!0,callback:function(){t.Events.setGroup(!0),e.dispose(!0,!0),t.Events.setGroup(!1)}}},t.ContextMenu.blockHelpOption=function(e){return{enabled:!("function"==typeof e.helpUrl?!e.helpUrl():!e.helpUrl),text:t.Msg.HELP,callback:function(){e.showHelp()}}},t.ContextMenu.blockDuplicateOption=function(e){var o=e.isDuplicatable();return{text:t.Msg.DUPLICATE_BLOCK,enabled:o,callback:function(){t.duplicate(e)}}},t.ContextMenu.blockCommentOption=function(e){var o={enabled:!t.utils.userAgent.IE};return e.getCommentIcon()?(o.text=t.Msg.REMOVE_COMMENT,o.callback=function(){e.setCommentText(null)}):(o.text=t.Msg.ADD_COMMENT,o.callback=function(){e.setCommentText("")}),o},t.ContextMenu.commentDeleteOption=function(e){return{text:t.Msg.REMOVE_COMMENT,enabled:!0,callback:function(){t.Events.setGroup(!0),e.dispose(!0,!0),t.Events.setGroup(!1)}}},t.ContextMenu.commentDuplicateOption=function(e){return{text:t.Msg.DUPLICATE_COMMENT,enabled:!0,callback:function(){t.duplicate(e)}}},t.ContextMenu.workspaceCommentOption=function(e,o){if(!t.WorkspaceCommentSvg)throw Error("Missing require for Blockly.WorkspaceCommentSvg");var i={enabled:!t.utils.userAgent.IE};return i.text=t.Msg.ADD_COMMENT,i.callback=function(){var i=new t.WorkspaceCommentSvg(e,t.Msg.WORKSPACE_COMMENT_DEFAULT_TEXT,t.WorkspaceCommentSvg.DEFAULT_SIZE,t.WorkspaceCommentSvg.DEFAULT_SIZE),n=e.getInjectionDiv().getBoundingClientRect();n=new t.utils.Coordinate(o.clientX-n.left,o.clientY-n.top);var s=e.getOriginOffsetInPixels();(n=t.utils.Coordinate.difference(n,s)).scale(1/e.scale),i.moveBy(n.x,n.y),e.rendered&&(i.initSvg(),i.render(),i.select())},i},t.RenderedConnection=function(e,o){t.RenderedConnection.superClass_.constructor.call(this,e,o),this.db_=e.workspace.connectionDBList[o],this.dbOpposite_=e.workspace.connectionDBList[t.OPPOSITE_TYPE[o]],this.offsetInBlock_=new t.utils.Coordinate(0,0),this.trackedState_=t.RenderedConnection.TrackedState.WILL_TRACK},t.utils.object.inherits(t.RenderedConnection,t.Connection),t.RenderedConnection.TrackedState={WILL_TRACK:-1,UNTRACKED:0,TRACKED:1},t.RenderedConnection.prototype.dispose=function(){t.RenderedConnection.superClass_.dispose.call(this),this.trackedState_==t.RenderedConnection.TrackedState.TRACKED&&this.db_.removeConnection(this,this.y)},t.RenderedConnection.prototype.getSourceBlock=function(){return t.RenderedConnection.superClass_.getSourceBlock.call(this)},t.RenderedConnection.prototype.targetBlock=function(){return t.RenderedConnection.superClass_.targetBlock.call(this)},t.RenderedConnection.prototype.distanceFrom=function(t){var e=this.x-t.x;return t=this.y-t.y,Math.sqrt(e*e+t*t)},t.RenderedConnection.prototype.bumpAwayFrom=function(e){if(!this.sourceBlock_.workspace.isDragging()){var o=this.sourceBlock_.getRootBlock();if(!o.isInFlyout){var i=!1;if(!o.isMovable()){if(!(o=e.getSourceBlock().getRootBlock()).isMovable())return;e=this,i=!0}var n=t.selected==o;n||o.addSelect();var s=e.x+t.SNAP_RADIUS+Math.floor(Math.random()*t.BUMP_RANDOMNESS)-this.x,r=e.y+t.SNAP_RADIUS+Math.floor(Math.random()*t.BUMP_RANDOMNESS)-this.y;i&&(r=-r),o.RTL&&(s=e.x-t.SNAP_RADIUS-Math.floor(Math.random()*t.BUMP_RANDOMNESS)-this.x),o.moveBy(s,r),n||o.removeSelect()}}},t.RenderedConnection.prototype.moveTo=function(e,o){this.trackedState_==t.RenderedConnection.TrackedState.WILL_TRACK?(this.db_.addConnection(this,o),this.trackedState_=t.RenderedConnection.TrackedState.TRACKED):this.trackedState_==t.RenderedConnection.TrackedState.TRACKED&&(this.db_.removeConnection(this,this.y),this.db_.addConnection(this,o)),this.x=e,this.y=o},t.RenderedConnection.prototype.moveBy=function(t,e){this.moveTo(this.x+t,this.y+e)},t.RenderedConnection.prototype.moveToOffset=function(t){this.moveTo(t.x+this.offsetInBlock_.x,t.y+this.offsetInBlock_.y)},t.RenderedConnection.prototype.setOffsetInBlock=function(t,e){this.offsetInBlock_.x=t,this.offsetInBlock_.y=e},t.RenderedConnection.prototype.getOffsetInBlock=function(){return this.offsetInBlock_},t.RenderedConnection.prototype.tighten=function(){var e=this.targetConnection.x-this.x,o=this.targetConnection.y-this.y;if(0!=e||0!=o){var i=this.targetBlock(),n=i.getSvgRoot();if(!n)throw Error("block is not rendered.");n=t.utils.getRelativeXY(n),i.getSvgRoot().setAttribute("transform","translate("+(n.x-e)+","+(n.y-o)+")"),i.moveConnections(-e,-o)}},t.RenderedConnection.prototype.closest=function(t,e){return this.dbOpposite_.searchForClosest(this,t,e)},t.RenderedConnection.prototype.highlight=function(){var e=this.sourceBlock_.workspace.getRenderer().getConstants(),o=e.shapeFor(this);this.type==t.INPUT_VALUE||this.type==t.OUTPUT_VALUE?(e=e.TAB_OFFSET_FROM_TOP,o=t.utils.svgPaths.moveBy(0,-e)+t.utils.svgPaths.lineOnAxis("v",e)+o.pathDown+t.utils.svgPaths.lineOnAxis("v",e)):(e=e.NOTCH_OFFSET_LEFT-e.CORNER_RADIUS,o=t.utils.svgPaths.moveBy(-e,0)+t.utils.svgPaths.lineOnAxis("h",e)+o.pathLeft+t.utils.svgPaths.lineOnAxis("h",e)),e=this.sourceBlock_.getRelativeToSurfaceXY(),t.Connection.highlightedPath_=t.utils.dom.createSvgElement("path",{class:"blocklyHighlightedConnectionPath",d:o,transform:"translate("+(this.x-e.x)+","+(this.y-e.y)+")"+(this.sourceBlock_.RTL?" scale(-1 1)":"")},this.sourceBlock_.getSvgRoot())},t.RenderedConnection.prototype.unhighlight=function(){t.utils.dom.removeNode(t.Connection.highlightedPath_),delete t.Connection.highlightedPath_},t.RenderedConnection.prototype.setTracking=function(e){e&&this.trackedState_==t.RenderedConnection.TrackedState.TRACKED||!e&&this.trackedState_==t.RenderedConnection.TrackedState.UNTRACKED||this.sourceBlock_.isInFlyout||(e?(this.db_.addConnection(this,this.y),this.trackedState_=t.RenderedConnection.TrackedState.TRACKED):(this.trackedState_==t.RenderedConnection.TrackedState.TRACKED&&this.db_.removeConnection(this,this.y),this.trackedState_=t.RenderedConnection.TrackedState.UNTRACKED))},t.RenderedConnection.prototype.stopTrackingAll=function(){if(this.setTracking(!1),this.targetConnection)for(var t=this.targetBlock().getDescendants(!1),e=0;eo)&&t.RenderedConnection.superClass_.isConnectionAllowed.call(this,e)},t.RenderedConnection.prototype.onFailedConnect=function(t){this.bumpAwayFrom(t)},t.RenderedConnection.prototype.disconnectInternal_=function(e,o){t.RenderedConnection.superClass_.disconnectInternal_.call(this,e,o),e.rendered&&e.render(),o.rendered&&(o.updateDisabled(),o.render())},t.RenderedConnection.prototype.respawnShadow_=function(){var e=this.getSourceBlock(),o=this.getShadowDom();if(e.workspace&&o&&t.Events.recordUndo){if(t.RenderedConnection.superClass_.respawnShadow_.call(this),!(o=this.targetBlock()))throw Error("Couldn't respawn the shadow block that should exist here.");o.initSvg(),o.render(!1),e.rendered&&e.render()}},t.RenderedConnection.prototype.neighbours=function(t){return this.dbOpposite_.getNeighbours(this,t)},t.RenderedConnection.prototype.connect_=function(e){t.RenderedConnection.superClass_.connect_.call(this,e);var o=this.getSourceBlock();e=e.getSourceBlock(),o.rendered&&o.updateDisabled(),e.rendered&&e.updateDisabled(),o.rendered&&e.rendered&&(this.type==t.NEXT_STATEMENT||this.type==t.PREVIOUS_STATEMENT?e.render():o.render())},t.RenderedConnection.prototype.onCheckChanged_=function(){!this.isConnected()||this.targetConnection&&this.checkType(this.targetConnection)||((this.isSuperior()?this.targetBlock():this.sourceBlock_).unplug(),this.sourceBlock_.bumpNeighbours())},t.Marker=function(){this.drawer_=this.curNode_=this.colour=null,this.type="marker"},t.Marker.prototype.setDrawer=function(t){this.drawer_=t},t.Marker.prototype.getDrawer=function(){return this.drawer_},t.Marker.prototype.getCurNode=function(){return this.curNode_},t.Marker.prototype.setCurNode=function(t){var e=this.curNode_;this.curNode_=t,this.drawer_&&this.drawer_.draw(e,this.curNode_)},t.Marker.prototype.draw=function(){this.drawer_&&this.drawer_.draw(this.curNode_,this.curNode_)},t.Marker.prototype.hide=function(){this.drawer_&&this.drawer_.hide()},t.Marker.prototype.dispose=function(){this.getDrawer()&&this.getDrawer().dispose()},t.Cursor=function(){t.Cursor.superClass_.constructor.call(this),this.type="cursor"},t.utils.object.inherits(t.Cursor,t.Marker),t.Cursor.prototype.next=function(){var e=this.getCurNode();if(!e)return null;for(e=e.next();e&&e.next()&&(e.getType()==t.ASTNode.types.NEXT||e.getType()==t.ASTNode.types.BLOCK);)e=e.next();return e&&this.setCurNode(e),e},t.Cursor.prototype.in=function(){var e=this.getCurNode();return e?(e.getType()!=t.ASTNode.types.PREVIOUS&&e.getType()!=t.ASTNode.types.OUTPUT||(e=e.next()),(e=e.in())&&this.setCurNode(e),e):null},t.Cursor.prototype.prev=function(){var e=this.getCurNode();if(!e)return null;for(e=e.prev();e&&e.prev()&&(e.getType()==t.ASTNode.types.NEXT||e.getType()==t.ASTNode.types.BLOCK);)e=e.prev();return e&&this.setCurNode(e),e},t.Cursor.prototype.out=function(){var e=this.getCurNode();return e?((e=e.out())&&e.getType()==t.ASTNode.types.BLOCK&&(e=e.prev()||e),e&&this.setCurNode(e),e):null},t.Cursor.prototype.onBlocklyAction=function(e){if(this.getCurNode()&&this.getCurNode().getType()===t.ASTNode.types.FIELD&&this.getCurNode().getLocation().onBlocklyAction(e))return!0;switch(e.name){case t.navigation.actionNames.PREVIOUS:return this.prev(),!0;case t.navigation.actionNames.OUT:return this.out(),!0;case t.navigation.actionNames.NEXT:return this.next(),!0;case t.navigation.actionNames.IN:return this.in(),!0;default:return!1}},t.BasicCursor=function(){t.BasicCursor.superClass_.constructor.call(this)},t.utils.object.inherits(t.BasicCursor,t.Cursor),t.BasicCursor.prototype.next=function(){var t=this.getCurNode();return t?((t=this.getNextNode_(t,this.validNode_))&&this.setCurNode(t),t):null},t.BasicCursor.prototype.in=function(){return this.next()},t.BasicCursor.prototype.prev=function(){var t=this.getCurNode();return t?((t=this.getPreviousNode_(t,this.validNode_))&&this.setCurNode(t),t):null},t.BasicCursor.prototype.out=function(){return this.prev()},t.BasicCursor.prototype.getNextNode_=function(t,e){if(!t)return null;var o=t.in()||t.next();return e(o)?o:o?this.getNextNode_(o,e):e(t=this.findSiblingOrParent_(t.out()))?t:t?this.getNextNode_(t,e):null},t.BasicCursor.prototype.getPreviousNode_=function(t,e){if(!t)return null;var o=t.prev();return e(o=o?this.getRightMostChild_(o):t.out())?o:o?this.getPreviousNode_(o,e):null},t.BasicCursor.prototype.validNode_=function(e){var o=!1;return(e=e&&e.getType())!=t.ASTNode.types.OUTPUT&&e!=t.ASTNode.types.INPUT&&e!=t.ASTNode.types.FIELD&&e!=t.ASTNode.types.NEXT&&e!=t.ASTNode.types.PREVIOUS&&e!=t.ASTNode.types.WORKSPACE||(o=!0),o},t.BasicCursor.prototype.findSiblingOrParent_=function(t){if(!t)return null;var e=t.next();return e||this.findSiblingOrParent_(t.out())},t.BasicCursor.prototype.getRightMostChild_=function(t){if(!t.in())return t;for(t=t.in();t.next();)t=t.next();return this.getRightMostChild_(t)},t.TabNavigateCursor=function(){t.TabNavigateCursor.superClass_.constructor.call(this)},t.utils.object.inherits(t.TabNavigateCursor,t.BasicCursor),t.TabNavigateCursor.prototype.validNode_=function(e){var o=!1,i=e&&e.getType();return e&&(e=e.getLocation(),i==t.ASTNode.types.FIELD&&e&&e.isTabNavigable()&&e.isClickable()&&(o=!0)),o},t.utils.Rect=function(t,e,o,i){this.top=t,this.bottom=e,this.left=o,this.right=i},t.utils.Rect.prototype.contains=function(t,e){return t>=this.left&&t<=this.right&&e>=this.top&&e<=this.bottom},t.BlockSvg=function(e,o,i){this.svgGroup_=t.utils.dom.createSvgElement("g",{},null),this.svgGroup_.translate_="",this.style=e.getRenderer().getConstants().getBlockStyle(null),this.pathObject=e.getRenderer().makePathObject(this.svgGroup_,this.style),this.rendered=!1,this.workspace=e,this.previousConnection=this.nextConnection=this.outputConnection=null,this.useDragSurface_=t.utils.is3dSupported()&&!!e.getBlockDragSurface();var n=this.pathObject.svgPath;n.tooltip=this,t.Tooltip.bindMouseEvents(n),t.BlockSvg.superClass_.constructor.call(this,e,o,i),this.svgGroup_.dataset&&(this.svgGroup_.dataset.id=this.id)},t.utils.object.inherits(t.BlockSvg,t.Block),t.BlockSvg.prototype.height=0,t.BlockSvg.prototype.width=0,t.BlockSvg.prototype.dragStartXY_=null,t.BlockSvg.prototype.warningTextDb_=null,t.BlockSvg.INLINE=-1,t.BlockSvg.COLLAPSED_WARNING_ID="TEMP_COLLAPSED_WARNING_",t.BlockSvg.prototype.initSvg=function(){if(!this.workspace.rendered)throw TypeError("Workspace is headless.");for(var e,o=0;e=this.inputList[o];o++)e.init();for(e=this.getIcons(),o=0;o=this.connections_.length)return-1;e=t.y;for(var i=o;0<=i&&this.connections_[i].y==e;){if(this.connections_[i]==t)return i;i--}for(;ot)){e=i;break}o=i}}return e},t.ConnectionDB.prototype.removeConnection=function(t,e){if(-1==(t=this.findIndexOfConnection_(t,e)))throw Error("Unable to find connection in connectionDB.");this.connections_.splice(t,1)},t.ConnectionDB.prototype.getNeighbours=function(t,e){function o(t){var o=n-i[t].x,r=s-i[t].y;return Math.sqrt(o*o+r*r)<=e&&l.push(i[t]),r(t=this.subscribedWorkspaces_.indexOf(t)))throw Error("Cannot unsubscribe a workspace that hasn't been subscribed.");this.subscribedWorkspaces_.splice(t,1)},t.ThemeManager.prototype.subscribe=function(t,e,o){this.componentDB_[e]||(this.componentDB_[e]=[]),this.componentDB_[e].push({element:t,propertyName:o}),e=this.theme_&&this.theme_.getComponentStyle(e),t.style[o]=e||""},t.ThemeManager.prototype.unsubscribe=function(t){if(t)for(var e,o=Object.keys(this.componentDB_),i=0;e=o[i];i++){for(var n=this.componentDB_[e],s=n.length-1;0<=s;s--)n[s].element===t&&n.splice(s,1);this.componentDB_[e].length||delete this.componentDB_[e]}},t.ThemeManager.prototype.dispose=function(){this.componentDB_=this.subscribedWorkspaces_=this.theme_=this.owner_=null},t.TouchGesture=function(e,o){t.TouchGesture.superClass_.constructor.call(this,e,o),this.isMultiTouch_=!1,this.cachedPoints_=Object.create(null),this.startDistance_=this.previousScale_=0,this.isPinchZoomEnabled_=this.onStartWrapper_=null},t.utils.object.inherits(t.TouchGesture,t.Gesture),t.TouchGesture.ZOOM_IN_MULTIPLIER=5,t.TouchGesture.ZOOM_OUT_MULTIPLIER=6,t.TouchGesture.prototype.doStart=function(e){this.isPinchZoomEnabled_=this.startWorkspace_.options.zoomOptions&&this.startWorkspace_.options.zoomOptions.pinch,t.TouchGesture.superClass_.doStart.call(this,e),!this.isEnding_&&t.Touch.isTouchEvent(e)&&this.handleTouchStart(e)},t.TouchGesture.prototype.bindMouseEvents=function(e){this.onStartWrapper_=t.bindEventWithChecks_(document,"mousedown",null,this.handleStart.bind(this),!0),this.onMoveWrapper_=t.bindEventWithChecks_(document,"mousemove",null,this.handleMove.bind(this),!0),this.onUpWrapper_=t.bindEventWithChecks_(document,"mouseup",null,this.handleUp.bind(this),!0),e.preventDefault(),e.stopPropagation()},t.TouchGesture.prototype.handleStart=function(e){!this.isDragging()&&t.Touch.isTouchEvent(e)&&(this.handleTouchStart(e),this.isMultiTouch()&&t.longStop_())},t.TouchGesture.prototype.handleMove=function(e){this.isDragging()?t.Touch.shouldHandleEvent(e)&&t.TouchGesture.superClass_.handleMove.call(this,e):this.isMultiTouch()?(t.Touch.isTouchEvent(e)&&this.handleTouchMove(e),t.longStop_()):t.TouchGesture.superClass_.handleMove.call(this,e)},t.TouchGesture.prototype.handleUp=function(e){t.Touch.isTouchEvent(e)&&!this.isDragging()&&this.handleTouchEnd(e),!this.isMultiTouch()||this.isDragging()?t.Touch.shouldHandleEvent(e)&&t.TouchGesture.superClass_.handleUp.call(this,e):(e.preventDefault(),e.stopPropagation(),this.dispose())},t.TouchGesture.prototype.isMultiTouch=function(){return this.isMultiTouch_},t.TouchGesture.prototype.dispose=function(){t.TouchGesture.superClass_.dispose.call(this),this.onStartWrapper_&&t.unbindEvent_(this.onStartWrapper_)},t.TouchGesture.prototype.handleTouchStart=function(e){var o=t.Touch.getTouchIdentifierFromEvent(e);this.cachedPoints_[o]=this.getTouchPoint(e),2==(o=Object.keys(this.cachedPoints_)).length&&(this.startDistance_=t.utils.Coordinate.distance(this.cachedPoints_[o[0]],this.cachedPoints_[o[1]]),this.isMultiTouch_=!0,e.preventDefault())},t.TouchGesture.prototype.handleTouchMove=function(e){var o=t.Touch.getTouchIdentifierFromEvent(e);this.cachedPoints_[o]=this.getTouchPoint(e),o=Object.keys(this.cachedPoints_),this.isPinchZoomEnabled_&&2===o.length?this.handlePinch_(e):t.TouchGesture.superClass_.handleMove.call(this,e)},t.TouchGesture.prototype.handlePinch_=function(e){var o=Object.keys(this.cachedPoints_);if(o=t.utils.Coordinate.distance(this.cachedPoints_[o[0]],this.cachedPoints_[o[1]])/this.startDistance_,0this.previousScale_){var i=o-this.previousScale_;i=0Object.keys(this.cachedPoints_).length&&(this.cachedPoints_=Object.create(null),this.previousScale_=0)},t.TouchGesture.prototype.getTouchPoint=function(e){return this.startWorkspace_?new t.utils.Coordinate(e.pageX?e.pageX:e.changedTouches[0].pageX,e.pageY?e.pageY:e.changedTouches[0].pageY):null},t.WorkspaceAudio=function(t){this.parentWorkspace_=t,this.SOUNDS_=Object.create(null)},t.WorkspaceAudio.prototype.lastSound_=null,t.WorkspaceAudio.prototype.dispose=function(){this.SOUNDS_=this.parentWorkspace_=null},t.WorkspaceAudio.prototype.load=function(e,o){if(e.length){try{var i=new t.utils.global.Audio}catch(t){return}for(var n,s=0;s=this.remainingCapacity()||(this.currentGesture_&&this.currentGesture_.cancel(),"comment"==t.tagName.toLowerCase()?this.pasteWorkspaceComment_(t):this.pasteBlock_(t))},t.WorkspaceSvg.prototype.pasteBlock_=function(e){t.Events.disable();try{var o=t.Xml.domToBlock(e,this),i=this.getMarker(t.navigation.MARKER_NAME).getCurNode();if(this.keyboardAccessibilityMode&&i&&i.isConnection()){var n=i.getLocation();return void t.navigation.insertBlock(o,n)}var s=parseInt(e.getAttribute("x"),10),r=parseInt(e.getAttribute("y"),10);if(!isNaN(s)&&!isNaN(r)){this.RTL&&(s=-s);do{e=!1;var a,l=this.getAllBlocks(!1);for(i=0;a=l[i];i++){var c=a.getRelativeToSurfaceXY();if(1>=Math.abs(s-c.x)&&1>=Math.abs(r-c.y)){e=!0;break}}if(!e){var h,u=o.getConnections_(!1);for(i=0;h=u[i];i++)if(h.closest(t.SNAP_RADIUS,new t.utils.Coordinate(s,r)).connection){e=!0;break}}e&&(s=this.RTL?s-t.SNAP_RADIUS:s+t.SNAP_RADIUS,r+=2*t.SNAP_RADIUS)}while(e);o.moveBy(s,r)}}finally{t.Events.enable()}t.Events.isEnabled()&&!o.isShadow()&&t.Events.fire(new t.Events.BlockCreate(o)),o.select()},t.WorkspaceSvg.prototype.pasteWorkspaceComment_=function(e){t.Events.disable();try{var o=t.WorkspaceCommentSvg.fromXml(e,this),i=parseInt(e.getAttribute("x"),10),n=parseInt(e.getAttribute("y"),10);isNaN(i)||isNaN(n)||(this.RTL&&(i=-i),o.moveBy(i+50,n+50))}finally{t.Events.enable()}t.Events.isEnabled(),o.select()},t.WorkspaceSvg.prototype.refreshToolboxSelection=function(){var t=this.isFlyout?this.targetWorkspace:this;t&&!t.currentGesture_&&t.toolbox_&&t.toolbox_.getFlyout()&&t.toolbox_.refreshSelection()},t.WorkspaceSvg.prototype.renameVariableById=function(e,o){t.WorkspaceSvg.superClass_.renameVariableById.call(this,e,o),this.refreshToolboxSelection()},t.WorkspaceSvg.prototype.deleteVariableById=function(e){t.WorkspaceSvg.superClass_.deleteVariableById.call(this,e),this.refreshToolboxSelection()},t.WorkspaceSvg.prototype.createVariable=function(e,o,i){return e=t.WorkspaceSvg.superClass_.createVariable.call(this,e,o,i),this.refreshToolboxSelection(),e},t.WorkspaceSvg.prototype.recordDeleteAreas=function(){this.deleteAreaTrash_=this.trashcan&&this.svgGroup_.parentNode?this.trashcan.getClientRect():null,this.deleteAreaToolbox_=this.flyout_?this.flyout_.getClientRect():this.toolbox_?this.toolbox_.getClientRect():null},t.WorkspaceSvg.prototype.isDeleteArea=function(e){return this.deleteAreaTrash_&&this.deleteAreaTrash_.contains(e.clientX,e.clientY)?t.DELETE_AREA_TRASH:this.deleteAreaToolbox_&&this.deleteAreaToolbox_.contains(e.clientX,e.clientY)?t.DELETE_AREA_TOOLBOX:t.DELETE_AREA_NONE},t.WorkspaceSvg.prototype.onMouseDown_=function(t){var e=this.getGesture(t);e&&e.handleWsStart(t,this)},t.WorkspaceSvg.prototype.startDrag=function(e,o){(e=t.utils.mouseToSvg(e,this.getParentSvg(),this.getInverseScreenCTM())).x/=this.scale,e.y/=this.scale,this.dragDeltaXY_=t.utils.Coordinate.difference(o,e)},t.WorkspaceSvg.prototype.moveDrag=function(e){return(e=t.utils.mouseToSvg(e,this.getParentSvg(),this.getInverseScreenCTM())).x/=this.scale,e.y/=this.scale,t.utils.Coordinate.sum(this.dragDeltaXY_,e)},t.WorkspaceSvg.prototype.isDragging=function(){return null!=this.currentGesture_&&this.currentGesture_.isDragging()},t.WorkspaceSvg.prototype.isDraggable=function(){return this.options.moveOptions&&this.options.moveOptions.drag},t.WorkspaceSvg.prototype.isContentBounded=function(){return this.options.moveOptions&&this.options.moveOptions.scrollbars||this.options.moveOptions&&this.options.moveOptions.wheel||this.options.moveOptions&&this.options.moveOptions.drag||this.options.zoomOptions&&this.options.zoomOptions.controls||this.options.zoomOptions&&this.options.zoomOptions.wheel||this.options.zoomOptions&&this.options.zoomOptions.pinch},t.WorkspaceSvg.prototype.isMovable=function(){return this.options.moveOptions&&this.options.moveOptions.scrollbars||this.options.moveOptions&&this.options.moveOptions.wheel||this.options.moveOptions&&this.options.moveOptions.drag||this.options.zoomOptions&&this.options.zoomOptions.wheel||this.options.zoomOptions&&this.options.zoomOptions.pinch},t.WorkspaceSvg.prototype.onMouseWheel_=function(e){if(t.Gesture.inProgress())e.preventDefault(),e.stopPropagation();else{var o=this.options.zoomOptions&&this.options.zoomOptions.wheel,i=this.options.moveOptions&&this.options.moveOptions.wheel;if(o||i){var n=t.utils.getScrollDeltaPixels(e);!o||!e.ctrlKey&&i?(o=this.scrollX-n.x,i=this.scrollY-n.y,e.shiftKey&&!n.x&&(o=this.scrollX-n.y,i=this.scrollY),this.scroll(o,i)):(n=-n.y/50,o=t.utils.mouseToSvg(e,this.getParentSvg(),this.getInverseScreenCTM()),this.zoom(o.x,o.y,n)),e.preventDefault()}}},t.WorkspaceSvg.prototype.getBlocksBoundingBox=function(){var e=this.getTopBlocks(!1),o=this.getTopComments(!1);if(!(e=e.concat(o)).length)return new t.utils.Rect(0,0,0,0);o=e[0].getBoundingRectangle();for(var i=1;io.bottom&&(o.bottom=n.bottom),n.lefto.right&&(o.right=n.right)}return o},t.WorkspaceSvg.prototype.cleanUp=function(){this.setResizesEnabled(!1),t.Events.setGroup(!0);for(var e,o=this.getTopBlocks(!0),i=0,n=0;e=o[n];n++)if(e.isMovable()){var s=e.getRelativeToSurfaceXY();e.moveBy(-s.x,i-s.y),e.snapToGrid(),i=e.getRelativeToSurfaceXY().y+e.getHeightWidth().height+this.renderer_.getConstants().MIN_BLOCK_HEIGHT}t.Events.setGroup(!1),this.setResizesEnabled(!0)},t.WorkspaceSvg.prototype.showContextMenu=function(e){function o(t){if(t.isDeletable())_=_.concat(t.getDescendants(!1));else{t=t.getChildren(!1);for(var e=0;e_.length?i():t.confirm(t.Msg.DELETE_ALL_BLOCKS.replace("%1",_.length),(function(t){t&&i()}))}},n.push(l),this.configureContextMenu&&this.configureContextMenu(n,e),t.ContextMenu.show(e,n,this.RTL)}},t.WorkspaceSvg.prototype.updateToolbox=function(e){if(e=t.Options.parseToolboxTree(e)){if(!this.options.languageTree)throw Error("Existing toolbox is null. Can't create new toolbox.");if(e.getElementsByTagName("category").length){if(!this.toolbox_)throw Error("Existing toolbox has no categories. Can't change mode.");this.options.languageTree=e,this.toolbox_.renderTree(e)}else{if(!this.flyout_)throw Error("Existing toolbox has categories. Can't change mode.");this.options.languageTree=e,this.flyout_.show(e.childNodes)}}else if(this.options.languageTree)throw Error("Can't nullify an existing toolbox.")},t.WorkspaceSvg.prototype.markFocused=function(){this.options.parentWorkspace?this.options.parentWorkspace.markFocused():(t.mainWorkspace=this,this.setBrowserFocus())},t.WorkspaceSvg.prototype.setBrowserFocus=function(){document.activeElement&&document.activeElement.blur();try{this.getParentSvg().focus({preventScroll:!0})}catch(t){try{this.getParentSvg().parentNode.setActive()}catch(t){this.getParentSvg().parentNode.focus({preventScroll:!0})}}},t.WorkspaceSvg.prototype.zoom=function(t,e,o){o=Math.pow(this.options.zoomOptions.scaleSpeed,o);var i=this.scale*o;if(this.scale!=i){i>this.options.zoomOptions.maxScale?o=this.options.zoomOptions.maxScale/this.scale:ithis.options.zoomOptions.maxScale?e=this.options.zoomOptions.maxScale:this.options.zoomOptions.minScale&&eo.viewBottom||o.contentLefto.viewRight){switch(i=null,e&&(i=t.Events.getGroup(),t.Events.setGroup(e.group)),e.type){case t.Events.BLOCK_CREATE:case t.Events.BLOCK_MOVE:var r=s.getBlockById(e.blockId);r&&(r=r.getRootBlock());break;case t.Events.COMMENT_CREATE:case t.Events.COMMENT_MOVE:r=s.getCommentById(e.commentId)}if(r){(n=r.getBoundingRectangle()).height=n.bottom-n.top,n.width=n.right-n.left;var a=o.viewTop,l=o.viewBottom-n.height;l=Math.max(a,l),a=t.utils.math.clamp(a,n.top,l)-n.top,l=o.viewLeft;var c=o.viewRight-n.width;o.RTL?l=Math.min(c,l):c=Math.max(l,c),o=t.utils.math.clamp(l,n.left,c)-n.left,r.moveBy(o,a)}e&&(!e.group&&r&&console.log("WARNING: Moved object in bounds but there was no event group. This may break undo."),null!==i&&t.Events.setGroup(i))}}})),t.svgResize(s),t.WidgetDiv.createDom(),t.DropDownDiv.createDom(),t.Tooltip.createDom(),s},t.init_=function(e){var o=e.options,i=e.getParentSvg();if(t.bindEventWithChecks_(i.parentNode,"contextmenu",null,(function(e){t.utils.isTargetInput(e)||e.preventDefault()})),i=t.bindEventWithChecks_(window,"resize",null,(function(){t.hideChaff(!0),t.svgResize(e)})),e.setResizeHandlerWrapper(i),t.inject.bindDocumentEvents_(),o.languageTree){i=e.getToolbox();var n=e.getFlyout(!0);i?i.init():n&&(n.init(e),n.show(o.languageTree.childNodes),n.scrollToStart())}i=t.Scrollbar.scrollbarThickness,o.hasTrashcan&&(i=e.trashcan.init(i)),o.zoomOptions&&o.zoomOptions.controls&&e.zoomControls_.init(i),o.moveOptions&&o.moveOptions.scrollbars?(e.scrollbar=new t.ScrollbarPair(e),e.scrollbar.resize()):e.setMetrics({x:.5,y:.5}),o.hasSounds&&t.inject.loadSounds_(o.pathToMedia,e)},t.inject.bindDocumentEvents_=function(){t.documentEventsBound_||(t.bindEventWithChecks_(document,"scroll",null,(function(){for(var e,o=t.Workspace.getAll(),i=0;e=o[i];i++)e.updateInverseScreenCTM&&e.updateInverseScreenCTM()})),t.bindEventWithChecks_(document,"keydown",null,t.onKeyDown),t.bindEvent_(document,"touchend",null,t.longStop_),t.bindEvent_(document,"touchcancel",null,t.longStop_),t.utils.userAgent.IPAD&&t.bindEventWithChecks_(window,"orientationchange",document,(function(){t.svgResize(t.getMainWorkspace())}))),t.documentEventsBound_=!0},t.inject.loadSounds_=function(e,o){var i=o.getAudioManager();i.load([e+"click.mp3",e+"click.wav",e+"click.ogg"],"click"),i.load([e+"disconnect.wav",e+"disconnect.mp3",e+"disconnect.ogg"],"disconnect"),i.load([e+"delete.mp3",e+"delete.ogg",e+"delete.wav"],"delete");var n=[];e=function(){for(;n.length;)t.unbindEvent_(n.pop());i.preload()},n.push(t.bindEventWithChecks_(document,"mousemove",null,e,!0)),n.push(t.bindEventWithChecks_(document,"touchstart",null,e,!0))},t.Names=function(t,e){if(this.variablePrefix_=e||"",this.reservedDict_=Object.create(null),t)for(t=t.split(","),e=0;e1'),n.appendChild(i),o.push(n)),t.Blocks.variables_get){e.sort(t.VariableModel.compareByName),i=0;for(var s;s=e[i];i++)(n=t.utils.xml.createElement("block")).setAttribute("type","variables_get"),n.setAttribute("gap",8),n.appendChild(t.Variables.generateVariableFieldDom(s)),o.push(n)}}return o},t.Variables.VAR_LETTER_OPTIONS="ijkmnopqrstuvwxyzabcdefgh",t.Variables.generateUniqueName=function(e){return t.Variables.generateUniqueNameFromOptions(t.Variables.VAR_LETTER_OPTIONS.charAt(0),e.getAllVariableNames())},t.Variables.generateUniqueNameFromOptions=function(e,o){if(!o.length)return e;for(var i=t.Variables.VAR_LETTER_OPTIONS,n="",s=i.indexOf(e);;){for(var r=!1,a=0;as?t.WidgetDiv.positionInternal_(e,0,i.height+s):t.WidgetDiv.positionInternal_(e,s,i.height)},t.WidgetDiv.calculateX_=function(t,e,o,i){return i?(e=Math.max(e.right-o.width,t.left),Math.min(e,t.right-o.width)):(e=Math.min(e.left,t.right-o.width),Math.max(e,t.left))},t.WidgetDiv.calculateY_=function(t,e,o){return e.bottom+o.height>=t.bottom?e.top-o.height:e.bottom},t.VERSION="3.20200402.1",t.mainWorkspace=null,t.selected=null,t.draggingConnections=[],t.clipboardXml_=null,t.clipboardSource_=null,t.clipboardTypeCounts_=null,t.cache3dSupported_=null,t.parentContainer=null,t.svgSize=function(t){return{width:t.cachedWidth_,height:t.cachedHeight_}},t.resizeSvgContents=function(t){t.resizeContents()},t.svgResize=function(t){for(;t.options.parentWorkspace;)t=t.options.parentWorkspace;var e=t.getParentSvg(),o=e.parentNode;if(o){var i=o.offsetWidth;o=o.offsetHeight,e.cachedWidth_!=i&&(e.setAttribute("width",i+"px"),e.cachedWidth_=i),e.cachedHeight_!=o&&(e.setAttribute("height",o+"px"),e.cachedHeight_=o),t.resize()}},t.onKeyDown=function(e){var o=t.mainWorkspace;if(o&&!(t.utils.isTargetInput(e)||o.rendered&&!o.isVisible()))if(o.options.readOnly)t.navigation.onKeyPress(e);else{var i=!1;if(e.keyCode==t.utils.KeyCodes.ESC)t.hideChaff(),t.navigation.onBlocklyAction(t.navigation.ACTION_EXIT);else{if(t.navigation.onKeyPress(e))return;if(e.keyCode==t.utils.KeyCodes.BACKSPACE||e.keyCode==t.utils.KeyCodes.DELETE){if(e.preventDefault(),t.Gesture.inProgress())return;t.selected&&t.selected.isDeletable()&&(i=!0)}else if(e.altKey||e.ctrlKey||e.metaKey){if(t.Gesture.inProgress())return;t.selected&&t.selected.isDeletable()&&t.selected.isMovable()&&(e.keyCode==t.utils.KeyCodes.C?(t.hideChaff(),t.copy_(t.selected)):e.keyCode!=t.utils.KeyCodes.X||t.selected.workspace.isFlyout||(t.copy_(t.selected),i=!0)),e.keyCode==t.utils.KeyCodes.V?t.clipboardXml_&&((e=t.clipboardSource_).isFlyout&&(e=e.targetWorkspace),t.clipboardTypeCounts_&&e.isCapacityAvailable(t.clipboardTypeCounts_)&&(t.Events.setGroup(!0),e.paste(t.clipboardXml_),t.Events.setGroup(!1))):e.keyCode==t.utils.KeyCodes.Z&&(t.hideChaff(),o.undo(e.shiftKey))}}i&&!t.selected.workspace.isFlyout&&(t.Events.setGroup(!0),t.hideChaff(),t.selected.dispose(!0,!0),t.Events.setGroup(!1))}},t.copy_=function(e){if(e.isComment)var o=e.toXmlWithXY();else{o=t.Xml.blockToDom(e,!0),t.Xml.deleteNext(o);var i=e.getRelativeToSurfaceXY();o.setAttribute("x",e.RTL?-i.x:i.x),o.setAttribute("y",i.y)}t.clipboardXml_=o,t.clipboardSource_=e.workspace,t.clipboardTypeCounts_=e.isComment?null:t.utils.getBlockTypeCounts(e,!0)},t.duplicate=function(e){var o=t.clipboardXml_,i=t.clipboardSource_;t.copy_(e),e.workspace.paste(t.clipboardXml_),t.clipboardXml_=o,t.clipboardSource_=i},t.onContextMenu_=function(e){t.utils.isTargetInput(e)||e.preventDefault()},t.hideChaff=function(e){t.Tooltip.hide(),t.WidgetDiv.hide(),t.DropDownDiv.hideWithoutAnimation(),e||((e=t.getMainWorkspace()).trashcan&&e.trashcan.flyout&&e.trashcan.flyout.hide(),(e=e.getToolbox())&&e.getFlyout()&&e.getFlyout().autoClose&&e.clearSelection())},t.getMainWorkspace=function(){return t.mainWorkspace},t.alert=function(t,e){alert(t),e&&e()},t.confirm=function(t,e){e(confirm(t))},t.prompt=function(t,e,o){o(prompt(t,e))},t.jsonInitFactory_=function(t){return function(){this.jsonInit(t)}},t.defineBlocksWithJsonArray=function(e){for(var o=0;o90-e||t>-90-e&&t<-90+e},t.HorizontalFlyout.prototype.getClientRect=function(){if(!this.svgGroup_)return null;var e=this.svgGroup_.getBoundingClientRect(),o=e.top;return this.toolboxPosition_==t.TOOLBOX_AT_TOP?new t.utils.Rect(-1e9,o+e.height,-1e9,1e9):new t.utils.Rect(o,1e9,-1e9,1e9)},t.HorizontalFlyout.prototype.reflowInternal_=function(){this.workspace_.scale=this.targetWorkspace_.scale;for(var e,o=0,i=this.workspace_.getTopBlocks(!1),n=0;e=i[n];n++)o=Math.max(o,e.getHeightWidth().height);if(o+=1.5*this.MARGIN,o*=this.workspace_.scale,o+=t.Scrollbar.scrollbarThickness,this.height_!=o){for(n=0;e=i[n];n++)e.flyoutRect_&&this.moveRectToBlock_(e.flyoutRect_,e);this.height_=o,this.position()}},t.VerticalFlyout=function(e){e.getMetrics=this.getMetrics_.bind(this),e.setMetrics=this.setMetrics_.bind(this),t.VerticalFlyout.superClass_.constructor.call(this,e),this.horizontalLayout_=!1},t.utils.object.inherits(t.VerticalFlyout,t.Flyout),t.VerticalFlyout.prototype.getMetrics_=function(){if(!this.isVisible())return null;try{var t=this.workspace_.getCanvas().getBBox()}catch(e){t={height:0,y:0,width:0,x:0}}var e=this.SCROLLBAR_PADDING,o=this.height_-2*this.SCROLLBAR_PADDING,i=this.width_;return this.RTL||(i-=this.SCROLLBAR_PADDING),{viewHeight:o,viewWidth:i,contentHeight:t.height*this.workspace_.scale+2*this.MARGIN,contentWidth:t.width*this.workspace_.scale+2*this.MARGIN,viewTop:-this.workspace_.scrollY+t.y,viewLeft:-this.workspace_.scrollX,contentTop:t.y,contentLeft:t.x,absoluteTop:e,absoluteLeft:0}},t.VerticalFlyout.prototype.setMetrics_=function(t){var e=this.getMetrics_();e&&("number"==typeof t.y&&(this.workspace_.scrollY=-e.contentHeight*t.y),this.workspace_.translate(this.workspace_.scrollX+e.absoluteLeft,this.workspace_.scrollY+e.absoluteTop))},t.VerticalFlyout.prototype.position=function(){if(this.isVisible()){var e=this.targetWorkspace_.getMetrics();e&&(this.height_=e.viewHeight,this.setBackgroundPath_(this.width_-this.CORNER_RADIUS,e.viewHeight-2*this.CORNER_RADIUS),this.positionAt_(this.width_,this.height_,this.targetWorkspace_.toolboxPosition==this.toolboxPosition_?e.toolboxWidth?this.toolboxPosition_==t.TOOLBOX_AT_LEFT?e.toolboxWidth:e.viewWidth-this.width_:this.toolboxPosition_==t.TOOLBOX_AT_LEFT?0:e.viewWidth:this.toolboxPosition_==t.TOOLBOX_AT_LEFT?0:e.viewWidth+e.absoluteLeft-this.width_,0))}},t.VerticalFlyout.prototype.setBackgroundPath_=function(e,o){var i=this.toolboxPosition_==t.TOOLBOX_AT_RIGHT,n=e+this.CORNER_RADIUS;(n=["M "+(i?n:0)+",0"]).push("h",i?-e:e),n.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,i?0:1,i?-this.CORNER_RADIUS:this.CORNER_RADIUS,this.CORNER_RADIUS),n.push("v",Math.max(0,o)),n.push("a",this.CORNER_RADIUS,this.CORNER_RADIUS,0,0,i?0:1,i?this.CORNER_RADIUS:-this.CORNER_RADIUS,this.CORNER_RADIUS),n.push("h",i?e:-e),n.push("z"),this.svgBackground_.setAttribute("d",n.join(" "))},t.VerticalFlyout.prototype.scrollToStart=function(){this.scrollbar_.set(0)},t.VerticalFlyout.prototype.wheel_=function(e){var o=t.utils.getScrollDeltaPixels(e);if(o.y){var i=this.getMetrics_();o=i.viewTop-i.contentTop+o.y,o=Math.min(o,i.contentHeight-i.viewHeight),o=Math.max(o,0),this.scrollbar_.set(o),t.WidgetDiv.hide()}e.preventDefault(),e.stopPropagation()},t.VerticalFlyout.prototype.layout_=function(t,e){this.workspace_.scale=this.targetWorkspace_.scale;for(var o,i=this.MARGIN,n=this.RTL?i:i+this.tabWidth_,s=0;o=t[s];s++)if("block"==o.type){for(var r,a=(o=o.block).getDescendants(!1),l=0;r=a[l];l++)r.isInFlyout=!0;o.render(),a=o.getSvgRoot(),l=o.getHeightWidth(),r=o.outputConnection?n-this.tabWidth_:n,o.moveBy(r,i),r=this.createRect_(o,this.RTL?r-l.width:r,i,l,s),this.addBlockListeners_(a,o,r),i+=l.height+e[s]}else"button"==o.type&&(this.initFlyoutButton_(o.button,n,i),i+=o.button.height+e[s])},t.VerticalFlyout.prototype.isDragTowardWorkspace=function(t){t=Math.atan2(t.y,t.x)/Math.PI*180;var e=this.dragAngleRange_;return t-e||t<-180+e||t>180-e},t.VerticalFlyout.prototype.getClientRect=function(){if(!this.svgGroup_)return null;var e=this.svgGroup_.getBoundingClientRect(),o=e.left;return this.toolboxPosition_==t.TOOLBOX_AT_LEFT?new t.utils.Rect(-1e9,1e9,-1e9,o+e.width):new t.utils.Rect(-1e9,1e9,o,1e9)},t.VerticalFlyout.prototype.reflowInternal_=function(){this.workspace_.scale=this.targetWorkspace_.scale;for(var e,o=0,i=this.workspace_.getTopBlocks(!1),n=0;e=i[n];n++){var s=e.getHeightWidth().width;e.outputConnection&&(s-=this.tabWidth_),o=Math.max(o,s)}for(n=0;e=this.buttons_[n];n++)o=Math.max(o,e.width);if(o+=1.5*this.MARGIN+this.tabWidth_,o*=this.workspace_.scale,o+=t.Scrollbar.scrollbarThickness,this.width_!=o){for(n=0;e=i[n];n++){if(this.RTL){s=e.getRelativeToSurfaceXY().x;var r=o/this.workspace_.scale-this.MARGIN;e.outputConnection||(r-=this.tabWidth_),e.moveBy(r-s,0)}e.flyoutRect_&&this.moveRectToBlock_(e.flyoutRect_,e)}if(this.RTL)for(n=0;e=this.buttons_[n];n++)i=e.getPosition().y,e.moveTo(o/this.workspace_.scale-e.width-this.MARGIN-this.tabWidth_,i);this.width_=o,this.position()}},t.FlyoutButton=function(e,o,i,n){this.workspace_=e,this.targetWorkspace_=o,this.text_=i.getAttribute("text"),this.position_=new t.utils.Coordinate(0,0),this.isLabel_=n,this.callbackKey_=i.getAttribute("callbackKey")||i.getAttribute("callbackkey"),this.cssClass_=i.getAttribute("web-class")||null,this.onMouseUpWrapper_=null},t.FlyoutButton.MARGIN_X=5,t.FlyoutButton.MARGIN_Y=2,t.FlyoutButton.prototype.width=0,t.FlyoutButton.prototype.height=0,t.FlyoutButton.prototype.createDom=function(){var e=this.isLabel_?"blocklyFlyoutLabel":"blocklyFlyoutButton";if(this.cssClass_&&(e+=" "+this.cssClass_),this.svgGroup_=t.utils.dom.createSvgElement("g",{class:e},this.workspace_.getCanvas()),!this.isLabel_)var o=t.utils.dom.createSvgElement("rect",{class:"blocklyFlyoutButtonShadow",rx:4,ry:4,x:1,y:1},this.svgGroup_);e=t.utils.dom.createSvgElement("rect",{class:this.isLabel_?"blocklyFlyoutLabelBackground":"blocklyFlyoutButtonBackground",rx:4,ry:4},this.svgGroup_);var i=t.utils.dom.createSvgElement("text",{class:this.isLabel_?"blocklyFlyoutLabelText":"blocklyText",x:0,y:0,"text-anchor":"middle"},this.svgGroup_),n=t.utils.replaceMessageReferences(this.text_);this.workspace_.RTL&&(n+="‏"),i.textContent=n,this.isLabel_&&(this.svgText_=i,this.workspace_.getThemeManager().subscribe(this.svgText_,"flyoutForegroundColour","fill"));var s=t.utils.style.getComputedStyle(i,"fontSize"),r=t.utils.style.getComputedStyle(i,"fontWeight"),a=t.utils.style.getComputedStyle(i,"fontFamily");return this.width=t.utils.dom.getFastTextWidthWithSizeString(i,s,r,a),n=t.utils.dom.measureFontMetrics(n,s,r,a),this.height=n.height,this.isLabel_||(this.width+=2*t.FlyoutButton.MARGIN_X,this.height+=2*t.FlyoutButton.MARGIN_Y,o.setAttribute("width",this.width),o.setAttribute("height",this.height)),e.setAttribute("width",this.width),e.setAttribute("height",this.height),i.setAttribute("x",this.width/2),i.setAttribute("y",this.height/2-n.height/2+n.baseline),this.updateTransform_(),this.onMouseUpWrapper_=t.bindEventWithChecks_(this.svgGroup_,"mouseup",this,this.onMouseUp_),this.svgGroup_},t.FlyoutButton.prototype.show=function(){this.updateTransform_(),this.svgGroup_.setAttribute("display","block")},t.FlyoutButton.prototype.updateTransform_=function(){this.svgGroup_.setAttribute("transform","translate("+this.position_.x+","+this.position_.y+")")},t.FlyoutButton.prototype.moveTo=function(t,e){this.position_.x=t,this.position_.y=e,this.updateTransform_()},t.FlyoutButton.prototype.getPosition=function(){return this.position_},t.FlyoutButton.prototype.getTargetWorkspace=function(){return this.targetWorkspace_},t.FlyoutButton.prototype.dispose=function(){this.onMouseUpWrapper_&&t.unbindEvent_(this.onMouseUpWrapper_),this.svgGroup_&&t.utils.dom.removeNode(this.svgGroup_),this.svgText_&&this.workspace_.getThemeManager().unsubscribe(this.svgText_)},t.FlyoutButton.prototype.onMouseUp_=function(t){(t=this.targetWorkspace_.getGesture(t))&&t.cancel(),this.isLabel_&&this.callbackKey_?console.warn("Labels should not have callbacks. Label text: "+this.text_):this.isLabel_||this.callbackKey_&&this.targetWorkspace_.getButtonCallback(this.callbackKey_)?this.isLabel_||this.targetWorkspace_.getButtonCallback(this.callbackKey_)(this):console.warn("Buttons should have callbacks. Button text: "+this.text_)},t.Css.register(".blocklyFlyoutButton {,fill: #888;,cursor: default;,},.blocklyFlyoutButtonShadow {,fill: #666;,},.blocklyFlyoutButton:hover {,fill: #aaa;,},.blocklyFlyoutLabel {,cursor: default;,},.blocklyFlyoutLabelBackground {,opacity: 0;,}".split(",")),t.Generator=function(t){this.name_=t,this.FUNCTION_NAME_PLACEHOLDER_REGEXP_=new RegExp(this.FUNCTION_NAME_PLACEHOLDER_,"g")},t.Generator.NAME_TYPE="generated_function",t.Generator.prototype.INFINITE_LOOP_TRAP=null,t.Generator.prototype.STATEMENT_PREFIX=null,t.Generator.prototype.STATEMENT_SUFFIX=null,t.Generator.prototype.INDENT=" ",t.Generator.prototype.COMMENT_WRAP=60,t.Generator.prototype.ORDER_OVERRIDES=[],t.Generator.prototype.workspaceToCode=function(e){e||(console.warn("No workspace specified in workspaceToCode call. Guessing."),e=t.getMainWorkspace());var o=[];this.init(e),e=e.getTopBlocks(!0);for(var i,n=0;i=e[n];n++){var s=this.blockToCode(i);Array.isArray(s)&&(s=s[0]),s&&(i.outputConnection&&(s=this.scrubNakedValue(s),this.STATEMENT_PREFIX&&!i.suppressPrefixSuffix&&(s=this.injectId(this.STATEMENT_PREFIX,i)+s),this.STATEMENT_SUFFIX&&!i.suppressPrefixSuffix&&(s+=this.injectId(this.STATEMENT_SUFFIX,i))),o.push(s))}return o=o.join("\n"),(o=(o=(o=this.finish(o)).replace(/^\s+\n/,"")).replace(/\n\s+$/,"\n")).replace(/[ \t]+\n/g,"\n")},t.Generator.prototype.prefixLines=function(t,e){return e+t.replace(/(?!\n$)\n/g,"\n"+e)},t.Generator.prototype.allNestedComments=function(t){var e=[];t=t.getDescendants(!0);for(var o=0;ot&&(t=(t=this.getParent())?t.getDepth()+1:0,this.setDepth_(t)),t},t.tree.BaseNode.prototype.setDepth_=function(t){if(t!=this.depth_){this.depth_=t;var e=this.getRowElement();if(e){var o=this.getPixelIndent_()+"px";this.rightToLeft_?e.style.paddingRight=o:e.style.paddingLeft=o}this.forEachChild((function(e){e.setDepth_(t+1)}))}},t.tree.BaseNode.prototype.contains=function(t){for(;t;){if(t==this)return!0;t=t.getParent()}return!1},t.tree.BaseNode.prototype.getChildren=function(){var t=[];return this.forEachChild((function(e){t.push(e)})),t},t.tree.BaseNode.prototype.getPreviousSibling=function(){return this.previousSibling_},t.tree.BaseNode.prototype.getNextSibling=function(){return this.nextSibling_},t.tree.BaseNode.prototype.isLastSibling=function(){return!this.nextSibling_},t.tree.BaseNode.prototype.isSelected=function(){return this.selected_},t.tree.BaseNode.prototype.select=function(){var t=this.getTree();t&&t.setSelectedItem(this)},t.tree.BaseNode.prototype.setSelected=function(e){if(this.selected_!=e){this.selected_=e,this.updateRow();var o=this.getElement();o&&(t.utils.aria.setState(o,t.utils.aria.State.SELECTED,e),e&&(e=this.getTree().getElement(),t.utils.aria.setState(e,t.utils.aria.State.ACTIVEDESCENDANT,this.getId())))}},t.tree.BaseNode.prototype.setExpanded=function(e){var o,i=e!=this.expanded_;this.expanded_=e;var n=this.getTree(),s=this.getElement();this.hasChildren()?(!e&&n&&this.contains(n.getSelectedItem())&&this.select(),s&&((o=this.getChildrenElement())&&(t.utils.style.setElementShown(o,e),t.utils.aria.setState(s,t.utils.aria.State.EXPANDED,e),e&&this.isInDocument()&&!o.hasChildNodes()&&(this.forEachChild((function(t){o.appendChild(t.toDom())})),this.forEachChild((function(t){t.enterDocument()})))),this.updateExpandIcon())):(o=this.getChildrenElement())&&t.utils.style.setElementShown(o,!1),s&&this.updateIcon_(),i&&(e?this.doNodeExpanded():this.doNodeCollapsed())},t.tree.BaseNode.prototype.doNodeExpanded=function(){},t.tree.BaseNode.prototype.doNodeCollapsed=function(){},t.tree.BaseNode.prototype.toggle=function(){this.setExpanded(!this.expanded_)},t.tree.BaseNode.prototype.toDom=function(){var t=this.expanded_&&this.hasChildren(),e=document.createElement("div");return e.style.backgroundPosition=this.getBackgroundPosition(),t||(e.style.display="none"),t&&this.forEachChild((function(t){e.appendChild(t.toDom())})),(t=document.createElement("div")).id=this.getId(),t.appendChild(this.getRowDom()),t.appendChild(e),t},t.tree.BaseNode.prototype.getPixelIndent_=function(){return Math.max(0,(this.getDepth()-1)*this.config_.indentWidth)},t.tree.BaseNode.prototype.getRowDom=function(){var t=document.createElement("div");return t.className=this.getRowClassName(),t.style["padding-"+(this.rightToLeft_?"right":"left")]=this.getPixelIndent_()+"px",t.appendChild(this.getIconDom()),t.appendChild(this.getLabelDom()),t},t.tree.BaseNode.prototype.getRowClassName=function(){var t="";return this.isSelected()&&(t=" "+(this.config_.cssSelectedRow||"")),this.config_.cssTreeRow+t},t.tree.BaseNode.prototype.getLabelDom=function(){var t=document.createElement("span");return t.className=this.config_.cssItemLabel||"",t.textContent=this.content,t},t.tree.BaseNode.prototype.getIconDom=function(){var t=document.createElement("span");return t.style.display="inline-block",t.className=this.getCalculatedIconClass(),t},t.tree.BaseNode.prototype.getCalculatedIconClass=function(){throw Error("unimplemented abstract method")},t.tree.BaseNode.prototype.getBackgroundPosition=function(){return(this.isLastSibling()?"-100":(this.getDepth()-1)*this.config_.indentWidth)+"px 0"},t.tree.BaseNode.prototype.getElement=function(){var e=t.tree.BaseNode.superClass_.getElement.call(this);return e||(e=document.getElementById(this.getId()),this.setElementInternal(e)),e},t.tree.BaseNode.prototype.getRowElement=function(){var t=this.getElement();return t?t.firstChild:null},t.tree.BaseNode.prototype.getIconElement=function(){var t=this.getRowElement();return t?t.firstChild:null},t.tree.BaseNode.prototype.getLabelElement=function(){var t=this.getRowElement();return t&&t.lastChild?t.lastChild.previousSibling:null},t.tree.BaseNode.prototype.getChildrenElement=function(){var t=this.getElement();return t?t.lastChild:null},t.tree.BaseNode.prototype.updateRow=function(){var t=this.getRowElement();t&&(t.className=this.getRowClassName())},t.tree.BaseNode.prototype.updateExpandIcon=function(){var t=this.getChildrenElement();t&&(t.style.backgroundPosition=this.getBackgroundPosition())},t.tree.BaseNode.prototype.updateIcon_=function(){this.getIconElement().className=this.getCalculatedIconClass()},t.tree.BaseNode.prototype.onMouseDown=function(t){"expand"==t.target.getAttribute("type")&&this.hasChildren()?this.isUserCollapsible_&&this.toggle():(this.select(),this.updateRow())},t.tree.BaseNode.prototype.onClick_=function(t){t.preventDefault()},t.tree.BaseNode.prototype.onKeyDown=function(e){var o=!0;switch(e.keyCode){case t.utils.KeyCodes.RIGHT:if(e.altKey)break;o=this.selectChild();break;case t.utils.KeyCodes.LEFT:if(e.altKey)break;o=this.selectParent();break;case t.utils.KeyCodes.DOWN:o=this.selectNext();break;case t.utils.KeyCodes.UP:o=this.selectPrevious();break;default:o=!1}return o&&e.preventDefault(),o},t.tree.BaseNode.prototype.selectNext=function(){var t=this.getNextShownNode();return t&&t.select(),!0},t.tree.BaseNode.prototype.selectPrevious=function(){var t=this.getPreviousShownNode();return t&&t.select(),!0},t.tree.BaseNode.prototype.selectParent=function(){if(this.hasChildren()&&this.expanded_&&this.isUserCollapsible_)this.setExpanded(!1);else{var t=this.getParent(),e=this.getTree();t&&t!=e&&t.select()}return!0},t.tree.BaseNode.prototype.selectChild=function(){return!!this.hasChildren()&&(this.expanded_?this.getChildAt(0).select():this.setExpanded(!0),!0)},t.tree.BaseNode.prototype.getLastShownDescendant=function(){return this.expanded_&&this.hasChildren()?this.getChildAt(this.getChildCount()-1).getLastShownDescendant():this},t.tree.BaseNode.prototype.getNextShownNode=function(){if(this.hasChildren()&&this.expanded_)return this.getChildAt(0);for(var t,e=this;e!=this.getTree();){if(null!=(t=e.getNextSibling()))return t;e=e.getParent()}return null},t.tree.BaseNode.prototype.getPreviousShownNode=function(){var t=this.getPreviousSibling();if(null!=t)return t.getLastShownDescendant();t=this.getParent();var e=this.getTree();return t==e||this==e?null:t},t.tree.BaseNode.prototype.setTreeInternal=function(t){this.tree!=t&&(this.tree=t,this.forEachChild((function(e){e.setTreeInternal(t)})))},t.tree.TreeNode=function(e,o,i){this.toolbox_=e,t.tree.BaseNode.call(this,o,i)},t.utils.object.inherits(t.tree.TreeNode,t.tree.BaseNode),t.tree.TreeNode.prototype.getTree=function(){if(this.tree)return this.tree;var t=this.getParent();return t&&(t=t.getTree())?(this.setTreeInternal(t),t):null},t.tree.TreeNode.prototype.getCalculatedIconClass=function(){var t=this.expanded_;if(t&&this.expandedIconClass)return this.expandedIconClass;var e=this.iconClass;if(!t&&e)return e;if(e=this.config_,this.hasChildren()){if(t&&e.cssExpandedFolderIcon)return e.cssTreeIcon+" "+e.cssExpandedFolderIcon;if(!t&&e.cssCollapsedFolderIcon)return e.cssTreeIcon+" "+e.cssCollapsedFolderIcon}else if(e.cssFileIcon)return e.cssTreeIcon+" "+e.cssFileIcon;return""},t.tree.TreeNode.prototype.onClick_=function(t){this.hasChildren()&&this.isUserCollapsible_?(this.toggle(),this.select()):this.isSelected()?this.getTree().setSelectedItem(null):this.select(),this.updateRow()},t.tree.TreeNode.prototype.onMouseDown=function(t){},t.tree.TreeNode.prototype.onKeyDown=function(e){if(this.tree.toolbox_.horizontalLayout_){var o={},i=t.utils.KeyCodes.DOWN,n=t.utils.KeyCodes.UP;o[t.utils.KeyCodes.RIGHT]=this.rightToLeft_?n:i,o[t.utils.KeyCodes.LEFT]=this.rightToLeft_?i:n,o[t.utils.KeyCodes.UP]=t.utils.KeyCodes.LEFT,o[t.utils.KeyCodes.DOWN]=t.utils.KeyCodes.RIGHT,Object.defineProperties(e,{keyCode:{value:o[e.keyCode]||e.keyCode}})}return t.tree.TreeNode.superClass_.onKeyDown.call(this,e)},t.tree.TreeNode.prototype.onSizeChanged=function(t){this.onSizeChanged_=t},t.tree.TreeNode.prototype.resizeToolbox_=function(){this.onSizeChanged_&&this.onSizeChanged_.call(this.toolbox_)},t.tree.TreeNode.prototype.doNodeExpanded=t.tree.TreeNode.prototype.resizeToolbox_,t.tree.TreeNode.prototype.doNodeCollapsed=t.tree.TreeNode.prototype.resizeToolbox_,t.tree.TreeControl=function(e,o){this.toolbox_=e,this.onKeydownWrapper_=this.onClickWrapper_=this.onBlurWrapper_=this.onFocusWrapper_=null,t.tree.BaseNode.call(this,"",o),this.selected_=this.expanded_=!0,this.selectedItem_=this},t.utils.object.inherits(t.tree.TreeControl,t.tree.BaseNode),t.tree.TreeControl.prototype.getTree=function(){return this},t.tree.TreeControl.prototype.getToolbox=function(){return this.toolbox_},t.tree.TreeControl.prototype.getDepth=function(){return 0},t.tree.TreeControl.prototype.handleFocus_=function(e){this.focused_=!0,e=this.getElement(),t.utils.dom.addClass(e,"focused"),this.selectedItem_&&this.selectedItem_.select()},t.tree.TreeControl.prototype.handleBlur_=function(e){this.focused_=!1,e=this.getElement(),t.utils.dom.removeClass(e,"focused")},t.tree.TreeControl.prototype.hasFocus=function(){return this.focused_},t.tree.TreeControl.prototype.setExpanded=function(t){this.expanded_=t},t.tree.TreeControl.prototype.getIconElement=function(){var t=this.getRowElement();return t?t.firstChild:null},t.tree.TreeControl.prototype.updateExpandIcon=function(){},t.tree.TreeControl.prototype.getRowClassName=function(){return t.tree.TreeControl.superClass_.getRowClassName.call(this)+" "+this.config_.cssHideRoot},t.tree.TreeControl.prototype.getCalculatedIconClass=function(){var t=this.expanded_;if(t&&this.expandedIconClass)return this.expandedIconClass;var e=this.iconClass;return!t&&e?e:t&&this.config_.cssExpandedRootIcon?this.config_.cssTreeIcon+" "+this.config_.cssExpandedRootIcon:""},t.tree.TreeControl.prototype.setSelectedItem=function(t){if(t!=this.selectedItem_&&(!this.onBeforeSelected_||this.onBeforeSelected_.call(this.toolbox_,t))){var e=this.getSelectedItem();this.selectedItem_&&this.selectedItem_.setSelected(!1),(this.selectedItem_=t)&&t.setSelected(!0),this.onAfterSelected_&&this.onAfterSelected_.call(this.toolbox_,e,t)}},t.tree.TreeControl.prototype.onBeforeSelected=function(t){this.onBeforeSelected_=t},t.tree.TreeControl.prototype.onAfterSelected=function(t){this.onAfterSelected_=t},t.tree.TreeControl.prototype.getSelectedItem=function(){return this.selectedItem_},t.tree.TreeControl.prototype.initAccessibility=function(){t.tree.TreeControl.superClass_.initAccessibility.call(this);var e=this.getElement();t.utils.aria.setRole(e,t.utils.aria.Role.TREE),t.utils.aria.setState(e,t.utils.aria.State.LABELLEDBY,this.getLabelElement().id)},t.tree.TreeControl.prototype.enterDocument=function(){t.tree.TreeControl.superClass_.enterDocument.call(this);var e=this.getElement();e.className=this.config_.cssRoot,e.setAttribute("hideFocus","true"),this.attachEvents_(),this.initAccessibility()},t.tree.TreeControl.prototype.exitDocument=function(){t.tree.TreeControl.superClass_.exitDocument.call(this),this.detachEvents_()},t.tree.TreeControl.prototype.attachEvents_=function(){var e=this.getElement();e.tabIndex=0,this.onFocusWrapper_=t.bindEvent_(e,"focus",this,this.handleFocus_),this.onBlurWrapper_=t.bindEvent_(e,"blur",this,this.handleBlur_),this.onClickWrapper_=t.bindEventWithChecks_(e,"click",this,this.handleMouseEvent_),this.onKeydownWrapper_=t.bindEvent_(e,"keydown",this,this.handleKeyEvent_)},t.tree.TreeControl.prototype.detachEvents_=function(){this.onFocusWrapper_&&(t.unbindEvent_(this.onFocusWrapper_),this.onFocusWrapper_=null),this.onBlurWrapper_&&(t.unbindEvent_(this.onBlurWrapper_),this.onBlurWrapper_=null),this.onClickWrapper_&&(t.unbindEvent_(this.onClickWrapper_),this.onClickWrapper_=null),this.onKeydownWrapper_&&(t.unbindEvent_(this.onKeydownWrapper_),this.onKeydownWrapper_=null)},t.tree.TreeControl.prototype.handleMouseEvent_=function(t){var e=this.getNodeFromEvent_(t);if(e)switch(t.type){case"mousedown":e.onMouseDown(t);break;case"click":e.onClick_(t)}},t.tree.TreeControl.prototype.handleKeyEvent_=function(e){var o=!1;return(o=this.selectedItem_&&this.selectedItem_.onKeyDown(e)||o)&&(t.utils.style.scrollIntoContainerView(this.selectedItem_.getElement(),this.getElement().parentNode),e.preventDefault()),o},t.tree.TreeControl.prototype.getNodeFromEvent_=function(e){for(var o=e.target;null!=o;){if(e=t.tree.BaseNode.allNodes[o.id])return e;if(o==this.getElement())break;if(o.getAttribute("role")==t.utils.aria.Role.GROUP)break;o=o.parentNode}return null},t.tree.TreeControl.prototype.createNode=function(e){return new t.tree.TreeNode(this.toolbox_,e||"",this.config_)},t.Toolbox=function(t){this.workspace_=t,this.RTL=t.options.RTL,this.horizontalLayout_=t.options.horizontalLayout,this.toolboxPosition=t.options.toolboxPosition,this.config_={indentWidth:19,cssRoot:"blocklyTreeRoot",cssHideRoot:"blocklyHidden",cssTreeRow:"blocklyTreeRow",cssItemLabel:"blocklyTreeLabel",cssTreeIcon:"blocklyTreeIcon",cssExpandedFolderIcon:"blocklyTreeIconOpen",cssFileIcon:"blocklyTreeIconNone",cssSelectedRow:"blocklyTreeSelected"},this.treeSeparatorConfig_={cssTreeRow:"blocklyTreeSeparator"},this.horizontalLayout_&&(this.config_.cssTreeRow+=t.RTL?" blocklyHorizontalTreeRtl":" blocklyHorizontalTree",this.treeSeparatorConfig_.cssTreeRow="blocklyTreeSeparatorHorizontal "+(t.RTL?"blocklyHorizontalTreeRtl":"blocklyHorizontalTree"),this.config_.cssTreeIcon=""),this.flyout_=null},t.Toolbox.prototype.width=0,t.Toolbox.prototype.height=0,t.Toolbox.prototype.selectedOption_=null,t.Toolbox.prototype.lastCategory_=null,t.Toolbox.prototype.init=function(){var e=this.workspace_,o=this.workspace_.getParentSvg();this.HtmlDiv=document.createElement("div"),this.HtmlDiv.className="blocklyToolboxDiv blocklyNonSelectable",this.HtmlDiv.setAttribute("dir",e.RTL?"RTL":"LTR"),o.parentNode.insertBefore(this.HtmlDiv,o);var i=e.getThemeManager();if(i.subscribe(this.HtmlDiv,"toolboxBackgroundColour","background-color"),i.subscribe(this.HtmlDiv,"toolboxForegroundColour","color"),t.bindEventWithChecks_(this.HtmlDiv,"mousedown",this,(function(e){t.utils.isRightButton(e)||e.target==this.HtmlDiv?t.hideChaff(!1):t.hideChaff(!0),t.Touch.clearTouchIdentifier()}),!1,!0),(i=new t.Options({parentWorkspace:e,rtl:e.RTL,oneBasedIndex:e.options.oneBasedIndex,horizontalLayout:e.horizontalLayout,renderer:e.options.renderer,rendererOverrides:e.options.rendererOverrides})).toolboxPosition=e.options.toolboxPosition,e.horizontalLayout){if(!t.HorizontalFlyout)throw Error("Missing require for Blockly.HorizontalFlyout");this.flyout_=new t.HorizontalFlyout(i)}else{if(!t.VerticalFlyout)throw Error("Missing require for Blockly.VerticalFlyout");this.flyout_=new t.VerticalFlyout(i)}if(!this.flyout_)throw Error("One of Blockly.VerticalFlyout or Blockly.Horizontal must berequired.");t.utils.dom.insertAfter(this.flyout_.createDom("svg"),o),this.flyout_.init(e),this.config_.cleardotPath=e.options.pathToMedia+"1x1.gif",this.config_.cssCollapsedFolderIcon="blocklyTreeIconClosed"+(e.RTL?"Rtl":"Ltr"),this.renderTree(e.options.languageTree)},t.Toolbox.prototype.renderTree=function(e){this.tree_&&(this.tree_.dispose(),this.lastCategory_=null);var o=new t.tree.TreeControl(this,this.config_);this.tree_=o,o.setSelectedItem(null),o.onBeforeSelected(this.handleBeforeTreeSelected_),o.onAfterSelected(this.handleAfterTreeSelected_);var i=null;if(e){if(this.tree_.blocks=[],this.hasColours_=!1,i=this.syncTrees_(e,this.tree_,this.workspace_.options.pathToMedia),this.tree_.blocks.length)throw Error("Toolbox cannot have both blocks and categories in the root level.");this.workspace_.resizeContents()}o.render(this.HtmlDiv),i&&o.setSelectedItem(i),this.addColour_(),this.position(),this.horizontalLayout_&&t.utils.aria.setState(this.tree_.getElement(),t.utils.aria.State.ORIENTATION,"horizontal")},t.Toolbox.prototype.handleBeforeTreeSelected_=function(t){if(t==this.tree_)return!1;if(this.lastCategory_&&(this.lastCategory_.getRowElement().style.backgroundColor=""),t){var e=t.hexColour||"#57e";t.getRowElement().style.backgroundColor=e,this.addColour_(t)}return!0},t.Toolbox.prototype.handleAfterTreeSelected_=function(e,o){o&&o.blocks&&o.blocks.length?(this.flyout_.show(o.blocks),this.lastCategory_!=o&&this.flyout_.scrollToStart(),this.workspace_.keyboardAccessibilityMode&&t.navigation.setState(t.navigation.STATE_TOOLBOX)):(this.flyout_.hide(),!this.workspace_.keyboardAccessibilityMode||o instanceof t.Toolbox.TreeSeparator||t.navigation.setState(t.navigation.STATE_WS)),e!=o&&e!=this&&((e=new t.Events.Ui(null,"category",e&&e.content,o&&o.content)).workspaceId=this.workspace_.id,t.Events.fire(e)),o&&(this.lastCategory_=o)},t.Toolbox.prototype.handleNodeSizeChanged_=function(){t.svgResize(this.workspace_)},t.Toolbox.prototype.onBlocklyAction=function(e){var o=this.tree_.getSelectedItem();if(!o)return!1;switch(e.name){case t.navigation.actionNames.PREVIOUS:return o.selectPrevious();case t.navigation.actionNames.OUT:return o.selectParent();case t.navigation.actionNames.NEXT:return o.selectNext();case t.navigation.actionNames.IN:return o.selectChild();default:return!1}},t.Toolbox.prototype.dispose=function(){this.flyout_.dispose(),this.tree_.dispose(),this.workspace_.getThemeManager().unsubscribe(this.HtmlDiv),t.utils.dom.removeNode(this.HtmlDiv),this.lastCategory_=null},t.Toolbox.prototype.getWidth=function(){return this.width},t.Toolbox.prototype.getHeight=function(){return this.height},t.Toolbox.prototype.getFlyout=function(){return this.flyout_},t.Toolbox.prototype.position=function(){var e=this.HtmlDiv;if(e){var o=t.svgSize(this.workspace_.getParentSvg());this.horizontalLayout_?(e.style.left="0",e.style.height="auto",e.style.width=o.width+"px",this.height=e.offsetHeight,this.toolboxPosition==t.TOOLBOX_AT_TOP?e.style.top="0":e.style.bottom="0"):(this.toolboxPosition==t.TOOLBOX_AT_RIGHT?e.style.right="0":e.style.left="0",e.style.height=o.height+"px",this.width=e.offsetWidth),this.flyout_.position()}},t.Toolbox.prototype.syncTrees_=function(e,o,i){for(var n,s=null,r=null,a=0;n=e.childNodes[a];a++)if(n.tagName)switch(n.tagName.toUpperCase()){case"CATEGORY":r=t.utils.replaceMessageReferences(n.getAttribute("name"));var l=this.tree_.createNode(r);l.onSizeChanged(this.handleNodeSizeChanged_),l.blocks=[],o.add(l);var c=n.getAttribute("custom");c?l.blocks=c:(c=this.syncTrees_(n,l,i))&&(s=c),c=n.getAttribute("categorystyle");var h=n.getAttribute("colour");h&&c?(l.hexColour="",console.warn('Toolbox category "'+r+'" can not have both a style and a colour')):c?this.setColourFromStyle_(c,l,r):this.setColour_(h,l,r),"true"==n.getAttribute("expanded")?(l.blocks.length&&(s=l),l.setExpanded(!0)):l.setExpanded(!1),r=n;break;case"SEP":if(r&&"CATEGORY"==r.tagName.toUpperCase()){o.add(new t.Toolbox.TreeSeparator(this.treeSeparatorConfig_));break}case"BLOCK":case"SHADOW":case"LABEL":case"BUTTON":o.blocks.push(n),r=n}return s},t.Toolbox.prototype.setColour_=function(e,o,i){if(null===(e=t.utils.replaceMessageReferences(e))||""===e)o.hexColour="";else{var n=Number(e);isNaN(n)?(n=t.utils.colour.parse(e))?(o.hexColour=n,this.hasColours_=!0):(o.hexColour="",console.warn('Toolbox category "'+i+'" has unrecognized colour attribute: '+e)):(o.hexColour=t.hueToHex(n),this.hasColours_=!0)}},t.Toolbox.prototype.setColourFromStyle_=function(t,e,o){e.styleName=t;var i=this.workspace_.getTheme();t&&i&&((i=i.categoryStyles[t])&&i.colour?this.setColour_(i.colour,e,o):console.warn('Style "'+t+'" must exist and contain a colour value'))},t.Toolbox.prototype.updateColourFromTheme_=function(t){if(t=t||this.tree_){t=t.getChildren(!1);for(var e,o=0;e=t[o];o++)e.styleName&&(this.setColourFromStyle_(e.styleName,e,""),this.addColour_()),this.updateColourFromTheme_(e)}},t.Toolbox.prototype.updateColourFromTheme=function(){var t=this.tree_;t&&(this.updateColourFromTheme_(t),this.updateSelectedItemColour_(t))},t.Toolbox.prototype.updateSelectedItemColour_=function(t){if(t=t.getSelectedItem()){var e=t.hexColour||"#57e";t.getRowElement().style.backgroundColor=e,this.addColour_(t)}},t.Toolbox.prototype.addColour_=function(t){t=(t||this.tree_).getChildren(!1);for(var e,o=0;e=t[o];o++){var i=e.getRowElement();if(i){var n=this.hasColours_?"8px solid "+(e.hexColour||"#ddd"):"none";this.workspace_.RTL?i.style.borderRight=n:i.style.borderLeft=n}this.addColour_(e)}},t.Toolbox.prototype.clearSelection=function(){this.tree_.setSelectedItem(null)},t.Toolbox.prototype.addStyle=function(e){t.utils.dom.addClass(this.HtmlDiv,e)},t.Toolbox.prototype.removeStyle=function(e){t.utils.dom.removeClass(this.HtmlDiv,e)},t.Toolbox.prototype.getClientRect=function(){if(!this.HtmlDiv)return null;var e=this.HtmlDiv.getBoundingClientRect(),o=e.top,i=o+e.height,n=e.left;return e=n+e.width,this.toolboxPosition==t.TOOLBOX_AT_TOP?new t.utils.Rect(-1e7,i,-1e7,1e7):this.toolboxPosition==t.TOOLBOX_AT_BOTTOM?new t.utils.Rect(o,1e7,-1e7,1e7):this.toolboxPosition==t.TOOLBOX_AT_LEFT?new t.utils.Rect(-1e7,1e7,-1e7,e):new t.utils.Rect(-1e7,1e7,n,1e7)},t.Toolbox.prototype.refreshSelection=function(){var t=this.tree_.getSelectedItem();t&&t.blocks&&this.flyout_.show(t.blocks)},t.Toolbox.prototype.selectFirstCategory=function(){this.tree_.getSelectedItem()||this.tree_.selectChild()},t.Toolbox.TreeSeparator=function(e){t.tree.TreeNode.call(this,null,"",e)},t.utils.object.inherits(t.Toolbox.TreeSeparator,t.tree.TreeNode),t.Css.register([".blocklyToolboxDelete {",'cursor: url("<<>>/handdelete.cur"), auto;',"}",".blocklyToolboxGrab {",'cursor: url("<<>>/handclosed.cur"), auto;',"cursor: grabbing;","cursor: -webkit-grabbing;","}",".blocklyToolboxDiv {","background-color: #ddd;","overflow-x: visible;","overflow-y: auto;","position: absolute;","z-index: 70;","-webkit-tap-highlight-color: transparent;","}",".blocklyTreeRoot {","padding: 4px 0;","}",".blocklyTreeRoot:focus {","outline: none;","}",".blocklyTreeRow {","height: 22px;","line-height: 22px;","margin-bottom: 3px;","padding-right: 8px;","white-space: nowrap;","}",".blocklyHorizontalTree {","float: left;","margin: 1px 5px 8px 0;","}",".blocklyHorizontalTreeRtl {","float: right;","margin: 1px 0 8px 5px;","}",'.blocklyToolboxDiv[dir="RTL"] .blocklyTreeRow {',"margin-left: 8px;","}",".blocklyTreeRow:not(.blocklyTreeSelected):hover {","background-color: rgba(255, 255, 255, 0.2);","}",".blocklyTreeSeparator {","border-bottom: solid #e5e5e5 1px;","height: 0;","margin: 5px 0;","}",".blocklyTreeSeparatorHorizontal {","border-right: solid #e5e5e5 1px;","width: 0;","padding: 5px 0;","margin: 0 5px;","}",".blocklyTreeIcon {","background-image: url(<<>>/sprites.png);","height: 16px;","vertical-align: middle;","width: 16px;","}",".blocklyTreeIconClosedLtr {","background-position: -32px -1px;","}",".blocklyTreeIconClosedRtl {","background-position: 0 -1px;","}",".blocklyTreeIconOpen {","background-position: -16px -1px;","}",".blocklyTreeSelected>.blocklyTreeIconClosedLtr {","background-position: -32px -17px;","}",".blocklyTreeSelected>.blocklyTreeIconClosedRtl {","background-position: 0 -17px;","}",".blocklyTreeSelected>.blocklyTreeIconOpen {","background-position: -16px -17px;","}",".blocklyTreeIconNone,",".blocklyTreeSelected>.blocklyTreeIconNone {","background-position: -48px -1px;","}",".blocklyTreeLabel {","cursor: default;","font-family: sans-serif;","font-size: 16px;","padding: 0 3px;","vertical-align: middle;","}",".blocklyToolboxDelete .blocklyTreeLabel {",'cursor: url("<<>>/handdelete.cur"), auto;',"}",".blocklyTreeSelected .blocklyTreeLabel {","color: #fff;","}"]),t.Trashcan=function(e){if(this.workspace_=e,this.contents_=[],this.flyout=null,!(0>=this.workspace_.options.maxTrashcanContents)){if(e=new t.Options({scrollbars:!0,parentWorkspace:this.workspace_,rtl:this.workspace_.RTL,oneBasedIndex:this.workspace_.options.oneBasedIndex,renderer:this.workspace_.options.renderer,rendererOverrides:this.workspace_.options.rendererOverrides}),this.workspace_.horizontalLayout){if(e.toolboxPosition=this.workspace_.toolboxPosition==t.TOOLBOX_AT_TOP?t.TOOLBOX_AT_BOTTOM:t.TOOLBOX_AT_TOP,!t.HorizontalFlyout)throw Error("Missing require for Blockly.HorizontalFlyout");this.flyout=new t.HorizontalFlyout(e)}else{if(e.toolboxPosition=this.workspace_.toolboxPosition==t.TOOLBOX_AT_RIGHT?t.TOOLBOX_AT_LEFT:t.TOOLBOX_AT_RIGHT,!t.VerticalFlyout)throw Error("Missing require for Blockly.VerticalFlyout");this.flyout=new t.VerticalFlyout(e)}this.workspace_.addChangeListener(this.onDelete_.bind(this))}},t.Trashcan.prototype.WIDTH_=47,t.Trashcan.prototype.BODY_HEIGHT_=44,t.Trashcan.prototype.LID_HEIGHT_=16,t.Trashcan.prototype.MARGIN_BOTTOM_=20,t.Trashcan.prototype.MARGIN_SIDE_=20,t.Trashcan.prototype.MARGIN_HOTSPOT_=10,t.Trashcan.prototype.SPRITE_LEFT_=0,t.Trashcan.prototype.SPRITE_TOP_=32,t.Trashcan.prototype.HAS_BLOCKS_LID_ANGLE_=.1,t.Trashcan.ANIMATION_LENGTH_=80,t.Trashcan.ANIMATION_FRAMES_=4,t.Trashcan.OPACITY_MIN_=.4,t.Trashcan.OPACITY_MAX_=.8,t.Trashcan.MAX_LID_ANGLE_=45,t.Trashcan.prototype.isOpen=!1,t.Trashcan.prototype.minOpenness_=0,t.Trashcan.prototype.svgGroup_=null,t.Trashcan.prototype.svgLid_=null,t.Trashcan.prototype.lidTask_=0,t.Trashcan.prototype.lidOpen_=0,t.Trashcan.prototype.left_=0,t.Trashcan.prototype.top_=0,t.Trashcan.prototype.createDom=function(){this.svgGroup_=t.utils.dom.createSvgElement("g",{class:"blocklyTrash"},null);var e=String(Math.random()).substring(2),o=t.utils.dom.createSvgElement("clipPath",{id:"blocklyTrashBodyClipPath"+e},this.svgGroup_);t.utils.dom.createSvgElement("rect",{width:this.WIDTH_,height:this.BODY_HEIGHT_,y:this.LID_HEIGHT_},o);var i=t.utils.dom.createSvgElement("image",{width:t.SPRITE.width,x:-this.SPRITE_LEFT_,height:t.SPRITE.height,y:-this.SPRITE_TOP_,"clip-path":"url(#blocklyTrashBodyClipPath"+e+")"},this.svgGroup_);return i.setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",this.workspace_.options.pathToMedia+t.SPRITE.url),o=t.utils.dom.createSvgElement("clipPath",{id:"blocklyTrashLidClipPath"+e},this.svgGroup_),t.utils.dom.createSvgElement("rect",{width:this.WIDTH_,height:this.LID_HEIGHT_},o),this.svgLid_=t.utils.dom.createSvgElement("image",{width:t.SPRITE.width,x:-this.SPRITE_LEFT_,height:t.SPRITE.height,y:-this.SPRITE_TOP_,"clip-path":"url(#blocklyTrashLidClipPath"+e+")"},this.svgGroup_),this.svgLid_.setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",this.workspace_.options.pathToMedia+t.SPRITE.url),t.bindEventWithChecks_(this.svgGroup_,"mouseup",this,this.click),t.bindEvent_(i,"mouseover",this,this.mouseOver_),t.bindEvent_(i,"mouseout",this,this.mouseOut_),this.animateLid_(),this.svgGroup_},t.Trashcan.prototype.init=function(e){return 0this.minOpenness_&&1>this.lidOpen_&&(this.lidTask_=setTimeout(this.animateLid_.bind(this),t.Trashcan.ANIMATION_LENGTH_/e))},t.Trashcan.prototype.setLidAngle_=function(e){var o=this.workspace_.toolboxPosition==t.TOOLBOX_AT_RIGHT||this.workspace_.horizontalLayout&&this.workspace_.RTL;this.svgLid_.setAttribute("transform","rotate("+(o?-e:e)+","+(o?4:this.WIDTH_-4)+","+(this.LID_HEIGHT_-2)+")")},t.Trashcan.prototype.setMinOpenness_=function(e){this.minOpenness_=e,this.isOpen||this.setLidAngle_(e*t.Trashcan.MAX_LID_ANGLE_)},t.Trashcan.prototype.close=function(){this.setOpen(!1)},t.Trashcan.prototype.click=function(){if(this.contents_.length){for(var e,o=[],i=0;e=this.contents_[i];i++)o[i]=t.Xml.textToDom(e);this.flyout.show(o)}},t.Trashcan.prototype.mouseOver_=function(){this.contents_.length&&this.setOpen(!0)},t.Trashcan.prototype.mouseOut_=function(){this.setOpen(!1)},t.Trashcan.prototype.onDelete_=function(e){if(!(0>=this.workspace_.options.maxTrashcanContents)&&e.type==t.Events.BLOCK_DELETE&&"shadow"!=e.oldXml.tagName.toLowerCase()&&(e=this.cleanBlockXML_(e.oldXml),-1==this.contents_.indexOf(e))){for(this.contents_.unshift(e);this.contents_.length>this.workspace_.options.maxTrashcanContents;)this.contents_.pop();this.setMinOpenness_(this.HAS_BLOCKS_LID_ANGLE_)}},t.Trashcan.prototype.cleanBlockXML_=function(e){for(var o=e=e.cloneNode(!0);o;){o.removeAttribute&&(o.removeAttribute("x"),o.removeAttribute("y"),o.removeAttribute("id"),o.removeAttribute("disabled"),"comment"==o.nodeName&&(o.removeAttribute("h"),o.removeAttribute("w"),o.removeAttribute("pinned")));var i=o.firstChild||o.nextSibling;if(!i)for(i=o.parentNode;i;){if(i.nextSibling){i=i.nextSibling;break}i=i.parentNode}o=i}return t.Xml.domToText(e)},t.VariablesDynamic={},t.VariablesDynamic.onCreateVariableButtonClick_String=function(e){t.Variables.createVariableButtonHandler(e.getTargetWorkspace(),void 0,"String")},t.VariablesDynamic.onCreateVariableButtonClick_Number=function(e){t.Variables.createVariableButtonHandler(e.getTargetWorkspace(),void 0,"Number")},t.VariablesDynamic.onCreateVariableButtonClick_Colour=function(e){t.Variables.createVariableButtonHandler(e.getTargetWorkspace(),void 0,"Colour")},t.VariablesDynamic.flyoutCategory=function(e){var o=[],i=document.createElement("button");return i.setAttribute("text",t.Msg.NEW_STRING_VARIABLE),i.setAttribute("callbackKey","CREATE_VARIABLE_STRING"),o.push(i),(i=document.createElement("button")).setAttribute("text",t.Msg.NEW_NUMBER_VARIABLE),i.setAttribute("callbackKey","CREATE_VARIABLE_NUMBER"),o.push(i),(i=document.createElement("button")).setAttribute("text",t.Msg.NEW_COLOUR_VARIABLE),i.setAttribute("callbackKey","CREATE_VARIABLE_COLOUR"),o.push(i),e.registerButtonCallback("CREATE_VARIABLE_STRING",t.VariablesDynamic.onCreateVariableButtonClick_String),e.registerButtonCallback("CREATE_VARIABLE_NUMBER",t.VariablesDynamic.onCreateVariableButtonClick_Number),e.registerButtonCallback("CREATE_VARIABLE_COLOUR",t.VariablesDynamic.onCreateVariableButtonClick_Colour),e=t.VariablesDynamic.flyoutCategoryBlocks(e),o.concat(e)},t.VariablesDynamic.flyoutCategoryBlocks=function(e){var o=[];if(0<(e=e.getAllVariables()).length){if(t.Blocks.variables_set_dynamic){var i=e[e.length-1],n=t.utils.xml.createElement("block");n.setAttribute("type","variables_set_dynamic"),n.setAttribute("gap",24),n.appendChild(t.Variables.generateVariableFieldDom(i)),o.push(n)}if(t.Blocks.variables_get_dynamic){e.sort(t.VariableModel.compareByName),i=0;for(var s;s=e[i];i++)(n=t.utils.xml.createElement("block")).setAttribute("type","variables_get_dynamic"),n.setAttribute("gap",8),n.appendChild(t.Variables.generateVariableFieldDom(s)),o.push(n)}}return o},t.ZoomControls=function(t){this.workspace_=t},t.ZoomControls.prototype.WIDTH_=32,t.ZoomControls.prototype.HEIGHT_=110,t.ZoomControls.prototype.MARGIN_BOTTOM_=20,t.ZoomControls.prototype.MARGIN_SIDE_=20,t.ZoomControls.prototype.svgGroup_=null,t.ZoomControls.prototype.left_=0,t.ZoomControls.prototype.top_=0,t.ZoomControls.prototype.createDom=function(){this.svgGroup_=t.utils.dom.createSvgElement("g",{},null);var e=String(Math.random()).substring(2);return this.createZoomOutSvg_(e),this.createZoomInSvg_(e),this.workspace_.isMovable()&&this.createZoomResetSvg_(e),this.svgGroup_},t.ZoomControls.prototype.init=function(t){return this.verticalSpacing_=this.MARGIN_BOTTOM_+t,this.verticalSpacing_+this.HEIGHT_},t.ZoomControls.prototype.dispose=function(){this.svgGroup_&&t.utils.dom.removeNode(this.svgGroup_)},t.ZoomControls.prototype.position=function(){if(this.verticalSpacing_){var e=this.workspace_.getMetrics();e&&(this.left_=e.toolboxPosition==t.TOOLBOX_AT_LEFT||this.workspace_.horizontalLayout&&!this.workspace_.RTL?e.viewWidth+e.absoluteLeft-this.WIDTH_-this.MARGIN_SIDE_-t.Scrollbar.scrollbarThickness:this.MARGIN_SIDE_+t.Scrollbar.scrollbarThickness,e.toolboxPosition==t.TOOLBOX_AT_BOTTOM?(this.top_=this.verticalSpacing_,this.zoomInGroup_.setAttribute("transform","translate(0, 34)"),this.zoomResetGroup_&&this.zoomResetGroup_.setAttribute("transform","translate(0, 77)")):(this.top_=e.viewHeight+e.absoluteTop-this.HEIGHT_-this.verticalSpacing_,this.zoomInGroup_.setAttribute("transform","translate(0, 43)"),this.zoomOutGroup_.setAttribute("transform","translate(0, 77)")),this.svgGroup_.setAttribute("transform","translate("+this.left_+","+this.top_+")"))}},t.ZoomControls.prototype.createZoomOutSvg_=function(e){var o=this.workspace_;this.zoomOutGroup_=t.utils.dom.createSvgElement("g",{class:"blocklyZoom"},this.svgGroup_);var i=t.utils.dom.createSvgElement("clipPath",{id:"blocklyZoomoutClipPath"+e},this.zoomOutGroup_);t.utils.dom.createSvgElement("rect",{width:32,height:32},i),(e=t.utils.dom.createSvgElement("image",{width:t.SPRITE.width,height:t.SPRITE.height,x:-64,y:-92,"clip-path":"url(#blocklyZoomoutClipPath"+e+")"},this.zoomOutGroup_)).setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",o.options.pathToMedia+t.SPRITE.url),t.bindEventWithChecks_(e,"mousedown",null,(function(e){o.markFocused(),o.zoomCenter(-1),t.Touch.clearTouchIdentifier(),e.stopPropagation(),e.preventDefault()}))},t.ZoomControls.prototype.createZoomInSvg_=function(e){var o=this.workspace_;this.zoomInGroup_=t.utils.dom.createSvgElement("g",{class:"blocklyZoom"},this.svgGroup_);var i=t.utils.dom.createSvgElement("clipPath",{id:"blocklyZoominClipPath"+e},this.zoomInGroup_);t.utils.dom.createSvgElement("rect",{width:32,height:32},i),(e=t.utils.dom.createSvgElement("image",{width:t.SPRITE.width,height:t.SPRITE.height,x:-32,y:-92,"clip-path":"url(#blocklyZoominClipPath"+e+")"},this.zoomInGroup_)).setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",o.options.pathToMedia+t.SPRITE.url),t.bindEventWithChecks_(e,"mousedown",null,(function(e){o.markFocused(),o.zoomCenter(1),t.Touch.clearTouchIdentifier(),e.stopPropagation(),e.preventDefault()}))},t.ZoomControls.prototype.createZoomResetSvg_=function(e){var o=this.workspace_;this.zoomResetGroup_=t.utils.dom.createSvgElement("g",{class:"blocklyZoom"},this.svgGroup_);var i=t.utils.dom.createSvgElement("clipPath",{id:"blocklyZoomresetClipPath"+e},this.zoomResetGroup_);t.utils.dom.createSvgElement("rect",{width:32,height:32},i),(e=t.utils.dom.createSvgElement("image",{width:t.SPRITE.width,height:t.SPRITE.height,y:-92,"clip-path":"url(#blocklyZoomresetClipPath"+e+")"},this.zoomResetGroup_)).setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",o.options.pathToMedia+t.SPRITE.url),t.bindEventWithChecks_(e,"mousedown",null,(function(e){o.markFocused(),o.setScale(o.options.zoomOptions.startScale),o.beginCanvasTransition(),o.scrollCenter(),setTimeout(o.endCanvasTransition.bind(o),500),t.Touch.clearTouchIdentifier(),e.stopPropagation(),e.preventDefault()}))},t.Css.register([".blocklyZoom>image, .blocklyZoom>svg>image {","opacity: .4;","}",".blocklyZoom>image:hover, .blocklyZoom>svg>image:hover {","opacity: .6;","}",".blocklyZoom>image:active, .blocklyZoom>svg>image:active {","opacity: .8;","}"]),t.Mutator=function(e){t.Mutator.superClass_.constructor.call(this,null),this.quarkNames_=e},t.utils.object.inherits(t.Mutator,t.Icon),t.Mutator.prototype.workspaceWidth_=0,t.Mutator.prototype.workspaceHeight_=0,t.Mutator.prototype.setBlock=function(t){this.block_=t},t.Mutator.prototype.getWorkspace=function(){return this.workspace_},t.Mutator.prototype.drawIcon_=function(e){t.utils.dom.createSvgElement("rect",{class:"blocklyIconShape",rx:"4",ry:"4",height:"16",width:"16"},e),t.utils.dom.createSvgElement("path",{class:"blocklyIconSymbol",d:"m4.203,7.296 0,1.368 -0.92,0.677 -0.11,0.41 0.9,1.559 0.41,0.11 1.043,-0.457 1.187,0.683 0.127,1.134 0.3,0.3 1.8,0 0.3,-0.299 0.127,-1.138 1.185,-0.682 1.046,0.458 0.409,-0.11 0.9,-1.559 -0.11,-0.41 -0.92,-0.677 0,-1.366 0.92,-0.677 0.11,-0.41 -0.9,-1.559 -0.409,-0.109 -1.046,0.458 -1.185,-0.682 -0.127,-1.138 -0.3,-0.299 -1.8,0 -0.3,0.3 -0.126,1.135 -1.187,0.682 -1.043,-0.457 -0.41,0.11 -0.899,1.559 0.108,0.409z"},e),t.utils.dom.createSvgElement("circle",{class:"blocklyIconShape",r:"2.7",cx:"8",cy:"8"},e)},t.Mutator.prototype.iconClick_=function(e){this.block_.isEditable()&&t.Icon.prototype.iconClick_.call(this,e)},t.Mutator.prototype.createEditor_=function(){if(this.svgDialog_=t.utils.dom.createSvgElement("svg",{x:t.Bubble.BORDER_WIDTH,y:t.Bubble.BORDER_WIDTH},null),this.quarkNames_.length)for(var e,o=t.utils.xml.createElement("xml"),i=0;e=this.quarkNames_[i];i++){var n=t.utils.xml.createElement("block");n.setAttribute("type",e),o.appendChild(n)}else o=null;return(i=new t.Options({disable:!1,parentWorkspace:this.block_.workspace,media:this.block_.workspace.options.pathToMedia,rtl:this.block_.RTL,horizontalLayout:!1,renderer:this.block_.workspace.options.renderer,rendererOverrides:this.block_.workspace.options.rendererOverrides})).toolboxPosition=this.block_.RTL?t.TOOLBOX_AT_RIGHT:t.TOOLBOX_AT_LEFT,i.languageTree=o,i.getMetrics=this.getFlyoutMetrics_.bind(this),this.workspace_=new t.WorkspaceSvg(i),this.workspace_.isMutator=!0,this.workspace_.addChangeListener(t.Events.disableOrphans),o=this.workspace_.addFlyout("g"),(i=this.workspace_.createDom("blocklyMutatorBackground")).insertBefore(o,this.workspace_.svgBlockCanvas_),this.svgDialog_.appendChild(i),this.svgDialog_},t.Mutator.prototype.updateEditable=function(){t.Mutator.superClass_.updateEditable.call(this),this.block_.isInFlyout||(this.block_.isEditable()?this.iconGroup_&&t.utils.dom.removeClass(this.iconGroup_,"blocklyIconGroupReadonly"):(this.setVisible(!1),this.iconGroup_&&t.utils.dom.addClass(this.iconGroup_,"blocklyIconGroupReadonly")))},t.Mutator.prototype.resizeBubble_=function(){var e=2*t.Bubble.BORDER_WIDTH,o=this.workspace_.getCanvas().getBBox(),i=this.block_.RTL?-o.x:o.width+o.x;o=o.height+3*e;var n=this.workspace_.getFlyout();n&&(n=n.getMetrics_(),o=Math.max(o,n.contentHeight+20)),i+=3*e,(Math.abs(this.workspaceWidth_-i)>e||Math.abs(this.workspaceHeight_-o)>e)&&(this.workspaceWidth_=i,this.workspaceHeight_=o,this.bubble_.setBubbleSize(i+e,o+e),this.svgDialog_.setAttribute("width",this.workspaceWidth_),this.svgDialog_.setAttribute("height",this.workspaceHeight_)),this.block_.RTL&&(e="translate("+this.workspaceWidth_+",0)",this.workspace_.getCanvas().setAttribute("transform",e)),this.workspace_.resize()},t.Mutator.prototype.onBubbleMove_=function(){this.workspace_&&this.workspace_.recordDeleteAreas()},t.Mutator.prototype.setVisible=function(e){if(e!=this.isVisible())if(t.Events.fire(new t.Events.Ui(this.block_,"mutatorOpen",!e,e)),e){this.bubble_=new t.Bubble(this.block_.workspace,this.createEditor_(),this.block_.pathObject.svgPath,this.iconXY_,null,null),this.bubble_.setSvgId(this.block_.id),this.bubble_.registerMoveEvent(this.onBubbleMove_.bind(this));var o=this.workspace_.options.languageTree;e=this.workspace_.getFlyout(),o&&(e.init(this.workspace_),e.show(o.childNodes)),this.rootBlock_=this.block_.decompose(this.workspace_),o=this.rootBlock_.getDescendants(!1);for(var i,n=0;i=o[n];n++)i.render();if(this.rootBlock_.setMovable(!1),this.rootBlock_.setDeletable(!1),e?(o=2*e.CORNER_RADIUS,e=e.getWidth()+o):e=o=16,this.block_.RTL&&(e=-e),this.rootBlock_.moveBy(e,o),this.block_.saveConnections){var s=this,r=this.block_;r.saveConnections(this.rootBlock_),this.sourceListener_=function(){r.saveConnections(s.rootBlock_)},this.block_.workspace.addChangeListener(this.sourceListener_)}this.resizeBubble_(),this.workspace_.addChangeListener(this.workspaceChanged_.bind(this)),this.applyColour()}else this.svgDialog_=null,this.workspace_.dispose(),this.rootBlock_=this.workspace_=null,this.bubble_.dispose(),this.bubble_=null,this.workspaceHeight_=this.workspaceWidth_=0,this.sourceListener_&&(this.block_.workspace.removeChangeListener(this.sourceListener_),this.sourceListener_=null)},t.Mutator.prototype.workspaceChanged_=function(e){if(e.type!=t.Events.UI&&(e.type!=t.Events.CHANGE||"disabled"!=e.element)){if(!this.workspace_.isDragging()){e=this.workspace_.getTopBlocks(!1);for(var o,i=0;o=e[i];i++){var n=o.getRelativeToSurfaceXY(),s=o.getHeightWidth();20>n.y+s.height&&o.moveBy(0,20-s.height-n.y)}}if(this.rootBlock_.workspace==this.workspace_){if(t.Events.setGroup(!0),e=(e=(o=this.block_).mutationToDom())&&t.Xml.domToText(e),o.compose(this.rootBlock_),o.initSvg(),o.render(),t.getMainWorkspace().keyboardAccessibilityMode&&t.navigation.moveCursorOnBlockMutation(o),e!=(i=(i=o.mutationToDom())&&t.Xml.domToText(i))){t.Events.fire(new t.Events.BlockChange(o,"mutation",null,e,i));var r=t.Events.getGroup();setTimeout((function(){t.Events.setGroup(r),o.bumpNeighbours(),t.Events.setGroup(!1)}),t.BUMP_DELAY)}this.workspace_.isDragging()||this.resizeBubble_(),t.Events.setGroup(!1)}}},t.Mutator.prototype.getFlyoutMetrics_=function(){return{viewHeight:this.workspaceHeight_,viewWidth:this.workspaceWidth_-this.workspace_.getFlyout().getWidth(),absoluteTop:0,absoluteLeft:this.workspace_.RTL?0:this.workspace_.getFlyout().getWidth()}},t.Mutator.prototype.dispose=function(){this.block_.mutator=null,t.Icon.prototype.dispose.call(this)},t.Mutator.prototype.updateBlockStyle=function(){var t=this.workspace_;if(t&&t.getAllBlocks(!1)){for(var e=t.getAllBlocks(!1),o=0;o=e&&this.sourceBlock_.outputConnection&&!o}else this.fullBlockClickTarget_=!1;this.fullBlockClickTarget_?this.clickTarget_=this.sourceBlock_.getSvgRoot():this.createBorderRect_(),this.createTextElement_()},t.FieldTextInput.prototype.doClassValidation_=function(t){return null==t?null:String(t)},t.FieldTextInput.prototype.doValueInvalid_=function(e){this.isBeingEdited_&&(this.isTextValid_=!1,e=this.value_,this.value_=this.htmlInput_.untypedDefaultValue_,this.sourceBlock_&&t.Events.isEnabled()&&t.Events.fire(new t.Events.BlockChange(this.sourceBlock_,"field",this.name||null,e,this.value_)))},t.FieldTextInput.prototype.doValueUpdate_=function(t){this.isTextValid_=!0,this.value_=t,this.isBeingEdited_||(this.isDirty_=!0)},t.FieldTextInput.prototype.applyColour=function(){this.sourceBlock_&&this.getConstants().FULL_BLOCK_FIELDS&&(this.borderRect_?this.borderRect_.setAttribute("stroke",this.sourceBlock_.style.colourTertiary):this.sourceBlock_.pathObject.svgPath.setAttribute("fill",this.getConstants().FIELD_BORDER_RECT_COLOUR))},t.FieldTextInput.prototype.render_=function(){if(t.FieldTextInput.superClass_.render_.call(this),this.isBeingEdited_){this.resizeEditor_();var e=this.htmlInput_;this.isTextValid_?(t.utils.dom.removeClass(e,"blocklyInvalidInput"),t.utils.aria.setState(e,t.utils.aria.State.INVALID,!1)):(t.utils.dom.addClass(e,"blocklyInvalidInput"),t.utils.aria.setState(e,t.utils.aria.State.INVALID,!0))}},t.FieldTextInput.prototype.setSpellcheck=function(t){t!=this.spellcheck_&&(this.spellcheck_=t,this.htmlInput_&&this.htmlInput_.setAttribute("spellcheck",this.spellcheck_))},t.FieldTextInput.prototype.showEditor_=function(e,o){this.workspace_=this.sourceBlock_.workspace,!(e=o||!1)&&(t.utils.userAgent.MOBILE||t.utils.userAgent.ANDROID||t.utils.userAgent.IPAD)?this.showPromptEditor_():this.showInlineEditor_(e)},t.FieldTextInput.prototype.showPromptEditor_=function(){var e=this;t.prompt(t.Msg.CHANGE_VALUE_TITLE,this.getText(),(function(t){e.setValue(t)}))},t.FieldTextInput.prototype.showInlineEditor_=function(e){t.WidgetDiv.show(this,this.sourceBlock_.RTL,this.widgetDispose_.bind(this)),this.htmlInput_=this.widgetCreate_(),this.isBeingEdited_=!0,e||(this.htmlInput_.focus({preventScroll:!0}),this.htmlInput_.select())},t.FieldTextInput.prototype.widgetCreate_=function(){var e=t.WidgetDiv.DIV;t.utils.dom.addClass(this.getClickTarget_(),"editing");var o=document.createElement("input");o.className="blocklyHtmlInput",o.setAttribute("spellcheck",this.spellcheck_);var i=this.workspace_.getScale(),n=this.getConstants().FIELD_TEXT_FONTSIZE*i+"pt";if(e.style.fontSize=n,o.style.fontSize=n,n=t.FieldTextInput.BORDERRADIUS*i+"px",this.fullBlockClickTarget_){n=((n=this.getScaledBBox()).bottom-n.top)/2+"px";var s=this.sourceBlock_.getParent()?this.sourceBlock_.getParent().style.colourTertiary:this.sourceBlock_.style.colourTertiary;o.style.border=1*i+"px solid "+s,e.style.borderRadius=n,e.style.transition="box-shadow 0.25s ease 0s",this.getConstants().FIELD_TEXTINPUT_BOX_SHADOW&&(e.style.boxShadow="rgba(255, 255, 255, 0.3) 0px 0px 0px "+4*i+"px")}return o.style.borderRadius=n,e.appendChild(o),o.value=o.defaultValue=this.getEditorText_(this.value_),o.untypedDefaultValue_=this.value_,o.oldValue_=null,this.resizeEditor_(),this.bindInputEvents_(o),o},t.FieldTextInput.prototype.widgetDispose_=function(){this.isBeingEdited_=!1,this.isTextValid_=!0,this.forceRerender(),this.onFinishEditing_&&this.onFinishEditing_(this.value_),this.unbindInputEvents_();var e=t.WidgetDiv.DIV.style;e.width="auto",e.height="auto",e.fontSize="",e.transition="",e.boxShadow="",this.htmlInput_=null,t.utils.dom.removeClass(this.getClickTarget_(),"editing")},t.FieldTextInput.prototype.bindInputEvents_=function(e){this.onKeyDownWrapper_=t.bindEventWithChecks_(e,"keydown",this,this.onHtmlInputKeyDown_),this.onKeyInputWrapper_=t.bindEventWithChecks_(e,"input",this,this.onHtmlInputChange_)},t.FieldTextInput.prototype.unbindInputEvents_=function(){this.onKeyDownWrapper_&&(t.unbindEvent_(this.onKeyDownWrapper_),this.onKeyDownWrapper_=null),this.onKeyInputWrapper_&&(t.unbindEvent_(this.onKeyInputWrapper_),this.onKeyInputWrapper_=null)},t.FieldTextInput.prototype.onHtmlInputKeyDown_=function(e){e.keyCode==t.utils.KeyCodes.ENTER?(t.WidgetDiv.hide(),t.DropDownDiv.hideWithoutAnimation()):e.keyCode==t.utils.KeyCodes.ESC?(this.htmlInput_.value=this.htmlInput_.defaultValue,t.WidgetDiv.hide(),t.DropDownDiv.hideWithoutAnimation()):e.keyCode==t.utils.KeyCodes.TAB&&(t.WidgetDiv.hide(),t.DropDownDiv.hideWithoutAnimation(),this.sourceBlock_.tab(this,!e.shiftKey),e.preventDefault())},t.FieldTextInput.prototype.onHtmlInputChange_=function(e){(e=this.htmlInput_.value)!==this.htmlInput_.oldValue_&&(this.htmlInput_.oldValue_=e,t.Events.setGroup(!0),e=this.getValueFromEditorText_(e),this.setValue(e),this.forceRerender(),this.resizeEditor_(),t.Events.setGroup(!1))},t.FieldTextInput.prototype.setEditorValue_=function(t){this.isDirty_=!0,this.isBeingEdited_&&(this.htmlInput_.value=this.getEditorText_(t)),this.setValue(t)},t.FieldTextInput.prototype.resizeEditor_=function(){var e=t.WidgetDiv.DIV,o=this.getScaledBBox();e.style.width=o.right-o.left+"px",e.style.height=o.bottom-o.top+"px",o=new t.utils.Coordinate(this.sourceBlock_.RTL?o.right-e.offsetWidth:o.left,o.top),e.style.left=o.x+"px",e.style.top=o.y+"px"},t.FieldTextInput.numberValidator=function(t){return console.warn("Blockly.FieldTextInput.numberValidator is deprecated. Use Blockly.FieldNumber instead."),null===t?null:(t=(t=(t=String(t)).replace(/O/gi,"0")).replace(/,/g,""),t=Number(t||0),isNaN(t)?null:String(t))},t.FieldTextInput.nonnegativeIntegerValidator=function(e){return(e=t.FieldTextInput.numberValidator(e))&&(e=String(Math.max(0,Math.floor(e)))),e},t.FieldTextInput.prototype.isTabNavigable=function(){return!0},t.FieldTextInput.prototype.getText_=function(){return this.isBeingEdited_&&this.htmlInput_?this.htmlInput_.value:null},t.FieldTextInput.prototype.getEditorText_=function(t){return String(t)},t.FieldTextInput.prototype.getValueFromEditorText_=function(t){return t},t.fieldRegistry.register("field_input",t.FieldTextInput),t.FieldAngle=function(e,o,i){this.clockwise_=t.FieldAngle.CLOCKWISE,this.offset_=t.FieldAngle.OFFSET,this.wrap_=t.FieldAngle.WRAP,this.round_=t.FieldAngle.ROUND,t.FieldAngle.superClass_.constructor.call(this,e||0,o,i),this.moveSurfaceWrapper_=this.clickSurfaceWrapper_=this.clickWrapper_=this.line_=this.gauge_=null},t.utils.object.inherits(t.FieldAngle,t.FieldTextInput),t.FieldAngle.fromJson=function(e){return new t.FieldAngle(e.angle,void 0,e)},t.FieldAngle.prototype.SERIALIZABLE=!0,t.FieldAngle.ROUND=15,t.FieldAngle.HALF=50,t.FieldAngle.CLOCKWISE=!1,t.FieldAngle.OFFSET=0,t.FieldAngle.WRAP=360,t.FieldAngle.RADIUS=t.FieldAngle.HALF-1,t.FieldAngle.prototype.configure_=function(e){switch(t.FieldAngle.superClass_.configure_.call(this,e),e.mode){case"compass":this.clockwise_=!0,this.offset_=90;break;case"protractor":this.clockwise_=!1,this.offset_=0}var o=e.clockwise;"boolean"==typeof o&&(this.clockwise_=o),null!=(o=e.offset)&&(o=Number(o),isNaN(o)||(this.offset_=o)),null!=(o=e.wrap)&&(o=Number(o),isNaN(o)||(this.wrap_=o)),null!=(e=e.round)&&(e=Number(e),isNaN(e)||(this.round_=e))},t.FieldAngle.prototype.initView=function(){t.FieldAngle.superClass_.initView.call(this),this.symbol_=t.utils.dom.createSvgElement("tspan",{},null),this.symbol_.appendChild(document.createTextNode("°")),this.textElement_.appendChild(this.symbol_)},t.FieldAngle.prototype.render_=function(){t.FieldAngle.superClass_.render_.call(this),this.updateGraph_()},t.FieldAngle.prototype.showEditor_=function(e){t.FieldAngle.superClass_.showEditor_.call(this,e,t.utils.userAgent.MOBILE||t.utils.userAgent.ANDROID||t.utils.userAgent.IPAD),e=this.dropdownCreate_(),t.DropDownDiv.getContentDiv().appendChild(e),t.DropDownDiv.setColour(this.sourceBlock_.style.colourPrimary,this.sourceBlock_.style.colourTertiary),t.DropDownDiv.showPositionedByField(this,this.dropdownDispose_.bind(this)),this.updateGraph_()},t.FieldAngle.prototype.dropdownCreate_=function(){var e=t.utils.dom.createSvgElement("svg",{xmlns:t.utils.dom.SVG_NS,"xmlns:html":t.utils.dom.HTML_NS,"xmlns:xlink":t.utils.dom.XLINK_NS,version:"1.1",height:2*t.FieldAngle.HALF+"px",width:2*t.FieldAngle.HALF+"px",style:"touch-action: none"},null),o=t.utils.dom.createSvgElement("circle",{cx:t.FieldAngle.HALF,cy:t.FieldAngle.HALF,r:t.FieldAngle.RADIUS,class:"blocklyAngleCircle"},e);this.gauge_=t.utils.dom.createSvgElement("path",{class:"blocklyAngleGauge"},e),this.line_=t.utils.dom.createSvgElement("line",{x1:t.FieldAngle.HALF,y1:t.FieldAngle.HALF,class:"blocklyAngleLine"},e);for(var i=0;360>i;i+=15)t.utils.dom.createSvgElement("line",{x1:t.FieldAngle.HALF+t.FieldAngle.RADIUS,y1:t.FieldAngle.HALF,x2:t.FieldAngle.HALF+t.FieldAngle.RADIUS-(0==i%45?10:5),y2:t.FieldAngle.HALF,class:"blocklyAngleMarks",transform:"rotate("+i+","+t.FieldAngle.HALF+","+t.FieldAngle.HALF+")"},e);return this.clickWrapper_=t.bindEventWithChecks_(e,"click",this,this.hide_),this.clickSurfaceWrapper_=t.bindEventWithChecks_(o,"click",this,this.onMouseMove_,!0,!0),this.moveSurfaceWrapper_=t.bindEventWithChecks_(o,"mousemove",this,this.onMouseMove_,!0,!0),e},t.FieldAngle.prototype.dropdownDispose_=function(){this.clickWrapper_&&(t.unbindEvent_(this.clickWrapper_),this.clickWrapper_=null),this.clickSurfaceWrapper_&&(t.unbindEvent_(this.clickSurfaceWrapper_),this.clickSurfaceWrapper_=null),this.moveSurfaceWrapper_&&(t.unbindEvent_(this.moveSurfaceWrapper_),this.moveSurfaceWrapper_=null),this.line_=this.gauge_=null},t.FieldAngle.prototype.hide_=function(){t.DropDownDiv.hideIfOwner(this),t.WidgetDiv.hide()},t.FieldAngle.prototype.onMouseMove_=function(e){var o=this.gauge_.ownerSVGElement.getBoundingClientRect(),i=e.clientX-o.left-t.FieldAngle.HALF;e=e.clientY-o.top-t.FieldAngle.HALF,o=Math.atan(-e/i),isNaN(o)||(o=t.utils.math.toDegrees(o),0>i?o+=180:0(t%=360)&&(t+=360),t>this.wrap_&&(t-=360),t},t.Css.register(".blocklyAngleCircle {,stroke: #444;,stroke-width: 1;,fill: #ddd;,fill-opacity: .8;,},.blocklyAngleMarks {,stroke: #444;,stroke-width: 1;,},.blocklyAngleGauge {,fill: #f88;,fill-opacity: .8;,pointer-events: none;,},.blocklyAngleLine {,stroke: #f00;,stroke-width: 2;,stroke-linecap: round;,pointer-events: none;,}".split(",")),t.fieldRegistry.register("field_angle",t.FieldAngle),t.FieldCheckbox=function(e,o,i){this.checkChar_=null,null==e&&(e="FALSE"),t.FieldCheckbox.superClass_.constructor.call(this,e,o,i)},t.utils.object.inherits(t.FieldCheckbox,t.Field),t.FieldCheckbox.fromJson=function(e){return new t.FieldCheckbox(e.checked,void 0,e)},t.FieldCheckbox.CHECK_CHAR="✓",t.FieldCheckbox.prototype.SERIALIZABLE=!0,t.FieldCheckbox.prototype.CURSOR="default",t.FieldCheckbox.prototype.configure_=function(e){t.FieldCheckbox.superClass_.configure_.call(this,e),e.checkCharacter&&(this.checkChar_=e.checkCharacter)},t.FieldCheckbox.prototype.initView=function(){t.FieldCheckbox.superClass_.initView.call(this),t.utils.dom.addClass(this.textElement_,"blocklyCheckbox"),this.textElement_.style.display=this.value_?"block":"none"},t.FieldCheckbox.prototype.render_=function(){this.textContent_&&(this.textContent_.nodeValue=this.getDisplayText_()),this.updateSize_(this.getConstants().FIELD_CHECKBOX_X_OFFSET)},t.FieldCheckbox.prototype.getDisplayText_=function(){return this.checkChar_||t.FieldCheckbox.CHECK_CHAR},t.FieldCheckbox.prototype.setCheckCharacter=function(t){this.checkChar_=t,this.forceRerender()},t.FieldCheckbox.prototype.showEditor_=function(){this.setValue(!this.value_)},t.FieldCheckbox.prototype.doClassValidation_=function(t){return!0===t||"TRUE"===t?"TRUE":!1===t||"FALSE"===t?"FALSE":null},t.FieldCheckbox.prototype.doValueUpdate_=function(t){this.value_=this.convertValueToBool_(t),this.textElement_&&(this.textElement_.style.display=this.value_?"block":"none")},t.FieldCheckbox.prototype.getValue=function(){return this.value_?"TRUE":"FALSE"},t.FieldCheckbox.prototype.getValueBoolean=function(){return this.value_},t.FieldCheckbox.prototype.getText=function(){return String(this.convertValueToBool_(this.value_))},t.FieldCheckbox.prototype.convertValueToBool_=function(t){return"string"==typeof t?"TRUE"==t:!!t},t.fieldRegistry.register("field_checkbox",t.FieldCheckbox),t.FieldColour=function(e,o,i){t.FieldColour.superClass_.constructor.call(this,e||t.FieldColour.COLOURS[0],o,i),this.onKeyDownWrapper_=this.onMouseLeaveWrapper_=this.onMouseEnterWrapper_=this.onMouseMoveWrapper_=this.onClickWrapper_=this.highlightedIndex_=this.picker_=null},t.utils.object.inherits(t.FieldColour,t.Field),t.FieldColour.fromJson=function(e){return new t.FieldColour(e.colour,void 0,e)},t.FieldColour.prototype.SERIALIZABLE=!0,t.FieldColour.prototype.CURSOR="default",t.FieldColour.prototype.isDirty_=!1,t.FieldColour.prototype.colours_=null,t.FieldColour.prototype.titles_=null,t.FieldColour.prototype.columns_=0,t.FieldColour.prototype.configure_=function(e){t.FieldColour.superClass_.configure_.call(this,e),e.colourOptions&&(this.colours_=e.colourOptions,this.titles_=e.colourTitles),e.columns&&(this.columns_=e.columns)},t.FieldColour.prototype.initView=function(){this.size_=new t.utils.Size(this.getConstants().FIELD_COLOUR_DEFAULT_WIDTH,this.getConstants().FIELD_COLOUR_DEFAULT_HEIGHT),this.getConstants().FIELD_COLOUR_FULL_BLOCK?this.clickTarget_=this.sourceBlock_.getSvgRoot():(this.createBorderRect_(),this.borderRect_.style.fillOpacity="1")},t.FieldColour.prototype.applyColour=function(){this.getConstants().FIELD_COLOUR_FULL_BLOCK?(this.sourceBlock_.pathObject.svgPath.setAttribute("fill",this.getValue()),this.sourceBlock_.pathObject.svgPath.setAttribute("stroke","#fff")):this.borderRect_&&(this.borderRect_.style.fill=this.getValue())},t.FieldColour.prototype.doClassValidation_=function(e){return"string"!=typeof e?null:t.utils.colour.parse(e)},t.FieldColour.prototype.doValueUpdate_=function(t){this.value_=t,this.borderRect_?this.borderRect_.style.fill=t:this.sourceBlock_&&this.sourceBlock_.rendered&&(this.sourceBlock_.pathObject.svgPath.setAttribute("fill",t),this.sourceBlock_.pathObject.svgPath.setAttribute("stroke","#fff"))},t.FieldColour.prototype.getText=function(){var t=this.value_;return/^#(.)\1(.)\2(.)\3$/.test(t)&&(t="#"+t[1]+t[3]+t[5]),t},t.FieldColour.COLOURS="#ffffff #cccccc #c0c0c0 #999999 #666666 #333333 #000000 #ffcccc #ff6666 #ff0000 #cc0000 #990000 #660000 #330000 #ffcc99 #ff9966 #ff9900 #ff6600 #cc6600 #993300 #663300 #ffff99 #ffff66 #ffcc66 #ffcc33 #cc9933 #996633 #663333 #ffffcc #ffff33 #ffff00 #ffcc00 #999900 #666600 #333300 #99ff99 #66ff99 #33ff33 #33cc00 #009900 #006600 #003300 #99ffff #33ffff #66cccc #00cccc #339999 #336666 #003333 #ccffff #66ffff #33ccff #3366ff #3333ff #000099 #000066 #ccccff #9999ff #6666cc #6633ff #6600cc #333399 #330099 #ffccff #ff99ff #cc66cc #cc33cc #993399 #663366 #330033".split(" "),t.FieldColour.TITLES=[],t.FieldColour.COLUMNS=7,t.FieldColour.prototype.setColours=function(t,e){return this.colours_=t,e&&(this.titles_=e),this},t.FieldColour.prototype.setColumns=function(t){return this.columns_=t,this},t.FieldColour.prototype.showEditor_=function(){this.picker_=this.dropdownCreate_(),t.DropDownDiv.getContentDiv().appendChild(this.picker_),t.DropDownDiv.showPositionedByField(this,this.dropdownDispose_.bind(this)),this.picker_.focus({preventScroll:!0})},t.FieldColour.prototype.onClick_=function(e){null!==(e=(e=e.target)&&e.label)&&(this.setValue(e),t.DropDownDiv.hideIfOwner(this))},t.FieldColour.prototype.onKeyDown_=function(e){var o=!1;e.keyCode===t.utils.KeyCodes.UP?(this.moveHighlightBy_(0,-1),o=!0):e.keyCode===t.utils.KeyCodes.DOWN?(this.moveHighlightBy_(0,1),o=!0):e.keyCode===t.utils.KeyCodes.LEFT?(this.moveHighlightBy_(-1,0),o=!0):e.keyCode===t.utils.KeyCodes.RIGHT?(this.moveHighlightBy_(1,0),o=!0):e.keyCode===t.utils.KeyCodes.ENTER&&((o=this.getHighlighted_())&&null!==(o=o&&o.label)&&this.setValue(o),t.DropDownDiv.hideWithoutAnimation(),o=!0),o&&e.stopPropagation()},t.FieldColour.prototype.onBlocklyAction=function(e){if(this.picker_){if(e===t.navigation.ACTION_PREVIOUS)return this.moveHighlightBy_(0,-1),!0;if(e===t.navigation.ACTION_NEXT)return this.moveHighlightBy_(0,1),!0;if(e===t.navigation.ACTION_OUT)return this.moveHighlightBy_(-1,0),!0;if(e===t.navigation.ACTION_IN)return this.moveHighlightBy_(1,0),!0}return t.FieldColour.superClass_.onBlocklyAction.call(this,e)},t.FieldColour.prototype.moveHighlightBy_=function(e,o){var i=this.colours_||t.FieldColour.COLOURS,n=this.columns_||t.FieldColour.COLUMNS,s=this.highlightedIndex_%n,r=Math.floor(this.highlightedIndex_/n);s+=e,r+=o,0>e?0>s&&0s&&(s=0):0n-1&&rn-1&&s--:0>o?0>r&&(r=0):0Math.floor(i.length/n)-1&&(r=Math.floor(i.length/n)-1),this.setHighlightedCell_(this.picker_.childNodes[r].childNodes[s],r*n+s)},t.FieldColour.prototype.onMouseMove_=function(t){var e=(t=t.target)&&Number(t.getAttribute("data-index"));null!==e&&e!==this.highlightedIndex_&&this.setHighlightedCell_(t,e)},t.FieldColour.prototype.onMouseEnter_=function(){this.picker_.focus({preventScroll:!0})},t.FieldColour.prototype.onMouseLeave_=function(){this.picker_.blur();var e=this.getHighlighted_();e&&t.utils.dom.removeClass(e,"blocklyColourHighlighted")},t.FieldColour.prototype.getHighlighted_=function(){var e=this.columns_||t.FieldColour.COLUMNS,o=this.picker_.childNodes[Math.floor(this.highlightedIndex_/e)];return o?o.childNodes[this.highlightedIndex_%e]:null},t.FieldColour.prototype.setHighlightedCell_=function(e,o){var i=this.getHighlighted_();i&&t.utils.dom.removeClass(i,"blocklyColourHighlighted"),t.utils.dom.addClass(e,"blocklyColourHighlighted"),this.highlightedIndex_=o,t.utils.aria.setState(this.picker_,t.utils.aria.State.ACTIVEDESCENDANT,e.getAttribute("id"))},t.FieldColour.prototype.dropdownCreate_=function(){var e=this.columns_||t.FieldColour.COLUMNS,o=this.colours_||t.FieldColour.COLOURS,i=this.titles_||t.FieldColour.TITLES,n=this.getValue(),s=document.createElement("table");s.className="blocklyColourTable",s.tabIndex=0,s.dir="ltr",t.utils.aria.setRole(s,t.utils.aria.Role.GRID),t.utils.aria.setState(s,t.utils.aria.State.EXPANDED,!0),t.utils.aria.setState(s,t.utils.aria.State.ROWCOUNT,Math.floor(o.length/e)),t.utils.aria.setState(s,t.utils.aria.State.COLCOUNT,e);for(var r,a=0;atr>td {","border: .5px solid #888;","box-sizing: border-box;","cursor: pointer;","display: inline-block;","height: 20px;","padding: 0;","width: 20px;","}",".blocklyColourTable>tr>td.blocklyColourHighlighted {","border-color: #eee;","box-shadow: 2px 2px 7px 2px rgba(0,0,0,.3);","position: relative;","}",".blocklyColourSelected, .blocklyColourSelected:hover {","border-color: #eee !important;","outline: 1px solid #333;","position: relative;","}"]),t.fieldRegistry.register("field_colour",t.FieldColour),t.FieldDropdown=function(e,o,i){"function"!=typeof e&&t.FieldDropdown.validateOptions_(e),this.menuGenerator_=e,this.generatedOptions_=null,this.trimOptions_(),this.selectedOption_=this.getOptions(!1)[0],t.FieldDropdown.superClass_.constructor.call(this,this.selectedOption_[1],o,i),this.svgArrow_=this.arrow_=this.imageElement_=this.menu_=this.selectedMenuItem_=null},t.utils.object.inherits(t.FieldDropdown,t.Field),t.FieldDropdown.fromJson=function(e){return new t.FieldDropdown(e.options,void 0,e)},t.FieldDropdown.prototype.SERIALIZABLE=!0,t.FieldDropdown.CHECKMARK_OVERHANG=25,t.FieldDropdown.MAX_MENU_HEIGHT_VH=.45,t.FieldDropdown.IMAGE_Y_OFFSET=5,t.FieldDropdown.IMAGE_Y_PADDING=2*t.FieldDropdown.IMAGE_Y_OFFSET,t.FieldDropdown.ARROW_CHAR=t.utils.userAgent.ANDROID?"▼":"▾",t.FieldDropdown.prototype.CURSOR="default",t.FieldDropdown.prototype.initView=function(){this.shouldAddBorderRect_()?this.createBorderRect_():this.clickTarget_=this.sourceBlock_.getSvgRoot(),this.createTextElement_(),this.imageElement_=t.utils.dom.createSvgElement("image",{},this.fieldGroup_),this.getConstants().FIELD_DROPDOWN_SVG_ARROW?this.createSVGArrow_():this.createTextArrow_(),this.borderRect_&&t.utils.dom.addClass(this.borderRect_,"blocklyDropdownRect")},t.FieldDropdown.prototype.shouldAddBorderRect_=function(){return!this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW||this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW&&!this.sourceBlock_.isShadow()},t.FieldDropdown.prototype.createTextArrow_=function(){this.arrow_=t.utils.dom.createSvgElement("tspan",{},this.textElement_),this.arrow_.appendChild(document.createTextNode(this.sourceBlock_.RTL?t.FieldDropdown.ARROW_CHAR+" ":" "+t.FieldDropdown.ARROW_CHAR)),this.sourceBlock_.RTL?this.textElement_.insertBefore(this.arrow_,this.textContent_):this.textElement_.appendChild(this.arrow_)},t.FieldDropdown.prototype.createSVGArrow_=function(){this.svgArrow_=t.utils.dom.createSvgElement("image",{height:this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE+"px",width:this.getConstants().FIELD_DROPDOWN_SVG_ARROW_SIZE+"px"},this.fieldGroup_),this.svgArrow_.setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",this.getConstants().FIELD_DROPDOWN_SVG_ARROW_DATAURI)},t.FieldDropdown.prototype.showEditor_=function(e){if(this.menu_=this.dropdownCreate_(),this.menu_.openingCoords=e&&"number"==typeof e.clientX?new t.utils.Coordinate(e.clientX,e.clientY):null,this.menu_.render(t.DropDownDiv.getContentDiv()),t.utils.dom.addClass(this.menu_.getElement(),"blocklyDropdownMenu"),this.getConstants().FIELD_DROPDOWN_COLOURED_DIV){e=this.sourceBlock_.isShadow()?this.sourceBlock_.getParent().getColour():this.sourceBlock_.getColour();var o=this.sourceBlock_.isShadow()?this.sourceBlock_.getParent().style.colourTertiary:this.sourceBlock_.style.colourTertiary;t.DropDownDiv.setColour(e,o)}t.DropDownDiv.showPositionedByField(this,this.dropdownDispose_.bind(this)),this.menu_.focus(),this.selectedMenuItem_&&t.utils.style.scrollIntoContainerView(this.selectedMenuItem_.getElement(),this.menu_.getElement()),this.applyColour()},t.FieldDropdown.prototype.dropdownCreate_=function(){var e=new t.Menu;e.setRightToLeft(this.sourceBlock_.RTL),e.setRole(t.utils.aria.Role.LISTBOX);var o=this.getOptions(!1);this.selectedMenuItem_=null;for(var i=0;ie.length)){for(o=[],i=0;i=i||0>=o)throw Error("Height and width values of an image field must be greater than 0.");this.flipRtl_=!1,this.altText_="",t.FieldImage.superClass_.constructor.call(this,e||"",null,a),a||(this.flipRtl_=!!r,this.altText_=t.utils.replaceMessageReferences(n)||""),this.size_=new t.utils.Size(o,i+t.FieldImage.Y_PADDING),this.imageHeight_=i,this.clickHandler_=null,"function"==typeof s&&(this.clickHandler_=s),this.imageElement_=null},t.utils.object.inherits(t.FieldImage,t.Field),t.FieldImage.fromJson=function(e){return new t.FieldImage(e.src,e.width,e.height,void 0,void 0,void 0,e)},t.FieldImage.Y_PADDING=1,t.FieldImage.prototype.EDITABLE=!1,t.FieldImage.prototype.isDirty_=!1,t.FieldImage.prototype.configure_=function(e){t.FieldImage.superClass_.configure_.call(this,e),this.flipRtl_=!!e.flipRtl,this.altText_=t.utils.replaceMessageReferences(e.alt)||""},t.FieldImage.prototype.initView=function(){this.imageElement_=t.utils.dom.createSvgElement("image",{height:this.imageHeight_+"px",width:this.size_.width+"px",alt:this.altText_},this.fieldGroup_),this.imageElement_.setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",this.value_),this.clickHandler_&&(this.imageElement_.style.cursor="pointer")},t.FieldImage.prototype.updateSize_=function(){},t.FieldImage.prototype.doClassValidation_=function(t){return"string"!=typeof t?null:t},t.FieldImage.prototype.doValueUpdate_=function(e){this.value_=e,this.imageElement_&&this.imageElement_.setAttributeNS(t.utils.dom.XLINK_NS,"xlink:href",String(this.value_))},t.FieldImage.prototype.getFlipRtl=function(){return this.flipRtl_},t.FieldImage.prototype.setAlt=function(t){t!=this.altText_&&(this.altText_=t||"",this.imageElement_&&this.imageElement_.setAttribute("alt",this.altText_))},t.FieldImage.prototype.showEditor_=function(){this.clickHandler_&&this.clickHandler_(this)},t.FieldImage.prototype.setOnClickHandler=function(t){this.clickHandler_=t},t.FieldImage.prototype.getText_=function(){return this.altText_},t.fieldRegistry.register("field_image",t.FieldImage),t.FieldMultilineInput=function(e,o,i){null==e&&(e=""),t.FieldMultilineInput.superClass_.constructor.call(this,e,o,i),this.textGroup_=null},t.utils.object.inherits(t.FieldMultilineInput,t.FieldTextInput),t.FieldMultilineInput.fromJson=function(e){var o=t.utils.replaceMessageReferences(e.text);return new t.FieldMultilineInput(o,void 0,e)},t.FieldMultilineInput.prototype.initView=function(){this.createBorderRect_(),this.textGroup_=t.utils.dom.createSvgElement("g",{class:"blocklyEditableText"},this.fieldGroup_)},t.FieldMultilineInput.prototype.getDisplayText_=function(){var e=this.value_;if(!e)return t.Field.NBSP;var o=e.split("\n");e="";for(var i=0;ithis.maxDisplayLength&&(n=n.substring(0,this.maxDisplayLength-4)+"..."),e+=n=n.replace(/\s/g,t.Field.NBSP),i!==o.length-1&&(e+="\n")}return this.sourceBlock_.RTL&&(e+="‏"),e},t.FieldMultilineInput.prototype.render_=function(){for(var e;e=this.textGroup_.firstChild;)this.textGroup_.removeChild(e);e=this.getDisplayText_().split("\n");for(var o=0,i=0;io&&(o=s),i+=this.getConstants().FIELD_TEXT_HEIGHT+(0this.max_&&t.utils.aria.setState(e,t.utils.aria.State.VALUEMAX,this.max_),e},t.fieldRegistry.register("field_number",t.FieldNumber),t.FieldVariable=function(e,o,i,n,s){this.menuGenerator_=t.FieldVariable.dropdownCreate,this.defaultVariableName=e||"",this.size_=new t.utils.Size(0,0),s&&this.configure_(s),o&&this.setValidator(o),s||this.setTypes_(i,n)},t.utils.object.inherits(t.FieldVariable,t.FieldDropdown),t.FieldVariable.fromJson=function(e){var o=t.utils.replaceMessageReferences(e.variable);return new t.FieldVariable(o,void 0,void 0,void 0,e)},t.FieldVariable.prototype.workspace_=null,t.FieldVariable.prototype.SERIALIZABLE=!0,t.FieldVariable.prototype.configure_=function(e){t.FieldVariable.superClass_.configure_.call(this,e),this.setTypes_(e.variableTypes,e.defaultType)},t.FieldVariable.prototype.initModel=function(){if(!this.variable_){var e=t.Variables.getOrCreateVariablePackage(this.sourceBlock_.workspace,null,this.defaultVariableName,this.defaultType_);this.doValueUpdate_(e.getId())}},t.FieldVariable.prototype.shouldAddBorderRect_=function(){return t.FieldVariable.superClass_.shouldAddBorderRect_.call(this)&&(!this.getConstants().FIELD_DROPDOWN_NO_BORDER_RECT_SHADOW||"variables_get"!=this.sourceBlock_.type)},t.FieldVariable.prototype.fromXml=function(e){var o=e.getAttribute("id"),i=e.textContent,n=e.getAttribute("variabletype")||e.getAttribute("variableType")||"";if(o=t.Variables.getOrCreateVariablePackage(this.sourceBlock_.workspace,o,i,n),null!=n&&n!==o.type)throw Error("Serialized variable type with id '"+o.getId()+"' had type "+o.type+", and does not match variable field that references it: "+t.Xml.domToText(e)+".");this.setValue(o.getId())},t.FieldVariable.prototype.toXml=function(t){return this.initModel(),t.id=this.variable_.getId(),t.textContent=this.variable_.name,this.variable_.type&&t.setAttribute("variabletype",this.variable_.type),t},t.FieldVariable.prototype.setSourceBlock=function(e){if(e.isShadow())throw Error("Variable fields are not allowed to exist on shadow blocks.");t.FieldVariable.superClass_.setSourceBlock.call(this,e)},t.FieldVariable.prototype.getValue=function(){return this.variable_?this.variable_.getId():null},t.FieldVariable.prototype.getText=function(){return this.variable_?this.variable_.name:""},t.FieldVariable.prototype.getVariable=function(){return this.variable_},t.FieldVariable.prototype.getValidator=function(){return this.variable_?this.validator_:null},t.FieldVariable.prototype.doClassValidation_=function(e){if(null===e)return null;var o=t.Variables.getVariable(this.sourceBlock_.workspace,e);return o?(o=o.type,this.typeIsAllowed_(o)?e:(console.warn("Variable type doesn't match this field! Type was "+o),null)):(console.warn("Variable id doesn't point to a real variable! ID was "+e),null)},t.FieldVariable.prototype.doValueUpdate_=function(e){this.variable_=t.Variables.getVariable(this.sourceBlock_.workspace,e),t.FieldVariable.superClass_.doValueUpdate_.call(this,e)},t.FieldVariable.prototype.typeIsAllowed_=function(t){var e=this.getVariableTypes_();if(!e)return!0;for(var o=0;orect,",t+" .blocklyEditableText>rect {","fill: "+this.FIELD_BORDER_RECT_COLOUR+";","fill-opacity: .6;","stroke: none;","}",t+" .blocklyNonEditableText>text,",t+" .blocklyEditableText>text {","fill: #000;","}",t+" .blocklyFlyoutLabelText {","fill: #000;","}",t+" .blocklyText.blocklyBubbleText {","fill: #000;","}",t+" .blocklyEditableText:not(.editing):hover>rect {","stroke: #fff;","stroke-width: 2;","}",t+" .blocklyHtmlInput {","font-family: "+this.FIELD_TEXT_FONTFAMILY+";","font-weight: "+this.FIELD_TEXT_FONTWEIGHT+";","}",t+" .blocklySelected>.blocklyPath {","stroke: #fc3;","stroke-width: 3px;","}",t+" .blocklyHighlightedConnectionPath {","stroke: #fc3;","}",t+" .blocklyReplaceable .blocklyPath {","fill-opacity: .5;","}",t+" .blocklyReplaceable .blocklyPathLight,",t+" .blocklyReplaceable .blocklyPathDark {","display: none;","}",t+" .blocklyInsertionMarker>.blocklyPath {","fill-opacity: "+this.INSERTION_MARKER_OPACITY+";","stroke: none","}"]},t.blockRendering.MarkerSvg=function(t,e,o){this.workspace_=t,this.marker_=o,this.parent_=null,this.constants_=e,this.currentMarkerSvg=null,t=this.isCursor()?this.constants_.CURSOR_COLOUR:this.constants_.MARKER_COLOUR,this.colour_=o.colour||t},t.blockRendering.MarkerSvg.CURSOR_CLASS="blocklyCursor",t.blockRendering.MarkerSvg.MARKER_CLASS="blocklyMarker",t.blockRendering.MarkerSvg.HEIGHT_MULTIPLIER=.75,t.blockRendering.MarkerSvg.prototype.getSvgRoot=function(){return this.svgGroup_},t.blockRendering.MarkerSvg.prototype.isCursor=function(){return"cursor"==this.marker_.type},t.blockRendering.MarkerSvg.prototype.createDom=function(){var e=this.isCursor()?t.blockRendering.MarkerSvg.CURSOR_CLASS:t.blockRendering.MarkerSvg.MARKER_CLASS;return this.svgGroup_=t.utils.dom.createSvgElement("g",{class:e},null),this.createDomInternal_(),this.applyColour_(),this.svgGroup_},t.blockRendering.MarkerSvg.prototype.setParent_=function(t){this.isCursor()?(this.parent_&&this.parent_.setCursorSvg(null),t.setCursorSvg(this.getSvgRoot())):(this.parent_&&this.parent_.setMarkerSvg(null),t.setMarkerSvg(this.getSvgRoot())),this.parent_=t},t.blockRendering.MarkerSvg.prototype.showWithBlockPrevOutput_=function(e){if(e){var o=e.width,i=e.height,n=i*t.blockRendering.MarkerSvg.HEIGHT_MULTIPLIER,s=this.constants_.CURSOR_BLOCK_PADDING;if(e.previousConnection){var r=this.constants_.shapeFor(e.previousConnection);this.positionPrevious_(o,s,n,r)}else e.outputConnection?(r=this.constants_.shapeFor(e.outputConnection),this.positionOutput_(o,i,r)):this.positionBlock_(o,s,n);this.setParent_(e),this.showCurrent_()}},t.blockRendering.MarkerSvg.prototype.showWithCoordinates_=function(t){var e=t.getWsCoordinate();t=e.x,e=e.y,this.workspace_.RTL&&(t-=this.constants_.CURSOR_WS_WIDTH),this.positionLine_(t,e,this.constants_.CURSOR_WS_WIDTH),this.setParent_(this.workspace_),this.showCurrent_()},t.blockRendering.MarkerSvg.prototype.showWithField_=function(t){var e=(t=t.getLocation()).getSize().width,o=t.getSize().height;this.positionRect_(0,0,e,o),this.setParent_(t),this.showCurrent_()},t.blockRendering.MarkerSvg.prototype.showWithInput_=function(t){var e=(t=t.getLocation()).getSourceBlock();this.positionInput_(t),this.setParent_(e),this.showCurrent_()},t.blockRendering.MarkerSvg.prototype.showWithNext_=function(t){var e=t.getLocation();t=e.getSourceBlock();var o=0;e=e.getOffsetInBlock().y;var i=t.getHeightWidth().width;this.workspace_.RTL&&(o=-i),this.positionLine_(o,e,i),this.setParent_(t),this.showCurrent_()},t.blockRendering.MarkerSvg.prototype.showWithStack_=function(t){var e=(t=t.getLocation()).getHeightWidth(),o=e.width+this.constants_.CURSOR_STACK_PADDING;e=e.height+this.constants_.CURSOR_STACK_PADDING;var i=-this.constants_.CURSOR_STACK_PADDING/2,n=-this.constants_.CURSOR_STACK_PADDING/2,s=i;this.workspace_.RTL&&(s=-(o+i)),this.positionRect_(s,n,o,e),this.setParent_(t),this.showCurrent_()},t.blockRendering.MarkerSvg.prototype.showCurrent_=function(){this.hide(),this.currentMarkerSvg.style.display=""},t.blockRendering.MarkerSvg.prototype.positionBlock_=function(e,o,i){e=t.utils.svgPaths.moveBy(-o,i)+t.utils.svgPaths.lineOnAxis("V",-o)+t.utils.svgPaths.lineOnAxis("H",e+2*o)+t.utils.svgPaths.lineOnAxis("V",i),this.markerBlock_.setAttribute("d",e),this.workspace_.RTL&&this.flipRtl_(this.markerBlock_),this.currentMarkerSvg=this.markerBlock_},t.blockRendering.MarkerSvg.prototype.positionInput_=function(e){var o=e.getOffsetInBlock().x,i=e.getOffsetInBlock().y;e=t.utils.svgPaths.moveTo(0,0)+this.constants_.shapeFor(e).pathDown,this.markerInput_.setAttribute("d",e),this.markerInput_.setAttribute("transform","translate("+o+","+i+")"+(this.workspace_.RTL?" scale(-1 1)":"")),this.currentMarkerSvg=this.markerInput_},t.blockRendering.MarkerSvg.prototype.positionLine_=function(t,e,o){this.markerSvgLine_.setAttribute("x",t),this.markerSvgLine_.setAttribute("y",e),this.markerSvgLine_.setAttribute("width",o),this.currentMarkerSvg=this.markerSvgLine_},t.blockRendering.MarkerSvg.prototype.positionOutput_=function(e,o,i){e=t.utils.svgPaths.moveBy(e,0)+t.utils.svgPaths.lineOnAxis("h",-(e-i.width))+t.utils.svgPaths.lineOnAxis("v",this.constants_.TAB_OFFSET_FROM_TOP)+i.pathDown+t.utils.svgPaths.lineOnAxis("V",o)+t.utils.svgPaths.lineOnAxis("H",e),this.markerBlock_.setAttribute("d",e),this.workspace_.RTL&&this.flipRtl_(this.markerBlock_),this.currentMarkerSvg=this.markerBlock_},t.blockRendering.MarkerSvg.prototype.positionPrevious_=function(e,o,i,n){e=t.utils.svgPaths.moveBy(-o,i)+t.utils.svgPaths.lineOnAxis("V",-o)+t.utils.svgPaths.lineOnAxis("H",this.constants_.NOTCH_OFFSET_LEFT)+n.pathLeft+t.utils.svgPaths.lineOnAxis("H",e+2*o)+t.utils.svgPaths.lineOnAxis("V",i),this.markerBlock_.setAttribute("d",e),this.workspace_.RTL&&this.flipRtl_(this.markerBlock_),this.currentMarkerSvg=this.markerBlock_},t.blockRendering.MarkerSvg.prototype.positionRect_=function(t,e,o,i){this.markerSvgRect_.setAttribute("x",t),this.markerSvgRect_.setAttribute("y",e),this.markerSvgRect_.setAttribute("width",o),this.markerSvgRect_.setAttribute("height",i),this.currentMarkerSvg=this.markerSvgRect_},t.blockRendering.MarkerSvg.prototype.flipRtl_=function(t){t.setAttribute("transform","scale(-1 1)")},t.blockRendering.MarkerSvg.prototype.hide=function(){this.markerSvgLine_.style.display="none",this.markerSvgRect_.style.display="none",this.markerInput_.style.display="none",this.markerBlock_.style.display="none"},t.blockRendering.MarkerSvg.prototype.draw=function(t,e){if(e){this.constants_=this.workspace_.getRenderer().getConstants();var o=this.isCursor()?this.constants_.CURSOR_COLOUR:this.constants_.MARKER_COLOUR;this.colour_=this.marker_.colour||o,this.applyColour_(),this.showAtLocation_(e),this.firemarkerEvent_(t,e),void 0!==(t=this.currentMarkerSvg.childNodes[0])&&t.beginElement&&t.beginElement()}else this.hide()},t.blockRendering.MarkerSvg.prototype.showAtLocation_=function(e){e.getType()==t.ASTNode.types.BLOCK?(e=e.getLocation(),this.showWithBlockPrevOutput_(e)):e.getType()==t.ASTNode.types.OUTPUT?(e=e.getLocation().getSourceBlock(),this.showWithBlockPrevOutput_(e)):e.getLocation().type==t.INPUT_VALUE?this.showWithInput_(e):e.getLocation().type==t.NEXT_STATEMENT?this.showWithNext_(e):e.getType()==t.ASTNode.types.PREVIOUS?(e=e.getLocation().getSourceBlock(),this.showWithBlockPrevOutput_(e)):e.getType()==t.ASTNode.types.FIELD?this.showWithField_(e):e.getType()==t.ASTNode.types.WORKSPACE?this.showWithCoordinates_(e):e.getType()==t.ASTNode.types.STACK&&this.showWithStack_(e)},t.blockRendering.MarkerSvg.prototype.firemarkerEvent_=function(e,o){var i=o.getSourceBlock(),n=this.isCursor()?"cursorMove":"markerMove";e=new t.Events.Ui(i,n,e,o),o.getType()==t.ASTNode.types.WORKSPACE&&(e.workspaceId=o.getLocation().id),t.Events.fire(e)},t.blockRendering.MarkerSvg.prototype.getBlinkProperties_=function(){return{attributeType:"XML",attributeName:"fill",dur:"1s",values:this.colour_+";transparent;transparent;",repeatCount:"indefinite"}},t.blockRendering.MarkerSvg.prototype.createDomInternal_=function(){if(this.markerSvg_=t.utils.dom.createSvgElement("g",{width:this.constants_.CURSOR_WS_WIDTH,height:this.constants_.WS_CURSOR_HEIGHT},this.svgGroup_),this.markerSvgLine_=t.utils.dom.createSvgElement("rect",{width:this.constants_.CURSOR_WS_WIDTH,height:this.constants_.WS_CURSOR_HEIGHT,style:"display: none"},this.markerSvg_),this.markerSvgRect_=t.utils.dom.createSvgElement("rect",{class:"blocklyVerticalMarker",rx:10,ry:10,style:"display: none"},this.markerSvg_),this.markerInput_=t.utils.dom.createSvgElement("path",{transform:"",style:"display: none"},this.markerSvg_),this.markerBlock_=t.utils.dom.createSvgElement("path",{transform:"",style:"display: none",fill:"none","stroke-width":this.constants_.CURSOR_STROKE_WIDTH},this.markerSvg_),this.isCursor()){var e=this.getBlinkProperties_();t.utils.dom.createSvgElement("animate",e,this.markerSvgLine_),t.utils.dom.createSvgElement("animate",e,this.markerInput_),e.attributeName="stroke",t.utils.dom.createSvgElement("animate",e,this.markerBlock_)}return this.markerSvg_},t.blockRendering.MarkerSvg.prototype.applyColour_=function(){if(this.markerSvgLine_.setAttribute("fill",this.colour_),this.markerSvgRect_.setAttribute("stroke",this.colour_),this.markerInput_.setAttribute("fill",this.colour_),this.markerBlock_.setAttribute("stroke",this.colour_),this.isCursor()){var t=this.colour_+";transparent;transparent;";this.markerSvgLine_.firstChild.setAttribute("values",t),this.markerInput_.firstChild.setAttribute("values",t),this.markerBlock_.firstChild.setAttribute("values",t)}},t.blockRendering.MarkerSvg.prototype.dispose=function(){this.svgGroup_&&t.utils.dom.removeNode(this.svgGroup_)},t.blockRendering.Types={NONE:0,FIELD:1,HAT:2,ICON:4,SPACER:8,BETWEEN_ROW_SPACER:16,IN_ROW_SPACER:32,EXTERNAL_VALUE_INPUT:64,INPUT:128,INLINE_INPUT:256,STATEMENT_INPUT:512,CONNECTION:1024,PREVIOUS_CONNECTION:2048,NEXT_CONNECTION:4096,OUTPUT_CONNECTION:8192,CORNER:16384,LEFT_SQUARE_CORNER:32768,LEFT_ROUND_CORNER:65536,RIGHT_SQUARE_CORNER:131072,RIGHT_ROUND_CORNER:262144,JAGGED_EDGE:524288,ROW:1048576,TOP_ROW:2097152,BOTTOM_ROW:4194304,INPUT_ROW:8388608},t.blockRendering.Types.LEFT_CORNER=t.blockRendering.Types.LEFT_SQUARE_CORNER|t.blockRendering.Types.LEFT_ROUND_CORNER,t.blockRendering.Types.RIGHT_CORNER=t.blockRendering.Types.RIGHT_SQUARE_CORNER|t.blockRendering.Types.RIGHT_ROUND_CORNER,t.blockRendering.Types.nextTypeValue_=16777216,t.blockRendering.Types.getType=function(e){return t.blockRendering.Types.hasOwnProperty(e)||(t.blockRendering.Types[e]=t.blockRendering.Types.nextTypeValue_,t.blockRendering.Types.nextTypeValue_<<=1),t.blockRendering.Types[e]},t.blockRendering.Types.isField=function(e){return e.type&t.blockRendering.Types.FIELD},t.blockRendering.Types.isHat=function(e){return e.type&t.blockRendering.Types.HAT},t.blockRendering.Types.isIcon=function(e){return e.type&t.blockRendering.Types.ICON},t.blockRendering.Types.isSpacer=function(e){return e.type&t.blockRendering.Types.SPACER},t.blockRendering.Types.isInRowSpacer=function(e){return e.type&t.blockRendering.Types.IN_ROW_SPACER},t.blockRendering.Types.isInput=function(e){return e.type&t.blockRendering.Types.INPUT},t.blockRendering.Types.isExternalInput=function(e){return e.type&t.blockRendering.Types.EXTERNAL_VALUE_INPUT},t.blockRendering.Types.isInlineInput=function(e){return e.type&t.blockRendering.Types.INLINE_INPUT},t.blockRendering.Types.isStatementInput=function(e){return e.type&t.blockRendering.Types.STATEMENT_INPUT},t.blockRendering.Types.isPreviousConnection=function(e){return e.type&t.blockRendering.Types.PREVIOUS_CONNECTION},t.blockRendering.Types.isNextConnection=function(e){return e.type&t.blockRendering.Types.NEXT_CONNECTION},t.blockRendering.Types.isPreviousOrNextConnection=function(e){return e.type&(t.blockRendering.Types.PREVIOUS_CONNECTION|t.blockRendering.Types.NEXT_CONNECTION)},t.blockRendering.Types.isLeftRoundedCorner=function(e){return e.type&t.blockRendering.Types.LEFT_ROUND_CORNER},t.blockRendering.Types.isRightRoundedCorner=function(e){return e.type&t.blockRendering.Types.RIGHT_ROUND_CORNER},t.blockRendering.Types.isLeftSquareCorner=function(e){return e.type&t.blockRendering.Types.LEFT_SQUARE_CORNER},t.blockRendering.Types.isRightSquareCorner=function(e){return e.type&t.blockRendering.Types.RIGHT_SQUARE_CORNER},t.blockRendering.Types.isCorner=function(e){return e.type&t.blockRendering.Types.CORNER},t.blockRendering.Types.isJaggedEdge=function(e){return e.type&t.blockRendering.Types.JAGGED_EDGE},t.blockRendering.Types.isRow=function(e){return e.type&t.blockRendering.Types.ROW},t.blockRendering.Types.isBetweenRowSpacer=function(e){return e.type&t.blockRendering.Types.BETWEEN_ROW_SPACER},t.blockRendering.Types.isTopRow=function(e){return e.type&t.blockRendering.Types.TOP_ROW},t.blockRendering.Types.isBottomRow=function(e){return e.type&t.blockRendering.Types.BOTTOM_ROW},t.blockRendering.Types.isTopOrBottomRow=function(e){return e.type&(t.blockRendering.Types.TOP_ROW|t.blockRendering.Types.BOTTOM_ROW)},t.blockRendering.Types.isInputRow=function(e){return e.type&t.blockRendering.Types.INPUT_ROW},t.blockRendering.Measurable=function(e){this.height=this.width=0,this.type=t.blockRendering.Types.NONE,this.centerline=this.xPos=0,this.constants_=e,this.notchOffset=this.constants_.NOTCH_OFFSET_LEFT},t.blockRendering.Connection=function(e,o){t.blockRendering.Connection.superClass_.constructor.call(this,e),this.connectionModel=o,this.shape=this.constants_.shapeFor(o),this.isDynamicShape=!!this.shape.isDynamic,this.type|=t.blockRendering.Types.CONNECTION},t.utils.object.inherits(t.blockRendering.Connection,t.blockRendering.Measurable),t.blockRendering.OutputConnection=function(e,o){t.blockRendering.OutputConnection.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.OUTPUT_CONNECTION,this.height=this.isDynamicShape?0:this.shape.height,this.startX=this.width=this.isDynamicShape?0:this.shape.width,this.connectionOffsetY=this.constants_.TAB_OFFSET_FROM_TOP,this.connectionOffsetX=0},t.utils.object.inherits(t.blockRendering.OutputConnection,t.blockRendering.Connection),t.blockRendering.PreviousConnection=function(e,o){t.blockRendering.PreviousConnection.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.PREVIOUS_CONNECTION,this.height=this.shape.height,this.width=this.shape.width},t.utils.object.inherits(t.blockRendering.PreviousConnection,t.blockRendering.Connection),t.blockRendering.NextConnection=function(e,o){t.blockRendering.NextConnection.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.NEXT_CONNECTION,this.height=this.shape.height,this.width=this.shape.width},t.utils.object.inherits(t.blockRendering.NextConnection,t.blockRendering.Connection),t.blockRendering.InputConnection=function(e,o){t.blockRendering.InputConnection.superClass_.constructor.call(this,e,o.connection),this.type|=t.blockRendering.Types.INPUT,this.input=o,this.align=o.align,(this.connectedBlock=o.connection&&o.connection.targetBlock()?o.connection.targetBlock():null)?(e=this.connectedBlock.getHeightWidth(),this.connectedBlockWidth=e.width,this.connectedBlockHeight=e.height):this.connectedBlockHeight=this.connectedBlockWidth=0,this.connectionOffsetY=this.connectionOffsetX=0},t.utils.object.inherits(t.blockRendering.InputConnection,t.blockRendering.Connection),t.blockRendering.InlineInput=function(e,o){t.blockRendering.InlineInput.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.INLINE_INPUT,this.connectedBlock?(this.width=this.connectedBlockWidth,this.height=this.connectedBlockHeight):(this.height=this.constants_.EMPTY_INLINE_INPUT_HEIGHT,this.width=this.constants_.EMPTY_INLINE_INPUT_PADDING),this.connectionHeight=this.isDynamicShape?this.shape.height(this.height):this.shape.height,this.connectionWidth=this.isDynamicShape?this.shape.width(this.height):this.shape.width,this.connectedBlock||(this.width+=this.connectionWidth*(this.isDynamicShape?2:1)),this.connectionOffsetY=this.isDynamicShape?this.shape.connectionOffsetY(this.connectionHeight):this.constants_.TAB_OFFSET_FROM_TOP,this.connectionOffsetX=this.isDynamicShape?this.shape.connectionOffsetX(this.connectionWidth):0},t.utils.object.inherits(t.blockRendering.InlineInput,t.blockRendering.InputConnection),t.blockRendering.StatementInput=function(e,o){t.blockRendering.StatementInput.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.STATEMENT_INPUT,this.height=this.connectedBlock?this.connectedBlockHeight+this.constants_.STATEMENT_BOTTOM_SPACER:this.constants_.EMPTY_STATEMENT_INPUT_HEIGHT,this.width=this.constants_.STATEMENT_INPUT_NOTCH_OFFSET+this.shape.width},t.utils.object.inherits(t.blockRendering.StatementInput,t.blockRendering.InputConnection),t.blockRendering.ExternalValueInput=function(e,o){t.blockRendering.ExternalValueInput.superClass_.constructor.call(this,e,o),this.type|=t.blockRendering.Types.EXTERNAL_VALUE_INPUT,this.height=this.connectedBlock?this.connectedBlockHeight-this.constants_.TAB_OFFSET_FROM_TOP-this.constants_.MEDIUM_PADDING:this.shape.height,this.width=this.shape.width+this.constants_.EXTERNAL_VALUE_INPUT_PADDING,this.connectionOffsetY=this.constants_.TAB_OFFSET_FROM_TOP,this.connectionHeight=this.shape.height,this.connectionWidth=this.shape.width},t.utils.object.inherits(t.blockRendering.ExternalValueInput,t.blockRendering.InputConnection),t.blockRendering.Icon=function(e,o){t.blockRendering.Icon.superClass_.constructor.call(this,e),this.icon=o,this.isVisible=o.isVisible(),this.type|=t.blockRendering.Types.ICON,e=o.getCorrectedSize(),this.height=e.height,this.width=e.width},t.utils.object.inherits(t.blockRendering.Icon,t.blockRendering.Measurable),t.blockRendering.JaggedEdge=function(e){t.blockRendering.JaggedEdge.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.JAGGED_EDGE,this.height=this.constants_.JAGGED_TEETH.height,this.width=this.constants_.JAGGED_TEETH.width},t.utils.object.inherits(t.blockRendering.JaggedEdge,t.blockRendering.Measurable),t.blockRendering.Field=function(e,o,i){t.blockRendering.Field.superClass_.constructor.call(this,e),this.field=o,this.isEditable=o.EDITABLE,this.flipRtl=o.getFlipRtl(),this.type|=t.blockRendering.Types.FIELD,e=this.field.getSize(),this.height=e.height,this.width=e.width,this.parentInput=i},t.utils.object.inherits(t.blockRendering.Field,t.blockRendering.Measurable),t.blockRendering.Hat=function(e){t.blockRendering.Hat.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.HAT,this.height=this.constants_.START_HAT.height,this.width=this.constants_.START_HAT.width,this.ascenderHeight=this.height},t.utils.object.inherits(t.blockRendering.Hat,t.blockRendering.Measurable),t.blockRendering.SquareCorner=function(e,o){t.blockRendering.SquareCorner.superClass_.constructor.call(this,e),this.type=(o&&"left"!=o?t.blockRendering.Types.RIGHT_SQUARE_CORNER:t.blockRendering.Types.LEFT_SQUARE_CORNER)|t.blockRendering.Types.CORNER,this.width=this.height=this.constants_.NO_PADDING},t.utils.object.inherits(t.blockRendering.SquareCorner,t.blockRendering.Measurable),t.blockRendering.RoundCorner=function(e,o){t.blockRendering.RoundCorner.superClass_.constructor.call(this,e),this.type=(o&&"left"!=o?t.blockRendering.Types.RIGHT_ROUND_CORNER:t.blockRendering.Types.LEFT_ROUND_CORNER)|t.blockRendering.Types.CORNER,this.width=this.constants_.CORNER_RADIUS,this.height=this.constants_.CORNER_RADIUS/2},t.utils.object.inherits(t.blockRendering.RoundCorner,t.blockRendering.Measurable),t.blockRendering.InRowSpacer=function(e,o){t.blockRendering.InRowSpacer.superClass_.constructor.call(this,e),this.type=this.type|t.blockRendering.Types.SPACER|t.blockRendering.Types.IN_ROW_SPACER,this.width=o,this.height=this.constants_.SPACER_DEFAULT_HEIGHT},t.utils.object.inherits(t.blockRendering.InRowSpacer,t.blockRendering.Measurable),t.blockRendering.Row=function(e){this.type=t.blockRendering.Types.ROW,this.elements=[],this.xPos=this.yPos=this.widthWithConnectedBlocks=this.minWidth=this.minHeight=this.width=this.height=0,this.hasJaggedEdge=this.hasDummyInput=this.hasInlineInput=this.hasStatement=this.hasExternalInput=!1,this.constants_=e,this.notchOffset=this.constants_.NOTCH_OFFSET_LEFT,this.align=null},t.blockRendering.Row.prototype.measure=function(){throw Error("Unexpected attempt to measure a base Row.")},t.blockRendering.Row.prototype.getLastInput=function(){for(var e,o=this.elements.length-1;e=this.elements[o];o--)if(t.blockRendering.Types.isInput(e))return e;return null},t.blockRendering.Row.prototype.startsWithElemSpacer=function(){return!0},t.blockRendering.Row.prototype.endsWithElemSpacer=function(){return!0},t.blockRendering.Row.prototype.getFirstSpacer=function(){for(var e,o=0;e=this.elements[o];o++)if(t.blockRendering.Types.isSpacer(e))return e;return null},t.blockRendering.Row.prototype.getLastSpacer=function(){for(var e,o=this.elements.length-1;e=this.elements[o];o--)if(t.blockRendering.Types.isSpacer(e))return e;return null},t.blockRendering.TopRow=function(e){t.blockRendering.TopRow.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.TOP_ROW,this.ascenderHeight=this.capline=0,this.hasPreviousConnection=!1,this.connection=null},t.utils.object.inherits(t.blockRendering.TopRow,t.blockRendering.Row),t.blockRendering.TopRow.prototype.hasLeftSquareCorner=function(t){var e=(t.hat?"cap"===t.hat:this.constants_.ADD_START_HATS)&&!t.outputConnection&&!t.previousConnection,o=t.getPreviousBlock();return!!t.outputConnection||e||!!o&&o.getNextBlock()==t},t.blockRendering.TopRow.prototype.hasRightSquareCorner=function(t){return!0},t.blockRendering.TopRow.prototype.measure=function(){for(var e,o=0,i=0,n=0,s=0;e=this.elements[s];s++)i+=e.width,t.blockRendering.Types.isSpacer(e)||(t.blockRendering.Types.isHat(e)?n=Math.max(n,e.ascenderHeight):o=Math.max(o,e.height));this.width=Math.max(this.minWidth,i),this.height=Math.max(this.minHeight,o)+n,this.capline=this.ascenderHeight=n,this.widthWithConnectedBlocks=this.width},t.blockRendering.TopRow.prototype.startsWithElemSpacer=function(){return!1},t.blockRendering.TopRow.prototype.endsWithElemSpacer=function(){return!1},t.blockRendering.BottomRow=function(e){t.blockRendering.BottomRow.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.BOTTOM_ROW,this.hasNextConnection=!1,this.connection=null,this.baseline=this.descenderHeight=0},t.utils.object.inherits(t.blockRendering.BottomRow,t.blockRendering.Row),t.blockRendering.BottomRow.prototype.hasLeftSquareCorner=function(t){return!!t.outputConnection||!!t.getNextBlock()},t.blockRendering.BottomRow.prototype.hasRightSquareCorner=function(t){return!0},t.blockRendering.BottomRow.prototype.measure=function(){for(var e,o=0,i=0,n=0,s=0;e=this.elements[s];s++)i+=e.width,t.blockRendering.Types.isSpacer(e)||(t.blockRendering.Types.isNextConnection(e)?n=Math.max(n,e.height):o=Math.max(o,e.height));this.width=Math.max(this.minWidth,i),this.height=Math.max(this.minHeight,o)+n,this.descenderHeight=n,this.widthWithConnectedBlocks=this.width},t.blockRendering.BottomRow.prototype.startsWithElemSpacer=function(){return!1},t.blockRendering.BottomRow.prototype.endsWithElemSpacer=function(){return!1},t.blockRendering.SpacerRow=function(e,o,i){t.blockRendering.SpacerRow.superClass_.constructor.call(this,e),this.type=this.type|t.blockRendering.Types.SPACER|t.blockRendering.Types.BETWEEN_ROW_SPACER,this.width=i,this.height=o,this.followsStatement=!1,this.widthWithConnectedBlocks=0,this.elements=[new t.blockRendering.InRowSpacer(this.constants_,i)]},t.utils.object.inherits(t.blockRendering.SpacerRow,t.blockRendering.Row),t.blockRendering.SpacerRow.prototype.measure=function(){},t.blockRendering.InputRow=function(e){t.blockRendering.InputRow.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.INPUT_ROW,this.connectedBlockWidths=0},t.utils.object.inherits(t.blockRendering.InputRow,t.blockRendering.Row),t.blockRendering.InputRow.prototype.measure=function(){this.width=this.minWidth,this.height=this.minHeight;for(var e,o=0,i=0;e=this.elements[i];i++)this.width+=e.width,t.blockRendering.Types.isInput(e)&&(t.blockRendering.Types.isStatementInput(e)?o+=e.connectedBlockWidth:t.blockRendering.Types.isExternalInput(e)&&0!=e.connectedBlockWidth&&(o+=e.connectedBlockWidth-e.connectionWidth)),t.blockRendering.Types.isSpacer(e)||(this.height=Math.max(this.height,e.height));this.connectedBlockWidths=o,this.widthWithConnectedBlocks=this.width+o},t.blockRendering.InputRow.prototype.endsWithElemSpacer=function(){return!this.hasExternalInput&&!this.hasStatement},t.blockRendering.RenderInfo=function(e,o){this.block_=o,this.renderer_=e,this.constants_=this.renderer_.getConstants(),this.outputConnection=o.outputConnection?new t.blockRendering.OutputConnection(this.constants_,o.outputConnection):null,this.isInline=o.getInputsInline()&&!o.isCollapsed(),this.isCollapsed=o.isCollapsed(),this.isInsertionMarker=o.isInsertionMarker(),this.RTL=o.RTL,this.statementEdge=this.width=this.widthWithChildren=this.height=0,this.rows=[],this.inputRows=[],this.hiddenIcons=[],this.topRow=new t.blockRendering.TopRow(this.constants_),this.bottomRow=new t.blockRendering.BottomRow(this.constants_),this.startY=this.startX=0},t.blockRendering.RenderInfo.prototype.getRenderer=function(){return this.renderer_},t.blockRendering.RenderInfo.prototype.measure=function(){this.createRows_(),this.addElemSpacing_(),this.addRowSpacing_(),this.computeBounds_(),this.alignRowElements_(),this.finalize_()},t.blockRendering.RenderInfo.prototype.createRows_=function(){this.populateTopRow_(),this.rows.push(this.topRow);var e=new t.blockRendering.InputRow(this.constants_);this.inputRows.push(e);var o=this.block_.getIcons();if(o.length)for(var i,n=0;i=o[n];n++){var s=new t.blockRendering.Icon(this.constants_,i);this.isCollapsed&&i.collapseHidden?this.hiddenIcons.push(s):e.elements.push(s)}for(i=null,n=0;o=this.block_.inputList[n];n++)if(o.isVisible()){for(this.shouldStartNewRow_(o,i)&&(this.rows.push(e),e=new t.blockRendering.InputRow(this.constants_),this.inputRows.push(e)),i=0;s=o.fieldRow[i];i++)e.elements.push(new t.blockRendering.Field(this.constants_,s,o));this.addInput_(o,e),i=o}this.isCollapsed&&(e.hasJaggedEdge=!0,e.elements.push(new t.blockRendering.JaggedEdge(this.constants_))),(e.elements.length||e.hasDummyInput)&&this.rows.push(e),this.populateBottomRow_(),this.rows.push(this.bottomRow)},t.blockRendering.RenderInfo.prototype.populateTopRow_=function(){var e=!!this.block_.previousConnection,o=(this.block_.hat?"cap"===this.block_.hat:this.constants_.ADD_START_HATS)&&!this.outputConnection&&!e;this.topRow.hasLeftSquareCorner(this.block_)?this.topRow.elements.push(new t.blockRendering.SquareCorner(this.constants_)):this.topRow.elements.push(new t.blockRendering.RoundCorner(this.constants_)),o?(e=new t.blockRendering.Hat(this.constants_),this.topRow.elements.push(e),this.topRow.capline=e.ascenderHeight):e&&(this.topRow.hasPreviousConnection=!0,this.topRow.connection=new t.blockRendering.PreviousConnection(this.constants_,this.block_.previousConnection),this.topRow.elements.push(this.topRow.connection)),this.block_.inputList.length&&this.block_.inputList[0].type==t.NEXT_STATEMENT&&!this.block_.isCollapsed()?this.topRow.minHeight=this.constants_.TOP_ROW_PRECEDES_STATEMENT_MIN_HEIGHT:this.topRow.minHeight=this.constants_.TOP_ROW_MIN_HEIGHT,this.topRow.hasRightSquareCorner(this.block_)?this.topRow.elements.push(new t.blockRendering.SquareCorner(this.constants_,"right")):this.topRow.elements.push(new t.blockRendering.RoundCorner(this.constants_,"right"))},t.blockRendering.RenderInfo.prototype.populateBottomRow_=function(){this.bottomRow.hasNextConnection=!!this.block_.nextConnection,this.bottomRow.minHeight=this.block_.inputList.length&&this.block_.inputList[this.block_.inputList.length-1].type==t.NEXT_STATEMENT?this.constants_.BOTTOM_ROW_AFTER_STATEMENT_MIN_HEIGHT:this.constants_.BOTTOM_ROW_MIN_HEIGHT,this.bottomRow.hasLeftSquareCorner(this.block_)?this.bottomRow.elements.push(new t.blockRendering.SquareCorner(this.constants_)):this.bottomRow.elements.push(new t.blockRendering.RoundCorner(this.constants_)),this.bottomRow.hasNextConnection&&(this.bottomRow.connection=new t.blockRendering.NextConnection(this.constants_,this.block_.nextConnection),this.bottomRow.elements.push(this.bottomRow.connection)),this.bottomRow.hasRightSquareCorner(this.block_)?this.bottomRow.elements.push(new t.blockRendering.SquareCorner(this.constants_,"right")):this.bottomRow.elements.push(new t.blockRendering.RoundCorner(this.constants_,"right"))},t.blockRendering.RenderInfo.prototype.addInput_=function(e,o){this.isInline&&e.type==t.INPUT_VALUE?(o.elements.push(new t.blockRendering.InlineInput(this.constants_,e)),o.hasInlineInput=!0):e.type==t.NEXT_STATEMENT?(o.elements.push(new t.blockRendering.StatementInput(this.constants_,e)),o.hasStatement=!0):e.type==t.INPUT_VALUE?(o.elements.push(new t.blockRendering.ExternalValueInput(this.constants_,e)),o.hasExternalInput=!0):e.type==t.DUMMY_INPUT&&(o.minHeight=Math.max(o.minHeight,e.getSourceBlock()&&e.getSourceBlock().isShadow()?this.constants_.DUMMY_INPUT_SHADOW_MIN_HEIGHT:this.constants_.DUMMY_INPUT_MIN_HEIGHT),o.hasDummyInput=!0),null==o.align&&(o.align=e.align)},t.blockRendering.RenderInfo.prototype.shouldStartNewRow_=function(e,o){return!(!o||e.type!=t.NEXT_STATEMENT&&o.type!=t.NEXT_STATEMENT&&(e.type!=t.INPUT_VALUE&&e.type!=t.DUMMY_INPUT||this.isInline))},t.blockRendering.RenderInfo.prototype.addElemSpacing_=function(){for(var e,o=0;e=this.rows[o];o++){var i=e.elements;if(e.elements=[],e.startsWithElemSpacer()&&e.elements.push(new t.blockRendering.InRowSpacer(this.constants_,this.getInRowSpacing_(null,i[0]))),i.length){for(var n=0;n.blocklyPathLight,",e+" .blocklyInsertionMarker>.blocklyPathDark {","fill-opacity: "+this.INSERTION_MARKER_OPACITY+";","stroke: none","}"])},t.geras.Highlighter=function(t){this.info_=t,this.inlineSteps_=this.steps_="",this.RTL_=this.info_.RTL,t=t.getRenderer(),this.constants_=t.getConstants(),this.highlightConstants_=t.getHighlightConstants(),this.highlightOffset_=this.highlightConstants_.OFFSET,this.outsideCornerPaths_=this.highlightConstants_.OUTSIDE_CORNER,this.insideCornerPaths_=this.highlightConstants_.INSIDE_CORNER,this.puzzleTabPaths_=this.highlightConstants_.PUZZLE_TAB,this.notchPaths_=this.highlightConstants_.NOTCH,this.startPaths_=this.highlightConstants_.START_HAT,this.jaggedTeethPaths_=this.highlightConstants_.JAGGED_TEETH},t.geras.Highlighter.prototype.getPath=function(){return this.steps_+"\n"+this.inlineSteps_},t.geras.Highlighter.prototype.drawTopCorner=function(e){this.steps_+=t.utils.svgPaths.moveBy(e.xPos,this.info_.startY);for(var o,i=0;o=e.elements[i];i++)t.blockRendering.Types.isLeftSquareCorner(o)?this.steps_+=this.highlightConstants_.START_POINT:t.blockRendering.Types.isLeftRoundedCorner(o)?this.steps_+=this.outsideCornerPaths_.topLeft(this.RTL_):t.blockRendering.Types.isPreviousConnection(o)?this.steps_+=this.notchPaths_.pathLeft:t.blockRendering.Types.isHat(o)?this.steps_+=this.startPaths_.path(this.RTL_):t.blockRendering.Types.isSpacer(o)&&0!=o.width&&(this.steps_+=t.utils.svgPaths.lineOnAxis("H",o.xPos+o.width-this.highlightOffset_));this.steps_+=t.utils.svgPaths.lineOnAxis("H",e.xPos+e.width-this.highlightOffset_)},t.geras.Highlighter.prototype.drawJaggedEdge_=function(e){this.info_.RTL&&(this.steps_+=this.jaggedTeethPaths_.pathLeft+t.utils.svgPaths.lineOnAxis("v",e.height-this.jaggedTeethPaths_.height-this.highlightOffset_))},t.geras.Highlighter.prototype.drawValueInput=function(e){var o=e.getLastInput();if(this.RTL_){var i=e.height-o.connectionHeight;this.steps_+=t.utils.svgPaths.moveTo(o.xPos+o.width-this.highlightOffset_,e.yPos)+this.puzzleTabPaths_.pathDown(this.RTL_)+t.utils.svgPaths.lineOnAxis("v",i)}else this.steps_+=t.utils.svgPaths.moveTo(o.xPos+o.width,e.yPos)+this.puzzleTabPaths_.pathDown(this.RTL_)},t.geras.Highlighter.prototype.drawStatementInput=function(e){var o=e.getLastInput();if(this.RTL_){var i=e.height-2*this.insideCornerPaths_.height;this.steps_+=t.utils.svgPaths.moveTo(o.xPos,e.yPos)+this.insideCornerPaths_.pathTop(this.RTL_)+t.utils.svgPaths.lineOnAxis("v",i)+this.insideCornerPaths_.pathBottom(this.RTL_)+t.utils.svgPaths.lineTo(e.width-o.xPos-this.insideCornerPaths_.width,0)}else this.steps_+=t.utils.svgPaths.moveTo(o.xPos,e.yPos+e.height)+this.insideCornerPaths_.pathBottom(this.RTL_)+t.utils.svgPaths.lineTo(e.width-o.xPos-this.insideCornerPaths_.width,0)},t.geras.Highlighter.prototype.drawRightSideRow=function(e){var o=e.xPos+e.width-this.highlightOffset_;e.followsStatement&&(this.steps_+=t.utils.svgPaths.lineOnAxis("H",o)),this.RTL_&&(this.steps_+=t.utils.svgPaths.lineOnAxis("H",o),e.height>this.highlightOffset_&&(this.steps_+=t.utils.svgPaths.lineOnAxis("V",e.yPos+e.height-this.highlightOffset_)))},t.geras.Highlighter.prototype.drawBottomRow=function(e){if(this.RTL_)this.steps_+=t.utils.svgPaths.lineOnAxis("V",e.baseline-this.highlightOffset_);else{var o=this.info_.bottomRow.elements[0];t.blockRendering.Types.isLeftSquareCorner(o)?this.steps_+=t.utils.svgPaths.moveTo(e.xPos+this.highlightOffset_,e.baseline-this.highlightOffset_):t.blockRendering.Types.isLeftRoundedCorner(o)&&(this.steps_+=t.utils.svgPaths.moveTo(e.xPos,e.baseline),this.steps_+=this.outsideCornerPaths_.bottomLeft())}},t.geras.Highlighter.prototype.drawLeft=function(){var e=this.info_.outputConnection;e&&(e=e.connectionOffsetY+e.height,this.RTL_?this.steps_+=t.utils.svgPaths.moveTo(this.info_.startX,e):(this.steps_+=t.utils.svgPaths.moveTo(this.info_.startX+this.highlightOffset_,this.info_.bottomRow.baseline-this.highlightOffset_),this.steps_+=t.utils.svgPaths.lineOnAxis("V",e)),this.steps_+=this.puzzleTabPaths_.pathUp(this.RTL_)),this.RTL_||(e=this.info_.topRow,t.blockRendering.Types.isLeftRoundedCorner(e.elements[0])?this.steps_+=t.utils.svgPaths.lineOnAxis("V",this.outsideCornerPaths_.height):this.steps_+=t.utils.svgPaths.lineOnAxis("V",e.capline+this.highlightOffset_))},t.geras.Highlighter.prototype.drawInlineInput=function(e){var o=this.highlightOffset_,i=e.xPos+e.connectionWidth,n=e.centerline-e.height/2,s=e.width-e.connectionWidth,r=n+o;this.RTL_?(n=e.connectionOffsetY-o,e=e.height-(e.connectionOffsetY+e.connectionHeight)+o,this.inlineSteps_+=t.utils.svgPaths.moveTo(i-o,r)+t.utils.svgPaths.lineOnAxis("v",n)+this.puzzleTabPaths_.pathDown(this.RTL_)+t.utils.svgPaths.lineOnAxis("v",e)+t.utils.svgPaths.lineOnAxis("h",s)):this.inlineSteps_+=t.utils.svgPaths.moveTo(e.xPos+e.width+o,r)+t.utils.svgPaths.lineOnAxis("v",e.height)+t.utils.svgPaths.lineOnAxis("h",-s)+t.utils.svgPaths.moveTo(i,n+e.connectionOffsetY)+this.puzzleTabPaths_.pathDown(this.RTL_)},t.geras.InlineInput=function(e,o){t.geras.InlineInput.superClass_.constructor.call(this,e,o),this.connectedBlock&&(this.width+=this.constants_.DARK_PATH_OFFSET,this.height+=this.constants_.DARK_PATH_OFFSET)},t.utils.object.inherits(t.geras.InlineInput,t.blockRendering.InlineInput),t.geras.StatementInput=function(e,o){t.geras.StatementInput.superClass_.constructor.call(this,e,o),this.connectedBlock&&(this.height+=this.constants_.DARK_PATH_OFFSET)},t.utils.object.inherits(t.geras.StatementInput,t.blockRendering.StatementInput),t.geras.RenderInfo=function(e,o){t.geras.RenderInfo.superClass_.constructor.call(this,e,o)},t.utils.object.inherits(t.geras.RenderInfo,t.blockRendering.RenderInfo),t.geras.RenderInfo.prototype.getRenderer=function(){return this.renderer_},t.geras.RenderInfo.prototype.populateBottomRow_=function(){t.geras.RenderInfo.superClass_.populateBottomRow_.call(this),this.block_.inputList.length&&this.block_.inputList[this.block_.inputList.length-1].type==t.NEXT_STATEMENT||(this.bottomRow.minHeight=this.constants_.MEDIUM_PADDING-this.constants_.DARK_PATH_OFFSET)},t.geras.RenderInfo.prototype.addInput_=function(e,o){this.isInline&&e.type==t.INPUT_VALUE?(o.elements.push(new t.geras.InlineInput(this.constants_,e)),o.hasInlineInput=!0):e.type==t.NEXT_STATEMENT?(o.elements.push(new t.geras.StatementInput(this.constants_,e)),o.hasStatement=!0):e.type==t.INPUT_VALUE?(o.elements.push(new t.blockRendering.ExternalValueInput(this.constants_,e)),o.hasExternalInput=!0):e.type==t.DUMMY_INPUT&&(o.minHeight=Math.max(o.minHeight,this.constants_.DUMMY_INPUT_MIN_HEIGHT),o.hasDummyInput=!0),this.isInline||null!=o.align||(o.align=e.align)},t.geras.RenderInfo.prototype.addElemSpacing_=function(){for(var e,o=!1,i=0;e=this.rows[i];i++)e.hasExternalInput&&(o=!0);for(i=0;e=this.rows[i];i++){var n=e.elements;if(e.elements=[],e.startsWithElemSpacer()&&e.elements.push(new t.blockRendering.InRowSpacer(this.constants_,this.getInRowSpacing_(null,n[0]))),n.length){for(var s=0;so?o:s,n=n?-1:1,e=(i?-1:1)*e/2,t.utils.svgPaths.lineTo(-n*s,e)+t.utils.svgPaths.lineTo(n*s,e)}var o=this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH;return{type:this.SHAPES.HEXAGONAL,isDynamic:!0,width:function(t){return(t/=2)>o?o:t},height:function(t){return t},connectionOffsetY:function(t){return t/2},connectionOffsetX:function(t){return-t},pathDown:function(t){return e(t,!1,!1)},pathUp:function(t){return e(t,!0,!1)},pathRightDown:function(t){return e(t,!1,!0)},pathRightUp:function(t){return e(t,!1,!0)}}},t.zelos.ConstantProvider.prototype.makeRounded=function(){function e(e,o,n){var s=e>i?e-i:0;return e=(e>i?i:e)/2,t.utils.svgPaths.arc("a","0 0,1",e,t.utils.svgPaths.point((o?-1:1)*e,(o?-1:1)*e))+t.utils.svgPaths.lineOnAxis("v",(n?1:-1)*s)+t.utils.svgPaths.arc("a","0 0,1",e,t.utils.svgPaths.point((o?1:-1)*e,(o?-1:1)*e))}var o=this.MAX_DYNAMIC_CONNECTION_SHAPE_WIDTH,i=2*o;return{type:this.SHAPES.ROUND,isDynamic:!0,width:function(t){return(t/=2)>o?o:t},height:function(t){return t},connectionOffsetY:function(t){return t/2},connectionOffsetX:function(t){return-t},pathDown:function(t){return e(t,!1,!1)},pathUp:function(t){return e(t,!0,!1)},pathRightDown:function(t){return e(t,!1,!0)},pathRightUp:function(t){return e(t,!1,!0)}}},t.zelos.ConstantProvider.prototype.makeSquared=function(){function e(e,i,n){return e-=2*o,t.utils.svgPaths.arc("a","0 0,1",o,t.utils.svgPaths.point((i?-1:1)*o,(i?-1:1)*o))+t.utils.svgPaths.lineOnAxis("v",(n?1:-1)*e)+t.utils.svgPaths.arc("a","0 0,1",o,t.utils.svgPaths.point((i?1:-1)*o,(i?-1:1)*o))}var o=this.CORNER_RADIUS;return{type:this.SHAPES.SQUARE,isDynamic:!0,width:function(t){return o},height:function(t){return t},connectionOffsetY:function(t){return t/2},connectionOffsetX:function(t){return-t},pathDown:function(t){return e(t,!1,!1)},pathUp:function(t){return e(t,!0,!1)},pathRightDown:function(t){return e(t,!1,!0)},pathRightUp:function(t){return e(t,!1,!0)}}},t.zelos.ConstantProvider.prototype.shapeFor=function(e){var o=e.getCheck();switch(!o&&e.targetConnection&&(o=e.targetConnection.getCheck()),e.type){case t.INPUT_VALUE:case t.OUTPUT_VALUE:if(null!=(e=e.getSourceBlock().getOutputShape()))switch(e){case this.SHAPES.HEXAGONAL:return this.HEXAGONAL;case this.SHAPES.ROUND:return this.ROUNDED;case this.SHAPES.SQUARE:return this.SQUARED}return o&&-1!=o.indexOf("Boolean")?this.HEXAGONAL:(o&&-1!=o.indexOf("Number")||o&&o.indexOf("String"),this.ROUNDED);case t.PREVIOUS_STATEMENT:case t.NEXT_STATEMENT:return this.NOTCH;default:throw Error("Unknown type")}},t.zelos.ConstantProvider.prototype.makeNotch=function(){function e(e){return t.utils.svgPaths.curve("c",[t.utils.svgPaths.point(e*s/2,0),t.utils.svgPaths.point(e*s*3/4,a/2),t.utils.svgPaths.point(e*s,a)])+t.utils.svgPaths.line([t.utils.svgPaths.point(e*s,r)])+t.utils.svgPaths.curve("c",[t.utils.svgPaths.point(e*s/4,a/2),t.utils.svgPaths.point(e*s/2,a),t.utils.svgPaths.point(e*s,a)])+t.utils.svgPaths.lineOnAxis("h",e*n)+t.utils.svgPaths.curve("c",[t.utils.svgPaths.point(e*s/2,0),t.utils.svgPaths.point(e*s*3/4,-a/2),t.utils.svgPaths.point(e*s,-a)])+t.utils.svgPaths.line([t.utils.svgPaths.point(e*s,-r)])+t.utils.svgPaths.curve("c",[t.utils.svgPaths.point(e*s/4,-a/2),t.utils.svgPaths.point(e*s/2,-a),t.utils.svgPaths.point(e*s,-a)])}var o=this.NOTCH_WIDTH,i=this.NOTCH_HEIGHT,n=o/3,s=n/3,r=i/2,a=r/2,l=e(1),c=e(-1);return{type:this.SHAPES.NOTCH,width:o,height:i,pathLeft:l,pathRight:c}},t.zelos.ConstantProvider.prototype.makeInsideCorners=function(){var e=this.CORNER_RADIUS,o=t.utils.svgPaths.arc("a","0 0,0",e,t.utils.svgPaths.point(-e,e)),i=t.utils.svgPaths.arc("a","0 0,1",e,t.utils.svgPaths.point(-e,e));return{width:e,height:e,pathTop:o,pathBottom:t.utils.svgPaths.arc("a","0 0,0",e,t.utils.svgPaths.point(e,e)),rightWidth:e,rightHeight:e,pathTopRight:i,pathBottomRight:t.utils.svgPaths.arc("a","0 0,1",e,t.utils.svgPaths.point(e,e))}},t.zelos.ConstantProvider.prototype.generateSecondaryColour_=function(e){return t.utils.colour.blend("#000",e,.15)||e},t.zelos.ConstantProvider.prototype.generateTertiaryColour_=function(e){return t.utils.colour.blend("#000",e,.25)||e},t.zelos.ConstantProvider.prototype.createDom=function(e,o,i){t.zelos.ConstantProvider.superClass_.createDom.call(this,e,o,i),e=t.utils.dom.createSvgElement("defs",{},e),o=t.utils.dom.createSvgElement("filter",{id:"blocklySelectedGlowFilter"+this.randomIdentifier,height:"160%",width:"180%",y:"-30%",x:"-40%"},e),t.utils.dom.createSvgElement("feGaussianBlur",{in:"SourceGraphic",stdDeviation:this.SELECTED_GLOW_SIZE},o),i=t.utils.dom.createSvgElement("feComponentTransfer",{result:"outBlur"},o),t.utils.dom.createSvgElement("feFuncA",{type:"table",tableValues:"0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"},i),t.utils.dom.createSvgElement("feFlood",{"flood-color":this.SELECTED_GLOW_COLOUR,"flood-opacity":1,result:"outColor"},o),t.utils.dom.createSvgElement("feComposite",{in:"outColor",in2:"outBlur",operator:"in",result:"outGlow"},o),this.selectedGlowFilterId=o.id,this.selectedGlowFilter_=o,e=t.utils.dom.createSvgElement("filter",{id:"blocklyReplacementGlowFilter"+this.randomIdentifier,height:"160%",width:"180%",y:"-30%",x:"-40%"},e),t.utils.dom.createSvgElement("feGaussianBlur",{in:"SourceGraphic",stdDeviation:this.REPLACEMENT_GLOW_SIZE},e),o=t.utils.dom.createSvgElement("feComponentTransfer",{result:"outBlur"},e),t.utils.dom.createSvgElement("feFuncA",{type:"table",tableValues:"0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1"},o),t.utils.dom.createSvgElement("feFlood",{"flood-color":this.REPLACEMENT_GLOW_COLOUR,"flood-opacity":1,result:"outColor"},e),t.utils.dom.createSvgElement("feComposite",{in:"outColor",in2:"outBlur",operator:"in",result:"outGlow"},e),t.utils.dom.createSvgElement("feComposite",{in:"SourceGraphic",in2:"outGlow",operator:"over"},e),this.replacementGlowFilterId=e.id,this.replacementGlowFilter_=e},t.zelos.ConstantProvider.prototype.getCSS_=function(t){return[t+" .blocklyText, ",t+" .blocklyFlyoutLabelText {","font-family: "+this.FIELD_TEXT_FONTFAMILY+";","font-size: "+this.FIELD_TEXT_FONTSIZE+"pt;","font-weight: "+this.FIELD_TEXT_FONTWEIGHT+";","}",t+" .blocklyText {","fill: #fff;","}",t+" .blocklyNonEditableText>rect:not(.blocklyDropdownRect),",t+" .blocklyEditableText>rect:not(.blocklyDropdownRect) {","fill: "+this.FIELD_BORDER_RECT_COLOUR+";","}",t+" .blocklyNonEditableText>text,",t+" .blocklyEditableText>text,",t+" .blocklyNonEditableText>g>text,",t+" .blocklyEditableText>g>text {","fill: #575E75;","}",t+" .blocklyFlyoutLabelText {","fill: #575E75;","}",t+" .blocklyText.blocklyBubbleText {","fill: #575E75;","}",t+" .blocklyDraggable:not(.blocklyDisabled)"," .blocklyEditableText:not(.editing):hover>rect ,",t+" .blocklyDraggable:not(.blocklyDisabled)"," .blocklyEditableText:not(.editing):hover>.blocklyPath {","stroke: #fff;","stroke-width: 2;","}",t+" .blocklyHtmlInput {","font-family: "+this.FIELD_TEXT_FONTFAMILY+";","font-weight: "+this.FIELD_TEXT_FONTWEIGHT+";","color: #575E75;","}",t+" .blocklyDropdownText {","fill: #fff !important;","}",t+".blocklyWidgetDiv .goog-menuitem,",t+".blocklyDropDownDiv .goog-menuitem {","font-family: "+this.FIELD_TEXT_FONTFAMILY+";","}",t+".blocklyDropDownDiv .goog-menuitem-content {","color: #fff;","}",t+" .blocklyHighlightedConnectionPath {","stroke: "+this.SELECTED_GLOW_COLOUR+";","}",t+" .blocklyDisabled > .blocklyOutlinePath {","fill: url(#blocklyDisabledPattern"+this.randomIdentifier+")","}",t+" .blocklyInsertionMarker>.blocklyPath {","fill-opacity: "+this.INSERTION_MARKER_OPACITY+";","stroke: none","}"]},t.zelos.TopRow=function(e){t.zelos.TopRow.superClass_.constructor.call(this,e)},t.utils.object.inherits(t.zelos.TopRow,t.blockRendering.TopRow),t.zelos.TopRow.prototype.endsWithElemSpacer=function(){return!1},t.zelos.TopRow.prototype.hasLeftSquareCorner=function(t){var e=(t.hat?"cap"===t.hat:this.constants_.ADD_START_HATS)&&!t.outputConnection&&!t.previousConnection;return!!t.outputConnection||e},t.zelos.TopRow.prototype.hasRightSquareCorner=function(t){return!!t.outputConnection&&!t.statementInputCount&&!t.nextConnection},t.zelos.BottomRow=function(e){t.zelos.BottomRow.superClass_.constructor.call(this,e)},t.utils.object.inherits(t.zelos.BottomRow,t.blockRendering.BottomRow),t.zelos.BottomRow.prototype.endsWithElemSpacer=function(){return!1},t.zelos.BottomRow.prototype.hasLeftSquareCorner=function(t){return!!t.outputConnection},t.zelos.BottomRow.prototype.hasRightSquareCorner=function(t){return!!t.outputConnection&&!t.statementInputCount&&!t.nextConnection},t.zelos.RightConnectionShape=function(e){t.zelos.RightConnectionShape.superClass_.constructor.call(this,e),this.type|=t.blockRendering.Types.getType("RIGHT_CONNECTION"),this.width=this.height=0},t.utils.object.inherits(t.zelos.RightConnectionShape,t.blockRendering.Measurable),t.zelos.StatementInput=function(e,o){if(t.zelos.StatementInput.superClass_.constructor.call(this,e,o),this.connectedBlock){for(e=this.connectedBlock;e.getNextBlock();)e=e.getNextBlock();e.nextConnection||(this.height=this.connectedBlockHeight,this.connectedBottomNextConnection=!0)}},t.utils.object.inherits(t.zelos.StatementInput,t.blockRendering.StatementInput),t.zelos.RenderInfo=function(e,o){t.zelos.RenderInfo.superClass_.constructor.call(this,e,o),this.topRow=new t.zelos.TopRow(this.constants_),this.bottomRow=new t.zelos.BottomRow(this.constants_),this.isInline=!0,this.isMultiRow=!o.getInputsInline()||o.isCollapsed(),this.hasStatementInput=0=this.rows.length-1?!!this.bottomRow.hasNextConnection:!!r.precedesStatement,t.blockRendering.Types.isInputRow(s)&&s.hasStatement)s.measure(),o=s.width-s.getLastInput().width+e;else if(n&&(2==i||r)&&t.blockRendering.Types.isInputRow(s)&&!s.hasStatement){r=s.xPos,n=null;for(var a,l=0;a=s.elements[l];l++)t.blockRendering.Types.isSpacer(a)&&(n=a),!(n&&(t.blockRendering.Types.isField(a)||t.blockRendering.Types.isInput(a))&&ri?i:this.height/2)*(1-Math.sin(Math.acos((i-this.constants_.SMALL_PADDING)/i)));default:return 0}if(t.blockRendering.Types.isInlineInput(e)){var s=e.connectedBlock;return e=s?s.pathObject.outputShapeType:e.shape.type,s&&s.outputConnection&&(s.statementInputCount||s.nextConnection)||i==n.SHAPES.HEXAGONAL&&i!=e?0:o-this.constants_.SHAPE_IN_SHAPE_PADDING[i][e]}return t.blockRendering.Types.isField(e)?i==n.SHAPES.ROUND&&e.field instanceof t.FieldTextInput?o-2.75*n.GRID_UNIT:o-this.constants_.SHAPE_IN_SHAPE_PADDING[i][0]:t.blockRendering.Types.isIcon(e)?this.constants_.SMALL_PADDING:0},t.zelos.RenderInfo.prototype.finalizeVerticalAlignment_=function(){if(!this.outputConnection)for(var e=2;e=this.rows.length-1?!!this.bottomRow.hasNextConnection:!!n.precedesStatement;if(s?this.topRow.hasPreviousConnection:o.followsStatement){var a=3==i.elements.length&&(i.elements[1].field instanceof t.FieldLabel||i.elements[1].field instanceof t.FieldImage);if(!s&&a)o.height-=this.constants_.SMALL_PADDING,n.height-=this.constants_.SMALL_PADDING,i.height-=this.constants_.MEDIUM_PADDING;else if(s||r){if(r){for(s=!1,r=0;a=i.elements[r];r++)if(t.blockRendering.Types.isInlineInput(a)&&a.connectedBlock&&!a.connectedBlock.isShadow()&&40<=a.connectedBlock.getHeightWidth().height){s=!0;break}s&&(o.height-=this.constants_.SMALL_PADDING,n.height-=this.constants_.SMALL_PADDING)}}else o.height+=this.constants_.SMALL_PADDING}}},t.zelos.RenderInfo.prototype.finalize_=function(){this.finalizeOutputConnection_(),this.finalizeHorizontalAlignment_(),this.finalizeVerticalAlignment_(),t.zelos.RenderInfo.superClass_.finalize_.call(this),this.rightSide&&(this.widthWithChildren+=this.rightSide.width)},t.zelos.Drawer=function(e,o){t.zelos.Drawer.superClass_.constructor.call(this,e,o)},t.utils.object.inherits(t.zelos.Drawer,t.blockRendering.Drawer),t.zelos.Drawer.prototype.draw=function(){var e=this.block_.pathObject;e.beginDrawing(),this.hideHiddenIcons_(),this.drawOutline_(),this.drawInternals_(),e.setPath(this.outlinePath_+"\n"+this.inlinePath_),this.info_.RTL&&e.flipRTL(),t.blockRendering.useDebugger&&this.block_.renderingDebugger.drawDebug(this.block_,this.info_),this.recordSizeOnBlock_(),this.info_.outputConnection&&(e.outputShapeType=this.info_.outputConnection.shape.type),e.endDrawing()},t.zelos.Drawer.prototype.drawOutline_=function(){this.info_.outputConnection&&this.info_.outputConnection.isDynamicShape&&!this.info_.hasStatementInput&&!this.info_.bottomRow.hasNextConnection?(this.drawFlatTop_(),this.drawRightDynamicConnection_(),this.drawFlatBottom_(),this.drawLeftDynamicConnection_()):t.zelos.Drawer.superClass_.drawOutline_.call(this)},t.zelos.Drawer.prototype.drawLeft_=function(){this.info_.outputConnection&&this.info_.outputConnection.isDynamicShape?this.drawLeftDynamicConnection_():t.zelos.Drawer.superClass_.drawLeft_.call(this)},t.zelos.Drawer.prototype.drawRightSideRow_=function(e){if(!(0>=e.height))if(e.precedesStatement||e.followsStatement){var o=this.constants_.INSIDE_CORNERS.rightHeight;o=e.height-(e.precedesStatement?o:0),this.outlinePath_+=(e.followsStatement?this.constants_.INSIDE_CORNERS.pathBottomRight:"")+(0","GT"],["‏≥","GTE"]]},{type:"input_value",name:"B"}],inputsInline:!0,output:"Boolean",style:"logic_blocks",helpUrl:"%{BKY_LOGIC_COMPARE_HELPURL}",extensions:["logic_compare","logic_op_tooltip"]},{type:"logic_operation",message0:"%1 %2 %3",args0:[{type:"input_value",name:"A",check:"Boolean"},{type:"field_dropdown",name:"OP",options:[["%{BKY_LOGIC_OPERATION_AND}","AND"],["%{BKY_LOGIC_OPERATION_OR}","OR"]]},{type:"input_value",name:"B",check:"Boolean"}],inputsInline:!0,output:"Boolean",style:"logic_blocks",helpUrl:"%{BKY_LOGIC_OPERATION_HELPURL}",extensions:["logic_op_tooltip"]},{type:"logic_negate",message0:"%{BKY_LOGIC_NEGATE_TITLE}",args0:[{type:"input_value",name:"BOOL",check:"Boolean"}],output:"Boolean",style:"logic_blocks",tooltip:"%{BKY_LOGIC_NEGATE_TOOLTIP}",helpUrl:"%{BKY_LOGIC_NEGATE_HELPURL}"},{type:"logic_null",message0:"%{BKY_LOGIC_NULL}",output:null,style:"logic_blocks",tooltip:"%{BKY_LOGIC_NULL_TOOLTIP}",helpUrl:"%{BKY_LOGIC_NULL_HELPURL}"},{type:"logic_ternary",message0:"%{BKY_LOGIC_TERNARY_CONDITION} %1",args0:[{type:"input_value",name:"IF",check:"Boolean"}],message1:"%{BKY_LOGIC_TERNARY_IF_TRUE} %1",args1:[{type:"input_value",name:"THEN"}],message2:"%{BKY_LOGIC_TERNARY_IF_FALSE} %1",args2:[{type:"input_value",name:"ELSE"}],output:null,style:"logic_blocks",tooltip:"%{BKY_LOGIC_TERNARY_TOOLTIP}",helpUrl:"%{BKY_LOGIC_TERNARY_HELPURL}",extensions:["logic_ternary"]}]),t.defineBlocksWithJsonArray([{type:"controls_if_if",message0:"%{BKY_CONTROLS_IF_IF_TITLE_IF}",nextStatement:null,enableContextMenu:!1,style:"logic_blocks",tooltip:"%{BKY_CONTROLS_IF_IF_TOOLTIP}"},{type:"controls_if_elseif",message0:"%{BKY_CONTROLS_IF_ELSEIF_TITLE_ELSEIF}",previousStatement:null,nextStatement:null,enableContextMenu:!1,style:"logic_blocks",tooltip:"%{BKY_CONTROLS_IF_ELSEIF_TOOLTIP}"},{type:"controls_if_else",message0:"%{BKY_CONTROLS_IF_ELSE_TITLE_ELSE}",previousStatement:null,enableContextMenu:!1,style:"logic_blocks",tooltip:"%{BKY_CONTROLS_IF_ELSE_TOOLTIP}"}]),t.Constants.Logic.TOOLTIPS_BY_OP={EQ:"%{BKY_LOGIC_COMPARE_TOOLTIP_EQ}",NEQ:"%{BKY_LOGIC_COMPARE_TOOLTIP_NEQ}",LT:"%{BKY_LOGIC_COMPARE_TOOLTIP_LT}",LTE:"%{BKY_LOGIC_COMPARE_TOOLTIP_LTE}",GT:"%{BKY_LOGIC_COMPARE_TOOLTIP_GT}",GTE:"%{BKY_LOGIC_COMPARE_TOOLTIP_GTE}",AND:"%{BKY_LOGIC_OPERATION_TOOLTIP_AND}",OR:"%{BKY_LOGIC_OPERATION_TOOLTIP_OR}"},t.Extensions.register("logic_op_tooltip",t.Extensions.buildTooltipForDropdown("OP",t.Constants.Logic.TOOLTIPS_BY_OP)),t.Constants.Logic.CONTROLS_IF_MUTATOR_MIXIN={elseifCount_:0,elseCount_:0,suppressPrefixSuffix:!0,mutationToDom:function(){if(!this.elseifCount_&&!this.elseCount_)return null;var e=t.utils.xml.createElement("mutation");return this.elseifCount_&&e.setAttribute("elseif",this.elseifCount_),this.elseCount_&&e.setAttribute("else",1),e},domToMutation:function(t){this.elseifCount_=parseInt(t.getAttribute("elseif"),10)||0,this.elseCount_=parseInt(t.getAttribute("else"),10)||0,this.rebuildShape_()},decompose:function(t){var e=t.newBlock("controls_if_if");e.initSvg();for(var o=e.nextConnection,i=1;i<=this.elseifCount_;i++){var n=t.newBlock("controls_if_elseif");n.initSvg(),o.connect(n.previousConnection),o=n.nextConnection}return this.elseCount_&&((t=t.newBlock("controls_if_else")).initSvg(),o.connect(t.previousConnection)),e},compose:function(t){t=t.nextConnection.targetBlock(),this.elseCount_=this.elseifCount_=0;for(var e=[null],o=[null],i=null;t;){switch(t.type){case"controls_if_elseif":this.elseifCount_++,e.push(t.valueConnection_),o.push(t.statementConnection_);break;case"controls_if_else":this.elseCount_++,i=t.statementConnection_;break;default:throw TypeError("Unknown block type: "+t.type)}t=t.nextConnection&&t.nextConnection.targetBlock()}this.updateShape_(),this.reconnectChildBlocks_(e,o,i)},saveConnections:function(t){t=t.nextConnection.targetBlock();for(var e=1;t;){switch(t.type){case"controls_if_elseif":var o=this.getInput("IF"+e),i=this.getInput("DO"+e);t.valueConnection_=o&&o.connection.targetConnection,t.statementConnection_=i&&i.connection.targetConnection,e++;break;case"controls_if_else":i=this.getInput("ELSE"),t.statementConnection_=i&&i.connection.targetConnection;break;default:throw TypeError("Unknown block type: "+t.type)}t=t.nextConnection&&t.nextConnection.targetBlock()}},rebuildShape_:function(){var t=[null],e=[null],o=null;this.getInput("ELSE")&&(o=this.getInput("ELSE").connection.targetConnection);for(var i=1;this.getInput("IF"+i);){var n=this.getInput("IF"+i),s=this.getInput("DO"+i);t.push(n.connection.targetConnection),e.push(s.connection.targetConnection),i++}this.updateShape_(),this.reconnectChildBlocks_(t,e,o)},updateShape_:function(){this.getInput("ELSE")&&this.removeInput("ELSE");for(var e=1;this.getInput("IF"+e);)this.removeInput("IF"+e),this.removeInput("DO"+e),e++;for(e=1;e<=this.elseifCount_;e++)this.appendValueInput("IF"+e).setCheck("Boolean").appendField(t.Msg.CONTROLS_IF_MSG_ELSEIF),this.appendStatementInput("DO"+e).appendField(t.Msg.CONTROLS_IF_MSG_THEN);this.elseCount_&&this.appendStatementInput("ELSE").appendField(t.Msg.CONTROLS_IF_MSG_ELSE)},reconnectChildBlocks_:function(e,o,i){for(var n=1;n<=this.elseifCount_;n++)t.Mutator.reconnect(e[n],this,"IF"+n),t.Mutator.reconnect(o[n],this,"DO"+n);t.Mutator.reconnect(i,this,"ELSE")}},t.Extensions.registerMutator("controls_if_mutator",t.Constants.Logic.CONTROLS_IF_MUTATOR_MIXIN,null,["controls_if_elseif","controls_if_else"]),t.Constants.Logic.CONTROLS_IF_TOOLTIP_EXTENSION=function(){this.setTooltip(function(){return this.elseifCount_||this.elseCount_?!this.elseifCount_&&this.elseCount_?t.Msg.CONTROLS_IF_TOOLTIP_2:this.elseifCount_&&!this.elseCount_?t.Msg.CONTROLS_IF_TOOLTIP_3:this.elseifCount_&&this.elseCount_?t.Msg.CONTROLS_IF_TOOLTIP_4:"":t.Msg.CONTROLS_IF_TOOLTIP_1}.bind(this))},t.Extensions.register("controls_if_tooltip",t.Constants.Logic.CONTROLS_IF_TOOLTIP_EXTENSION),t.Constants.Logic.LOGIC_COMPARE_ONCHANGE_MIXIN={onchange:function(e){this.prevBlocks_||(this.prevBlocks_=[null,null]);var o=this.getInputTargetBlock("A"),i=this.getInputTargetBlock("B");o&&i&&!o.outputConnection.checkType(i.outputConnection)&&(t.Events.setGroup(e.group),(e=this.prevBlocks_[0])!==o&&(o.unplug(),!e||e.isDisposed()||e.isShadow()||this.getInput("A").connection.connect(e.outputConnection)),(o=this.prevBlocks_[1])!==i&&(i.unplug(),!o||o.isDisposed()||o.isShadow()||this.getInput("B").connection.connect(o.outputConnection)),this.bumpNeighbours(),t.Events.setGroup(!1)),this.prevBlocks_[0]=this.getInputTargetBlock("A"),this.prevBlocks_[1]=this.getInputTargetBlock("B")}},t.Constants.Logic.LOGIC_COMPARE_EXTENSION=function(){this.mixin(t.Constants.Logic.LOGIC_COMPARE_ONCHANGE_MIXIN)},t.Extensions.register("logic_compare",t.Constants.Logic.LOGIC_COMPARE_EXTENSION),t.Constants.Logic.LOGIC_TERNARY_ONCHANGE_MIXIN={prevParentConnection_:null,onchange:function(e){var o=this.getInputTargetBlock("THEN"),i=this.getInputTargetBlock("ELSE"),n=this.outputConnection.targetConnection;if((o||i)&&n)for(var s=0;2>s;s++){var r=1==s?o:i;r&&!r.outputConnection.checkType(n)&&(t.Events.setGroup(e.group),n===this.prevParentConnection_?(this.unplug(),n.getSourceBlock().bumpNeighbours()):(r.unplug(),r.bumpNeighbours()),t.Events.setGroup(!1))}this.prevParentConnection_=n}},t.Extensions.registerMixin("logic_ternary",t.Constants.Logic.LOGIC_TERNARY_ONCHANGE_MIXIN),t.Blocks.loops={},t.Constants.Loops={},t.Constants.Loops.HUE=120,t.defineBlocksWithJsonArray([{type:"controls_repeat_ext",message0:"%{BKY_CONTROLS_REPEAT_TITLE}",args0:[{type:"input_value",name:"TIMES",check:"Number"}],message1:"%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",args1:[{type:"input_statement",name:"DO"}],previousStatement:null,nextStatement:null,style:"loop_blocks",tooltip:"%{BKY_CONTROLS_REPEAT_TOOLTIP}",helpUrl:"%{BKY_CONTROLS_REPEAT_HELPURL}"},{type:"controls_repeat",message0:"%{BKY_CONTROLS_REPEAT_TITLE}",args0:[{type:"field_number",name:"TIMES",value:10,min:0,precision:1}],message1:"%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",args1:[{type:"input_statement",name:"DO"}],previousStatement:null,nextStatement:null,style:"loop_blocks",tooltip:"%{BKY_CONTROLS_REPEAT_TOOLTIP}",helpUrl:"%{BKY_CONTROLS_REPEAT_HELPURL}"},{type:"controls_whileUntil",message0:"%1 %2",args0:[{type:"field_dropdown",name:"MODE",options:[["%{BKY_CONTROLS_WHILEUNTIL_OPERATOR_WHILE}","WHILE"],["%{BKY_CONTROLS_WHILEUNTIL_OPERATOR_UNTIL}","UNTIL"]]},{type:"input_value",name:"BOOL",check:"Boolean"}],message1:"%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",args1:[{type:"input_statement",name:"DO"}],previousStatement:null,nextStatement:null,style:"loop_blocks",helpUrl:"%{BKY_CONTROLS_WHILEUNTIL_HELPURL}",extensions:["controls_whileUntil_tooltip"]},{type:"controls_for",message0:"%{BKY_CONTROLS_FOR_TITLE}",args0:[{type:"field_variable",name:"VAR",variable:null},{type:"input_value",name:"FROM",check:"Number",align:"RIGHT"},{type:"input_value",name:"TO",check:"Number",align:"RIGHT"},{type:"input_value",name:"BY",check:"Number",align:"RIGHT"}],message1:"%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",args1:[{type:"input_statement",name:"DO"}],inputsInline:!0,previousStatement:null,nextStatement:null,style:"loop_blocks",helpUrl:"%{BKY_CONTROLS_FOR_HELPURL}",extensions:["contextMenu_newGetVariableBlock","controls_for_tooltip"]},{type:"controls_forEach",message0:"%{BKY_CONTROLS_FOREACH_TITLE}",args0:[{type:"field_variable",name:"VAR",variable:null},{type:"input_value",name:"LIST",check:"Array"}],message1:"%{BKY_CONTROLS_REPEAT_INPUT_DO} %1",args1:[{type:"input_statement",name:"DO"}],previousStatement:null,nextStatement:null,style:"loop_blocks",helpUrl:"%{BKY_CONTROLS_FOREACH_HELPURL}",extensions:["contextMenu_newGetVariableBlock","controls_forEach_tooltip"]},{type:"controls_flow_statements",message0:"%1",args0:[{type:"field_dropdown",name:"FLOW",options:[["%{BKY_CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK}","BREAK"],["%{BKY_CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE}","CONTINUE"]]}],previousStatement:null,style:"loop_blocks",helpUrl:"%{BKY_CONTROLS_FLOW_STATEMENTS_HELPURL}",extensions:["controls_flow_tooltip","controls_flow_in_loop_check"]}]),t.Constants.Loops.WHILE_UNTIL_TOOLTIPS={WHILE:"%{BKY_CONTROLS_WHILEUNTIL_TOOLTIP_WHILE}",UNTIL:"%{BKY_CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL}"},t.Extensions.register("controls_whileUntil_tooltip",t.Extensions.buildTooltipForDropdown("MODE",t.Constants.Loops.WHILE_UNTIL_TOOLTIPS)),t.Constants.Loops.BREAK_CONTINUE_TOOLTIPS={BREAK:"%{BKY_CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK}",CONTINUE:"%{BKY_CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE}"},t.Extensions.register("controls_flow_tooltip",t.Extensions.buildTooltipForDropdown("FLOW",t.Constants.Loops.BREAK_CONTINUE_TOOLTIPS)),t.Constants.Loops.CUSTOM_CONTEXT_MENU_CREATE_VARIABLES_GET_MIXIN={customContextMenu:function(e){if(!this.isInFlyout){var o=this.getField("VAR").getVariable(),i=o.name;if(!this.isCollapsed()&&null!=i){var n={enabled:!0};n.text=t.Msg.VARIABLES_SET_CREATE_GET.replace("%1",i),o=t.Variables.generateVariableFieldDom(o),(i=t.utils.xml.createElement("block")).setAttribute("type","variables_get"),i.appendChild(o),n.callback=t.ContextMenu.callbackFactory(this,i),e.push(n)}}}},t.Extensions.registerMixin("contextMenu_newGetVariableBlock",t.Constants.Loops.CUSTOM_CONTEXT_MENU_CREATE_VARIABLES_GET_MIXIN),t.Extensions.register("controls_for_tooltip",t.Extensions.buildTooltipWithFieldText("%{BKY_CONTROLS_FOR_TOOLTIP}","VAR")),t.Extensions.register("controls_forEach_tooltip",t.Extensions.buildTooltipWithFieldText("%{BKY_CONTROLS_FOREACH_TOOLTIP}","VAR")),t.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN={LOOP_TYPES:["controls_repeat","controls_repeat_ext","controls_forEach","controls_for","controls_whileUntil"],suppressPrefixSuffix:!0,getSurroundLoop:function(e){do{if(-1!=t.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN.LOOP_TYPES.indexOf(e.type))return e;e=e.getSurroundParent()}while(e);return null},onchange:function(e){if(this.workspace.isDragging&&!this.workspace.isDragging()&&e.type==t.Events.BLOCK_MOVE&&e.blockId==this.id){var o=t.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN.getSurroundLoop(this);if(this.setWarningText(o?null:t.Msg.CONTROLS_FLOW_STATEMENTS_WARNING),!this.isInFlyout){var i=t.Events.getGroup();t.Events.setGroup(e.group),this.setEnabled(o),t.Events.setGroup(i)}}}},t.Extensions.registerMixin("controls_flow_in_loop_check",t.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN),t.Blocks.math={},t.Constants.Math={},t.Constants.Math.HUE=230,t.defineBlocksWithJsonArray([{type:"math_number",message0:"%1",args0:[{type:"field_number",name:"NUM",value:0}],output:"Number",helpUrl:"%{BKY_MATH_NUMBER_HELPURL}",style:"math_blocks",tooltip:"%{BKY_MATH_NUMBER_TOOLTIP}",extensions:["parent_tooltip_when_inline"]},{type:"math_arithmetic",message0:"%1 %2 %3",args0:[{type:"input_value",name:"A",check:"Number"},{type:"field_dropdown",name:"OP",options:[["%{BKY_MATH_ADDITION_SYMBOL}","ADD"],["%{BKY_MATH_SUBTRACTION_SYMBOL}","MINUS"],["%{BKY_MATH_MULTIPLICATION_SYMBOL}","MULTIPLY"],["%{BKY_MATH_DIVISION_SYMBOL}","DIVIDE"],["%{BKY_MATH_POWER_SYMBOL}","POWER"]]},{type:"input_value",name:"B",check:"Number"}],inputsInline:!0,output:"Number",style:"math_blocks",helpUrl:"%{BKY_MATH_ARITHMETIC_HELPURL}",extensions:["math_op_tooltip"]},{type:"math_single",message0:"%1 %2",args0:[{type:"field_dropdown",name:"OP",options:[["%{BKY_MATH_SINGLE_OP_ROOT}","ROOT"],["%{BKY_MATH_SINGLE_OP_ABSOLUTE}","ABS"],["-","NEG"],["ln","LN"],["log10","LOG10"],["e^","EXP"],["10^","POW10"]]},{type:"input_value",name:"NUM",check:"Number"}],output:"Number",style:"math_blocks",helpUrl:"%{BKY_MATH_SINGLE_HELPURL}",extensions:["math_op_tooltip"]},{type:"math_trig",message0:"%1 %2",args0:[{type:"field_dropdown",name:"OP",options:[["%{BKY_MATH_TRIG_SIN}","SIN"],["%{BKY_MATH_TRIG_COS}","COS"],["%{BKY_MATH_TRIG_TAN}","TAN"],["%{BKY_MATH_TRIG_ASIN}","ASIN"],["%{BKY_MATH_TRIG_ACOS}","ACOS"],["%{BKY_MATH_TRIG_ATAN}","ATAN"]]},{type:"input_value",name:"NUM",check:"Number"}],output:"Number",style:"math_blocks",helpUrl:"%{BKY_MATH_TRIG_HELPURL}",extensions:["math_op_tooltip"]},{type:"math_constant",message0:"%1",args0:[{type:"field_dropdown",name:"CONSTANT",options:[["π","PI"],["e","E"],["φ","GOLDEN_RATIO"],["sqrt(2)","SQRT2"],["sqrt(½)","SQRT1_2"],["∞","INFINITY"]]}],output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_CONSTANT_TOOLTIP}",helpUrl:"%{BKY_MATH_CONSTANT_HELPURL}"},{type:"math_number_property",message0:"%1 %2",args0:[{type:"input_value",name:"NUMBER_TO_CHECK",check:"Number"},{type:"field_dropdown",name:"PROPERTY",options:[["%{BKY_MATH_IS_EVEN}","EVEN"],["%{BKY_MATH_IS_ODD}","ODD"],["%{BKY_MATH_IS_PRIME}","PRIME"],["%{BKY_MATH_IS_WHOLE}","WHOLE"],["%{BKY_MATH_IS_POSITIVE}","POSITIVE"],["%{BKY_MATH_IS_NEGATIVE}","NEGATIVE"],["%{BKY_MATH_IS_DIVISIBLE_BY}","DIVISIBLE_BY"]]}],inputsInline:!0,output:"Boolean",style:"math_blocks",tooltip:"%{BKY_MATH_IS_TOOLTIP}",mutator:"math_is_divisibleby_mutator"},{type:"math_change",message0:"%{BKY_MATH_CHANGE_TITLE}",args0:[{type:"field_variable",name:"VAR",variable:"%{BKY_MATH_CHANGE_TITLE_ITEM}"},{type:"input_value",name:"DELTA",check:"Number"}],previousStatement:null,nextStatement:null,style:"variable_blocks",helpUrl:"%{BKY_MATH_CHANGE_HELPURL}",extensions:["math_change_tooltip"]},{type:"math_round",message0:"%1 %2",args0:[{type:"field_dropdown",name:"OP",options:[["%{BKY_MATH_ROUND_OPERATOR_ROUND}","ROUND"],["%{BKY_MATH_ROUND_OPERATOR_ROUNDUP}","ROUNDUP"],["%{BKY_MATH_ROUND_OPERATOR_ROUNDDOWN}","ROUNDDOWN"]]},{type:"input_value",name:"NUM",check:"Number"}],output:"Number",style:"math_blocks",helpUrl:"%{BKY_MATH_ROUND_HELPURL}",tooltip:"%{BKY_MATH_ROUND_TOOLTIP}"},{type:"math_on_list",message0:"%1 %2",args0:[{type:"field_dropdown",name:"OP",options:[["%{BKY_MATH_ONLIST_OPERATOR_SUM}","SUM"],["%{BKY_MATH_ONLIST_OPERATOR_MIN}","MIN"],["%{BKY_MATH_ONLIST_OPERATOR_MAX}","MAX"],["%{BKY_MATH_ONLIST_OPERATOR_AVERAGE}","AVERAGE"],["%{BKY_MATH_ONLIST_OPERATOR_MEDIAN}","MEDIAN"],["%{BKY_MATH_ONLIST_OPERATOR_MODE}","MODE"],["%{BKY_MATH_ONLIST_OPERATOR_STD_DEV}","STD_DEV"],["%{BKY_MATH_ONLIST_OPERATOR_RANDOM}","RANDOM"]]},{type:"input_value",name:"LIST",check:"Array"}],output:"Number",style:"math_blocks",helpUrl:"%{BKY_MATH_ONLIST_HELPURL}",mutator:"math_modes_of_list_mutator",extensions:["math_op_tooltip"]},{type:"math_modulo",message0:"%{BKY_MATH_MODULO_TITLE}",args0:[{type:"input_value",name:"DIVIDEND",check:"Number"},{type:"input_value",name:"DIVISOR",check:"Number"}],inputsInline:!0,output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_MODULO_TOOLTIP}",helpUrl:"%{BKY_MATH_MODULO_HELPURL}"},{type:"math_constrain",message0:"%{BKY_MATH_CONSTRAIN_TITLE}",args0:[{type:"input_value",name:"VALUE",check:"Number"},{type:"input_value",name:"LOW",check:"Number"},{type:"input_value",name:"HIGH",check:"Number"}],inputsInline:!0,output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_CONSTRAIN_TOOLTIP}",helpUrl:"%{BKY_MATH_CONSTRAIN_HELPURL}"},{type:"math_random_int",message0:"%{BKY_MATH_RANDOM_INT_TITLE}",args0:[{type:"input_value",name:"FROM",check:"Number"},{type:"input_value",name:"TO",check:"Number"}],inputsInline:!0,output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_RANDOM_INT_TOOLTIP}",helpUrl:"%{BKY_MATH_RANDOM_INT_HELPURL}"},{type:"math_random_float",message0:"%{BKY_MATH_RANDOM_FLOAT_TITLE_RANDOM}",output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_RANDOM_FLOAT_TOOLTIP}",helpUrl:"%{BKY_MATH_RANDOM_FLOAT_HELPURL}"},{type:"math_atan2",message0:"%{BKY_MATH_ATAN2_TITLE}",args0:[{type:"input_value",name:"X",check:"Number"},{type:"input_value",name:"Y",check:"Number"}],inputsInline:!0,output:"Number",style:"math_blocks",tooltip:"%{BKY_MATH_ATAN2_TOOLTIP}",helpUrl:"%{BKY_MATH_ATAN2_HELPURL}"}]),t.Constants.Math.TOOLTIPS_BY_OP={ADD:"%{BKY_MATH_ARITHMETIC_TOOLTIP_ADD}",MINUS:"%{BKY_MATH_ARITHMETIC_TOOLTIP_MINUS}",MULTIPLY:"%{BKY_MATH_ARITHMETIC_TOOLTIP_MULTIPLY}",DIVIDE:"%{BKY_MATH_ARITHMETIC_TOOLTIP_DIVIDE}",POWER:"%{BKY_MATH_ARITHMETIC_TOOLTIP_POWER}",ROOT:"%{BKY_MATH_SINGLE_TOOLTIP_ROOT}",ABS:"%{BKY_MATH_SINGLE_TOOLTIP_ABS}",NEG:"%{BKY_MATH_SINGLE_TOOLTIP_NEG}",LN:"%{BKY_MATH_SINGLE_TOOLTIP_LN}",LOG10:"%{BKY_MATH_SINGLE_TOOLTIP_LOG10}",EXP:"%{BKY_MATH_SINGLE_TOOLTIP_EXP}",POW10:"%{BKY_MATH_SINGLE_TOOLTIP_POW10}",SIN:"%{BKY_MATH_TRIG_TOOLTIP_SIN}",COS:"%{BKY_MATH_TRIG_TOOLTIP_COS}",TAN:"%{BKY_MATH_TRIG_TOOLTIP_TAN}",ASIN:"%{BKY_MATH_TRIG_TOOLTIP_ASIN}",ACOS:"%{BKY_MATH_TRIG_TOOLTIP_ACOS}",ATAN:"%{BKY_MATH_TRIG_TOOLTIP_ATAN}",SUM:"%{BKY_MATH_ONLIST_TOOLTIP_SUM}",MIN:"%{BKY_MATH_ONLIST_TOOLTIP_MIN}",MAX:"%{BKY_MATH_ONLIST_TOOLTIP_MAX}",AVERAGE:"%{BKY_MATH_ONLIST_TOOLTIP_AVERAGE}",MEDIAN:"%{BKY_MATH_ONLIST_TOOLTIP_MEDIAN}",MODE:"%{BKY_MATH_ONLIST_TOOLTIP_MODE}",STD_DEV:"%{BKY_MATH_ONLIST_TOOLTIP_STD_DEV}",RANDOM:"%{BKY_MATH_ONLIST_TOOLTIP_RANDOM}"},t.Extensions.register("math_op_tooltip",t.Extensions.buildTooltipForDropdown("OP",t.Constants.Math.TOOLTIPS_BY_OP)),t.Constants.Math.IS_DIVISIBLEBY_MUTATOR_MIXIN={mutationToDom:function(){var e=t.utils.xml.createElement("mutation"),o="DIVISIBLE_BY"==this.getFieldValue("PROPERTY");return e.setAttribute("divisor_input",o),e},domToMutation:function(t){t="true"==t.getAttribute("divisor_input"),this.updateShape_(t)},updateShape_:function(t){var e=this.getInput("DIVISOR");t?e||this.appendValueInput("DIVISOR").setCheck("Number"):e&&this.removeInput("DIVISOR")}},t.Constants.Math.IS_DIVISIBLE_MUTATOR_EXTENSION=function(){this.getField("PROPERTY").setValidator((function(t){t="DIVISIBLE_BY"==t,this.getSourceBlock().updateShape_(t)}))},t.Extensions.registerMutator("math_is_divisibleby_mutator",t.Constants.Math.IS_DIVISIBLEBY_MUTATOR_MIXIN,t.Constants.Math.IS_DIVISIBLE_MUTATOR_EXTENSION),t.Extensions.register("math_change_tooltip",t.Extensions.buildTooltipWithFieldText("%{BKY_MATH_CHANGE_TOOLTIP}","VAR")),t.Constants.Math.LIST_MODES_MUTATOR_MIXIN={updateType_:function(t){"MODE"==t?this.outputConnection.setCheck("Array"):this.outputConnection.setCheck("Number")},mutationToDom:function(){var e=t.utils.xml.createElement("mutation");return e.setAttribute("op",this.getFieldValue("OP")),e},domToMutation:function(t){this.updateType_(t.getAttribute("op"))}},t.Constants.Math.LIST_MODES_MUTATOR_EXTENSION=function(){this.getField("OP").setValidator(function(t){this.updateType_(t)}.bind(this))},t.Extensions.registerMutator("math_modes_of_list_mutator",t.Constants.Math.LIST_MODES_MUTATOR_MIXIN,t.Constants.Math.LIST_MODES_MUTATOR_EXTENSION),t.Blocks.procedures={},t.Blocks.procedures_defnoreturn={init:function(){var e=new t.FieldTextInput("",t.Procedures.rename);e.setSpellcheck(!1),this.appendDummyInput().appendField(t.Msg.PROCEDURES_DEFNORETURN_TITLE).appendField(e,"NAME").appendField("","PARAMS"),this.setMutator(new t.Mutator(["procedures_mutatorarg"])),(this.workspace.options.comments||this.workspace.options.parentWorkspace&&this.workspace.options.parentWorkspace.options.comments)&&t.Msg.PROCEDURES_DEFNORETURN_COMMENT&&this.setCommentText(t.Msg.PROCEDURES_DEFNORETURN_COMMENT),this.setStyle("procedure_blocks"),this.setTooltip(t.Msg.PROCEDURES_DEFNORETURN_TOOLTIP),this.setHelpUrl(t.Msg.PROCEDURES_DEFNORETURN_HELPURL),this.arguments_=[],this.argumentVarModels_=[],this.setStatements_(!0),this.statementConnection_=null},setStatements_:function(e){this.hasStatements_!==e&&(e?(this.appendStatementInput("STACK").appendField(t.Msg.PROCEDURES_DEFNORETURN_DO),this.getInput("RETURN")&&this.moveInputBefore("STACK","RETURN")):this.removeInput("STACK",!0),this.hasStatements_=e)},updateParams_:function(){var e="";this.arguments_.length&&(e=t.Msg.PROCEDURES_BEFORE_PARAMS+" "+this.arguments_.join(", ")),t.Events.disable();try{this.setFieldValue(e,"PARAMS")}finally{t.Events.enable()}},mutationToDom:function(e){var o=t.utils.xml.createElement("mutation");e&&o.setAttribute("name",this.getFieldValue("NAME"));for(var i=0;ii?t.JavaScript.valueToCode(e,o,t.JavaScript.ORDER_SUBTRACTION)||r:n?t.JavaScript.valueToCode(e,o,t.JavaScript.ORDER_UNARY_NEGATION)||r:t.JavaScript.valueToCode(e,o,s)||r,t.isNumber(e))e=Number(e)+i,n&&(e=-e);else{if(0i&&(e=e+" - "+-i,a=t.JavaScript.ORDER_SUBTRACTION);n&&(e=i?"-("+e+")":"-"+e,a=t.JavaScript.ORDER_UNARY_NEGATION),a=Math.floor(a),s=Math.floor(s),a&&s>=a&&(e="("+e+")")}return e},t.JavaScript.colour={},t.JavaScript.colour_picker=function(e){return[t.JavaScript.quote_(e.getFieldValue("COLOUR")),t.JavaScript.ORDER_ATOMIC]},t.JavaScript.colour_random=function(e){return[t.JavaScript.provideFunction_("colourRandom",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"() {"," var num = Math.floor(Math.random() * Math.pow(2, 24));"," return '#' + ('00000' + num.toString(16)).substr(-6);","}"])+"()",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.colour_rgb=function(e){var o=t.JavaScript.valueToCode(e,"RED",t.JavaScript.ORDER_COMMA)||0,i=t.JavaScript.valueToCode(e,"GREEN",t.JavaScript.ORDER_COMMA)||0;return e=t.JavaScript.valueToCode(e,"BLUE",t.JavaScript.ORDER_COMMA)||0,[t.JavaScript.provideFunction_("colourRgb",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(r, g, b) {"," r = Math.max(Math.min(Number(r), 100), 0) * 2.55;"," g = Math.max(Math.min(Number(g), 100), 0) * 2.55;"," b = Math.max(Math.min(Number(b), 100), 0) * 2.55;"," r = ('0' + (Math.round(r) || 0).toString(16)).slice(-2);"," g = ('0' + (Math.round(g) || 0).toString(16)).slice(-2);"," b = ('0' + (Math.round(b) || 0).toString(16)).slice(-2);"," return '#' + r + g + b;","}"])+"("+o+", "+i+", "+e+")",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.colour_blend=function(e){var o=t.JavaScript.valueToCode(e,"COLOUR1",t.JavaScript.ORDER_COMMA)||"'#000000'",i=t.JavaScript.valueToCode(e,"COLOUR2",t.JavaScript.ORDER_COMMA)||"'#000000'";return e=t.JavaScript.valueToCode(e,"RATIO",t.JavaScript.ORDER_COMMA)||.5,[t.JavaScript.provideFunction_("colourBlend",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(c1, c2, ratio) {"," ratio = Math.max(Math.min(Number(ratio), 1), 0);"," var r1 = parseInt(c1.substring(1, 3), 16);"," var g1 = parseInt(c1.substring(3, 5), 16);"," var b1 = parseInt(c1.substring(5, 7), 16);"," var r2 = parseInt(c2.substring(1, 3), 16);"," var g2 = parseInt(c2.substring(3, 5), 16);"," var b2 = parseInt(c2.substring(5, 7), 16);"," var r = Math.round(r1 * (1 - ratio) + r2 * ratio);"," var g = Math.round(g1 * (1 - ratio) + g2 * ratio);"," var b = Math.round(b1 * (1 - ratio) + b2 * ratio);"," r = ('0' + (r || 0).toString(16)).slice(-2);"," g = ('0' + (g || 0).toString(16)).slice(-2);"," b = ('0' + (b || 0).toString(16)).slice(-2);"," return '#' + r + g + b;","}"])+"("+o+", "+i+", "+e+")",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.lists={},t.JavaScript.lists_create_empty=function(e){return["[]",t.JavaScript.ORDER_ATOMIC]},t.JavaScript.lists_create_with=function(e){for(var o=Array(e.itemCount_),i=0;i b.toString() ? 1 : -1; },",' "IGNORE_CASE": function(a, b) {'," return a.toString().toLowerCase() > b.toString().toLowerCase() ? 1 : -1; },"," };"," var compare = compareFuncs[type];"," return function(a, b) { return compare(a, b) * direction; }","}"])+'("'+e+'", '+i+"))",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.lists_split=function(e){var o=t.JavaScript.valueToCode(e,"INPUT",t.JavaScript.ORDER_MEMBER),i=t.JavaScript.valueToCode(e,"DELIM",t.JavaScript.ORDER_NONE)||"''";if("SPLIT"==(e=e.getFieldValue("MODE")))o||(o="''"),e="split";else{if("JOIN"!=e)throw Error("Unknown mode: "+e);o||(o="[]"),e="join"}return[o+"."+e+"("+i+")",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.lists_reverse=function(e){return[(t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_FUNCTION_CALL)||"[]")+".slice().reverse()",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.logic={},t.JavaScript.controls_if=function(e){var o=0,i="";t.JavaScript.STATEMENT_PREFIX&&(i+=t.JavaScript.injectId(t.JavaScript.STATEMENT_PREFIX,e));do{var n=t.JavaScript.valueToCode(e,"IF"+o,t.JavaScript.ORDER_NONE)||"false",s=t.JavaScript.statementToCode(e,"DO"+o);t.JavaScript.STATEMENT_SUFFIX&&(s=t.JavaScript.prefixLines(t.JavaScript.injectId(t.JavaScript.STATEMENT_SUFFIX,e),t.JavaScript.INDENT)+s),i+=(0",GTE:">="}[e.getFieldValue("OP")],i="=="==o||"!="==o?t.JavaScript.ORDER_EQUALITY:t.JavaScript.ORDER_RELATIONAL;return[(t.JavaScript.valueToCode(e,"A",i)||"0")+" "+o+" "+(e=t.JavaScript.valueToCode(e,"B",i)||"0"),i]},t.JavaScript.logic_operation=function(e){var o="AND"==e.getFieldValue("OP")?"&&":"||",i="&&"==o?t.JavaScript.ORDER_LOGICAL_AND:t.JavaScript.ORDER_LOGICAL_OR,n=t.JavaScript.valueToCode(e,"A",i);if(e=t.JavaScript.valueToCode(e,"B",i),n||e){var s="&&"==o?"true":"false";n||(n=s),e||(e=s)}else e=n="false";return[n+" "+o+" "+e,i]},t.JavaScript.logic_negate=function(e){var o=t.JavaScript.ORDER_LOGICAL_NOT;return["!"+(t.JavaScript.valueToCode(e,"BOOL",o)||"true"),o]},t.JavaScript.logic_boolean=function(e){return["TRUE"==e.getFieldValue("BOOL")?"true":"false",t.JavaScript.ORDER_ATOMIC]},t.JavaScript.logic_null=function(e){return["null",t.JavaScript.ORDER_ATOMIC]},t.JavaScript.logic_ternary=function(e){return[(t.JavaScript.valueToCode(e,"IF",t.JavaScript.ORDER_CONDITIONAL)||"false")+" ? "+(t.JavaScript.valueToCode(e,"THEN",t.JavaScript.ORDER_CONDITIONAL)||"null")+" : "+(e=t.JavaScript.valueToCode(e,"ELSE",t.JavaScript.ORDER_CONDITIONAL)||"null"),t.JavaScript.ORDER_CONDITIONAL]},t.JavaScript.loops={},t.JavaScript.controls_repeat_ext=function(e){var o=e.getField("TIMES")?String(Number(e.getFieldValue("TIMES"))):t.JavaScript.valueToCode(e,"TIMES",t.JavaScript.ORDER_ASSIGNMENT)||"0",i=t.JavaScript.statementToCode(e,"DO");i=t.JavaScript.addLoopTrap(i,e),e="";var n=t.JavaScript.variableDB_.getDistinctName("count",t.VARIABLE_CATEGORY_NAME),s=o;return o.match(/^\w+$/)||t.isNumber(o)||(e+="var "+(s=t.JavaScript.variableDB_.getDistinctName("repeat_end",t.VARIABLE_CATEGORY_NAME))+" = "+o+";\n"),e+"for (var "+n+" = 0; "+n+" < "+s+"; "+n+"++) {\n"+i+"}\n"},t.JavaScript.controls_repeat=t.JavaScript.controls_repeat_ext,t.JavaScript.controls_whileUntil=function(e){var o="UNTIL"==e.getFieldValue("MODE"),i=t.JavaScript.valueToCode(e,"BOOL",o?t.JavaScript.ORDER_LOGICAL_NOT:t.JavaScript.ORDER_NONE)||"false",n=t.JavaScript.statementToCode(e,"DO");return o&&(i="!"+i),"while ("+i+") {\n"+(n=t.JavaScript.addLoopTrap(n,e))+"}\n"},t.JavaScript.controls_for=function(e){var o=t.JavaScript.variableDB_.getName(e.getFieldValue("VAR"),t.VARIABLE_CATEGORY_NAME),i=t.JavaScript.valueToCode(e,"FROM",t.JavaScript.ORDER_ASSIGNMENT)||"0",n=t.JavaScript.valueToCode(e,"TO",t.JavaScript.ORDER_ASSIGNMENT)||"0",s=t.JavaScript.valueToCode(e,"BY",t.JavaScript.ORDER_ASSIGNMENT)||"1",r=t.JavaScript.statementToCode(e,"DO");if(r=t.JavaScript.addLoopTrap(r,e),t.isNumber(i)&&t.isNumber(n)&&t.isNumber(s)){var a=Number(i)<=Number(n);e="for ("+o+" = "+i+"; "+o+(a?" <= ":" >= ")+n+"; "+o,e=(1==(o=Math.abs(Number(s)))?e+(a?"++":"--"):e+(a?" += ":" -= ")+o)+") {\n"+r+"}\n"}else e="",a=i,i.match(/^\w+$/)||t.isNumber(i)||(e+="var "+(a=t.JavaScript.variableDB_.getDistinctName(o+"_start",t.VARIABLE_CATEGORY_NAME))+" = "+i+";\n"),i=n,n.match(/^\w+$/)||t.isNumber(n)||(e+="var "+(i=t.JavaScript.variableDB_.getDistinctName(o+"_end",t.VARIABLE_CATEGORY_NAME))+" = "+n+";\n"),e+="var "+(n=t.JavaScript.variableDB_.getDistinctName(o+"_inc",t.VARIABLE_CATEGORY_NAME))+" = ",e=(e=t.isNumber(s)?e+(Math.abs(s)+";\n"):e+"Math.abs("+s+");\n")+"if ("+a+" > "+i+") {\n"+(t.JavaScript.INDENT+n)+" = -"+n+";\n",e+="}\n",e+="for ("+o+" = "+a+"; "+n+" >= 0 ? "+o+" <= "+i+" : "+o+" >= "+i+"; "+o+" += "+n+") {\n"+r+"}\n";return e},t.JavaScript.controls_forEach=function(e){var o=t.JavaScript.variableDB_.getName(e.getFieldValue("VAR"),t.VARIABLE_CATEGORY_NAME),i=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_ASSIGNMENT)||"[]",n=t.JavaScript.statementToCode(e,"DO");n=t.JavaScript.addLoopTrap(n,e),e="";var s=i;return i.match(/^\w+$/)||(e+="var "+(s=t.JavaScript.variableDB_.getDistinctName(o+"_list",t.VARIABLE_CATEGORY_NAME))+" = "+i+";\n"),e+"for (var "+(i=t.JavaScript.variableDB_.getDistinctName(o+"_index",t.VARIABLE_CATEGORY_NAME))+" in "+s+") {\n"+(n=t.JavaScript.INDENT+o+" = "+s+"["+i+"];\n"+n)+"}\n"},t.JavaScript.controls_flow_statements=function(e){var o="";if(t.JavaScript.STATEMENT_PREFIX&&(o+=t.JavaScript.injectId(t.JavaScript.STATEMENT_PREFIX,e)),t.JavaScript.STATEMENT_SUFFIX&&(o+=t.JavaScript.injectId(t.JavaScript.STATEMENT_SUFFIX,e)),t.JavaScript.STATEMENT_PREFIX){var i=t.Constants.Loops.CONTROL_FLOW_IN_LOOP_CHECK_MIXIN.getSurroundLoop(e);i&&!i.suppressPrefixSuffix&&(o+=t.JavaScript.injectId(t.JavaScript.STATEMENT_PREFIX,i))}switch(e.getFieldValue("FLOW")){case"BREAK":return o+"break;\n";case"CONTINUE":return o+"continue;\n"}throw Error("Unknown flow statement.")},t.JavaScript.math={},t.JavaScript.math_number=function(e){return[e=Number(e.getFieldValue("NUM")),0<=e?t.JavaScript.ORDER_ATOMIC:t.JavaScript.ORDER_UNARY_NEGATION]},t.JavaScript.math_arithmetic=function(e){var o={ADD:[" + ",t.JavaScript.ORDER_ADDITION],MINUS:[" - ",t.JavaScript.ORDER_SUBTRACTION],MULTIPLY:[" * ",t.JavaScript.ORDER_MULTIPLICATION],DIVIDE:[" / ",t.JavaScript.ORDER_DIVISION],POWER:[null,t.JavaScript.ORDER_COMMA]}[e.getFieldValue("OP")],i=o[0];o=o[1];var n=t.JavaScript.valueToCode(e,"A",o)||"0";return e=t.JavaScript.valueToCode(e,"B",o)||"0",i?[n+i+e,o]:["Math.pow("+n+", "+e+")",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.math_single=function(e){var o=e.getFieldValue("OP");if("NEG"==o)return"-"==(e=t.JavaScript.valueToCode(e,"NUM",t.JavaScript.ORDER_UNARY_NEGATION)||"0")[0]&&(e=" "+e),["-"+e,t.JavaScript.ORDER_UNARY_NEGATION];switch(e="SIN"==o||"COS"==o||"TAN"==o?t.JavaScript.valueToCode(e,"NUM",t.JavaScript.ORDER_DIVISION)||"0":t.JavaScript.valueToCode(e,"NUM",t.JavaScript.ORDER_NONE)||"0",o){case"ABS":var i="Math.abs("+e+")";break;case"ROOT":i="Math.sqrt("+e+")";break;case"LN":i="Math.log("+e+")";break;case"EXP":i="Math.exp("+e+")";break;case"POW10":i="Math.pow(10,"+e+")";break;case"ROUND":i="Math.round("+e+")";break;case"ROUNDUP":i="Math.ceil("+e+")";break;case"ROUNDDOWN":i="Math.floor("+e+")";break;case"SIN":i="Math.sin("+e+" / 180 * Math.PI)";break;case"COS":i="Math.cos("+e+" / 180 * Math.PI)";break;case"TAN":i="Math.tan("+e+" / 180 * Math.PI)"}if(i)return[i,t.JavaScript.ORDER_FUNCTION_CALL];switch(o){case"LOG10":i="Math.log("+e+") / Math.log(10)";break;case"ASIN":i="Math.asin("+e+") / Math.PI * 180";break;case"ACOS":i="Math.acos("+e+") / Math.PI * 180";break;case"ATAN":i="Math.atan("+e+") / Math.PI * 180";break;default:throw Error("Unknown math operator: "+o)}return[i,t.JavaScript.ORDER_DIVISION]},t.JavaScript.math_constant=function(e){return{PI:["Math.PI",t.JavaScript.ORDER_MEMBER],E:["Math.E",t.JavaScript.ORDER_MEMBER],GOLDEN_RATIO:["(1 + Math.sqrt(5)) / 2",t.JavaScript.ORDER_DIVISION],SQRT2:["Math.SQRT2",t.JavaScript.ORDER_MEMBER],SQRT1_2:["Math.SQRT1_2",t.JavaScript.ORDER_MEMBER],INFINITY:["Infinity",t.JavaScript.ORDER_ATOMIC]}[e.getFieldValue("CONSTANT")]},t.JavaScript.math_number_property=function(e){var o=t.JavaScript.valueToCode(e,"NUMBER_TO_CHECK",t.JavaScript.ORDER_MODULUS)||"0",i=e.getFieldValue("PROPERTY");if("PRIME"==i)return[t.JavaScript.provideFunction_("mathIsPrime",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(n) {"," // https://en.wikipedia.org/wiki/Primality_test#Naive_methods"," if (n == 2 || n == 3) {"," return true;"," }"," // False if n is NaN, negative, is 1, or not whole."," // And false if n is divisible by 2 or 3."," if (isNaN(n) || n <= 1 || n % 1 != 0 || n % 2 == 0 || n % 3 == 0) {"," return false;"," }"," // Check all the numbers of form 6k +/- 1, up to sqrt(n)."," for (var x = 6; x <= Math.sqrt(n) + 1; x += 6) {"," if (n % (x - 1) == 0 || n % (x + 1) == 0) {"," return false;"," }"," }"," return true;","}"])+"("+o+")",t.JavaScript.ORDER_FUNCTION_CALL];switch(i){case"EVEN":var n=o+" % 2 == 0";break;case"ODD":n=o+" % 2 == 1";break;case"WHOLE":n=o+" % 1 == 0";break;case"POSITIVE":n=o+" > 0";break;case"NEGATIVE":n=o+" < 0";break;case"DIVISIBLE_BY":n=o+" % "+(e=t.JavaScript.valueToCode(e,"DIVISOR",t.JavaScript.ORDER_MODULUS)||"0")+" == 0"}return[n,t.JavaScript.ORDER_EQUALITY]},t.JavaScript.math_change=function(e){var o=t.JavaScript.valueToCode(e,"DELTA",t.JavaScript.ORDER_ADDITION)||"0";return(e=t.JavaScript.variableDB_.getName(e.getFieldValue("VAR"),t.VARIABLE_CATEGORY_NAME))+" = (typeof "+e+" == 'number' ? "+e+" : 0) + "+o+";\n"},t.JavaScript.math_round=t.JavaScript.math_single,t.JavaScript.math_trig=t.JavaScript.math_single,t.JavaScript.math_on_list=function(e){var o=e.getFieldValue("OP");switch(o){case"SUM":e=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_MEMBER)||"[]",e+=".reduce(function(x, y) {return x + y;})";break;case"MIN":e="Math.min.apply(null, "+(e=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_COMMA)||"[]")+")";break;case"MAX":e="Math.max.apply(null, "+(e=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_COMMA)||"[]")+")";break;case"AVERAGE":e=(o=t.JavaScript.provideFunction_("mathMean",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(myList) {"," return myList.reduce(function(x, y) {return x + y;}) / myList.length;","}"]))+"("+(e=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_NONE)||"[]")+")";break;case"MEDIAN":e=(o=t.JavaScript.provideFunction_("mathMedian",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(myList) {"," var localList = myList.filter(function (x) {return typeof x == 'number';});"," if (!localList.length) return null;"," localList.sort(function(a, b) {return b - a;});"," if (localList.length % 2 == 0) {"," return (localList[localList.length / 2 - 1] + localList[localList.length / 2]) / 2;"," } else {"," return localList[(localList.length - 1) / 2];"," }","}"]))+"("+(e=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_NONE)||"[]")+")";break;case"MODE":e=(o=t.JavaScript.provideFunction_("mathModes",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(values) {"," var modes = [];"," var counts = [];"," var maxCount = 0;"," for (var i = 0; i < values.length; i++) {"," var value = values[i];"," var found = false;"," var thisCount;"," for (var j = 0; j < counts.length; j++) {"," if (counts[j][0] === value) {"," thisCount = ++counts[j][1];"," found = true;"," break;"," }"," }"," if (!found) {"," counts.push([value, 1]);"," thisCount = 1;"," }"," maxCount = Math.max(thisCount, maxCount);"," }"," for (var j = 0; j < counts.length; j++) {"," if (counts[j][1] == maxCount) {"," modes.push(counts[j][0]);"," }"," }"," return modes;","}"]))+"("+(e=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_NONE)||"[]")+")";break;case"STD_DEV":e=(o=t.JavaScript.provideFunction_("mathStandardDeviation",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(numbers) {"," var n = numbers.length;"," if (!n) return null;"," var mean = numbers.reduce(function(x, y) {return x + y;}) / n;"," var variance = 0;"," for (var j = 0; j < n; j++) {"," variance += Math.pow(numbers[j] - mean, 2);"," }"," variance = variance / n;"," return Math.sqrt(variance);","}"]))+"("+(e=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_NONE)||"[]")+")";break;case"RANDOM":e=(o=t.JavaScript.provideFunction_("mathRandomList",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(list) {"," var x = Math.floor(Math.random() * list.length);"," return list[x];","}"]))+"("+(e=t.JavaScript.valueToCode(e,"LIST",t.JavaScript.ORDER_NONE)||"[]")+")";break;default:throw Error("Unknown operator: "+o)}return[e,t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.math_modulo=function(e){return[(t.JavaScript.valueToCode(e,"DIVIDEND",t.JavaScript.ORDER_MODULUS)||"0")+" % "+(e=t.JavaScript.valueToCode(e,"DIVISOR",t.JavaScript.ORDER_MODULUS)||"0"),t.JavaScript.ORDER_MODULUS]},t.JavaScript.math_constrain=function(e){return["Math.min(Math.max("+(t.JavaScript.valueToCode(e,"VALUE",t.JavaScript.ORDER_COMMA)||"0")+", "+(t.JavaScript.valueToCode(e,"LOW",t.JavaScript.ORDER_COMMA)||"0")+"), "+(e=t.JavaScript.valueToCode(e,"HIGH",t.JavaScript.ORDER_COMMA)||"Infinity")+")",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.math_random_int=function(e){var o=t.JavaScript.valueToCode(e,"FROM",t.JavaScript.ORDER_COMMA)||"0";return e=t.JavaScript.valueToCode(e,"TO",t.JavaScript.ORDER_COMMA)||"0",[t.JavaScript.provideFunction_("mathRandomInt",["function "+t.JavaScript.FUNCTION_NAME_PLACEHOLDER_+"(a, b) {"," if (a > b) {"," // Swap a and b to ensure a is smaller."," var c = a;"," a = b;"," b = c;"," }"," return Math.floor(Math.random() * (b - a + 1) + a);","}"])+"("+o+", "+e+")",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.math_random_float=function(e){return["Math.random()",t.JavaScript.ORDER_FUNCTION_CALL]},t.JavaScript.math_atan2=function(e){var o=t.JavaScript.valueToCode(e,"X",t.JavaScript.ORDER_COMMA)||"0";return["Math.atan2("+(t.JavaScript.valueToCode(e,"Y",t.JavaScript.ORDER_COMMA)||"0")+", "+o+") / Math.PI * 180",t.JavaScript.ORDER_DIVISION]},t.JavaScript.procedures={},t.JavaScript.procedures_defreturn=function(e){var o=t.JavaScript.variableDB_.getName(e.getFieldValue("NAME"),t.PROCEDURE_CATEGORY_NAME),i="";t.JavaScript.STATEMENT_PREFIX&&(i+=t.JavaScript.injectId(t.JavaScript.STATEMENT_PREFIX,e)),t.JavaScript.STATEMENT_SUFFIX&&(i+=t.JavaScript.injectId(t.JavaScript.STATEMENT_SUFFIX,e)),i&&(i=t.JavaScript.prefixLines(i,t.JavaScript.INDENT));var n="";t.JavaScript.INFINITE_LOOP_TRAP&&(n=t.JavaScript.prefixLines(t.JavaScript.injectId(t.JavaScript.INFINITE_LOOP_TRAP,e),t.JavaScript.INDENT));var s=t.JavaScript.statementToCode(e,"STACK"),r=t.JavaScript.valueToCode(e,"RETURN",t.JavaScript.ORDER_NONE)||"",a="";s&&r&&(a=i),r&&(r=t.JavaScript.INDENT+"return "+r+";\n");for(var l=[],c=0;c\n \n \n \n 1\n 1\n \n \n 1\n \n \n 1\n \n \n \n \n 1\n \n \n Alias\n name\n \n \n Existing Key\n tpub, WIF, hex...\n \n \n \n \n \n \n Alias\n Alice\n \n \n \n \n 1\n 1\n \n \n \n \n Alias\n Alice\n \n \n \n \n \n \n \n \n Alias\n Bob\n \n \n \n \n \n \n 99\n 1\n \n \n \n \n Alias\n KeyLikely\n \n \n \n \n \n \n \n \n Alias\n Likely\n \n \n \n \n \n \n \n \n \n \n Alias\n User\n \n \n \n \n \n \n 99\n 1\n \n \n \n \n Alias\n Service\n \n \n \n \n \n \n 12960\n \n \n \n \n \n \n 3\n \n \n \n \n \n \n Alias\n Alice\n \n \n \n \n \n \n \n \n \n \n Alias\n Bob\n \n \n \n \n \n \n \n \n \n \n Alias\n Carol\n \n \n \n \n \n \n \n \n 12960\n \n \n \n \n \n \n \n \n \n \n \n \n',collapse:!0,comments:!0,disable:!0,maxBlocks:1/0,trashcan:!0,horizontalLayout:!0,toolboxPosition:"start",css:!0,media:"https://blockly-demo.appspot.com/static/media/",rtl:!1,scrollbars:!0,sounds:!0,oneBasedIndex:!0,grid:{spacing:20,length:1,colour:"#888",snap:!0}};i.a.Blocks.pk={init:function(){this.appendValueInput("pk").setCheck("key").appendField("Key"),this.setPreviousStatement(!0,"policy"),this.setColour(260),this.setTooltip("Requires a signature with a given public key"),this.setHelpUrl("")}},i.a.Blocks.begin={init:function(){this.appendDummyInput().appendField("Begin"),this.setNextStatement(!0,"policy"),this.setColour(160),this.setTooltip("Sets the beginning of the policy"),this.setHelpUrl("")}},i.a.Blocks.existing_key={init:function(){this.appendDummyInput().appendField(new i.a.FieldLabelSerializable("Existing Key"),"NAME").appendField(new i.a.FieldTextInput("tpub, WIF, hex..."),"key"),this.setOutput(!0,"key"),this.setColour(120),this.setTooltip("Sets the value of a key to an existing WIF key, xpub or hex public key"),this.setHelpUrl("")}},i.a.Blocks.alias_key={init:function(){this.appendDummyInput().appendField(new i.a.FieldLabelSerializable("Alias"),"label").appendField(new i.a.FieldTextInput("name"),"name"),this.setOutput(!0,"key"),this.setColour(120),this.setTooltip("Sets the value of a key to an alias"),this.setHelpUrl("")}},i.a.Blocks.thresh={init:function(){this.appendDummyInput().appendField("Threshold").appendField(new i.a.FieldNumber(1,1,1/0,1),"Threshold"),this.appendStatementInput("A").setCheck("thresh").appendField("Policies"),this.setPreviousStatement(!0,"policy"),this.setColour(230),this.setTooltip("Creates a threshold element (m-of-n), where the 'm' field is manually set and 'n' is implied by the number of sub-policies added. Requies all of its children to be wrapped in the 'Entry' block"),this.setHelpUrl("")}},i.a.Blocks.older={init:function(){this.appendDummyInput().appendField("Older").appendField(new i.a.FieldNumber(1,1,1/0,1),"NAME"),this.setPreviousStatement(!0,"policy"),this.setColour(20),this.setTooltip("Requires waiting a number of blocks from the confirmation height of a UTXO before it becomes spendable"),this.setHelpUrl("")}},i.a.Blocks.after={init:function(){this.appendDummyInput().appendField("After").appendField(new i.a.FieldNumber(1,1,1/0,1),"NAME"),this.setPreviousStatement(!0,"policy"),this.setColour(20),this.setTooltip("Requires the blockchain to reach a specific block height before the UTXO becomes spendable"),this.setHelpUrl("")}},i.a.Blocks.adapter={init:function(){this.appendStatementInput("NAME").setCheck("policy").appendField("Entry"),this.setPreviousStatement(!0,"thresh"),this.setNextStatement(!0,"thresh"),this.setColour(290),this.setTooltip("Adapter used to stack policies into 'Threshold' blocks"),this.setHelpUrl("")}},i.a.Blocks.and={init:function(){this.appendStatementInput("A").setCheck("policy"),this.appendDummyInput().appendField("AND"),this.appendStatementInput("B").setCheck("policy"),this.setPreviousStatement(!0,"policy"),this.setColour(230),this.setTooltip("Requires both sub-policies to be satisfied"),this.setHelpUrl("")}},i.a.Blocks.or={init:function(){this.appendStatementInput("A").setCheck("policy").appendField("Weight").appendField(new i.a.FieldNumber(1,1),"A_weight"),this.appendDummyInput().appendField("OR"),this.appendStatementInput("B").setCheck("policy").appendField("Weight").appendField(new i.a.FieldNumber(1,1),"B_weight"),this.setPreviousStatement(!0,"policy"),this.setColour(230),this.setTooltip("Requires either one of the two sub-policies to be satisfied. Weights can be used to indicate the relative probability of each sub-policy"),this.setHelpUrl("")}},i.a.JavaScript.begin=function(e){return""},i.a.JavaScript.pk=function(e){if(!e.getParent())return"";var n=i.a.JavaScript.valueToCode(e,"pk",i.a.JavaScript.ORDER_ATOMIC);return""==n&&(n="()"),"pk"+n},i.a.JavaScript.existing_key=function(e){return e.getParent()?[e.getFieldValue("key"),i.a.JavaScript.ORDER_NONE]:["",i.a.JavaScript.ORDER_NONE]},i.a.JavaScript.alias_key=function(e){return e.getParent()?[e.getFieldValue("name"),i.a.JavaScript.ORDER_NONE]:["",i.a.JavaScript.ORDER_NONE]},i.a.JavaScript.thresh=function(e){return"thresh("+e.getFieldValue("Threshold")+","+i.a.JavaScript.statementToCode(e,"A")+")"},i.a.JavaScript.older=function(e){return e.getParent()?"older("+e.getFieldValue("NAME")+")":""},i.a.JavaScript.after=function(e){return e.getParent()?"after("+e.getFieldValue("NAME")+")":""},i.a.JavaScript.adapter=function(e){return e.getParent()?i.a.JavaScript.statementToCode(e,"NAME")+(e.getNextBlock()?",":""):""},i.a.JavaScript.and=function(e){return e.getParent()?"and("+i.a.JavaScript.statementToCode(e,"A")+","+i.a.JavaScript.statementToCode(e,"B")+")":""},i.a.JavaScript.or=function(e){if(!e.getParent())return"";var n=e.getFieldValue("A_weight");"1"==n?n="":n+="@";var t=i.a.JavaScript.statementToCode(e,"A"),r=e.getFieldValue("B_weight");return"1"==r?r="":r+="@","or("+n+t+","+r+i.a.JavaScript.statementToCode(e,"B")+")"};var o=i.a.inject(e,r);o.addChangeListener((function(e){t.value=i.a.JavaScript.workspaceToCode(o)})),o.addChangeListener(i.a.Events.disableOrphans),setTimeout(()=>{if(l.restoreBlocks(),0==o.getTopBlocks().length){var e=o.newBlock("begin");e.setDeletable(!1),e.setEditable(!1),e.moveBy(20,20),e.initSvg(),e.render()}const n=document.createElement("span");n.innerHTML='',n.style.float="right",n.style["margin-right"]="10px";let t=!1;n.onclick=function(){t?document.exitFullscreen():document.getElementById("blocklyDiv").requestFullscreen(),t=!t},document.getElementsByClassName("blocklyToolboxDiv")[0].appendChild(n)},0),l.backupOnUnload()}("blocklyDiv","policy");let e=null;document.getElementById("stdin").disabled=!0;const n=document.getElementById("start_button"),t=document.getElementById("stop_button"),o=document.getElementById("start_message");n.disabled=!1,t.disabled=!0;const a=document.getElementById("descriptor"),u=document.getElementById("change_descriptor");n.onclick=i=>{0!=a.value.length&&(i.preventDefault(),async function(e,n){const t=document.getElementById("stdout"),o=document.getElementById("stdin");o.disabled=!1;const i=[];let a=0,l=null;try{l=await new r.a("testnet",e,n,"https://blockstream.info/testnet/api")}catch(e){console.error(e)}const u=e=>{if("clear"!=e)return o.disabled=!0,t.innerHTML.length>0&&(t.innerHTML+="\n"),t.innerHTML+=`> ${e}\n`,a=i.push(e),l.run(e).then(e=>{e&&(t.innerHTML+=`${e}\n`)}).catch(e=>t.innerHTML+=`${e}\n`).finally(()=>{o.disabled=!1,t.scrollTop=t.scrollHeight-t.clientHeight});t.innerHTML=""};return o.onkeydown=e=>{if("Enter"==e.key){if(0==o.value.length)return;u(o.value),o.value="",e.preventDefault()}else"ArrowUp"==e.key?a>0&&(o.value=i[--a]):"ArrowDown"==e.key&&a0?u.value:null).then(r=>{n.disabled=!0,a.disabled=!0,u.disabled=!0,o.innerHTML="Wallet created, running `sync`...",r.run("sync").then(()=>o.innerHTML="Ready!"),e=r,t.disabled=!1}).catch(e=>o.innerHTML=`${e}`))},t.onclick=r=>{null!=e&&(r.preventDefault(),e.free(),o.innerHTML="Wallet instance destroyed",n.disabled=!1,t.disabled=!0,a.disabled=!1,u.disabled=!1)};const c=document.getElementById("policy"),s=document.getElementById("compiler_script_type"),d=document.getElementById("compiler_output");document.getElementById("compile_button").onclick=e=>{if(0==c.value.length)return;e.preventDefault();const n=!e.target.form.elements.namedItem("alias").length;let t=e.target.form.elements.namedItem("alias"),o=e.target.form.elements.namedItem("type"),i=e.target.form.elements.namedItem("extra");n?(t=[t],o=[o],i=[i]):(t=Array.from(t),o=Array.from(o),i=Array.from(i));const a={};t.forEach(e=>{const n=o.filter(n=>n.attributes["data-index"].value==e.attributes["data-index"].value)[0].value,t=i.filter(n=>n.attributes["data-index"].value==e.attributes["data-index"].value)[0].value,r=e.value;a[r]={type:n,extra:t}}),Object(r.ub)(c.value,JSON.stringify(a),s.value).then(e=>d.innerHTML=e).catch(e=>d.innerHTML=`${e}`)}}()},12:function(e,n,t){"use strict";var r=t.w[e.i];e.exports=r;t(2);r.n()},2:function(e,n,t){"use strict";(function(e,r){t.d(n,"vb",(function(){return T})),t.d(n,"ub",(function(){return _})),t.d(n,"a",(function(){return E})),t.d(n,"qb",(function(){return R})),t.d(n,"eb",(function(){return x})),t.d(n,"sb",(function(){return B})),t.d(n,"E",(function(){return I})),t.d(n,"W",(function(){return F})),t.d(n,"l",(function(){return q})),t.d(n,"nb",(function(){return C})),t.d(n,"q",(function(){return N})),t.d(n,"P",(function(){return M})),t.d(n,"T",(function(){return D})),t.d(n,"Q",(function(){return O})),t.d(n,"i",(function(){return H})),t.d(n,"B",(function(){return J})),t.d(n,"mb",(function(){return L})),t.d(n,"p",(function(){return P})),t.d(n,"X",(function(){return U})),t.d(n,"pb",(function(){return X})),t.d(n,"n",(function(){return j})),t.d(n,"j",(function(){return W})),t.d(n,"m",(function(){return V})),t.d(n,"w",(function(){return $})),t.d(n,"A",(function(){return K})),t.d(n,"fb",(function(){return z})),t.d(n,"F",(function(){return Q})),t.d(n,"b",(function(){return G})),t.d(n,"o",(function(){return Y})),t.d(n,"L",(function(){return Z})),t.d(n,"x",(function(){return ee})),t.d(n,"cb",(function(){return ne})),t.d(n,"Y",(function(){return te})),t.d(n,"v",(function(){return re})),t.d(n,"e",(function(){return oe})),t.d(n,"Z",(function(){return ie})),t.d(n,"K",(function(){return ae})),t.d(n,"D",(function(){return le})),t.d(n,"d",(function(){return ue})),t.d(n,"c",(function(){return ce})),t.d(n,"hb",(function(){return se})),t.d(n,"kb",(function(){return de})),t.d(n,"lb",(function(){return fe})),t.d(n,"N",(function(){return pe})),t.d(n,"k",(function(){return me})),t.d(n,"db",(function(){return be})),t.d(n,"y",(function(){return he})),t.d(n,"I",(function(){return ke})),t.d(n,"g",(function(){return ye})),t.d(n,"h",(function(){return ge})),t.d(n,"M",(function(){return ve})),t.d(n,"O",(function(){return we})),t.d(n,"C",(function(){return Te})),t.d(n,"H",(function(){return _e})),t.d(n,"R",(function(){return Ae})),t.d(n,"bb",(function(){return Se})),t.d(n,"ab",(function(){return Ee})),t.d(n,"S",(function(){return Re})),t.d(n,"gb",(function(){return xe})),t.d(n,"s",(function(){return Be})),t.d(n,"t",(function(){return Ie})),t.d(n,"f",(function(){return Fe})),t.d(n,"J",(function(){return qe})),t.d(n,"G",(function(){return Ce})),t.d(n,"V",(function(){return Ne})),t.d(n,"z",(function(){return Me})),t.d(n,"r",(function(){return De})),t.d(n,"u",(function(){return Oe})),t.d(n,"U",(function(){return He})),t.d(n,"rb",(function(){return Je})),t.d(n,"jb",(function(){return Le})),t.d(n,"tb",(function(){return Pe})),t.d(n,"ob",(function(){return Ue})),t.d(n,"ib",(function(){return Xe}));var o=t(12);const i=new Array(32).fill(void 0);function a(e){return i[e]}i.push(void 0,null,!0,!1);let l=i.length;function u(e){const n=a(e);return function(e){e<36||(i[e]=l,l=e)}(e),n}let c=new("undefined"==typeof TextDecoder?(0,e.require)("util").TextDecoder:TextDecoder)("utf-8",{ignoreBOM:!0,fatal:!0});c.decode();let s=null;function d(){return null!==s&&s.buffer===o.j.buffer||(s=new Uint8Array(o.j.buffer)),s}function f(e,n){return c.decode(d().subarray(e,e+n))}function p(e){l===i.length&&i.push(i.length+1);const n=l;return l=i[n],i[n]=e,n}let m=0;let b=new("undefined"==typeof TextEncoder?(0,e.require)("util").TextEncoder:TextEncoder)("utf-8");const h="function"==typeof b.encodeInto?function(e,n){return b.encodeInto(e,n)}:function(e,n){const t=b.encode(e);return n.set(t),{read:e.length,written:t.length}};function k(e,n,t){if(void 0===t){const t=b.encode(e),r=n(t.length);return d().subarray(r,r+t.length).set(t),m=t.length,r}let r=e.length,o=n(r);const i=d();let a=0;for(;a127)break;i[o+a]=n}if(a!==r){0!==a&&(e=e.slice(a)),o=t(o,r,r=a+3*e.length);const n=d().subarray(o+a,o+r);a+=h(e,n).written}return m=a,o}let y=null;function g(){return null!==y&&y.buffer===o.j.buffer||(y=new Int32Array(o.j.buffer)),y}function v(e){return null==e}function w(e,n,t){o.g(e,n,p(t))}function T(){o.i()}function _(e,n,t){var r=k(e,o.e,o.f),i=m,a=k(n,o.e,o.f),l=m,c=k(t,o.e,o.f),s=m;return u(o.h(r,i,a,l,c,s))}function A(e){return function(){try{return e.apply(this,arguments)}catch(e){o.b(p(e))}}}function S(e,n){return d().subarray(e/1,e/1+n)}class E{static __wrap(e){const n=Object.create(E.prototype);return n.ptr=e,n}free(){const e=this.ptr;this.ptr=0,o.a(e)}constructor(e,n,t,r){var i=k(e,o.e,o.f),a=m,l=k(n,o.e,o.f),c=m,s=v(t)?0:k(t,o.e,o.f),d=m,f=k(r,o.e,o.f),p=m;return u(o.k(i,a,l,c,s,d,f,p))}run(e){var n=k(e,o.e,o.f),t=m;return u(o.l(this.ptr,n,t))}}const R=function(e){u(e)},x=function(e){return p(E.__wrap(e))},B=function(e,n){return p(f(e,n))},I=function(){return p(new Error)},F=function(e,n){var t=k(a(n).stack,o.e,o.f),r=m;g()[e/4+1]=r,g()[e/4+0]=t},q=function(e,n){try{console.error(f(e,n))}finally{o.d(e,n)}},C=function(e,n){const t=a(n);var r=k(JSON.stringify(void 0===t?null:t),o.e,o.f),i=m;g()[e/4+1]=i,g()[e/4+0]=r},N=function(e,n,t){a(e).getRandomValues(S(n,t))},M=function(e,n,t){a(e).randomFillSync(S(n,t))},D=A((function(){return p(self.self)})),O=function(e,n,t){return p(a(e).require(f(n,t)))},H=function(e){return p(a(e).crypto)},J=function(e){return p(a(e).msCrypto)},L=function(e){return void 0===a(e)},P=function(e){return p(a(e).getRandomValues)},U=function(){return p(e)},X=function(e){return p(a(e))},j=function(e){return p(fetch(a(e)))},W=function(e){console.debug(a(e))},V=function(e){console.error(a(e))},$=function(e){console.info(a(e))},K=function(e){console.log(a(e))},z=function(e){console.warn(a(e))},Q=A((function(){return p(new Headers)})),G=A((function(e,n,t,r,o){a(e).append(f(n,t),f(r,o))})),Y=function(e,n){return p(a(e).fetch(a(n)))},Z=A((function(e,n){return p(new Blob(a(e),a(n)))})),ee=function(e){return a(e)instanceof Response},ne=function(e,n){var t=k(a(n).url,o.e,o.f),r=m;g()[e/4+1]=r,g()[e/4+0]=t},te=function(e){return a(e).status},re=function(e){return p(a(e).headers)},oe=A((function(e){return p(a(e).arrayBuffer())})),ie=A((function(e){return p(a(e).text())})),ae=A((function(e,n,t){return p(new Request(f(e,n),a(t)))})),le=A((function(){return p(new FormData)})),ue=A((function(e,n,t,r){a(e).append(f(n,t),a(r))})),ce=A((function(e,n,t,r,o,i){a(e).append(f(n,t),a(r),f(o,i))})),se=function(e){const n=u(e).original;if(1==n.cnt--)return n.a=0,!0;return!1},de=function(e){return"function"==typeof a(e)},fe=function(e){const n=a(e);return"object"==typeof n&&null!==n},pe=function(e){return p(a(e).next)},me=function(e){return a(e).done},be=function(e){return p(a(e).value)},he=function(){return p(Symbol.iterator)},ke=function(e,n){return p(new Function(f(e,n)))},ye=A((function(e,n){return p(a(e).call(a(n)))})),ge=A((function(e,n,t){return p(a(e).call(a(n),a(t)))})),ve=A((function(e){return p(a(e).next())})),we=function(){return Date.now()},Te=function(){return p(new Object)},_e=function(e,n){try{var t={a:e,b:n},r=new Promise((e,n)=>{const r=t.a;t.a=0;try{return function(e,n,t,r){o.m(e,n,p(t),p(r))}(r,t.b,e,n)}finally{t.a=r}});return p(r)}finally{t.a=t.b=0}},Ae=function(e){return p(Promise.resolve(a(e)))},Se=function(e,n){return p(a(e).then(a(n)))},Ee=function(e,n,t){return p(a(e).then(a(n),a(t)))},Re=A((function(){return p(self.self)})),xe=A((function(){return p(window.window)})),Be=A((function(){return p(globalThis.globalThis)})),Ie=A((function(){return p(r.global)})),Fe=function(e){return p(a(e).buffer)},qe=function(e,n,t){return p(new Uint8Array(a(e),n>>>0,t>>>0))},Ce=function(e){return p(new Uint8Array(a(e)))},Ne=function(e,n,t){a(e).set(a(n),t>>>0)},Me=function(e){return a(e).length},De=A((function(e,n){return p(Reflect.get(a(e),a(n)))})),Oe=A((function(e,n){return Reflect.has(a(e),a(n))})),He=A((function(e,n,t){return Reflect.set(a(e),a(n),a(t))})),Je=function(e,n){const t=a(n);var r="string"==typeof t?t:void 0,i=v(r)?0:k(r,o.e,o.f),l=m;g()[e/4+1]=l,g()[e/4+0]=i},Le=function(e,n){var t=k(function e(n){const t=typeof n;if("number"==t||"boolean"==t||null==n)return""+n;if("string"==t)return`"${n}"`;if("symbol"==t){const e=n.description;return null==e?"Symbol":`Symbol(${e})`}if("function"==t){const e=n.name;return"string"==typeof e&&e.length>0?`Function(${e})`:"Function"}if(Array.isArray(n)){const t=n.length;let r="[";t>0&&(r+=e(n[0]));for(let o=1;o1))return toString.call(n);if(o=r[1],"Object"==o)try{return"Object("+JSON.stringify(n)+")"}catch(e){return"Object"}return n instanceof Error?`${n.name}: ${n.message}\n${n.stack}`:o}(a(n)),o.e,o.f),r=m;g()[e/4+1]=r,g()[e/4+0]=t},Pe=function(e,n){throw new Error(f(e,n))},Ue=function(){return p(o.j)},Xe=function(e,n,t){return p(function(e,n,t,r){const i={a:e,b:n,cnt:1,dtor:t},a=(...e)=>{i.cnt++;const n=i.a;i.a=0;try{return r(n,i.b,...e)}finally{0==--i.cnt?o.c.get(i.dtor)(n,i.b):i.a=n}};return a.original=i,a}(e,n,1126,w))}}).call(this,t(11)(e),t(5))}}]); \ No newline at end of file diff --git a/static/bdk-cli/playground/2715004f10f13ece5ea4.module.wasm b/static/bdk-cli/playground/2715004f10f13ece5ea4.module.wasm deleted file mode 100644 index c1b7ba6a6e..0000000000 Binary files a/static/bdk-cli/playground/2715004f10f13ece5ea4.module.wasm and /dev/null differ diff --git a/static/bdk-cli/playground/playground.js b/static/bdk-cli/playground/playground.js deleted file mode 100644 index a74dfb7e8c..0000000000 --- a/static/bdk-cli/playground/playground.js +++ /dev/null @@ -1 +0,0 @@ -!function(e){function n(n){for(var t,_,o=n[0],u=n[1],c=0,f=[];cconsole.error("Error importing `index.js`:",e))}]); \ No newline at end of file diff --git a/static/css/blog.css b/static/css/blog.css deleted file mode 100644 index 678e85fdee..0000000000 --- a/static/css/blog.css +++ /dev/null @@ -1,44 +0,0 @@ -h1.blog-title { - margin-top: 0; - margin-bottom: 0; -} - -span.blog-author { - font-weight: bolder; - font-size: 1.2em; -} - -div.tags { - display: flex; - justify-content: center; -} - -h3.blog-post { - display: flex; - align-items: center; - margin-bottom: 0; -} - -h3.blog-post span.anchor { - position: initial; -} - -h3.blog-post > span.date { - font-weight: lighter; - width: 10vh; - display: inline-block; - margin-left: 2vh; -} - -span.blog-post-tags { - margin-left: 12vh; -} - -a.tag-link::before { - width: 1em !important; - height: 2em !important; -} - -a.tag-link { - border-radius: 1px 3px 3px 1px !important; -} diff --git a/static/css/jsonview.css b/static/css/jsonview.css deleted file mode 100644 index 72419b32d1..0000000000 --- a/static/css/jsonview.css +++ /dev/null @@ -1,88 +0,0 @@ -.json { - padding: 16px; - background-color: #272822; - color: #FFF; - font-family: "Consolas", menlo, monospace; -} - -.line { - margin: 4px 0; - display: flex; - justify-content: flex-start; -} - -.caret-icon { - width: 28px; - text-align: center; - cursor: pointer; -} - -.json .caret-icon > i { - border: 0; -} - -.empty-icon { - width: 20px; -} - -.json-type { - margin-right: 4px; - margin-left: 4px; -} - -.json-key { - color: #EEE; - margin-right: 4px; - margin-left: 4px; -} - -.json-index { - margin-right: 4px; - margin-left: 4px; -} - -.json-separator { - -} - -.json-value { - margin-left: 8px; -} - -.json-number { - color: #f9ae58; -} - -.json-boolean { - color: #ec5f66; -} - -.json-string { - color: #86b25c; -} - -.json-size { - margin-right: 4px; - margin-left: 4px; -} - -.hide { - display: none; -} - -.json .fas { - display: inline-block; - width: 0; - height: 0; - border-style: solid; -} - -.json .fa-caret-down { - border-width: 6px 5px 0 5px; - border-color: #808080 transparent -} - -.json .fa-caret-right { - border-width: 5px 0 5px 6px; - border-color: transparent transparent transparent #808080; -} diff --git a/static/css/style.css b/static/css/style.css deleted file mode 100644 index fbb5e1c032..0000000000 --- a/static/css/style.css +++ /dev/null @@ -1,60 +0,0 @@ -#descriptor-examples-table { -} - -#descriptor-examples-table code, #descriptor-examples-table td:not(:first-child) { - overflow-x: auto; - white-space: pre-wrap; - white-space: -moz-pre-wrap; - white-space: -pre-wrap; - white-space: -o-pre-wrap; - word-wrap: break-word; - overflow-wrap: anywhere; -} - -#descriptor-examples-table > table > thead > tr > th:nth-child(2) { - width: 45%; -} - -#descriptor-examples-table > table > thead > tr > th:nth-child(2) { - width: 45%; -} - -.descriptor-support-table > table > thead > tr > th:nth-child(1) { - width: 25%; -} - -main .supporters { - max-width: 640px; - margin-left: auto; - margin-right: auto; -} -.justify-content-left { - justify-content: left !important; -} -.row { - display: flex; - flex-wrap: wrap; - margin-right: -15px; - margin-left: -15px; -} -.p-3 { - padding: 1rem !important; -} -small, .small { - font-size: 80%; - font-weight: 400; -} -.supporters img { - width: 75px !important; - height: 75px !important; - margin: 1rem auto !important; -} -img { - vertical-align: middle; - border-style: none; -} - -/* Make sure link still get the right color even if they are wrapped in `code` tags */ -a.highlight code { - color: var(--MAIN-LINK-color); -} diff --git a/static/docs-rs/bdk/0.1.0-beta.1/COPYRIGHT.txt b/static/docs-rs/bdk/0.1.0-beta.1/COPYRIGHT.txt deleted file mode 100644 index af77776cca..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/COPYRIGHT.txt +++ /dev/null @@ -1,45 +0,0 @@ -These documentation pages include resources by third parties. This copyright -file applies only to those resources. The following third party resources are -included, and carry their own copyright notices and license terms: - -* Fira Sans (FiraSans-Regular.woff, FiraSans-Medium.woff): - - Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ - with Reserved Font Name Fira Sans. - - Copyright (c) 2014, Telefonica S.A. - - Licensed under the SIL Open Font License, Version 1.1. - See FiraSans-LICENSE.txt. - -* rustdoc.css, main.js, and playpen.js: - - Copyright 2015 The Rust Developers. - Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or - the MIT license (LICENSE-MIT.txt) at your option. - -* normalize.css: - - Copyright (c) Nicolas Gallagher and Jonathan Neal. - Licensed under the MIT license (see LICENSE-MIT.txt). - -* Source Code Pro (SourceCodePro-Regular.woff, SourceCodePro-Semibold.woff): - - Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), - with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark - of Adobe Systems Incorporated in the United States and/or other countries. - - Licensed under the SIL Open Font License, Version 1.1. - See SourceCodePro-LICENSE.txt. - -* Source Serif Pro (SourceSerifPro-Regular.ttf.woff, - SourceSerifPro-Bold.ttf.woff, SourceSerifPro-It.ttf.woff): - - Copyright 2014 Adobe Systems Incorporated (http://www.adobe.com/), with - Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of - Adobe Systems Incorporated in the United States and/or other countries. - - Licensed under the SIL Open Font License, Version 1.1. - See SourceSerifPro-LICENSE.txt. - -This copyright file is intended to be distributed with rustdoc output. diff --git a/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-LICENSE.txt b/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-LICENSE.txt deleted file mode 100644 index d444ea92b6..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-LICENSE.txt +++ /dev/null @@ -1,94 +0,0 @@ -Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. -with Reserved Font Name < Fira >, - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-Medium.woff b/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-Medium.woff deleted file mode 100644 index 7d742c5fb7..0000000000 Binary files a/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-Medium.woff and /dev/null differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-Regular.woff b/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-Regular.woff deleted file mode 100644 index d8e0363f4e..0000000000 Binary files a/static/docs-rs/bdk/0.1.0-beta.1/FiraSans-Regular.woff and /dev/null differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/LICENSE-APACHE.txt b/static/docs-rs/bdk/0.1.0-beta.1/LICENSE-APACHE.txt deleted file mode 100644 index 16fe87b06e..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/LICENSE-APACHE.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/static/docs-rs/bdk/0.1.0-beta.1/LICENSE-MIT.txt b/static/docs-rs/bdk/0.1.0-beta.1/LICENSE-MIT.txt deleted file mode 100644 index 31aa79387f..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/LICENSE-MIT.txt +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-LICENSE.txt b/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-LICENSE.txt deleted file mode 100644 index 07542572e3..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-LICENSE.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. - -This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Regular.woff b/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Regular.woff deleted file mode 100644 index 5576670903..0000000000 Binary files a/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Regular.woff and /dev/null differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Semibold.woff b/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Semibold.woff deleted file mode 100644 index ca972a11dc..0000000000 Binary files a/static/docs-rs/bdk/0.1.0-beta.1/SourceCodePro-Semibold.woff and /dev/null differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Bold.ttf.woff b/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Bold.ttf.woff deleted file mode 100644 index ca254318fe..0000000000 Binary files a/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Bold.ttf.woff and /dev/null differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-It.ttf.woff b/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-It.ttf.woff deleted file mode 100644 index a287bbe6ed..0000000000 Binary files a/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-It.ttf.woff and /dev/null differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-LICENSE.md b/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-LICENSE.md deleted file mode 100644 index 22cb755f2f..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-LICENSE.md +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2014-2018 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. - -This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Regular.ttf.woff b/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Regular.ttf.woff deleted file mode 100644 index a3d55cfdf2..0000000000 Binary files a/static/docs-rs/bdk/0.1.0-beta.1/SourceSerifPro-Regular.ttf.woff and /dev/null differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/all.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/all.html deleted file mode 100644 index 3a505a083c..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/all.html +++ /dev/null @@ -1,3 +0,0 @@ -List of all items in this crate

    [] - - List of all items

    Structs

    Enums

    Traits

    Functions

    Typedefs

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/enum.CompactFiltersError.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/enum.CompactFiltersError.html deleted file mode 100644 index 03e77e6d1f..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/enum.CompactFiltersError.html +++ /dev/null @@ -1,56 +0,0 @@ -bdk::blockchain::compact_filters::CompactFiltersError - Rust

    [][src]Enum bdk::blockchain::compact_filters::CompactFiltersError

    pub enum CompactFiltersError {
    -    InvalidResponse,
    -    InvalidHeaders,
    -    InvalidFilterHeader,
    -    InvalidFilter,
    -    MissingBlock,
    -    DataCorruption,
    -    NotConnected,
    -    Timeout,
    -    NoPeers,
    -    DB(Error),
    -    IO(Error),
    -    BIP158(Error),
    -    Time(SystemTimeError),
    -    Global(Box<Error>),
    -}
    This is supported on feature="compact_filters" only.

    An error that can occur during sync with a CompactFiltersBlockchain

    -

    - Variants

    -
    InvalidResponse
    This is supported on feature="compact_filters" only.

    A peer sent an invalid or unexpected response

    -
    InvalidHeaders
    This is supported on feature="compact_filters" only.

    The headers returned are invalid

    -
    InvalidFilterHeader
    This is supported on feature="compact_filters" only.

    The compact filter headers returned are invalid

    -
    InvalidFilter
    This is supported on feature="compact_filters" only.

    The compact filter returned is invalid

    -
    MissingBlock
    This is supported on feature="compact_filters" only.

    The peer is missing a block in the valid chain

    -
    DataCorruption
    This is supported on feature="compact_filters" only.

    The data stored in the block filters storage are corrupted

    -
    NotConnected
    This is supported on feature="compact_filters" only.

    A peer is not connected

    -
    Timeout
    This is supported on feature="compact_filters" only.

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

    -
    NoPeers
    This is supported on feature="compact_filters" only.

    No peers have been specified

    -
    DB(Error)
    This is supported on feature="compact_filters" only.

    Internal database error

    -
    IO(Error)
    This is supported on feature="compact_filters" only.

    Internal I/O error

    -
    BIP158(Error)
    This is supported on feature="compact_filters" only.

    Invalid BIP158 filter

    -
    This is supported on feature="compact_filters" only.

    Internal system time error

    -
    Global(Box<Error>)
    This is supported on feature="compact_filters" only.

    Wrapper for crate::error::Error

    -

    Trait Implementations

    impl Debug for CompactFiltersError[src]

    impl Display for CompactFiltersError[src]

    impl Error for CompactFiltersError[src]

    impl From<CompactFiltersError> for Error[src]

    impl From<Error> for CompactFiltersError[src]

    impl From<Error> for CompactFiltersError[src]

    impl From<Error> for CompactFiltersError[src]

    impl From<Error> for CompactFiltersError[src]

    impl From<SystemTimeError> for CompactFiltersError[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/index.html deleted file mode 100644 index 9a0f04a20e..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/index.html +++ /dev/null @@ -1,31 +0,0 @@ -bdk::blockchain::compact_filters - Rust

    [][src]Module bdk::blockchain::compact_filters

    This is supported on feature="compact_filters" only.

    Compact Filters

    -

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

    -

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

    -

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

    -

    Example

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

    Structs

    -
    CompactFiltersBlockchainfeature="compact_filters"

    Structure implementing the required blockchain traits

    -
    Mempoolfeature="compact_filters"

    Container for unconfirmed, but valid Bitcoin transactions

    -
    Peerfeature="compact_filters"

    A Bitcoin peer

    -

    Enums

    -
    CompactFiltersErrorfeature="compact_filters"

    An error that can occur during sync with a CompactFiltersBlockchain

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Mempool.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Mempool.html deleted file mode 100644 index cd04378cbe..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Mempool.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

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

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Peer.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Peer.html deleted file mode 100644 index 11332c3bdb..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/peer/struct.Peer.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

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

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/sidebar-items.js deleted file mode 100644 index 22c61151d6..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["CompactFiltersError","An error that can occur during sync with a [`CompactFiltersBlockchain`]"]],"struct":[["CompactFiltersBlockchain","Structure implementing the required blockchain traits"],["Mempool","Container for unconfirmed, but valid Bitcoin transactions"],["Peer","A Bitcoin peer"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html deleted file mode 100644 index e66ceef644..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html +++ /dev/null @@ -1,28 +0,0 @@ -bdk::blockchain::compact_filters::CompactFiltersBlockchain - Rust

    [][src]Struct bdk::blockchain::compact_filters::CompactFiltersBlockchain

    pub struct CompactFiltersBlockchain { /* fields omitted */ }
    This is supported on feature="compact_filters" only.

    Structure implementing the required blockchain traits

    -

    Example

    -

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

    -

    Implementations

    impl CompactFiltersBlockchain[src]

    pub fn new<P: AsRef<Path>>(
        peers: Vec<Peer>,
        storage_dir: P,
        skip_blocks: Option<usize>
    ) -> Result<Self, CompactFiltersError>
    [src]

    This is supported on feature="compact_filters" only.

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

    -

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

    -

    Trait Implementations

    impl Blockchain for CompactFiltersBlockchain[src]

    impl Debug for CompactFiltersBlockchain[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> BlockchainMarker for T where
        T: Blockchain
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Mempool.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Mempool.html deleted file mode 100644 index d7cf23d992..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Mempool.html +++ /dev/null @@ -1,21 +0,0 @@ -bdk::blockchain::compact_filters::Mempool - Rust

    [][src]Struct bdk::blockchain::compact_filters::Mempool

    pub struct Mempool { /* fields omitted */ }
    This is supported on feature="compact_filters" only.

    Container for unconfirmed, but valid Bitcoin transactions

    -

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

    -

    Implementations

    impl Mempool[src]

    pub fn add_tx(&self, tx: Transaction)[src]

    This is supported on feature="compact_filters" only.

    Add a transaction to the mempool

    -

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

    -

    pub fn get_tx(&self, inventory: &Inventory) -> Option<Transaction>[src]

    This is supported on feature="compact_filters" only.

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

    -

    pub fn has_tx(&self, txid: &Txid) -> bool[src]

    This is supported on feature="compact_filters" only.

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

    -

    pub fn iter_txs(&self) -> Vec<Transaction>[src]

    This is supported on feature="compact_filters" only.

    Return the list of transactions contained in the mempool

    -

    Trait Implementations

    impl Debug for Mempool[src]

    impl Default for Mempool[src]

    Auto Trait Implementations

    impl RefUnwindSafe for Mempool

    impl Send for Mempool

    impl Sync for Mempool

    impl Unpin for Mempool

    impl UnwindSafe for Mempool

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Peer.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Peer.html deleted file mode 100644 index e870e68138..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/compact_filters/struct.Peer.html +++ /dev/null @@ -1,25 +0,0 @@ -bdk::blockchain::compact_filters::Peer - Rust

    [][src]Struct bdk::blockchain::compact_filters::Peer

    pub struct Peer { /* fields omitted */ }
    This is supported on feature="compact_filters" only.

    A Bitcoin peer

    -

    Implementations

    impl Peer[src]

    pub fn connect<A: ToSocketAddrs>(
        address: A,
        mempool: Arc<Mempool>,
        network: Network
    ) -> Result<Self, CompactFiltersError>
    [src]

    This is supported on feature="compact_filters" only.

    Connect to a peer over a plaintext TCP connection

    -

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

    -

    pub fn connect_proxy<T: ToTargetAddr, P: ToSocketAddrs>(
        target: T,
        proxy: P,
        credentials: Option<(&str, &str)>,
        mempool: Arc<Mempool>,
        network: Network
    ) -> Result<Self, CompactFiltersError>
    [src]

    This is supported on feature="compact_filters" only.

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

    -

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

    -

    pub fn get_version(&self) -> &VersionMessage[src]

    This is supported on feature="compact_filters" only.

    Return the [VersionMessage] sent by the peer

    -

    pub fn get_network(&self) -> Network[src]

    This is supported on feature="compact_filters" only.

    Return the Bitcoin [Network] in use

    -

    pub fn get_mempool(&self) -> Arc<Mempool>[src]

    This is supported on feature="compact_filters" only.

    Return the mempool used by this peer

    -

    pub fn is_connected(&self) -> bool[src]

    This is supported on feature="compact_filters" only.

    Return whether or not the peer is still connected

    -

    pub fn send(&self, payload: NetworkMessage) -> Result<(), CompactFiltersError>[src]

    This is supported on feature="compact_filters" only.

    Send a raw Bitcoin message to the peer

    -

    pub fn recv(
        &self,
        wait_for: &'static str,
        timeout: Option<Duration>
    ) -> Result<Option<NetworkMessage>, CompactFiltersError>
    [src]

    This is supported on feature="compact_filters" only.

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

    -

    Trait Implementations

    impl Debug for Peer[src]

    Auto Trait Implementations

    impl !RefUnwindSafe for Peer

    impl Send for Peer

    impl Sync for Peer

    impl Unpin for Peer

    impl !UnwindSafe for Peer

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/index.html deleted file mode 100644 index 6284002c9b..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/index.html +++ /dev/null @@ -1,11 +0,0 @@ -bdk::blockchain::electrum - Rust

    [][src]Module bdk::blockchain::electrum

    This is supported on feature="electrum" only.

    Electrum

    -

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

    -

    Example

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

    Structs

    -
    ElectrumBlockchainfeature="electrum"

    Wrapper over an Electrum Client that implements the required blockchain traits

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/sidebar-items.js deleted file mode 100644 index ca94a34fb0..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["ElectrumBlockchain","Wrapper over an Electrum Client that implements the required blockchain traits"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/struct.ElectrumBlockchain.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/struct.ElectrumBlockchain.html deleted file mode 100644 index 44ca3ba179..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/electrum/struct.ElectrumBlockchain.html +++ /dev/null @@ -1,21 +0,0 @@ -bdk::blockchain::electrum::ElectrumBlockchain - Rust

    [][src]Struct bdk::blockchain::electrum::ElectrumBlockchain

    pub struct ElectrumBlockchain(_);
    This is supported on feature="electrum" only.

    Wrapper over an Electrum Client that implements the required blockchain traits

    -

    Example

    -

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

    -

    Trait Implementations

    impl Blockchain for ElectrumBlockchain[src]

    impl From<Client> for ElectrumBlockchain[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> BlockchainMarker for T where
        T: Blockchain
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/enum.Capability.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/enum.Capability.html deleted file mode 100644 index 2fc3bbd7d1..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/enum.Capability.html +++ /dev/null @@ -1,32 +0,0 @@ -bdk::blockchain::Capability - Rust

    [][src]Enum bdk::blockchain::Capability

    pub enum Capability {
    -    FullHistory,
    -    GetAnyTx,
    -    AccurateFees,
    -}

    Capabilities that can be supported by a Blockchain backend

    -

    - Variants

    -
    FullHistory

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

    -
    GetAnyTx

    Can fetch any historical transaction given its txid

    -
    AccurateFees

    Can compute accurate fees for the transactions found during sync

    -

    Trait Implementations

    impl Clone for Capability[src]

    impl Copy for Capability[src]

    impl Debug for Capability[src]

    impl Eq for Capability[src]

    impl Hash for Capability[src]

    impl PartialEq<Capability> for Capability[src]

    impl StructuralEq for Capability[src]

    impl StructuralPartialEq for Capability[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/enum.EsploraError.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/enum.EsploraError.html deleted file mode 100644 index f4e7f9664c..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/enum.EsploraError.html +++ /dev/null @@ -1,34 +0,0 @@ -bdk::blockchain::esplora::EsploraError - Rust

    [][src]Enum bdk::blockchain::esplora::EsploraError

    pub enum EsploraError {
    -    Reqwest(Error),
    -    Parsing(ParseIntError),
    -    BitcoinEncoding(Error),
    -    TransactionNotFound(Txid),
    -}
    This is supported on feature="esplora" only.

    Errors that can happen during a sync with EsploraBlockchain

    -

    - Variants

    -
    Reqwest(Error)
    This is supported on feature="esplora" only.

    Error with the HTTP call

    -
    Parsing(ParseIntError)
    This is supported on feature="esplora" only.

    Invalid number returned

    -
    BitcoinEncoding(Error)
    This is supported on feature="esplora" only.

    Invalid Bitcoin data returned

    -
    TransactionNotFound(Txid)
    This is supported on feature="esplora" only.

    Transaction not found

    -

    Trait Implementations

    impl Debug for EsploraError[src]

    impl Display for EsploraError[src]

    impl Error for EsploraError[src]

    impl From<Error> for EsploraError[src]

    impl From<Error> for EsploraError[src]

    impl From<EsploraError> for Error[src]

    impl From<ParseIntError> for EsploraError[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/index.html deleted file mode 100644 index abb4d4d08a..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/index.html +++ /dev/null @@ -1,11 +0,0 @@ -bdk::blockchain::esplora - Rust

    [][src]Module bdk::blockchain::esplora

    This is supported on feature="esplora" only.

    Esplora

    -

    This module defines a Blockchain struct that can query an Esplora backend -populate the wallet's database by

    -

    Example

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

    Structs

    -
    EsploraBlockchainfeature="esplora"

    Structure that implements the logic to sync with Esplora

    -

    Enums

    -
    EsploraErrorfeature="esplora"

    Errors that can happen during a sync with EsploraBlockchain

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/sidebar-items.js deleted file mode 100644 index fc6ecf6be6..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["EsploraError","Errors that can happen during a sync with [`EsploraBlockchain`]"]],"struct":[["EsploraBlockchain","Structure that implements the logic to sync with Esplora"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/struct.EsploraBlockchain.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/struct.EsploraBlockchain.html deleted file mode 100644 index e2a5d3c475..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/esplora/struct.EsploraBlockchain.html +++ /dev/null @@ -1,22 +0,0 @@ -bdk::blockchain::esplora::EsploraBlockchain - Rust

    [][src]Struct bdk::blockchain::esplora::EsploraBlockchain

    pub struct EsploraBlockchain(_);
    This is supported on feature="esplora" only.

    Structure that implements the logic to sync with Esplora

    -

    Example

    -

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

    -

    Implementations

    impl EsploraBlockchain[src]

    pub fn new(base_url: &str) -> Self[src]

    This is supported on feature="esplora" only.

    Create a new instance of the client from a base URL

    -

    Trait Implementations

    impl Blockchain for EsploraBlockchain[src]

    impl Debug for EsploraBlockchain[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> BlockchainMarker for T where
        T: Blockchain
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.log_progress.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.log_progress.html deleted file mode 100644 index c9bf15bd7a..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.log_progress.html +++ /dev/null @@ -1,2 +0,0 @@ -bdk::blockchain::log_progress - Rust

    [][src]Function bdk::blockchain::log_progress

    pub fn log_progress() -> LogProgress

    Create a nwe instance of LogProgress

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.noop_progress.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.noop_progress.html deleted file mode 100644 index 046b7d470f..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.noop_progress.html +++ /dev/null @@ -1,2 +0,0 @@ -bdk::blockchain::noop_progress - Rust

    [][src]Function bdk::blockchain::noop_progress

    pub fn noop_progress() -> NoopProgress

    Create a new instance of NoopProgress

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.progress.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.progress.html deleted file mode 100644 index 5070df1d52..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/fn.progress.html +++ /dev/null @@ -1,2 +0,0 @@ -bdk::blockchain::progress - Rust

    [][src]Function bdk::blockchain::progress

    pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>)

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

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/index.html deleted file mode 100644 index 0d1ede0175..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/index.html +++ /dev/null @@ -1,28 +0,0 @@ -bdk::blockchain - Rust

    [][src]Module bdk::blockchain

    Blockchain backends

    -

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

    -

    Re-exports

    -
    pub use self::electrum::ElectrumBlockchain;
    pub use self::esplora::EsploraBlockchain;
    pub use self::compact_filters::CompactFiltersBlockchain;

    Modules

    -
    compact_filtersfeature="compact_filters"

    Compact Filters

    -
    electrumfeature="electrum"

    Electrum

    -
    esplorafeature="esplora"

    Esplora

    -

    Structs

    -
    LogProgress

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

    -
    NoopProgress

    Type that implements Progress and drops every update received

    -
    OfflineBlockchain

    Type that only implements Blockchain and is always "offline"

    -

    Enums

    -
    Capability

    Capabilities that can be supported by a Blockchain backend

    -

    Traits

    -
    Blockchain

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

    -
    BlockchainMarker

    Marker trait for a blockchain backend

    -
    Progress

    Trait for types that can receive and process progress updates during Blockchain::sync and -Blockchain::setup

    -

    Functions

    -
    log_progress

    Create a nwe instance of LogProgress

    -
    noop_progress

    Create a new instance of NoopProgress

    -
    progress

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

    -

    Type Definitions

    -
    ProgressData

    Data sent with a progress update over a channel

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/sidebar-items.js deleted file mode 100644 index caf2b0fe29..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Capability","Capabilities that can be supported by a [`Blockchain`] backend"]],"fn":[["log_progress","Create a nwe instance of [`LogProgress`]"],["noop_progress","Create a new instance of [`NoopProgress`]"],["progress","Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]"]],"mod":[["compact_filters","Compact Filters"],["electrum","Electrum"],["esplora","Esplora"]],"struct":[["LogProgress","Type that implements [`Progress`] and logs at level `INFO` every update received"],["NoopProgress","Type that implements [`Progress`] and drops every update received"],["OfflineBlockchain","Type that only implements [`Blockchain`] and is always \"offline\""]],"trait":[["Blockchain","Trait that defines the actions that must be supported by a blockchain backend"],["BlockchainMarker","Marker trait for a blockchain backend"],["Progress","Trait for types that can receive and process progress updates during [`Blockchain::sync`] and [`Blockchain::setup`]"]],"type":[["ProgressData","Data sent with a progress update over a [`channel`]"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.LogProgress.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.LogProgress.html deleted file mode 100644 index 90c9026c8b..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.LogProgress.html +++ /dev/null @@ -1,18 +0,0 @@ -bdk::blockchain::LogProgress - Rust

    [][src]Struct bdk::blockchain::LogProgress

    pub struct LogProgress;

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

    -

    Trait Implementations

    impl Clone for LogProgress[src]

    impl Progress for LogProgress[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.NoopProgress.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.NoopProgress.html deleted file mode 100644 index 14ff942c13..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.NoopProgress.html +++ /dev/null @@ -1,18 +0,0 @@ -bdk::blockchain::NoopProgress - Rust

    [][src]Struct bdk::blockchain::NoopProgress

    pub struct NoopProgress;

    Type that implements Progress and drops every update received

    -

    Trait Implementations

    impl Clone for NoopProgress[src]

    impl Progress for NoopProgress[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.OfflineBlockchain.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.OfflineBlockchain.html deleted file mode 100644 index 8a5fcd5f92..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/struct.OfflineBlockchain.html +++ /dev/null @@ -1,11 +0,0 @@ -bdk::blockchain::OfflineBlockchain - Rust

    [][src]Struct bdk::blockchain::OfflineBlockchain

    pub struct OfflineBlockchain;

    Type that only implements Blockchain and is always "offline"

    -

    Trait Implementations

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> BlockchainMarker for T where
        T: Blockchain
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Blockchain.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Blockchain.html deleted file mode 100644 index 37b5fa8bce..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Blockchain.html +++ /dev/null @@ -1,37 +0,0 @@ -bdk::blockchain::Blockchain - Rust

    [][src]Trait bdk::blockchain::Blockchain

    pub trait Blockchain: BlockchainMarker {
    -    fn get_capabilities(&self) -> HashSet<Capability>;
    -
    fn setup<D: BatchDatabase, P: 'static + Progress>(
            &self,
            stop_gap: Option<usize>,
            database: &mut D,
            progress_update: P
        ) -> Result<(), Error>; -
    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>; -
    fn broadcast(&self, tx: &Transaction) -> Result<(), Error>; -
    fn get_height(&self) -> Result<u32, Error>; -
    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>; - - fn sync<D: BatchDatabase, P: 'static + Progress>(
            &self,
            stop_gap: Option<usize>,
            database: &mut D,
            progress_update: P
        ) -> Result<(), Error> { ... } -}

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

    -
    -

    Required methods

    fn get_capabilities(&self) -> HashSet<Capability>

    Return the set of Capability supported by this backend

    -

    fn setup<D: BatchDatabase, P: 'static + Progress>(
        &self,
        stop_gap: Option<usize>,
        database: &mut D,
        progress_update: P
    ) -> Result<(), Error>

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

    -

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

    -

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

    -

    For types that do not have that distinction, only this method can be implemented, since -Blockchain::sync defaults to calling this internally if not overridden.

    -

    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>

    Fetch a transaction from the blockchain given its txid

    -

    fn broadcast(&self, tx: &Transaction) -> Result<(), Error>

    Broadcast a transaction

    -

    fn get_height(&self) -> Result<u32, Error>

    Return the current height

    -

    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>

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

    -
    Loading content... -

    Provided methods

    fn sync<D: BatchDatabase, P: 'static + Progress>(
        &self,
        stop_gap: Option<usize>,
        database: &mut D,
        progress_update: P
    ) -> Result<(), Error>

    Populate the internal database with transactions and UTXOs

    -

    If not overridden, it defaults to calling Blockchain::setup internally.

    -

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

    -

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

    -

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

    -
    Loading content... -

    Implementations on Foreign Types

    impl<T: Blockchain> Blockchain for Arc<T>[src]

    Loading content... -

    Implementors

    impl Blockchain for CompactFiltersBlockchain[src]

    impl Blockchain for ElectrumBlockchain[src]

    impl Blockchain for EsploraBlockchain[src]

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.BlockchainMarker.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.BlockchainMarker.html deleted file mode 100644 index abd1997c9f..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.BlockchainMarker.html +++ /dev/null @@ -1,12 +0,0 @@ -bdk::blockchain::BlockchainMarker - Rust

    [][src]Trait bdk::blockchain::BlockchainMarker

    pub trait BlockchainMarker { }

    Marker trait for a blockchain backend

    -

    This is a marker trait for blockchain types. It is automatically implemented for types that -implement Blockchain, so as a user of the library you won't have to implement this -manually.

    -

    Users of the library will probably never have to implement this trait manually, but they -could still need to import it to define types and structs with generics; -Implementing only the marker trait is pointless, since OfflineBlockchain -already does that, and whenever Blockchain is implemented, the marker trait is also -automatically implemented by the library.

    -
    -

    Implementors

    impl BlockchainMarker for OfflineBlockchain[src]

    impl<T: Blockchain> BlockchainMarker for T[src]

    The BlockchainMarker marker trait is automatically implemented for Blockchain types

    -
    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Progress.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Progress.html deleted file mode 100644 index c5b883f49e..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/trait.Progress.html +++ /dev/null @@ -1,11 +0,0 @@ -bdk::blockchain::Progress - Rust

    [][src]Trait bdk::blockchain::Progress

    pub trait Progress: Send {
    -    fn update(
            &self,
            progress: f32,
            message: Option<String>
        ) -> Result<(), Error>; -}

    Trait for types that can receive and process progress updates during Blockchain::sync and -Blockchain::setup

    -
    -

    Required methods

    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error>

    Send a new progress update

    -

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

    -
    Loading content... -

    Implementations on Foreign Types

    impl Progress for Sender<ProgressData>[src]

    Loading content... -

    Implementors

    impl Progress for LogProgress[src]

    impl Progress for NoopProgress[src]

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/type.ProgressData.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/type.ProgressData.html deleted file mode 100644 index ec3f541cb7..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/blockchain/type.ProgressData.html +++ /dev/null @@ -1,2 +0,0 @@ -bdk::blockchain::ProgressData - Rust

    [][src]Type Definition bdk::blockchain::ProgressData

    type ProgressData = (f32, Option<String>);

    Data sent with a progress update over a channel

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/index.html deleted file mode 100644 index 7d69c1a943..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/index.html +++ /dev/null @@ -1,17 +0,0 @@ -bdk::database - Rust

    [][src]Module bdk::database

    Database types

    -

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

    -

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

    -

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

    -

    Re-exports

    -
    pub use memory::MemoryDatabase;

    Modules

    -
    memory

    In-memory ephemeral database

    -

    Traits

    -
    BatchDatabase

    Trait for a database that supports batch operations

    -
    BatchOperations

    Trait for operations that can be batched

    -
    Database

    Trait for reading data from a database

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/index.html deleted file mode 100644 index c30317bfb8..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/index.html +++ /dev/null @@ -1,6 +0,0 @@ -bdk::database::memory - Rust

    [][src]Module bdk::database::memory

    In-memory ephemeral database

    -

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

    -

    Structs

    -
    MemoryDatabase

    In-memory ephemeral database

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/sidebar-items.js deleted file mode 100644 index 665f6718d0..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["MemoryDatabase","In-memory ephemeral database"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/struct.MemoryDatabase.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/struct.MemoryDatabase.html deleted file mode 100644 index f06b045d39..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/memory/struct.MemoryDatabase.html +++ /dev/null @@ -1,45 +0,0 @@ -bdk::database::memory::MemoryDatabase - Rust

    [][src]Struct bdk::database::memory::MemoryDatabase

    pub struct MemoryDatabase { /* fields omitted */ }

    In-memory ephemeral database

    -

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

    -

    Once it's dropped its content will be lost.

    -

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

    -

    Implementations

    impl MemoryDatabase[src]

    pub fn new() -> Self[src]

    Create a new empty database

    -

    Trait Implementations

    impl BatchDatabase for MemoryDatabase[src]

    type Batch = Self

    Container for the operations

    -

    impl BatchOperations for MemoryDatabase[src]

    impl Database for MemoryDatabase[src]

    impl Debug for MemoryDatabase[src]

    impl Default for MemoryDatabase[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/sidebar-items.js deleted file mode 100644 index 1d5816196c..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"mod":[["memory","In-memory ephemeral database"]],"trait":[["BatchDatabase","Trait for a database that supports batch operations"],["BatchOperations","Trait for operations that can be batched"],["Database","Trait for reading data from a database"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchDatabase.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchDatabase.html deleted file mode 100644 index 051a61e18b..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchDatabase.html +++ /dev/null @@ -1,14 +0,0 @@ -bdk::database::BatchDatabase - Rust

    [][src]Trait bdk::database::BatchDatabase

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

    Trait for a database that supports batch operations

    -

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

    -
    -

    Associated Types

    type Batch: BatchOperations

    Container for the operations

    -
    Loading content... -

    Required methods

    fn begin_batch(&self) -> Self::Batch

    Create a new batch container

    -

    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>

    Consume and apply a batch of operations

    -
    Loading content... -

    Implementations on Foreign Types

    impl BatchDatabase for Tree[src]

    type Batch = Batch

    Loading content... -

    Implementors

    impl BatchDatabase for MemoryDatabase[src]

    type Batch = Self

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchOperations.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchOperations.html deleted file mode 100644 index 4fc52b7d3b..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.BatchOperations.html +++ /dev/null @@ -1,31 +0,0 @@ -bdk::database::BatchOperations - Rust

    [][src]Trait bdk::database::BatchOperations

    pub trait BatchOperations {
    -    fn set_script_pubkey(
            &mut self,
            script: &Script,
            script_type: ScriptType,
            child: u32
        ) -> Result<(), Error>; -
    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>; -
    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>; -
    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>; -
    fn set_last_index(
            &mut self,
            script_type: ScriptType,
            value: u32
        ) -> Result<(), Error>; -
    fn del_script_pubkey_from_path(
            &mut self,
            script_type: ScriptType,
            child: u32
        ) -> Result<Option<Script>, Error>; -
    fn del_path_from_script_pubkey(
            &mut self,
            script: &Script
        ) -> Result<Option<(ScriptType, u32)>, Error>; -
    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>; -
    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>; -
    fn del_tx(
            &mut self,
            txid: &Txid,
            include_raw: bool
        ) -> Result<Option<TransactionDetails>, Error>; -
    fn del_last_index(
            &mut self,
            script_type: ScriptType
        ) -> Result<Option<u32>, Error>; -}

    Trait for operations that can be batched

    -

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

    -
    -

    Required methods

    fn set_script_pubkey(
        &mut self,
        script: &Script,
        script_type: ScriptType,
        child: u32
    ) -> Result<(), Error>

    Store a script_pubkey along with its script type and child number

    -

    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>

    Store a UTXO

    -

    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>

    Store a raw transaction

    -

    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>

    Store the metadata of a transaction

    -

    fn set_last_index(
        &mut self,
        script_type: ScriptType,
        value: u32
    ) -> Result<(), Error>

    Store the last derivation index for a given script type

    -

    fn del_script_pubkey_from_path(
        &mut self,
        script_type: ScriptType,
        child: u32
    ) -> Result<Option<Script>, Error>

    Delete a script_pubkey given the script type and its child number

    -

    fn del_path_from_script_pubkey(
        &mut self,
        script: &Script
    ) -> Result<Option<(ScriptType, u32)>, Error>

    Delete the data related to a specific script_pubkey, meaning the script type and the child -number

    -

    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>

    Delete a UTXO given its [OutPoint]

    -

    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>

    Delete a raw transaction given its [Txid]

    -

    fn del_tx(
        &mut self,
        txid: &Txid,
        include_raw: bool
    ) -> Result<Option<TransactionDetails>, Error>

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

    -

    fn del_last_index(
        &mut self,
        script_type: ScriptType
    ) -> Result<Option<u32>, Error>

    Delete the last derivation index for a script type

    -
    Loading content... -

    Implementations on Foreign Types

    impl BatchOperations for Tree[src]

    impl BatchOperations for Batch[src]

    Loading content... -

    Implementors

    impl BatchOperations for MemoryDatabase[src]

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.Database.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.Database.html deleted file mode 100644 index 05be68c384..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/database/trait.Database.html +++ /dev/null @@ -1,35 +0,0 @@ -bdk::database::Database - Rust

    [][src]Trait bdk::database::Database

    pub trait Database: BatchOperations {
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
            &mut self,
            script_type: ScriptType,
            bytes: B
        ) -> Result<(), Error>; -
    fn iter_script_pubkeys(
            &self,
            script_type: Option<ScriptType>
        ) -> Result<Vec<Script>, Error>; -
    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error>; -
    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>; -
    fn iter_txs(
            &self,
            include_raw: bool
        ) -> Result<Vec<TransactionDetails>, Error>; -
    fn get_script_pubkey_from_path(
            &self,
            script_type: ScriptType,
            child: u32
        ) -> Result<Option<Script>, Error>; -
    fn get_path_from_script_pubkey(
            &self,
            script: &Script
        ) -> Result<Option<(ScriptType, u32)>, Error>; -
    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>; -
    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>; -
    fn get_tx(
            &self,
            txid: &Txid,
            include_raw: bool
        ) -> Result<Option<TransactionDetails>, Error>; -
    fn get_last_index(
            &self,
            script_type: ScriptType
        ) -> Result<Option<u32>, Error>; -
    fn increment_last_index(
            &mut self,
            script_type: ScriptType
        ) -> Result<u32, Error>; -}

    Trait for reading data from a database

    -

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

    -
    -

    Required methods

    fn check_descriptor_checksum<B: AsRef<[u8]>>(
        &mut self,
        script_type: ScriptType,
        bytes: B
    ) -> Result<(), Error>

    Read and checks the descriptor checksum for a given script type

    -

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

    -

    fn iter_script_pubkeys(
        &self,
        script_type: Option<ScriptType>
    ) -> Result<Vec<Script>, Error>

    Return the list of script_pubkeys

    -

    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error>

    Return the list of UTXOs

    -

    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>

    Return the list of raw transactions

    -

    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error>

    Return the list of transactions metadata

    -

    fn get_script_pubkey_from_path(
        &self,
        script_type: ScriptType,
        child: u32
    ) -> Result<Option<Script>, Error>

    Fetch a script_pubkey given the script type and child number

    -

    fn get_path_from_script_pubkey(
        &self,
        script: &Script
    ) -> Result<Option<(ScriptType, u32)>, Error>

    Fetch the script type and child number of a given script_pubkey

    -

    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>

    Fetch a UTXO given its [OutPoint]

    -

    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>

    Fetch a raw transaction given its [Txid]

    -

    fn get_tx(
        &self,
        txid: &Txid,
        include_raw: bool
    ) -> Result<Option<TransactionDetails>, Error>

    Fetch the transaction metadata and optionally also the raw transaction

    -

    fn get_last_index(&self, script_type: ScriptType) -> Result<Option<u32>, Error>

    Return the last defivation index for a script type

    -

    fn increment_last_index(
        &mut self,
        script_type: ScriptType
    ) -> Result<u32, Error>

    Increment the last derivation index for a script type and returns it

    -

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

    -
    Loading content... -

    Implementations on Foreign Types

    impl Database for Tree[src]

    Loading content... -

    Implementors

    impl Database for MemoryDatabase[src]

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/fn.get_checksum.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/fn.get_checksum.html deleted file mode 100644 index 43647729e3..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/fn.get_checksum.html +++ /dev/null @@ -1,2 +0,0 @@ -bdk::descriptor::checksum::get_checksum - Rust

    [][src]Function bdk::descriptor::checksum::get_checksum

    pub fn get_checksum(desc: &str) -> Result<String, Error>

    Compute the checksum of a descriptor

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/index.html deleted file mode 100644 index b6b7a26f33..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/index.html +++ /dev/null @@ -1,6 +0,0 @@ -bdk::descriptor::checksum - Rust

    [][src]Module bdk::descriptor::checksum

    Descriptor checksum

    -

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

    -

    Functions

    -
    get_checksum

    Compute the checksum of a descriptor

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/sidebar-items.js deleted file mode 100644 index e1add094a5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/checksum/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"fn":[["get_checksum","Compute the checksum of a descriptor"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Descriptor.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Descriptor.html deleted file mode 100644 index f94eab51f0..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Descriptor.html +++ /dev/null @@ -1,80 +0,0 @@ -bdk::descriptor::Descriptor - Rust

    []Enum bdk::descriptor::Descriptor

    pub enum Descriptor<Pk> where
        Pk: MiniscriptKey
    { - Bare(Miniscript<Pk, Legacy>), - Pk(Pk), - Pkh(Pk), - Wpkh(Pk), - ShWpkh(Pk), - Sh(Miniscript<Pk, Legacy>), - Wsh(Miniscript<Pk, Segwitv0>), - ShWsh(Miniscript<Pk, Segwitv0>), -}

    Script descriptor

    -

    - Variants

    -
    Bare(Miniscript<Pk, Legacy>)

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

    -
    Pk(Pk)

    Pay-to-Pubkey

    -
    Pkh(Pk)

    Pay-to-PubKey-Hash

    -
    Wpkh(Pk)

    Pay-to-Witness-PubKey-Hash

    -
    ShWpkh(Pk)

    Pay-to-Witness-PubKey-Hash inside P2SH

    -

    Pay-to-ScriptHash with Legacy context

    -

    Pay-to-Witness-ScriptHash with Segwitv0 context

    -
    ShWsh(Miniscript<Pk, Segwitv0>)

    P2SH-P2WSH with Segwitv0 context

    -

    Implementations

    impl<Pk> Descriptor<Pk> where
        Pk: MiniscriptKey

    pub fn translate_pk<Fpk, Fpkh, Q, E>(
        &self,
        translatefpk: Fpk,
        translatefpkh: Fpkh
    ) -> Result<Descriptor<Q>, E> where
        Fpk: FnMut(&Pk) -> Result<Q, E>,
        Fpkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, E>,
        Q: MiniscriptKey

    Convert a descriptor using abstract keys to one using specific keys -This will panic if translatefpk returns an uncompressed key when -converting to a Segwit descriptor. To prevent this panic, ensure -translatefpk returns an error in this case instead.

    -

    impl<Pk> Descriptor<Pk> where
        Pk: MiniscriptKey + ToPublicKey

    pub fn address(&self, network: Network) -> Option<Address>

    Computes the Bitcoin address of the descriptor, if one exists

    -

    pub fn script_pubkey(&self) -> Script

    Computes the scriptpubkey of the descriptor

    -

    pub fn unsigned_script_sig(&self) -> Script

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

    -

    pub fn witness_script(&self) -> Script

    Computes the "witness script" of the descriptor, i.e. 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.

    -

    pub fn satisfy<S>(&self, txin: &mut TxIn, satisfier: S) -> Result<(), Error> where
        S: Satisfier<Pk>, 

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

    -

    pub fn max_satisfaction_weight(&self) -> usize

    Computes an upper bound on the weight of a satisfying witness to the -transaction. Assumes all signatures are 73 bytes, including push opcode -and sighash suffix. Includes the weight of the VarInts encoding the -scriptSig and witness stack length.

    -

    impl Descriptor<DescriptorPublicKey>

    pub fn derive(&self, path: &[ChildNumber]) -> Descriptor<DescriptorPublicKey>

    Derives all wildcard keys in the descriptor using the supplied path

    -

    pub fn parse_secret(
        s: &str
    ) -> Result<(Descriptor<DescriptorPublicKey>, HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>), Error>

    pub fn to_string_with_secret(
        &self,
        key_map: &HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>
    ) -> String

    Trait Implementations

    impl<Pk> Clone for Descriptor<Pk> where
        Pk: MiniscriptKey + Clone

    impl<Pk> Debug for Descriptor<Pk> where
        Pk: MiniscriptKey

    impl<Pk> Display for Descriptor<Pk> where
        Pk: MiniscriptKey

    impl<Pk> Eq for Descriptor<Pk> where
        Pk: MiniscriptKey + Eq

    impl ExtractPolicy for Descriptor<DescriptorPublicKey>[src]

    impl<Pk> FromStr for Descriptor<Pk> where
        Pk: MiniscriptKey,
        <Pk as FromStr>::Err: ToString,
        <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

    type Err = Error

    The associated error which can be returned from parsing.

    -

    impl<Pk> FromTree for Descriptor<Pk> where
        Pk: MiniscriptKey,
        <Pk as FromStr>::Err: ToString,
        <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

    fn from_tree(top: &Tree) -> Result<Descriptor<Pk>, Error>

    Parse an expression tree into a descriptor

    -

    impl<Pk> Liftable<Pk> for Descriptor<Pk> where
        Pk: MiniscriptKey

    impl<Pk> Ord for Descriptor<Pk> where
        Pk: MiniscriptKey + Ord

    impl<Pk> PartialEq<Descriptor<Pk>> for Descriptor<Pk> where
        Pk: MiniscriptKey + PartialEq<Pk>, 

    impl<Pk> PartialOrd<Descriptor<Pk>> for Descriptor<Pk> where
        Pk: MiniscriptKey + PartialOrd<Pk>, 

    impl<Pk> StructuralEq for Descriptor<Pk> where
        Pk: MiniscriptKey

    impl<Pk> StructuralPartialEq for Descriptor<Pk> where
        Pk: MiniscriptKey

    Auto Trait Implementations

    impl<Pk> RefUnwindSafe for Descriptor<Pk> where
        Pk: RefUnwindSafe,
        <Pk as MiniscriptKey>::Hash: RefUnwindSafe

    impl<Pk> Send for Descriptor<Pk> where
        Pk: Send + Sync,
        <Pk as MiniscriptKey>::Hash: Send + Sync

    impl<Pk> Sync for Descriptor<Pk> where
        Pk: Send + Sync,
        <Pk as MiniscriptKey>::Hash: Send + Sync

    impl<Pk> Unpin for Descriptor<Pk> where
        Pk: Unpin,
        <Pk as MiniscriptKey>::Hash: Unpin

    impl<Pk> UnwindSafe for Descriptor<Pk> where
        Pk: RefUnwindSafe + UnwindSafe,
        <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Legacy.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Legacy.html deleted file mode 100644 index bba267f6ac..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Legacy.html +++ /dev/null @@ -1,32 +0,0 @@ -bdk::descriptor::Legacy - Rust

    []Enum bdk::descriptor::Legacy

    pub enum Legacy {}

    Legacy ScriptContext

    -

    Trait Implementations

    impl Clone for Legacy

    impl Debug for Legacy

    impl Eq for Legacy

    impl Ord for Legacy

    impl PartialEq<Legacy> for Legacy

    impl PartialOrd<Legacy> for Legacy

    impl ScriptContext for Legacy

    impl StructuralEq for Legacy

    impl StructuralPartialEq for Legacy

    Auto Trait Implementations

    impl RefUnwindSafe for Legacy

    impl Send for Legacy

    impl Sync for Legacy

    impl Unpin for Legacy

    impl UnwindSafe for Legacy

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Segwitv0.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Segwitv0.html deleted file mode 100644 index 5011335983..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Segwitv0.html +++ /dev/null @@ -1,32 +0,0 @@ -bdk::descriptor::Segwitv0 - Rust

    []Enum bdk::descriptor::Segwitv0

    pub enum Segwitv0 {}

    Segwitv0 ScriptContext

    -

    Trait Implementations

    impl Clone for Segwitv0

    impl Debug for Segwitv0

    impl Eq for Segwitv0

    impl Ord for Segwitv0

    impl PartialEq<Segwitv0> for Segwitv0

    impl PartialOrd<Segwitv0> for Segwitv0

    impl ScriptContext for Segwitv0

    impl StructuralEq for Segwitv0

    impl StructuralPartialEq for Segwitv0

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Terminal.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Terminal.html deleted file mode 100644 index 123dafd5f4..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/enum.Terminal.html +++ /dev/null @@ -1,128 +0,0 @@ -bdk::descriptor::Terminal - Rust

    []Enum bdk::descriptor::Terminal

    pub enum Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
    { - True, - False, - PkK(Pk), - PkH(<Pk as MiniscriptKey>::Hash), - After(u32), - Older(u32), - Sha256(Hash), - Hash256(Hash), - Ripemd160(Hash), - Hash160(Hash), - Alt(Arc<Miniscript<Pk, Ctx>>), - Swap(Arc<Miniscript<Pk, Ctx>>), - Check(Arc<Miniscript<Pk, Ctx>>), - DupIf(Arc<Miniscript<Pk, Ctx>>), - Verify(Arc<Miniscript<Pk, Ctx>>), - NonZero(Arc<Miniscript<Pk, Ctx>>), - ZeroNotEqual(Arc<Miniscript<Pk, Ctx>>), - AndV(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - AndB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - AndOr(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - OrB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - OrD(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - OrC(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - OrI(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - Thresh(usizeVec<Arc<Miniscript<Pk, Ctx>>>), - Multi(usizeVec<Pk>), -}

    All AST elements

    -

    - Variants

    -
    True

    1

    -
    False

    0

    -
    PkK(Pk)

    <key>

    -
    PkH(<Pk as MiniscriptKey>::Hash)

    DUP HASH160 <keyhash> EQUALVERIFY

    -
    After(u32)

    n CHECKLOCKTIMEVERIFY

    -
    Older(u32)

    n CHECKSEQUENCEVERIFY

    -
    Sha256(Hash)

    SIZE 32 EQUALVERIFY SHA256 <hash> EQUAL

    -
    Hash256(Hash)

    SIZE 32 EQUALVERIFY HASH256 <hash> EQUAL

    -
    Ripemd160(Hash)

    SIZE 32 EQUALVERIFY RIPEMD160 <hash> EQUAL

    -
    Hash160(Hash)

    SIZE 32 EQUALVERIFY HASH160 <hash> EQUAL

    -
    Alt(Arc<Miniscript<Pk, Ctx>>)

    TOALTSTACK [E] FROMALTSTACK

    -
    Swap(Arc<Miniscript<Pk, Ctx>>)

    SWAP [E1]

    -
    Check(Arc<Miniscript<Pk, Ctx>>)

    [Kt]/[Ke] CHECKSIG

    -
    DupIf(Arc<Miniscript<Pk, Ctx>>)

    DUP IF [V] ENDIF

    -
    Verify(Arc<Miniscript<Pk, Ctx>>)

    [T] VERIFY

    -
    NonZero(Arc<Miniscript<Pk, Ctx>>)

    SIZE 0NOTEQUAL IF Fn ENDIF

    -
    ZeroNotEqual(Arc<Miniscript<Pk, Ctx>>)

    [X] 0NOTEQUAL

    -
    AndV(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

    [V] [T]/[V]/[F]/[Kt]

    -
    AndB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

    [E] [W] BOOLAND

    -
    AndOr(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

    [various] NOTIF [various] ELSE [various] ENDIF

    -
    OrB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

    [E] [W] BOOLOR

    -
    OrD(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

    [E] IFDUP NOTIF [T]/[E] ENDIF

    -
    OrC(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

    [E] NOTIF [V] ENDIF

    -
    OrI(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

    IF [various] ELSE [various] ENDIF

    -
    Thresh(usizeVec<Arc<Miniscript<Pk, Ctx>>>)

    [E] ([W] ADD)* k EQUAL

    -
    Multi(usizeVec<Pk>)

    k ()* n CHECKMULTISIG

    -

    Implementations

    impl<Pk, Ctx> Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn translate_pk<FPk, FPkh, Q, Error>(
        &self,
        translatefpk: &mut FPk,
        translatefpkh: &mut FPkh
    ) -> Result<Terminal<Q, Ctx>, Error> where
        FPk: FnMut(&Pk) -> Result<Q, Error>,
        FPkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, Error>,
        Q: MiniscriptKey

    Convert an AST element with one public key type to one of another -public key type .This will panic while converting to -Segwit Miniscript using uncompressed public keys

    -

    impl<Pk, Ctx> Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey + ToPublicKey

    pub fn encode(&self, builder: Builder) -> Builder

    Encode the element as a fragment of Bitcoin Script. The inverse -function, from Script to an AST element, is implemented in the -parse module.

    -

    pub fn script_size(&self) -> usize

    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.

    -

    pub fn max_dissatisfaction_witness_elements(&self) -> Option<usize>

    Maximum number of witness elements used to dissatisfy the Miniscript -fragment. Used to estimate the weight of the VarInt that specifies -this number in a serialized transaction.

    -

    Will panic if the fragment is not an E, W or Ke.

    -

    pub fn max_dissatisfaction_size(&self, one_cost: usize) -> Option<usize>

    Maximum dissatisfaction cost, in bytes, of a Miniscript fragment, -if it is possible to compute this. This function should probably -not ever be used directly. It is called from max_satisfaction_size.

    -

    Will panic if the fragment is not E, W or Ke

    -

    pub fn max_satisfaction_witness_elements(&self) -> usize

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

    -

    This number does not include the witness script itself, so 1 needs -to be added to the final result.

    -

    pub fn max_satisfaction_size(&self, one_cost: usize) -> usize

    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.

    -

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

    -

    Trait Implementations

    impl<Pk, Ctx> Clone for Terminal<Pk, Ctx> where
        Ctx: ScriptContext + Clone,
        Pk: MiniscriptKey + Clone,
        <Pk as MiniscriptKey>::Hash: Clone

    impl<Pk, Ctx> Debug for Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> Display for Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> Eq for Terminal<Pk, Ctx> where
        Ctx: ScriptContext + Eq,
        Pk: MiniscriptKey + Eq,
        <Pk as MiniscriptKey>::Hash: Eq

    impl<Pk, Ctx> FromTree for Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey,
        <Pk as FromStr>::Err: ToString,
        <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

    impl<Pk, Ctx> Hash for Terminal<Pk, Ctx> where
        Ctx: ScriptContext + Hash,
        Pk: MiniscriptKey + Hash,
        <Pk as MiniscriptKey>::Hash: Hash

    impl<Pk, Ctx> Liftable<Pk> for Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> Ord for Terminal<Pk, Ctx> where
        Ctx: ScriptContext + Ord,
        Pk: MiniscriptKey + Ord,
        <Pk as MiniscriptKey>::Hash: Ord

    impl<Pk, Ctx> PartialEq<Terminal<Pk, Ctx>> for Terminal<Pk, Ctx> where
        Ctx: ScriptContext + PartialEq<Ctx>,
        Pk: MiniscriptKey + PartialEq<Pk>,
        <Pk as MiniscriptKey>::Hash: PartialEq<<Pk as MiniscriptKey>::Hash>, 

    impl<Pk, Ctx> PartialOrd<Terminal<Pk, Ctx>> for Terminal<Pk, Ctx> where
        Ctx: ScriptContext + PartialOrd<Ctx>,
        Pk: MiniscriptKey + PartialOrd<Pk>,
        <Pk as MiniscriptKey>::Hash: PartialOrd<<Pk as MiniscriptKey>::Hash>, 

    impl<Pk, Ctx> StructuralEq for Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> StructuralPartialEq for Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    Auto Trait Implementations

    impl<Pk, Ctx> RefUnwindSafe for Terminal<Pk, Ctx> where
        Ctx: RefUnwindSafe,
        Pk: RefUnwindSafe,
        <Pk as MiniscriptKey>::Hash: RefUnwindSafe

    impl<Pk, Ctx> Send for Terminal<Pk, Ctx> where
        Ctx: Send + Sync,
        Pk: Send + Sync,
        <Pk as MiniscriptKey>::Hash: Send + Sync

    impl<Pk, Ctx> Sync for Terminal<Pk, Ctx> where
        Ctx: Send + Sync,
        Pk: Send + Sync,
        <Pk as MiniscriptKey>::Hash: Send + Sync

    impl<Pk, Ctx> Unpin for Terminal<Pk, Ctx> where
        Pk: Unpin,
        <Pk as MiniscriptKey>::Hash: Unpin

    impl<Pk, Ctx> UnwindSafe for Terminal<Pk, Ctx> where
        Ctx: RefUnwindSafe,
        Pk: RefUnwindSafe + UnwindSafe,
        <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/enum.Error.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/enum.Error.html deleted file mode 100644 index 51b1b133bc..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/enum.Error.html +++ /dev/null @@ -1,45 +0,0 @@ -bdk::descriptor::error::Error - Rust

    [][src]Enum bdk::descriptor::error::Error

    pub enum Error {
    -    InternalError,
    -    InvalidPrefix(Vec<u8>),
    -    HardenedDerivationOnXpub,
    -    MalformedInput,
    -    KeyParsingError(String),
    -    Policy(PolicyError),
    -    InputIndexDoesntExist,
    -    MissingPublicKey,
    -    MissingDetails,
    -    InvalidDescriptorCharacter(char),
    -    CantDeriveWithMiniscript,
    -    BIP32(Error),
    -    Base58(Error),
    -    PK(Error),
    -    Miniscript(Error),
    -    Hex(Error),
    -}

    Errors related to the parsing and usage of descriptors

    -

    - Variants

    -
    InternalError
    InvalidPrefix(Vec<u8>)
    HardenedDerivationOnXpub
    MalformedInput
    KeyParsingError(String)
    Policy(PolicyError)
    InputIndexDoesntExist
    MissingPublicKey
    MissingDetails
    InvalidDescriptorCharacter(char)
    CantDeriveWithMiniscript
    BIP32(Error)
    Base58(Error)
    PK(Error)
    Miniscript(Error)
    Hex(Error)

    Trait Implementations

    impl Debug for Error[src]

    impl Display for Error[src]

    impl Error for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<PolicyError> for Error[src]

    Auto Trait Implementations

    impl RefUnwindSafe for Error

    impl Send for Error

    impl Sync for Error

    impl Unpin for Error

    impl UnwindSafe for Error

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/index.html deleted file mode 100644 index 3c3a9a8451..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/index.html +++ /dev/null @@ -1,4 +0,0 @@ -bdk::descriptor::error - Rust

    [][src]Module bdk::descriptor::error

    Descriptor errors

    -

    Enums

    -
    Error

    Errors related to the parsing and usage of descriptors

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/sidebar-items.js deleted file mode 100644 index 1ad99d4faf..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/error/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Error","Errors related to the parsing and usage of descriptors"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/index.html deleted file mode 100644 index a4c4f2ecfd..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/index.html +++ /dev/null @@ -1,24 +0,0 @@ -bdk::descriptor - Rust

    [][src]Module bdk::descriptor

    Descriptors

    -

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

    -

    Re-exports

    -
    pub use self::checksum::get_checksum;
    pub use self::policy::Policy;

    Modules

    -
    checksum

    Descriptor checksum

    -
    error

    Descriptor errors

    -
    policy

    Descriptor policy

    -

    Structs

    -
    Miniscript

    Top-level script AST type

    -

    Enums

    -
    Descriptor

    Script descriptor

    -
    Legacy

    Legacy ScriptContext

    -
    Segwitv0

    Segwitv0 ScriptContext

    -
    Terminal

    All AST elements

    -

    Traits

    -
    ExtractPolicy

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

    -
    MiniscriptKey

    Public key trait which can be converted to Hash type

    -
    ScriptContext
    ToPublicKey

    Trait describing public key types which can be converted to bitcoin pubkeys

    -

    Type Definitions

    -
    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

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.PolicyError.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.PolicyError.html deleted file mode 100644 index 6f889566f7..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.PolicyError.html +++ /dev/null @@ -1,31 +0,0 @@ -bdk::descriptor::policy::PolicyError - Rust

    [][src]Enum bdk::descriptor::policy::PolicyError

    pub enum PolicyError {
    -    NotEnoughItemsSelected(String),
    -    TooManyItemsSelected(String),
    -    IndexOutOfRange(usize),
    -    AddOnLeaf,
    -    AddOnPartialComplete,
    -    MixedTimelockUnits,
    -    IncompatibleConditions,
    -}

    Errors that can happen while extracting and manipulating policies

    -

    - Variants

    -
    NotEnoughItemsSelected(String)
    TooManyItemsSelected(String)
    IndexOutOfRange(usize)
    AddOnLeaf
    AddOnPartialComplete
    MixedTimelockUnits
    IncompatibleConditions

    Trait Implementations

    impl Debug for PolicyError[src]

    impl Display for PolicyError[src]

    impl Error for PolicyError[src]

    impl From<PolicyError> for Error[src]

    impl From<PolicyError> for Error[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.Satisfaction.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.Satisfaction.html deleted file mode 100644 index 6ebd3a49a7..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.Satisfaction.html +++ /dev/null @@ -1,52 +0,0 @@ -bdk::descriptor::policy::Satisfaction - Rust

    [][src]Enum bdk::descriptor::policy::Satisfaction

    pub enum Satisfaction {
    -    Partial {
    -        n: usize,
    -        m: usize,
    -        items: Vec<usize>,
    -        conditions: ConditionMap,
    -    },
    -    PartialComplete {
    -        n: usize,
    -        m: usize,
    -        items: Vec<usize>,
    -        conditions: FoldedConditionMap,
    -    },
    -    Complete {
    -        condition: Condition,
    -    },
    -    None,
    -}

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

    -

    - Variants

    -
    Partial

    Only a partial satisfaction of some kind of threshold policy

    -

    Fields of Partial

    n: usize

    Total number of items

    -
    m: usize

    Threshold

    -
    items: Vec<usize>

    The items that can be satisfied by the descriptor

    -
    conditions: ConditionMap

    Extra conditions that also need to be satisfied

    -
    PartialComplete

    Can reach the threshold of some kind of threshold policy

    -

    Fields of PartialComplete

    n: usize

    Total number of items

    -
    m: usize

    Threshold

    -
    items: Vec<usize>

    The items that can be satisfied by the descriptor

    -
    conditions: FoldedConditionMap

    Extra conditions that also need to be satisfied

    -
    Complete

    Can satisfy the policy item

    -

    Fields of Complete

    condition: Condition

    Extra conditions that also need to be satisfied

    -
    None

    Cannot satisfy or contribute to the policy item

    -

    Implementations

    impl Satisfaction[src]

    pub fn is_leaf(&self) -> bool[src]

    Trait Implementations

    impl Clone for Satisfaction[src]

    impl Debug for Satisfaction[src]

    impl From<bool> for Satisfaction[src]

    impl Serialize for Satisfaction[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.SatisfiableItem.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.SatisfiableItem.html deleted file mode 100644 index a701a25eb3..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/enum.SatisfiableItem.html +++ /dev/null @@ -1,51 +0,0 @@ -bdk::descriptor::policy::SatisfiableItem - Rust

    [][src]Enum bdk::descriptor::policy::SatisfiableItem

    pub enum SatisfiableItem {
    -    Signature(PKOrF),
    -    SignatureKey(PKOrF),
    -    SHA256Preimage {
    -        hash: Hash,
    -    },
    -    HASH256Preimage {
    -        hash: Hash,
    -    },
    -    RIPEMD160Preimage {
    -        hash: Hash,
    -    },
    -    HASH160Preimage {
    -        hash: Hash,
    -    },
    -    AbsoluteTimelock {
    -        value: u32,
    -    },
    -    RelativeTimelock {
    -        value: u32,
    -    },
    -    Thresh {
    -        items: Vec<Policy>,
    -        threshold: usize,
    -    },
    -    Multisig {
    -        keys: Vec<PKOrF>,
    -        threshold: usize,
    -    },
    -}

    An item that need to be satisfied

    -

    - Variants

    -
    Signature(PKOrF)
    SignatureKey(PKOrF)
    SHA256Preimage

    Fields of SHA256Preimage

    hash: Hash
    HASH256Preimage

    Fields of HASH256Preimage

    hash: Hash
    RIPEMD160Preimage

    Fields of RIPEMD160Preimage

    hash: Hash
    HASH160Preimage

    Fields of HASH160Preimage

    hash: Hash
    AbsoluteTimelock

    Fields of AbsoluteTimelock

    value: u32
    RelativeTimelock

    Fields of RelativeTimelock

    value: u32
    Thresh

    Fields of Thresh

    items: Vec<Policy>threshold: usize
    Multisig

    Fields of Multisig

    keys: Vec<PKOrF>threshold: usize

    Implementations

    impl SatisfiableItem[src]

    pub fn is_leaf(&self) -> bool[src]

    pub fn id(&self) -> String[src]

    Trait Implementations

    impl Clone for SatisfiableItem[src]

    impl Debug for SatisfiableItem[src]

    impl From<SatisfiableItem> for Policy[src]

    impl Serialize for SatisfiableItem[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/index.html deleted file mode 100644 index f494586dc6..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/index.html +++ /dev/null @@ -1,23 +0,0 @@ -bdk::descriptor::policy - Rust

    [][src]Module bdk::descriptor::policy

    Descriptor policy

    -

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

    -

    Example

    -
    -let desc = "wsh(and_v(v:pk(cV3oCth6zxZ1UVsHLnGothsWNsaoxRhC6aeNi5VbSdFpwUkgkEci),or_d(pk(cVMTy7uebJgvFaSBwcgvwk8qn8xSLc97dKow4MBetjrrahZoimm2),older(12960))))";
    -
    -let (extended_desc, key_map) = ExtendedDescriptor::parse_secret(desc)?;
    -println!("{:?}", extended_desc);
    -
    -let signers = Arc::new(key_map.into());
    -let policy = extended_desc.extract_policy(signers)?;
    -println!("policy: {}", serde_json::to_string(&policy)?);
    -

    Structs

    -
    Condition

    An extra condition that must be satisfied but that is out of control of the user

    -
    PKOrF

    Raw public key or extended key fingerprint

    -
    Policy

    Descriptor spending policy

    -

    Enums

    -
    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 need to be satisfied

    -

    Type Definitions

    -
    ConditionMap
    FoldedConditionMap
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/sidebar-items.js deleted file mode 100644 index 6928dca21e..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["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 need to be satisfied"]],"struct":[["Condition","An extra condition that must be satisfied but that is out of control of the user"],["PKOrF","Raw public key or extended key fingerprint"],["Policy","Descriptor spending policy"]],"type":[["ConditionMap",""],["FoldedConditionMap",""]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Condition.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Condition.html deleted file mode 100644 index 9d37306985..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Condition.html +++ /dev/null @@ -1,38 +0,0 @@ -bdk::descriptor::policy::Condition - Rust

    [][src]Struct bdk::descriptor::policy::Condition

    pub struct Condition {
    -    pub csv: Option<u32>,
    -    pub timelock: Option<u32>,
    -}

    An extra condition that must be satisfied but that is out of control of the user

    -

    - Fields

    csv: Option<u32>timelock: Option<u32>

    Implementations

    impl Condition[src]

    pub fn is_null(&self) -> bool[src]

    Trait Implementations

    impl Clone for Condition[src]

    impl Copy for Condition[src]

    impl Debug for Condition[src]

    impl Default for Condition[src]

    impl Eq for Condition[src]

    impl Hash for Condition[src]

    impl Ord for Condition[src]

    impl PartialEq<Condition> for Condition[src]

    impl PartialOrd<Condition> for Condition[src]

    impl Serialize for Condition[src]

    impl StructuralEq for Condition[src]

    impl StructuralPartialEq for Condition[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.PKOrF.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.PKOrF.html deleted file mode 100644 index 49e3b43d94..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.PKOrF.html +++ /dev/null @@ -1,20 +0,0 @@ -bdk::descriptor::policy::PKOrF - Rust

    [][src]Struct bdk::descriptor::policy::PKOrF

    pub struct PKOrF { /* fields omitted */ }

    Raw public key or extended key fingerprint

    -

    Trait Implementations

    impl Clone for PKOrF[src]

    impl Debug for PKOrF[src]

    impl Default for PKOrF[src]

    impl Serialize for PKOrF[src]

    Auto Trait Implementations

    impl RefUnwindSafe for PKOrF

    impl Send for PKOrF

    impl Sync for PKOrF

    impl Unpin for PKOrF

    impl UnwindSafe for PKOrF

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Policy.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Policy.html deleted file mode 100644 index b50b8d43da..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/struct.Policy.html +++ /dev/null @@ -1,37 +0,0 @@ -bdk::descriptor::policy::Policy - Rust

    [][src]Struct bdk::descriptor::policy::Policy

    pub struct Policy {
    -    pub id: String,
    -    pub item: SatisfiableItem,
    -    pub satisfaction: Satisfaction,
    -    pub contribution: Satisfaction,
    -}

    Descriptor spending policy

    -

    - Fields

    id: String

    Identifier for this policy node

    -
    item: SatisfiableItem

    Type of this policy node

    -
    satisfaction: Satisfaction

    How a much given PSBT already satisfies this polcy node (currently unused)

    -
    contribution: Satisfaction

    How the wallet's descriptor can satisfy this policy node

    -

    Implementations

    impl Policy[src]

    pub fn requires_path(&self) -> bool[src]

    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 get_condition(
        &self,
        path: &BTreeMap<String, Vec<usize>>
    ) -> Result<Condition, PolicyError>
    [src]

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

    -

    Trait Implementations

    impl Clone for Policy[src]

    impl Debug for Policy[src]

    impl From<SatisfiableItem> for Policy[src]

    impl Serialize for Policy[src]

    Auto Trait Implementations

    impl RefUnwindSafe for Policy

    impl Send for Policy

    impl Sync for Policy

    impl Unpin for Policy

    impl UnwindSafe for Policy

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.ConditionMap.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.ConditionMap.html deleted file mode 100644 index 33b5632c7b..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.ConditionMap.html +++ /dev/null @@ -1 +0,0 @@ -bdk::descriptor::policy::ConditionMap - Rust

    [][src]Type Definition bdk::descriptor::policy::ConditionMap

    type ConditionMap = BTreeMap<usize, HashSet<Condition>>;
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.FoldedConditionMap.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.FoldedConditionMap.html deleted file mode 100644 index ac1cee86e6..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/policy/type.FoldedConditionMap.html +++ /dev/null @@ -1 +0,0 @@ -bdk::descriptor::policy::FoldedConditionMap - Rust

    [][src]Type Definition bdk::descriptor::policy::FoldedConditionMap

    type FoldedConditionMap = BTreeMap<Vec<usize>, HashSet<Condition>>;
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/sidebar-items.js deleted file mode 100644 index 8460b2d5c8..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Descriptor","Script descriptor"],["Legacy","Legacy ScriptContext"],["Segwitv0","Segwitv0 ScriptContext"],["Terminal","All AST elements"]],"mod":[["checksum","Descriptor checksum"],["error","Descriptor errors"],["policy","Descriptor policy"]],"struct":[["Miniscript","Top-level script AST type"]],"trait":[["ExtractPolicy","Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]"],["MiniscriptKey","Public key trait which can be converted to Hash type"],["ScriptContext",""],["ToPublicKey","Trait describing public key types which can be converted to bitcoin pubkeys"]],"type":[["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`]"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/struct.Miniscript.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/struct.Miniscript.html deleted file mode 100644 index ad08670aa5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/struct.Miniscript.html +++ /dev/null @@ -1,97 +0,0 @@ -bdk::descriptor::Miniscript - Rust

    []Struct bdk::descriptor::Miniscript

    pub struct Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
    { - pub node: Terminal<Pk, Ctx>, - pub ty: Type, - pub ext: ExtData, - // some fields omitted -}

    Top-level script AST type

    -

    - Fields

    node: Terminal<Pk, Ctx>

    A node in the Abstract Syntax Tree(

    -
    ty: Type

    The correctness and malleability type information for the AST node

    -
    ext: ExtData

    Additional information helpful for extra analysis.

    -

    Implementations

    impl<Pk, Ctx> Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn from_ast(t: Terminal<Pk, Ctx>) -> Result<Miniscript<Pk, Ctx>, Error>

    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.

    -

    impl<Pk, Ctx> Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn into_inner(self) -> Terminal<Pk, Ctx>

    Extracts the AstElem representing the root of the miniscript

    -

    pub fn as_inner(&self) -> &Terminal<Pk, Ctx>

    impl<Ctx> Miniscript<PublicKey, Ctx> where
        Ctx: ScriptContext

    pub fn parse(script: &Script) -> Result<Miniscript<PublicKey, Ctx>, Error>

    Attempt to parse a script into a Miniscript representation

    -

    impl<Pk, Ctx> Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey + ToPublicKey

    pub fn encode(&self) -> Script

    Encode as a Bitcoin script

    -

    pub fn script_size(&self) -> usize

    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.

    -

    pub fn max_satisfaction_witness_elements(&self) -> usize

    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 misformed Miniscript objects which do -not correspond to semantically sane Scripts. (Such scripts should be -rejected at parse time. Any exceptions are bugs.)

    -

    pub fn max_satisfaction_size(&self, one_cost: usize) -> usize

    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.

    -

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

    -

    impl<Pk, Ctx> Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn translate_pk<FPk, FPkh, Q, FuncError>(
        &self,
        translatefpk: &mut FPk,
        translatefpkh: &mut FPkh
    ) -> Result<Miniscript<Q, Ctx>, FuncError> where
        FPk: FnMut(&Pk) -> Result<Q, FuncError>,
        FPkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, FuncError>,
        Q: MiniscriptKey

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

    -

    impl<Pk, Ctx> Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey + ToPublicKey

    pub fn satisfy<S>(&self, satisfier: S) -> Option<Vec<Vec<u8>>> where
        S: Satisfier<Pk>, 

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

    -

    Trait Implementations

    impl<Pk, Ctx> Clone for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext + Clone,
        Pk: MiniscriptKey + Clone

    impl<Pk, Ctx> Debug for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> Display for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> Eq for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

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

    -

    impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx>[src]

    impl<Pk, Ctx> FromStr for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey,
        <Pk as FromStr>::Err: ToString,
        <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

    type Err = Error

    The associated error which can be returned from parsing.

    -

    impl<Pk, Ctx> FromTree for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey,
        <Pk as FromStr>::Err: ToString,
        <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

    fn from_tree(top: &Tree) -> Result<Miniscript<Pk, Ctx>, Error>

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

    -

    impl<Pk, Ctx> Hash for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext + Hash,
        Pk: MiniscriptKey + Hash

    impl<Pk, Ctx> Liftable<Pk> for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> Ord for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

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

    -

    impl<Pk, Ctx> PartialEq<Miniscript<Pk, Ctx>> for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

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

    -

    impl<Pk, Ctx> PartialOrd<Miniscript<Pk, Ctx>> for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

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

    -

    Auto Trait Implementations

    impl<Pk, Ctx> RefUnwindSafe for Miniscript<Pk, Ctx> where
        Ctx: RefUnwindSafe,
        Pk: RefUnwindSafe,
        <Pk as MiniscriptKey>::Hash: RefUnwindSafe

    impl<Pk, Ctx> Send for Miniscript<Pk, Ctx> where
        Ctx: Send + Sync,
        Pk: Send + Sync,
        <Pk as MiniscriptKey>::Hash: Send + Sync

    impl<Pk, Ctx> Sync for Miniscript<Pk, Ctx> where
        Ctx: Send + Sync,
        Pk: Send + Sync,
        <Pk as MiniscriptKey>::Hash: Send + Sync

    impl<Pk, Ctx> Unpin for Miniscript<Pk, Ctx> where
        Ctx: Unpin,
        Pk: Unpin,
        <Pk as MiniscriptKey>::Hash: Unpin

    impl<Pk, Ctx> UnwindSafe for Miniscript<Pk, Ctx> where
        Ctx: RefUnwindSafe + UnwindSafe,
        Pk: RefUnwindSafe + UnwindSafe,
        <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ExtractPolicy.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ExtractPolicy.html deleted file mode 100644 index 522bac569e..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ExtractPolicy.html +++ /dev/null @@ -1,6 +0,0 @@ -bdk::descriptor::ExtractPolicy - Rust

    [][src]Trait bdk::descriptor::ExtractPolicy

    pub trait ExtractPolicy {
    -    fn extract_policy(
            &self,
            signers: Arc<SignersContainer<DescriptorPublicKey>>
        ) -> Result<Option<Policy>, Error>; -}

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

    -
    -

    Required methods

    fn extract_policy(
        &self,
        signers: Arc<SignersContainer<DescriptorPublicKey>>
    ) -> Result<Option<Policy>, Error>

    Loading content... -

    Implementors

    impl ExtractPolicy for Descriptor<DescriptorPublicKey>[src]

    impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx>[src]

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.MiniscriptKey.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.MiniscriptKey.html deleted file mode 100644 index 5fedd105d6..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.MiniscriptKey.html +++ /dev/null @@ -1,18 +0,0 @@ -bdk::descriptor::MiniscriptKey - Rust

    []Trait bdk::descriptor::MiniscriptKey

    pub trait MiniscriptKey: Clone + Eq + Ord + Debug + Display + Hash + FromStr {
    -    type Hash: Clone + Eq + Ord + Debug + Display + Hash + FromStr;
    -    fn to_pubkeyhash(&self) -> Self::Hash;
    -
    -    fn is_uncompressed(&self) -> bool { ... }
    -}

    Public key trait which can be converted to Hash type

    -
    -

    Associated Types

    type Hash: Clone + Eq + Ord + Debug + Display + Hash + FromStr

    The associated Hash type with the publicKey

    -
    Loading content... -

    Required methods

    fn to_pubkeyhash(&self) -> Self::Hash

    Converts an object to PublicHash

    -
    Loading content... -

    Provided methods

    fn is_uncompressed(&self) -> bool

    Check if the publicKey is uncompressed. The default -implementation returns false

    -
    Loading content... -

    Implementations on Foreign Types

    impl MiniscriptKey for PublicKey

    fn is_uncompressed(&self) -> bool

    is_uncompressed returns true only for -bitcoin::Publickey type if the underlying key is uncompressed.

    -

    type Hash = Hash

    impl MiniscriptKey for DummyKey

    type Hash = DummyKeyHash

    impl MiniscriptKey for DescriptorPublicKey

    type Hash = Hash

    impl MiniscriptKey for String

    Loading content... -

    Implementors

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ScriptContext.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ScriptContext.html deleted file mode 100644 index 9c6bcf905b..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ScriptContext.html +++ /dev/null @@ -1,19 +0,0 @@ -bdk::descriptor::ScriptContext - Rust

    []Trait bdk::descriptor::ScriptContext

    pub trait ScriptContext: Sealed + Clone + PartialEq<Self> + Eq + Ord + PartialOrd<Self> + Debug {
    -    fn check_frag_non_malleable<Pk, Ctx>(
            _frag: &Terminal<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    ; -
    fn check_frag_validity<Pk, Ctx>(
            _frag: &Terminal<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    ; -}
    -

    Required methods

    fn check_frag_non_malleable<Pk, Ctx>(
        _frag: &Terminal<Pk, Ctx>
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    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.

    -

    fn check_frag_validity<Pk, Ctx>(
        _frag: &Terminal<Pk, Ctx>
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    Depending on script Context, some of the Terminals might not be valid. -For example, in Segwit Context with MiniscriptKey as bitcoin::PublicKey -uncompressed public keys are non-standard and thus invalid. -Post Tapscript upgrade, this would have to consider other nodes. -This does not recursively check

    -
    Loading content... -

    Implementors

    impl ScriptContext for Legacy

    impl ScriptContext for Segwitv0

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ToPublicKey.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ToPublicKey.html deleted file mode 100644 index a68f8be8e4..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/trait.ToPublicKey.html +++ /dev/null @@ -1,19 +0,0 @@ -bdk::descriptor::ToPublicKey - Rust

    []Trait bdk::descriptor::ToPublicKey

    pub trait ToPublicKey: MiniscriptKey {
    -    fn to_public_key(&self) -> PublicKey;
    -
    fn hash_to_hash160(hash: &Self::Hash) -> Hash; - - fn serialized_len(&self) -> usize { ... } -}

    Trait describing public key types which can be converted to bitcoin pubkeys

    -
    -

    Required methods

    fn to_public_key(&self) -> PublicKey

    Converts an object to a public key

    -

    fn hash_to_hash160(hash: &Self::Hash) -> Hash

    Converts a hashed version of the public key to a hash160 hash.

    -

    This method must be consistent with to_public_key, in the sense -that calling MiniscriptKey::to_pubkeyhash followed by this function -should give the same result as calling to_public_key and hashing -the result directly.

    -
    Loading content... -

    Provided methods

    fn serialized_len(&self) -> usize

    Computes the size of a public key when serialized in a script, -including the length bytes

    -
    Loading content... -

    Implementations on Foreign Types

    impl ToPublicKey for DummyKey

    impl ToPublicKey for DescriptorPublicKey

    impl ToPublicKey for PublicKey

    Loading content... -

    Implementors

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.ExtendedDescriptor.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.ExtendedDescriptor.html deleted file mode 100644 index 6cac36a187..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.ExtendedDescriptor.html +++ /dev/null @@ -1,2 +0,0 @@ -bdk::descriptor::ExtendedDescriptor - Rust

    [][src]Type Definition bdk::descriptor::ExtendedDescriptor

    type ExtendedDescriptor = Descriptor<DescriptorPublicKey>;

    Alias for a Descriptor that can contain extended keys using [DescriptorPublicKey]

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.HDKeyPaths.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.HDKeyPaths.html deleted file mode 100644 index 93e0240143..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/descriptor/type.HDKeyPaths.html +++ /dev/null @@ -1,3 +0,0 @@ -bdk::descriptor::HDKeyPaths - Rust

    [][src]Type Definition bdk::descriptor::HDKeyPaths

    type HDKeyPaths = BTreeMap<PublicKey, (Fingerprint, DerivationPath)>;

    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/static/docs-rs/bdk/0.1.0-beta.1/bdk/enum.Error.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/enum.Error.html deleted file mode 100644 index 7a1673fb2e..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/enum.Error.html +++ /dev/null @@ -1,80 +0,0 @@ -bdk::Error - Rust

    [][src]Enum bdk::Error

    pub enum Error {
    -    KeyMismatch(PublicKey, PublicKey),
    -    MissingInputUTXO(usize),
    -    InvalidU32Bytes(Vec<u8>),
    -    Generic(String),
    -    ScriptDoesntHaveAddressForm,
    -    SendAllMultipleOutputs,
    -    NoAddressees,
    -    OutputBelowDustLimit(usize),
    -    InsufficientFunds,
    -    InvalidAddressNetwork(Address),
    -    UnknownUTXO,
    -    DifferentTransactions,
    -    TransactionNotFound,
    -    TransactionConfirmed,
    -    IrreplaceableTransaction,
    -    FeeRateTooLow {
    -        required: FeeRate,
    -    },
    -    ChecksumMismatch,
    -    DifferentDescriptorStructure,
    -    SpendingPolicyRequired,
    -    InvalidPolicyPathError(PolicyError),
    -    Signer(SignerError),
    -    Uncapable(Capability),
    -    OfflineClient,
    -    InvalidProgressValue(f32),
    -    ProgressUpdateError,
    -    MissingCachedAddresses,
    -    InvalidOutpoint(OutPoint),
    -    Descriptor(Error),
    -    AddressValidator(AddressValidatorError),
    -    Encode(Error),
    -    Miniscript(Error),
    -    BIP32(Error),
    -    Secp256k1(Error),
    -    JSON(Error),
    -    Hex(Error),
    -    PSBT(Error),
    -    Electrum(Error),
    -    Esplora(EsploraError),
    -    CompactFilters(CompactFiltersError),
    -    Sled(Error),
    -}

    Errors that can be thrown by the Wallet

    -

    - Variants

    -
    KeyMismatch(PublicKey, PublicKey)
    MissingInputUTXO(usize)
    InvalidU32Bytes(Vec<u8>)
    Generic(String)
    ScriptDoesntHaveAddressForm
    SendAllMultipleOutputs
    NoAddressees
    OutputBelowDustLimit(usize)
    InsufficientFunds
    InvalidAddressNetwork(Address)
    UnknownUTXO
    DifferentTransactions
    TransactionNotFound
    TransactionConfirmed
    IrreplaceableTransaction
    FeeRateTooLow

    Fields of FeeRateTooLow

    required: FeeRate
    ChecksumMismatch
    DifferentDescriptorStructure
    SpendingPolicyRequired
    InvalidPolicyPathError(PolicyError)
    Signer(SignerError)
    Uncapable(Capability)
    OfflineClient
    InvalidProgressValue(f32)
    ProgressUpdateError
    MissingCachedAddresses
    InvalidOutpoint(OutPoint)
    Descriptor(Error)
    AddressValidator(AddressValidatorError)
    Encode(Error)
    Miniscript(Error)
    BIP32(Error)
    Secp256k1(Error)
    JSON(Error)
    Hex(Error)
    PSBT(Error)
    Electrum(Error)
    Esplora(EsploraError)
    CompactFilters(CompactFiltersError)
    Sled(Error)

    Trait Implementations

    impl Debug for Error[src]

    impl Display for Error[src]

    impl Error for Error[src]

    impl From<AddressValidatorError> for Error[src]

    impl From<CompactFiltersError> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for CompactFiltersError[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<EsploraError> for Error[src]

    impl From<PolicyError> for Error[src]

    impl From<SignerError> for Error[src]

    Auto Trait Implementations

    impl !RefUnwindSafe for Error

    impl Send for Error

    impl Sync for Error

    impl Unpin for Error

    impl !UnwindSafe for Error

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/enum.ScriptType.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/enum.ScriptType.html deleted file mode 100644 index d9a631eb91..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/enum.ScriptType.html +++ /dev/null @@ -1,36 +0,0 @@ -bdk::ScriptType - Rust

    [][src]Enum bdk::ScriptType

    pub enum ScriptType {
    -    External,
    -    Internal,
    -}

    Types of script

    -

    - Variants

    -
    External
    Internal

    Implementations

    impl ScriptType[src]

    pub fn as_byte(&self) -> u8[src]

    pub fn is_internal(&self) -> bool[src]

    Trait Implementations

    impl AsRef<[u8]> for ScriptType[src]

    impl Clone for ScriptType[src]

    impl Copy for ScriptType[src]

    impl Debug for ScriptType[src]

    impl<'de> Deserialize<'de> for ScriptType[src]

    impl Eq for ScriptType[src]

    impl Hash for ScriptType[src]

    impl PartialEq<ScriptType> for ScriptType[src]

    impl Serialize for ScriptType[src]

    impl StructuralEq for ScriptType[src]

    impl StructuralPartialEq for ScriptType[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Base32Len for T where
        T: AsRef<[u8]>, 

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<'f, T> CheckBase32<Vec<u5>> for T where
        T: AsRef<[u8]>, 

    type Err = Error

    Error type if conversion fails

    -

    impl<T> DeserializeOwned for T where
        T: for<'de> Deserialize<'de>, 
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToBase32 for T where
        T: AsRef<[u8]>, 

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/error/enum.Error.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/error/enum.Error.html deleted file mode 100644 index 113a951037..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/error/enum.Error.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

    Redirecting to ../../bdk/enum.Error.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/index.html deleted file mode 100644 index 99f31df86c..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/index.html +++ /dev/null @@ -1,14 +0,0 @@ -bdk - Rust

    [][src]Crate bdk

    Re-exports

    -
    pub extern crate bitcoin;
    pub extern crate miniscript;
    pub extern crate electrum_client;
    pub extern crate reqwest;
    pub extern crate sled;
    pub use descriptor::HDKeyPaths;
    pub use wallet::address_validator;
    pub use wallet::signer;
    pub use wallet::tx_builder::TxBuilder;
    pub use wallet::OfflineWallet;
    pub use wallet::Wallet;

    Modules

    -
    blockchain

    Blockchain backends

    -
    database

    Database types

    -
    descriptor

    Descriptors

    -
    wallet

    Wallet

    -

    Structs

    -
    FeeRate

    Fee rate

    -
    TransactionDetails

    A wallet transaction

    -
    UTXO

    A wallet unspent output

    -

    Enums

    -
    Error

    Errors that can be thrown by the Wallet

    -
    ScriptType

    Types of script

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/sidebar-items.js deleted file mode 100644 index 9e94a707e4..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Error","Errors that can be thrown by the `Wallet`"],["ScriptType","Types of script"]],"mod":[["blockchain","Blockchain backends"],["database","Database types"],["descriptor","Descriptors"],["wallet","Wallet"]],"struct":[["FeeRate","Fee rate"],["TransactionDetails","A wallet transaction"],["UTXO","A wallet unspent output"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.FeeRate.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.FeeRate.html deleted file mode 100644 index b7a709594a..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.FeeRate.html +++ /dev/null @@ -1,30 +0,0 @@ -bdk::FeeRate - Rust

    [][src]Struct bdk::FeeRate

    pub struct FeeRate(_);

    Fee rate

    -

    Implementations

    impl FeeRate[src]

    pub fn from_btc_per_kvb(btc_per_kvb: f32) -> Self[src]

    Create a new instance of FeeRate given a float fee rate in btc/kvbytes

    -

    pub fn from_sat_per_vb(sat_per_vb: f32) -> Self[src]

    Create a new instance of FeeRate given a float fee rate in satoshi/vbyte

    -

    pub fn default_min_relay_fee() -> Self[src]

    Create a new FeeRate with the default min relay fee value

    -

    pub fn as_sat_vb(&self) -> f32[src]

    Return the value as satoshi/vbyte

    -

    Trait Implementations

    impl Clone for FeeRate[src]

    impl Copy for FeeRate[src]

    impl Debug for FeeRate[src]

    impl Default for FeeRate[src]

    impl PartialEq<FeeRate> for FeeRate[src]

    impl PartialOrd<FeeRate> for FeeRate[src]

    impl StructuralPartialEq for FeeRate[src]

    Auto Trait Implementations

    impl RefUnwindSafe for FeeRate

    impl Send for FeeRate

    impl Sync for FeeRate

    impl Unpin for FeeRate

    impl UnwindSafe for FeeRate

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.TransactionDetails.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.TransactionDetails.html deleted file mode 100644 index 1aa1b86e06..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.TransactionDetails.html +++ /dev/null @@ -1,33 +0,0 @@ -bdk::TransactionDetails - Rust

    [][src]Struct bdk::TransactionDetails

    pub struct TransactionDetails {
    -    pub transaction: Option<Transaction>,
    -    pub txid: Txid,
    -    pub timestamp: u64,
    -    pub received: u64,
    -    pub sent: u64,
    -    pub fees: u64,
    -    pub height: Option<u32>,
    -}

    A wallet transaction

    -

    - Fields

    transaction: Option<Transaction>txid: Txidtimestamp: u64received: u64sent: u64fees: u64height: Option<u32>

    Trait Implementations

    impl Clone for TransactionDetails[src]

    impl Debug for TransactionDetails[src]

    impl Default for TransactionDetails[src]

    impl<'de> Deserialize<'de> for TransactionDetails[src]

    impl Eq for TransactionDetails[src]

    impl PartialEq<TransactionDetails> for TransactionDetails[src]

    impl Serialize for TransactionDetails[src]

    impl StructuralEq for TransactionDetails[src]

    impl StructuralPartialEq for TransactionDetails[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> DeserializeOwned for T where
        T: for<'de> Deserialize<'de>, 
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.UTXO.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.UTXO.html deleted file mode 100644 index 3032d4e7b5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/struct.UTXO.html +++ /dev/null @@ -1,28 +0,0 @@ -bdk::UTXO - Rust

    [][src]Struct bdk::UTXO

    pub struct UTXO {
    -    pub outpoint: OutPoint,
    -    pub txout: TxOut,
    -    pub is_internal: bool,
    -}

    A wallet unspent output

    -

    - Fields

    outpoint: OutPointtxout: TxOutis_internal: bool

    Trait Implementations

    impl Clone for UTXO[src]

    impl Debug for UTXO[src]

    impl<'de> Deserialize<'de> for UTXO[src]

    impl Eq for UTXO[src]

    impl PartialEq<UTXO> for UTXO[src]

    impl Serialize for UTXO[src]

    impl StructuralEq for UTXO[src]

    impl StructuralPartialEq for UTXO[src]

    Auto Trait Implementations

    impl RefUnwindSafe for UTXO

    impl Send for UTXO

    impl Sync for UTXO

    impl Unpin for UTXO

    impl UnwindSafe for UTXO

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> DeserializeOwned for T where
        T: for<'de> Deserialize<'de>, 
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/enum.ScriptType.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/enum.ScriptType.html deleted file mode 100644 index b10e9a3fe6..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/enum.ScriptType.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

    Redirecting to ../../bdk/enum.ScriptType.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.FeeRate.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.FeeRate.html deleted file mode 100644 index c8b0ec4f98..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.FeeRate.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

    Redirecting to ../../bdk/struct.FeeRate.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.TransactionDetails.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.TransactionDetails.html deleted file mode 100644 index 5db5e06868..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.TransactionDetails.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

    Redirecting to ../../bdk/struct.TransactionDetails.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.UTXO.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.UTXO.html deleted file mode 100644 index 1517bb40f5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/types/struct.UTXO.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

    Redirecting to ../../bdk/struct.UTXO.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/enum.AddressValidatorError.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/enum.AddressValidatorError.html deleted file mode 100644 index bed4a97a0e..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/enum.AddressValidatorError.html +++ /dev/null @@ -1,37 +0,0 @@ -bdk::wallet::address_validator::AddressValidatorError - Rust

    [][src]Enum bdk::wallet::address_validator::AddressValidatorError

    pub enum AddressValidatorError {
    -    UserRejected,
    -    ConnectionError,
    -    TimeoutError,
    -    InvalidScript,
    -    Message(String),
    -}

    Errors that can be returned to fail the validation of an address

    -

    - Variants

    -
    UserRejected
    ConnectionError
    TimeoutError
    InvalidScript
    Message(String)

    Trait Implementations

    impl Clone for AddressValidatorError[src]

    impl Debug for AddressValidatorError[src]

    impl Display for AddressValidatorError[src]

    impl Eq for AddressValidatorError[src]

    impl Error for AddressValidatorError[src]

    impl From<AddressValidatorError> for Error[src]

    impl PartialEq<AddressValidatorError> for AddressValidatorError[src]

    impl StructuralEq for AddressValidatorError[src]

    impl StructuralPartialEq for AddressValidatorError[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/index.html deleted file mode 100644 index 30b19c6bc3..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/index.html +++ /dev/null @@ -1,44 +0,0 @@ -bdk::wallet::address_validator - Rust

    [][src]Module bdk::wallet::address_validator

    Address validation callbacks

    -

    The typical usage of those callbacks is for displaying the newly-generated address on a -hardware wallet, so that the user can cross-check its correctness.

    -

    More generally speaking though, these callbacks can also be used to "do something" every time -an address is generated, without necessarily checking or validating it.

    -

    An address validator can be attached to a Wallet by using the -Wallet::add_address_validator method, and -whenever a new address is generated (either explicitly by the user with -Wallet::get_new_address or internally to create a change -address) all the attached validators will be polled, in sequence. All of them must complete -successfully to continue.

    -

    Example

    -
    -struct PrintAddressAndContinue;
    -
    -impl AddressValidator for PrintAddressAndContinue {
    -    fn validate(
    -        &self,
    -        script_type: ScriptType,
    -        hd_keypaths: &HDKeyPaths,
    -        script: &Script
    -    ) -> Result<(), AddressValidatorError> {
    -        let address = Address::from_script(script, Network::Testnet)
    -            .as_ref()
    -            .map(Address::to_string)
    -            .unwrap_or(script.to_string());
    -        println!("New address of type {:?}: {}", script_type, address);
    -        println!("HD keypaths: {:#?}", hd_keypaths);
    -
    -        Ok(())
    -    }
    -}
    -
    -let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -wallet.add_address_validator(Arc::new(Box::new(PrintAddressAndContinue)));
    -
    -let address = wallet.get_new_address()?;
    -println!("Address: {}", address);
    -

    Enums

    -
    AddressValidatorError

    Errors that can be returned to fail the validation of an address

    -

    Traits

    -
    AddressValidator

    Trait to build address validators

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/sidebar-items.js deleted file mode 100644 index 58959ba340..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["AddressValidatorError","Errors that can be returned to fail the validation of an address"]],"trait":[["AddressValidator","Trait to build address validators"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/trait.AddressValidator.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/trait.AddressValidator.html deleted file mode 100644 index 8c46006675..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/address_validator/trait.AddressValidator.html +++ /dev/null @@ -1,11 +0,0 @@ -bdk::wallet::address_validator::AddressValidator - Rust

    [][src]Trait bdk::wallet::address_validator::AddressValidator

    pub trait AddressValidator {
    -    fn validate(
            &self,
            script_type: ScriptType,
            hd_keypaths: &HDKeyPaths,
            script: &Script
        ) -> Result<(), AddressValidatorError>; -}

    Trait to build address validators

    -

    All the address validators attached to a wallet with Wallet::add_address_validator will be polled -every time an address (external or internal) is generated by the wallet. Errors returned in the -validator will be propagated up to the original caller that triggered the address generation.

    -

    For a usage example see this module's documentation.

    -
    -

    Required methods

    fn validate(
        &self,
        script_type: ScriptType,
        hd_keypaths: &HDKeyPaths,
        script: &Script
    ) -> Result<(), AddressValidatorError>

    Validate or inspect an address

    -
    Loading content... -

    Implementors

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/index.html deleted file mode 100644 index 3f56b8d644..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/index.html +++ /dev/null @@ -1,73 +0,0 @@ -bdk::wallet::coin_selection - Rust

    [][src]Module bdk::wallet::coin_selection

    Coin selection

    -

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

    -

    The coin selection algorithm is not globally part of a Wallet, instead it -is selected whenever a Wallet::create_tx call is made, through -the use of the TxBuilder structure, specifically with -TxBuilder::coin_selection method.

    -

    The DefaultCoinSelectionAlgorithm selects the default coin selection algorithm that -TxBuilder uses, if it's not explicitly overridden.

    -

    Example

    -
    -#[derive(Debug)]
    -struct AlwaysSpendEverything;
    -
    -impl CoinSelectionAlgorithm for AlwaysSpendEverything {
    -    fn coin_select(
    -        &self,
    -        utxos: Vec<UTXO>,
    -        _use_all_utxos: bool,
    -        fee_rate: FeeRate,
    -        amount_needed: u64,
    -        input_witness_weight: usize,
    -        fee_amount: f32,
    -    ) -> Result<CoinSelectionResult, bdk::Error> {
    -        let selected_amount = utxos.iter().fold(0, |acc, utxo| acc + utxo.txout.value);
    -        let all_utxos_selected = utxos
    -            .into_iter()
    -            .map(|utxo| {
    -                (
    -                    TxIn {
    -                        previous_output: utxo.outpoint,
    -                        ..Default::default()
    -                    },
    -                    utxo.txout.script_pubkey,
    -                )
    -            })
    -            .collect::<Vec<_>>();
    -        let additional_weight = all_utxos_selected.iter().fold(0, |acc, (txin, _)| {
    -            acc + serialize(txin).len() * 4 + input_witness_weight
    -        });
    -        let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0;
    -
    -        if (fee_amount + additional_fees).ceil() as u64 + amount_needed > selected_amount {
    -            return Err(bdk::Error::InsufficientFunds);
    -        }
    -
    -        Ok(CoinSelectionResult {
    -            txin: all_utxos_selected,
    -            selected_amount,
    -            fee_amount: fee_amount + additional_fees,
    -        })
    -    }
    -}
    -
    -// create wallet, sync, ...
    -
    -let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -let (psbt, details) = wallet.create_tx(
    -    TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
    -        .coin_selection(AlwaysSpendEverything),
    -)?;
    -
    -// inspect, sign, broadcast, ...
    -
    -

    Structs

    -
    CoinSelectionResult

    Result of a successful coin selection

    -
    DumbCoinSelection

    Simple and dumb coin selection

    -

    Traits

    -
    CoinSelectionAlgorithm

    Trait for generalized coin selection algorithms

    -

    Type Definitions

    -
    DefaultCoinSelectionAlgorithm

    Default coin selection algorithm used by TxBuilder if not -overridden

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/sidebar-items.js deleted file mode 100644 index d124fee721..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["CoinSelectionResult","Result of a successful coin selection"],["DumbCoinSelection","Simple and dumb coin selection"]],"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/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.CoinSelectionResult.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.CoinSelectionResult.html deleted file mode 100644 index 45549badf6..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.CoinSelectionResult.html +++ /dev/null @@ -1,20 +0,0 @@ -bdk::wallet::coin_selection::CoinSelectionResult - Rust

    [][src]Struct bdk::wallet::coin_selection::CoinSelectionResult

    pub struct CoinSelectionResult {
    -    pub txin: Vec<(TxIn, Script)>,
    -    pub selected_amount: u64,
    -    pub fee_amount: f32,
    -}

    Result of a successful coin selection

    -

    - Fields

    txin: Vec<(TxIn, Script)>

    List of inputs to use, with the respective previous script_pubkey

    -
    selected_amount: u64

    Sum of the selected inputs' value

    -
    fee_amount: f32

    Total fee amount in satoshi

    -

    Trait Implementations

    impl Debug for CoinSelectionResult[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.DumbCoinSelection.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.DumbCoinSelection.html deleted file mode 100644 index a49bbca57f..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/struct.DumbCoinSelection.html +++ /dev/null @@ -1,16 +0,0 @@ -bdk::wallet::coin_selection::DumbCoinSelection - Rust

    [][src]Struct bdk::wallet::coin_selection::DumbCoinSelection

    pub struct DumbCoinSelection;

    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

    impl CoinSelectionAlgorithm for DumbCoinSelection[src]

    impl Debug for DumbCoinSelection[src]

    impl Default for DumbCoinSelection[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html deleted file mode 100644 index 704db49dbf..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html +++ /dev/null @@ -1,18 +0,0 @@ -bdk::wallet::coin_selection::CoinSelectionAlgorithm - Rust

    [][src]Trait bdk::wallet::coin_selection::CoinSelectionAlgorithm

    pub trait CoinSelectionAlgorithm: Debug {
    -    fn coin_select(
            &self,
            utxos: Vec<UTXO>,
            use_all_utxos: bool,
            fee_rate: FeeRate,
            amount_needed: u64,
            input_witness_weight: usize,
            fee_amount: f32
        ) -> Result<CoinSelectionResult, Error>; -}

    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

    fn coin_select(
        &self,
        utxos: Vec<UTXO>,
        use_all_utxos: bool,
        fee_rate: FeeRate,
        amount_needed: u64,
        input_witness_weight: usize,
        fee_amount: f32
    ) -> Result<CoinSelectionResult, Error>

    Perform the coin selection

    -
      -
    • utxos: the list of spendable UTXOs
    • -
    • use_all_utxos: if true all utxos should be spent unconditionally
    • -
    • fee_rate: fee rate to use
    • -
    • amount_needed: the amount in satoshi to select
    • -
    • input_witness_weight: the weight of an input's witness to keep into account for the fees
    • -
    • fee_amount: the amount of fees in satoshi already accumulated from adding outputs
    • -
    -
    Loading content... -

    Implementors

    impl CoinSelectionAlgorithm for DumbCoinSelection[src]

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html deleted file mode 100644 index b1a07047c3..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html +++ /dev/null @@ -1,3 +0,0 @@ -bdk::wallet::coin_selection::DefaultCoinSelectionAlgorithm - Rust

    [][src]Type Definition bdk::wallet::coin_selection::DefaultCoinSelectionAlgorithm

    type DefaultCoinSelectionAlgorithm = DumbCoinSelection;

    Default coin selection algorithm used by TxBuilder if not -overridden

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/index.html deleted file mode 100644 index 7bd0bc5222..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/index.html +++ /dev/null @@ -1,28 +0,0 @@ -bdk::wallet::export - Rust

    [][src]Module bdk::wallet::export

    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 = WalletExport::from_str(import)?;
    -let wallet: OfflineWallet<_> = Wallet::new_offline(&import.descriptor(), import.change_descriptor().as_deref(), Network::Testnet, MemoryDatabase::default())?;
    -

    Export a Wallet

    -
    -let wallet: OfflineWallet<_> = Wallet::new_offline(
    -    "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
    -    Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
    -    Network::Testnet,
    -    MemoryDatabase::default()
    -)?;
    -let export = WalletExport::export_wallet(&wallet, "exported wallet", true)
    -    .map_err(ToString::to_string)
    -    .map_err(bdk::Error::Generic)?;
    -
    -println!("Exported: {}", export.to_string());
    -

    Structs

    -
    WalletExport

    Structure that contains the export of a wallet

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/sidebar-items.js deleted file mode 100644 index 06abb3c4ee..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["WalletExport","Structure that contains the export of a wallet"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/struct.WalletExport.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/struct.WalletExport.html deleted file mode 100644 index 3e5d692275..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/export/struct.WalletExport.html +++ /dev/null @@ -1,36 +0,0 @@ -bdk::wallet::export::WalletExport - Rust

    [][src]Struct bdk::wallet::export::WalletExport

    pub struct WalletExport {
    -    pub blockheight: u32,
    -    pub label: String,
    -    // some fields omitted
    -}

    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

    impl WalletExport[src]

    pub fn export_wallet<B: BlockchainMarker, D: BatchDatabase>(
        wallet: &Wallet<B, D>,
        label: &str,
        include_blockheight: bool
    ) -> Result<Self, &'static str>
    [src]

    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 descriptor(&self) -> String[src]

    Return the external descriptor

    -

    pub fn change_descriptor(&self) -> Option<String>[src]

    Return the internal descriptor, if present

    -

    Trait Implementations

    impl Debug for WalletExport[src]

    impl<'de> Deserialize<'de> for WalletExport[src]

    impl FromStr for WalletExport[src]

    type Err = Error

    The associated error which can be returned from parsing.

    -

    impl Serialize for WalletExport[src]

    impl ToString for WalletExport[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> DeserializeOwned for T where
        T: for<'de> Deserialize<'de>, 
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/index.html deleted file mode 100644 index bf698476e6..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/index.html +++ /dev/null @@ -1,16 +0,0 @@ -bdk::wallet - Rust

    [][src]Module bdk::wallet

    Wallet

    -

    This module defines the Wallet structure.

    -

    Modules

    -
    address_validator

    Address validation callbacks

    -
    coin_selection

    Coin selection

    -
    export

    Wallet export

    -
    signer

    Generalized signers

    -
    time

    Cross-platform time

    -
    tx_builder

    Transaction builder

    -

    Structs

    -
    Wallet

    A Bitcoin wallet

    -

    Traits

    -
    IsDust

    Trait to check if a value is below the dust limit

    -

    Type Definitions

    -
    OfflineWallet

    Type alias for a Wallet that uses OfflineBlockchain

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/sidebar-items.js deleted file mode 100644 index 811ec3c2b5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"mod":[["address_validator","Address validation callbacks"],["coin_selection","Coin selection"],["export","Wallet export"],["signer","Generalized signers"],["time","Cross-platform time"],["tx_builder","Transaction builder"]],"struct":[["Wallet","A Bitcoin wallet"]],"trait":[["IsDust","Trait to check if a value is below the dust limit"]],"type":[["OfflineWallet","Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerError.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerError.html deleted file mode 100644 index efbc4c0b8b..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerError.html +++ /dev/null @@ -1,50 +0,0 @@ -bdk::wallet::signer::SignerError - Rust

    [][src]Enum bdk::wallet::signer::SignerError

    pub enum SignerError {
    -    MissingKey,
    -    UserCanceled,
    -    MissingSighash,
    -    InputIndexOutOfRange,
    -    MissingNonWitnessUtxo,
    -    InvalidNonWitnessUtxo,
    -    MissingWitnessUtxo,
    -    MissingWitnessScript,
    -    MissingHDKeypath,
    -}

    Signing error

    -

    - Variants

    -
    MissingKey

    The private key is missing for the required public key

    -
    UserCanceled

    The user canceled the operation

    -
    MissingSighash

    The sighash is missing in the PSBT input

    -
    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 requied to sign this input

    -
    MissingHDKeypath

    The fingerprint and derivation path are missing from the psbt input

    -

    Trait Implementations

    impl Clone for SignerError[src]

    impl Debug for SignerError[src]

    impl Display for SignerError[src]

    impl Eq for SignerError[src]

    impl Error for SignerError[src]

    impl From<SignerError> for Error[src]

    impl PartialEq<SignerError> for SignerError[src]

    impl StructuralEq for SignerError[src]

    impl StructuralPartialEq for SignerError[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerId.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerId.html deleted file mode 100644 index 299e47f7b9..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/enum.SignerId.html +++ /dev/null @@ -1,31 +0,0 @@ -bdk::wallet::signer::SignerId - Rust

    [][src]Enum bdk::wallet::signer::SignerId

    pub enum SignerId<Pk: MiniscriptKey> {
    -    PkHash(<Pk as MiniscriptKey>::Hash),
    -    Fingerprint(Fingerprint),
    -}

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

    -

    - Variants

    -
    PkHash(<Pk as MiniscriptKey>::Hash)
    Fingerprint(Fingerprint)

    Trait Implementations

    impl<Pk: Clone + MiniscriptKey> Clone for SignerId<Pk>[src]

    impl<Pk: Debug + MiniscriptKey> Debug for SignerId<Pk>[src]

    impl<Pk: Eq + MiniscriptKey> Eq for SignerId<Pk>[src]

    impl From<Fingerprint> for SignerId<DescriptorPublicKey>[src]

    impl From<Hash> for SignerId<DescriptorPublicKey>[src]

    impl<Pk: Hash + MiniscriptKey> Hash for SignerId<Pk>[src]

    impl<Pk: PartialEq + MiniscriptKey> PartialEq<SignerId<Pk>> for SignerId<Pk>[src]

    impl<Pk: MiniscriptKey> StructuralEq for SignerId<Pk>[src]

    impl<Pk: MiniscriptKey> StructuralPartialEq for SignerId<Pk>[src]

    Auto Trait Implementations

    impl<Pk> RefUnwindSafe for SignerId<Pk> where
        <Pk as MiniscriptKey>::Hash: RefUnwindSafe

    impl<Pk> Send for SignerId<Pk> where
        <Pk as MiniscriptKey>::Hash: Send

    impl<Pk> Sync for SignerId<Pk> where
        <Pk as MiniscriptKey>::Hash: Sync

    impl<Pk> Unpin for SignerId<Pk> where
        <Pk as MiniscriptKey>::Hash: Unpin

    impl<Pk> UnwindSafe for SignerId<Pk> where
        <Pk as MiniscriptKey>::Hash: UnwindSafe

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/index.html deleted file mode 100644 index 6c88b63163..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/index.html +++ /dev/null @@ -1,54 +0,0 @@ -bdk::wallet::signer - Rust

    [][src]Module bdk::wallet::signer

    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 Signer for CustomSigner {
    -    fn sign(
    -        &self,
    -        psbt: &mut psbt::PartiallySignedTransaction,
    -        input_index: Option<usize>,
    -    ) -> Result<(), SignerError> {
    -        let input_index = input_index.ok_or(SignerError::InputIndexOutOfRange)?;
    -        self.device.sign_input(psbt, input_index)?;
    -
    -        Ok(())
    -    }
    -
    -    fn sign_whole_tx(&self) -> bool {
    -        false
    -    }
    -}
    -
    -let custom_signer = CustomSigner::connect();
    -
    -let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -wallet.add_signer(
    -    ScriptType::External,
    -    Fingerprint::from_str("e30f11b8").unwrap().into(),
    -    SignerOrdering(200),
    -    Arc::new(Box::new(custom_signer))
    -);
    -
    -

    Structs

    -
    SignerOrdering

    Defines the order in which signers are called

    -
    SignersContainer

    Container for multiple signers

    -

    Enums

    -
    SignerError

    Signing error

    -
    SignerId

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

    -

    Traits

    -
    Signer

    Trait for signers

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/sidebar-items.js deleted file mode 100644 index 8f3e3d79b6..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["SignerError","Signing error"],["SignerId","Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among multiple of them"]],"struct":[["SignerOrdering","Defines the order in which signers are called"],["SignersContainer","Container for multiple signers"]],"trait":[["Signer","Trait for signers"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignerOrdering.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignerOrdering.html deleted file mode 100644 index 1813c89d08..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignerOrdering.html +++ /dev/null @@ -1,34 +0,0 @@ -bdk::wallet::signer::SignerOrdering - Rust

    [][src]Struct bdk::wallet::signer::SignerOrdering

    pub struct SignerOrdering(pub usize);

    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.

    -

    Trait Implementations

    impl Clone for SignerOrdering[src]

    impl Debug for SignerOrdering[src]

    impl Default for SignerOrdering[src]

    impl Eq for SignerOrdering[src]

    impl Ord for SignerOrdering[src]

    impl PartialEq<SignerOrdering> for SignerOrdering[src]

    impl PartialOrd<SignerOrdering> for SignerOrdering[src]

    impl StructuralEq for SignerOrdering[src]

    impl StructuralPartialEq for SignerOrdering[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignersContainer.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignersContainer.html deleted file mode 100644 index 014f8c419a..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/struct.SignersContainer.html +++ /dev/null @@ -1,27 +0,0 @@ -bdk::wallet::signer::SignersContainer - Rust

    [][src]Struct bdk::wallet::signer::SignersContainer

    pub struct SignersContainer<Pk: MiniscriptKey>(_);

    Container for multiple signers

    -

    Implementations

    impl SignersContainer<DescriptorPublicKey>[src]

    pub fn as_key_map(&self) -> KeyMap[src]

    impl<Pk: MiniscriptKey> SignersContainer<Pk>[src]

    pub fn new() -> Self[src]

    Default constructor

    -

    pub fn add_external(
        &mut self,
        id: SignerId<Pk>,
        ordering: SignerOrdering,
        signer: Arc<Box<dyn Signer>>
    ) -> Option<Arc<Box<dyn Signer>>>
    [src]

    Adds an external signer to the container for the specified id. Optionally returns the -signer that was previosuly in the container, if any

    -

    pub fn remove(
        &mut self,
        id: SignerId<Pk>,
        ordering: SignerOrdering
    ) -> Option<Arc<Box<dyn Signer>>>
    [src]

    Removes a signer from the container and returns it

    -

    pub fn ids(&self) -> Vec<&SignerId<Pk>>[src]

    Returns the list of identifiers of all the signers in the container

    -

    pub fn signers(&self) -> Vec<&Arc<Box<dyn Signer>>>[src]

    Returns the list of signers in the container, sorted by lowest to highest ordering

    -

    pub fn find(&self, id: SignerId<Pk>) -> Option<&Arc<Box<dyn Signer>>>[src]

    Finds the signer with lowest ordering for a given id in the container.

    -

    Trait Implementations

    impl<Pk: Clone + MiniscriptKey> Clone for SignersContainer<Pk>[src]

    impl<Pk: Debug + MiniscriptKey> Debug for SignersContainer<Pk>[src]

    impl<Pk: Default + MiniscriptKey> Default for SignersContainer<Pk>[src]

    impl From<HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>> for SignersContainer<DescriptorPublicKey>[src]

    Auto Trait Implementations

    impl<Pk> !RefUnwindSafe for SignersContainer<Pk>

    impl<Pk> !Send for SignersContainer<Pk>

    impl<Pk> !Sync for SignersContainer<Pk>

    impl<Pk> Unpin for SignersContainer<Pk> where
        <Pk as MiniscriptKey>::Hash: Unpin

    impl<Pk> !UnwindSafe for SignersContainer<Pk>

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/trait.Signer.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/trait.Signer.html deleted file mode 100644 index 3fc46e577c..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/signer/trait.Signer.html +++ /dev/null @@ -1,23 +0,0 @@ -bdk::wallet::signer::Signer - Rust

    [][src]Trait bdk::wallet::signer::Signer

    pub trait Signer: Debug {
    -    fn sign(
            &self,
            psbt: &mut PartiallySignedTransaction,
            input_index: Option<usize>
        ) -> Result<(), SignerError>; -
    fn sign_whole_tx(&self) -> bool; - - fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> { ... } -}

    Trait for signers

    -

    This trait can be implemented to provide customized signers to the wallet. For an example see -this module's documentation.

    -
    -

    Required methods

    fn sign(
        &self,
        psbt: &mut PartiallySignedTransaction,
        input_index: Option<usize>
    ) -> Result<(), SignerError>

    Sign a PSBT

    -

    The input_index argument is only provided if the wallet doesn't declare to sign the whole -transaction in one go (see Signer::sign_whole_tx). Otherwise its value is None and -can be ignored.

    -

    fn sign_whole_tx(&self) -> bool

    Return whether or not the signer signs the whole transaction in one go instead of every -input individually

    -
    Loading content... -

    Provided methods

    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey>

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

    -
    Loading content... -

    Implementations on Foreign Types

    impl Signer for DescriptorXKey<ExtendedPrivKey>[src]

    impl Signer for PrivateKey[src]

    Loading content... -

    Implementors

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/struct.Wallet.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/struct.Wallet.html deleted file mode 100644 index 19f74f62e1..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/struct.Wallet.html +++ /dev/null @@ -1,70 +0,0 @@ -bdk::wallet::Wallet - Rust

    [][src]Struct bdk::wallet::Wallet

    pub struct Wallet<B: BlockchainMarker, D: BatchDatabase> { /* fields omitted */ }

    A Bitcoin wallet

    -

    A wallet takes descriptors, a database and a -blockchain and implements the basic functions that a Bitcoin wallets -needs to operate, like generating addresses, returning the balance, -creating transactions, etc.

    -

    A wallet can be either "online" if the blockchain type provided -implements Blockchain, or "offline" OfflineBlockchain is used. Offline wallets only expose -methods that don't need any interaction with the blockchain to work.

    -

    Implementations

    impl<B, D> Wallet<B, D> where
        B: BlockchainMarker,
        D: BatchDatabase
    [src]

    pub fn new_offline(
        descriptor: &str,
        change_descriptor: Option<&str>,
        network: Network,
        database: D
    ) -> Result<Self, Error>
    [src]

    Create a new "offline" wallet

    -

    pub fn get_new_address(&self) -> Result<Address, Error>[src]

    Return a newly generated address using the external descriptor

    -

    pub fn is_mine(&self, script: &Script) -> Result<bool, Error>[src]

    Return whether or not a script is part of this wallet (either internal or external)

    -

    pub fn list_unspent(&self) -> Result<Vec<UTXO>, Error>[src]

    Return the list of unspent outputs of this wallet

    -

    Note that this methods only operate on the internal database, which first needs to be -Wallet::sync manually.

    -

    pub fn list_transactions(
        &self,
        include_raw: bool
    ) -> Result<Vec<TransactionDetails>, Error>
    [src]

    Return the list of transactions made and received by the wallet

    -

    Optionally fill the TransactionDetails::transaction field with the raw transaction if -include_raw is true.

    -

    Note that this methods only operate on the internal database, which first needs to be -Wallet::sync manually.

    -

    pub fn get_balance(&self) -> Result<u64, Error>[src]

    Return the balance, meaning the sum of this wallet's unspent outputs' values

    -

    Note that this methods only operate on the internal database, which first needs to be -Wallet::sync manually.

    -

    pub fn add_signer(
        &mut self,
        script_type: ScriptType,
        id: SignerId<DescriptorPublicKey>,
        ordering: SignerOrdering,
        signer: Arc<Box<dyn Signer>>
    )
    [src]

    Add an external signer

    -

    See the signer module for an example.

    -

    pub fn add_address_validator(
        &mut self,
        validator: Arc<Box<dyn AddressValidator>>
    )
    [src]

    Add an address validator

    -

    See the address_validator module for an example.

    -

    pub fn create_tx<Cs: CoinSelectionAlgorithm>(
        &self,
        builder: TxBuilder<Cs>
    ) -> Result<(PSBT, TransactionDetails), Error>
    [src]

    Create a new transaction following the options specified in the builder

    -

    Example

    -
    -let (psbt, details) = wallet.create_tx(
    -    TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
    -)?;
    -// sign and broadcast ...
    -

    pub fn bump_fee<Cs: CoinSelectionAlgorithm>(
        &self,
        txid: &Txid,
        builder: TxBuilder<Cs>
    ) -> Result<(PSBT, TransactionDetails), Error>
    [src]

    Bump the fee of a transaction following the options specified in the builder

    -

    Return an error if the transaction is already confirmed or doesn't explicitly signal RBF.

    -

    NOTE: if the original transaction was made with TxBuilder::send_all, the same -option must be enabled when bumping its fees to correctly reduce the only output's value to -increase the fees.

    -

    Example

    -
    -let txid = Txid::from_str("faff0a466b70f5d5f92bd757a92c1371d4838bdd5bc53a06764e2488e51ce8f8").unwrap();
    -let (psbt, details) = wallet.bump_fee(
    -    &txid,
    -    TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(5.0)),
    -)?;
    -// sign and broadcast ...
    -

    pub fn sign(
        &self,
        psbt: PSBT,
        assume_height: Option<u32>
    ) -> Result<(PSBT, bool), Error>
    [src]

    Sign a transaction with all the wallet's signers, in the order specified by every signer's -SignerOrdering

    -

    Example

    -
    -let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
    -

    pub fn policies(&self, script_type: ScriptType) -> Result<Option<Policy>, Error>[src]

    Return the spending policies for the wallet's descriptor

    -

    pub fn public_descriptor(
        &self,
        script_type: ScriptType
    ) -> Result<Option<ExtendedDescriptor>, Error>
    [src]

    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 finalize_psbt(
        &self,
        psbt: PSBT,
        assume_height: Option<u32>
    ) -> Result<(PSBT, bool), Error>
    [src]

    Try to finalize a PSBT

    -

    impl<B, D> Wallet<B, D> where
        B: Blockchain,
        D: BatchDatabase
    [src]

    pub fn new(
        descriptor: &str,
        change_descriptor: Option<&str>,
        network: Network,
        database: D,
        client: B
    ) -> Result<Self, Error>
    [src]

    Create a new "online" wallet

    -

    pub fn sync<P: 'static + Progress>(
        &self,
        progress_update: P,
        max_address_param: Option<u32>
    ) -> Result<(), Error>
    [src]

    Sync the internal database with the blockchain

    -

    pub fn client(&self) -> Option<&B>[src]

    Return a reference to the internal blockchain client

    -

    pub fn broadcast(&self, tx: Transaction) -> Result<Txid, Error>[src]

    Broadcast a transaction to the network

    -

    Auto Trait Implementations

    impl<B, D> !RefUnwindSafe for Wallet<B, D>

    impl<B, D> !Send for Wallet<B, D>

    impl<B, D> !Sync for Wallet<B, D>

    impl<B, D> Unpin for Wallet<B, D> where
        B: Unpin,
        D: Unpin

    impl<B, D> !UnwindSafe for Wallet<B, D>

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/fn.get_timestamp.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/fn.get_timestamp.html deleted file mode 100644 index 201c354c30..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/fn.get_timestamp.html +++ /dev/null @@ -1,2 +0,0 @@ -bdk::wallet::time::get_timestamp - Rust

    [][src]Function bdk::wallet::time::get_timestamp

    pub fn get_timestamp() -> u64

    Return the current timestamp in seconds

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/index.html deleted file mode 100644 index 29bbc5d2b9..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/index.html +++ /dev/null @@ -1,8 +0,0 @@ -bdk::wallet::time - Rust

    [][src]Module bdk::wallet::time

    Cross-platform time

    -

    This module provides a function to get the current timestamp that works on all the platforms -supported by the library.

    -

    It can be useful to compare it with the timestamps found in -TransactionDetails.

    -

    Functions

    -
    get_timestamp

    Return the current timestamp in seconds

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/sidebar-items.js deleted file mode 100644 index 22164ef49f..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/time/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"fn":[["get_timestamp","Return the current timestamp in seconds"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/trait.IsDust.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/trait.IsDust.html deleted file mode 100644 index 42f509f659..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/trait.IsDust.html +++ /dev/null @@ -1,8 +0,0 @@ -bdk::wallet::IsDust - Rust

    [][src]Trait bdk::wallet::IsDust

    pub trait IsDust {
    -    fn is_dust(&self) -> bool;
    -}

    Trait to check if a value is below the dust limit

    -
    -

    Required methods

    fn is_dust(&self) -> bool

    Check whether or not a value is below dust limit

    -
    Loading content... -

    Implementations on Foreign Types

    impl IsDust for u64[src]

    Loading content... -

    Implementors

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html deleted file mode 100644 index 90f24df408..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html +++ /dev/null @@ -1,42 +0,0 @@ -bdk::wallet::tx_builder::ChangeSpendPolicy - Rust

    [][src]Enum bdk::wallet::tx_builder::ChangeSpendPolicy

    pub enum ChangeSpendPolicy {
    -    ChangeAllowed,
    -    OnlyChange,
    -    ChangeForbidden,
    -}

    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

    impl Clone for ChangeSpendPolicy[src]

    impl Copy for ChangeSpendPolicy[src]

    impl Debug for ChangeSpendPolicy[src]

    impl Default for ChangeSpendPolicy[src]

    impl Eq for ChangeSpendPolicy[src]

    impl Hash for ChangeSpendPolicy[src]

    impl Ord for ChangeSpendPolicy[src]

    impl PartialEq<ChangeSpendPolicy> for ChangeSpendPolicy[src]

    impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy[src]

    impl StructuralEq for ChangeSpendPolicy[src]

    impl StructuralPartialEq for ChangeSpendPolicy[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.TxOrdering.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.TxOrdering.html deleted file mode 100644 index 61219124a8..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/enum.TxOrdering.html +++ /dev/null @@ -1,42 +0,0 @@ -bdk::wallet::tx_builder::TxOrdering - Rust

    [][src]Enum bdk::wallet::tx_builder::TxOrdering

    pub enum TxOrdering {
    -    Shuffle,
    -    Untouched,
    -    BIP69Lexicographic,
    -}

    Ordering of the transaction's inputs and outputs

    -

    - Variants

    -
    Shuffle

    Randomized (default)

    -
    Untouched

    Unchanged

    -
    BIP69Lexicographic

    BIP69 / Lexicographic

    -

    Implementations

    impl TxOrdering[src]

    pub fn sort_tx(&self, tx: &mut Transaction)[src]

    Trait Implementations

    impl Clone for TxOrdering[src]

    impl Copy for TxOrdering[src]

    impl Debug for TxOrdering[src]

    impl Default for TxOrdering[src]

    impl Eq for TxOrdering[src]

    impl Hash for TxOrdering[src]

    impl Ord for TxOrdering[src]

    impl PartialEq<TxOrdering> for TxOrdering[src]

    impl PartialOrd<TxOrdering> for TxOrdering[src]

    impl StructuralEq for TxOrdering[src]

    impl StructuralPartialEq for TxOrdering[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/index.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/index.html deleted file mode 100644 index 90c59e1cb8..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/index.html +++ /dev/null @@ -1,16 +0,0 @@ -bdk::wallet::tx_builder - Rust

    [][src]Module bdk::wallet::tx_builder

    Transaction builder

    -

    Example

    -
    -// Create a transaction with one output to `to_address` of 50_000 satoshi, with a custom fee rate
    -// of 5.0 satoshi/vbyte, only spending non-change outputs and with RBF signaling
    -// enabled
    -let builder = TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
    -    .fee_rate(FeeRate::from_sat_per_vb(5.0))
    -    .do_not_spend_change()
    -    .enable_rbf();
    -

    Structs

    -
    TxBuilder

    A transaction builder

    -

    Enums

    -
    ChangeSpendPolicy

    Policy regarding the use of change outputs when creating a transaction

    -
    TxOrdering

    Ordering of the transaction's inputs and outputs

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/sidebar-items.js b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/sidebar-items.js deleted file mode 100644 index e51db729e0..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["ChangeSpendPolicy","Policy regarding the use of change outputs when creating a transaction"],["TxOrdering","Ordering of the transaction's inputs and outputs"]],"struct":[["TxBuilder","A transaction builder"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/struct.TxBuilder.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/struct.TxBuilder.html deleted file mode 100644 index 6ead2e15a2..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/tx_builder/struct.TxBuilder.html +++ /dev/null @@ -1,70 +0,0 @@ -bdk::wallet::tx_builder::TxBuilder - Rust

    [][src]Struct bdk::wallet::tx_builder::TxBuilder

    pub struct TxBuilder<Cs: CoinSelectionAlgorithm> { /* fields omitted */ }

    A transaction builder

    -

    This structure contains the configuration that the wallet must follow to build a transaction.

    -

    For an example see this module's documentation;

    -

    Implementations

    impl TxBuilder<DefaultCoinSelectionAlgorithm>[src]

    pub fn new() -> Self[src]

    Create an empty builder

    -

    pub fn with_recipients(recipients: Vec<(Script, u64)>) -> Self[src]

    Create a builder starting from a list of recipients

    -

    impl<Cs: CoinSelectionAlgorithm> TxBuilder<Cs>[src]

    pub fn set_recipients(self, recipients: Vec<(Script, u64)>) -> Self[src]

    Replace the recipients already added with a new list

    -

    pub fn add_recipient(self, script_pubkey: Script, amount: u64) -> Self[src]

    Add a recipient to the internal list

    -

    pub fn send_all(self) -> Self[src]

    Send all the selected utxos to a single output

    -

    Adding more than one recipients with this option enabled will result in an error.

    -

    The value associated with the only recipient is irrelevant and will be replaced by the wallet.

    -

    pub fn fee_rate(self, fee_rate: FeeRate) -> Self[src]

    Set a custom fee rate

    -

    pub fn policy_path(self, policy_path: BTreeMap<String, Vec<usize>>) -> Self[src]

    Set the policy path to use while creating the transaction

    -

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

    -

    pub fn utxos(self, utxos: Vec<OutPoint>) -> Self[src]

    Replace the internal list of utxos that must be spent with a new list

    -

    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(self, utxo: OutPoint) -> Self[src]

    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 unspendable(self, unspendable: Vec<OutPoint>) -> Self[src]

    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::utxos and -TxBuilder::add_utxo have priority over these. See the docs of the two linked methods -for more details.

    -

    pub fn add_unspendable(self, unspendable: OutPoint) -> Self[src]

    Add a utxo to the internal list of unspendable utxos

    -

    It's important to note that the "must-be-spent" utxos added with TxBuilder::utxos and -TxBuilder::add_utxo have priority over this. See the docs of the two linked methods -for more details.

    -

    pub fn sighash(self, sighash: SigHashType) -> Self[src]

    Sign with a specific sig hash

    -

    Use this option very carefully

    -

    pub fn ordering(self, ordering: TxOrdering) -> Self[src]

    Choose the ordering for inputs and outputs of the transaction

    -

    pub fn nlocktime(self, locktime: u32) -> Self[src]

    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 enable_rbf(self) -> Self[src]

    Enable signaling RBF

    -

    This will use the default nSequence value of 0xFFFFFFFD.

    -

    pub fn enable_rbf_with_sequence(self, nsequence: u32) -> Self[src]

    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 version(self, version: u32) -> Self[src]

    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 do_not_spend_change(self) -> Self[src]

    Do not spend change outputs

    -

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

    -

    pub fn only_spend_change(self) -> Self[src]

    Only spend change outputs

    -

    This effectively adds all the non-change outputs to the "unspendable" list. See -TxBuilder::unspendable.

    -

    pub fn change_policy(self, change_policy: ChangeSpendPolicy) -> Self[src]

    pub fn force_non_witness_utxo(self) -> Self[src]

    Fill-in the psbt::Input::non_witness_utxo field even if the wallet only has SegWit -descriptors.

    -

    This is useful for signers which always require it, like Trezor hardware wallets.

    -

    pub fn coin_selection<P: CoinSelectionAlgorithm>(
        self,
        coin_selection: P
    ) -> TxBuilder<P>
    [src]

    Choose the coin selection algorithm

    -

    Overrides the DefaultCoinSelectionAlgorithm.

    -

    Trait Implementations

    impl<Cs: Debug + CoinSelectionAlgorithm> Debug for TxBuilder<Cs>[src]

    impl<Cs: Default + CoinSelectionAlgorithm> Default for TxBuilder<Cs>[src]

    Auto Trait Implementations

    impl<Cs> RefUnwindSafe for TxBuilder<Cs> where
        Cs: RefUnwindSafe

    impl<Cs> Send for TxBuilder<Cs> where
        Cs: Send

    impl<Cs> Sync for TxBuilder<Cs> where
        Cs: Sync

    impl<Cs> Unpin for TxBuilder<Cs> where
        Cs: Unpin

    impl<Cs> UnwindSafe for TxBuilder<Cs> where
        Cs: UnwindSafe

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/type.OfflineWallet.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/type.OfflineWallet.html deleted file mode 100644 index 0f4efcc6f5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/type.OfflineWallet.html +++ /dev/null @@ -1,2 +0,0 @@ -bdk::wallet::OfflineWallet - Rust

    [][src]Type Definition bdk::wallet::OfflineWallet

    type OfflineWallet<D> = Wallet<OfflineBlockchain, D>;

    Type alias for a Wallet that uses OfflineBlockchain

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/utils/trait.IsDust.html b/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/utils/trait.IsDust.html deleted file mode 100644 index 71ab5675d6..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/bdk/wallet/utils/trait.IsDust.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

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

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/brush.svg b/static/docs-rs/bdk/0.1.0-beta.1/brush.svg deleted file mode 100644 index ea266e856a..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/brush.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/dark.css b/static/docs-rs/bdk/0.1.0-beta.1/dark.css deleted file mode 100644 index 5df3fef0bc..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/dark.css +++ /dev/null @@ -1 +0,0 @@ -body{background-color:#353535;color:#ddd;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:#ddd;}h1.fqn{border-bottom-color:#d2d2d2;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){border-bottom-color:#d2d2d2;}.in-band{background-color:#353535;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#2A2A2A;}pre{background-color:#2A2A2A;}.sidebar{background-color:#505050;}*{scrollbar-color:rgb(64,65,67) #717171;}.sidebar{scrollbar-color:rgba(32,34,37,.6) transparent;}::-webkit-scrollbar-track{background-color:#717171;}::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar::-webkit-scrollbar-track{background-color:#717171;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar .current{background-color:#333;}.source .sidebar{background-color:#353535;}.sidebar .location{border-color:#fff;background:#575757;color:#DDD;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#444;}.line-numbers span{color:#3B91E2;}.line-numbers .line-highlighted{background-color:#0a042f !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#DDD;}.docblock table,.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#ddd;}.content .highlighted{color:#eee !important;background-color:#616161;}.content .highlighted a,.content .highlighted span{color:#eee !important;}.content .highlighted.trait{background-color:#013191;}.content .highlighted.traitalias{background-color:#013191;}.content .highlighted.mod,.content .highlighted.externcrate{background-color:#afc6e4;}.content .highlighted.mod{background-color:#803a1b;}.content .highlighted.externcrate{background-color:#396bac;}.content .highlighted.enum{background-color:#5b4e68;}.content .highlighted.struct{background-color:#194e9f;}.content .highlighted.union{background-color:#b7bd49;}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{background-color:#4950ed;}.content .highlighted.type{background-color:#38902c;}.content .highlighted.foreigntype{background-color:#b200d6;}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{background-color:#217d1c;}.content .highlighted.constant,.content .highlighted.static{background-color:#0063cc;}.content .highlighted.primitive{background-color:#00708a;}.content .highlighted.keyword{background-color:#884719;}.content .stability::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#82b089;}.content span.struct,.content a.struct,.block a.current.struct{color:#2dbfb8;}.content span.type,.content a.type,.block a.current.type{color:#ff7f00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#dd7de8;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#09bd00;}.content span.union,.content a.union,.block a.current.union{color:#a6ae37;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#82a5c9;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#43aec7;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#bda000;}.content span.trait,.content a.trait,.block a.current.trait{color:#b78cf2;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#b397da;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#2BAB63;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}pre.rust .comment{color:#8d8d8b;}pre.rust .doccomment{color:#8ca375;}nav:not(.sidebar){border-bottom-color:#4e4e4e;}nav.main .current{border-top-color:#eee;border-bottom-color:#eee;}nav.main .separator{border-color:#eee;}a{color:#ddd;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.stability a{color:#D2991D;}.stab.internal a{color:#304FFE;}a.test-arrow{color:#dedede;}.collapse-toggle{color:#999;}#crate-search{color:#111;background-color:#f0f0f0;border-color:#000;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input{color:#111;background-color:#f0f0f0;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input:focus{border-color:#008dfd;}.search-focus:disabled{background-color:#c5c4c4;}#crate-search+.search-input:focus{box-shadow:0 0 8px 4px #078dd8;}.module-item .stab{color:#ddd;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;color:#2f2f2f;}.stab.internal{background:#FFB9B3;border-color:#B71C1C;color:#2f2f2f;}.stab.deprecated{background:#F3DFFF;border-color:#7F0087;color:#2f2f2f;}.stab.portability{background:#C4ECFF;border-color:#7BA5DB;color:#2f2f2f;}.stab.portability>code{color:#ddd;}#help>div{background:#4d4d4d;border-color:#bfbfbf;}#help dt{border-color:#bfbfbf;background:rgba(0,0,0,0);color:black;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:#ddd;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#ab8ac1;}pre.rust .kw-2,pre.rust .prelude-ty{color:#769acb;}pre.rust .number,pre.rust .string{color:#83a300;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#ee6868;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#d97f26;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#4a4949;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label{color:#999;}:target>code,:target>.in-band{background-color:#494a3d;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.8);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.8);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.8);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.8);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip .tooltiptext{background-color:#000;color:#fff;border-color:#000;}.tooltip .tooltiptext::after{border-color:transparent black transparent transparent;}#titles>div:not(.selected){background-color:#252525;border-top-color:#252525;}#titles>div:hover,#titles>div.selected{border-top-color:#0089ff;}#titles>div>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#505050;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#505050;border-right-color:#000;}#sidebar-filler{background-color:#505050;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu{border-color:#e0e0e0;background:#f0f0f0;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus{border-color:#ffb900;}#theme-choices{border-color:#e0e0e0;background-color:#353535;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#4e4e4e;}@media (max-width:700px){#theme-picker{background:#f0f0f0;}}#all-types{background-color:#505050;}#all-types:hover{background-color:#606060;}.search-results td span.alias{color:#fff;}.search-results td span.grey{color:#ccc;}#sidebar-toggle{background-color:#565656;}#sidebar-toggle:hover{background-color:#676767;}#source-sidebar{background-color:#565656;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#444;}div.files>.selected{background-color:#333;}.setting-line>.title{border-bottom-color:#ddd;} \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/down-arrow.svg b/static/docs-rs/bdk/0.1.0-beta.1/down-arrow.svg deleted file mode 100644 index 35437e77a7..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/down-arrow.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/favicon.ico b/static/docs-rs/bdk/0.1.0-beta.1/favicon.ico deleted file mode 100644 index b8ad23769a..0000000000 Binary files a/static/docs-rs/bdk/0.1.0-beta.1/favicon.ico and /dev/null differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/alloc/string/trait.ToString.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/alloc/string/trait.ToString.js deleted file mode 100644 index f3e935dbe1..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/alloc/string/trait.ToString.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl ToString for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.Blockchain.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.Blockchain.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.Blockchain.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.BlockchainMarker.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.BlockchainMarker.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.BlockchainMarker.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.Progress.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.Progress.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/blockchain/trait.Progress.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.BatchDatabase.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.BatchDatabase.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.BatchDatabase.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.BatchOperations.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.BatchOperations.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.BatchOperations.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.Database.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.Database.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/database/trait.Database.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ExtractPolicy.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ExtractPolicy.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ExtractPolicy.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.MiniscriptKey.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.MiniscriptKey.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.MiniscriptKey.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ScriptContext.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ScriptContext.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ScriptContext.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ToPublicKey.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ToPublicKey.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/descriptor/trait.ToPublicKey.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/signer/trait.Signer.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/signer/trait.Signer.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/signer/trait.Signer.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/trait.IsDust.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/trait.IsDust.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/bdk/wallet/trait.IsDust.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/clone/trait.Clone.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/clone/trait.Clone.js deleted file mode 100644 index 795f3aa5e4..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/clone/trait.Clone.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Clone for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Clone for NoopProgress","synthetic":false,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Clone for LogProgress","synthetic":false,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Clone for PKOrF","synthetic":false,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Clone for SatisfiableItem","synthetic":false,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Clone for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Clone for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Clone for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Clone for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl Clone for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Clone for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl Clone for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Clone for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: Clone + MiniscriptKey> Clone for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Clone for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Clone for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk: Clone + MiniscriptKey> Clone for SignersContainer<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Clone for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Clone for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.Eq.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.Eq.js deleted file mode 100644 index 7d046cd5c6..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.Eq.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Eq for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Eq for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Eq for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl Eq for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl Eq for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Eq for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: Eq + MiniscriptKey> Eq for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Eq for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Eq for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Eq for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Eq for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.Ord.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.Ord.js deleted file mode 100644 index def6b4a7cf..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.Ord.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Ord for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Ord for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Ord for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Ord for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.PartialEq.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.PartialEq.js deleted file mode 100644 index 317284f165..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.PartialEq.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl PartialEq<Capability> for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl PartialEq<Condition> for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl PartialEq<ScriptType> for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl PartialEq<FeeRate> for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl PartialEq<UTXO> for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl PartialEq<TransactionDetails> for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl PartialEq<AddressValidatorError> for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: PartialEq + MiniscriptKey> PartialEq<SignerId<Pk>> for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl PartialEq<SignerError> for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl PartialEq<SignerOrdering> for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl PartialEq<TxOrdering> for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl PartialEq<ChangeSpendPolicy> for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.PartialOrd.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.PartialOrd.js deleted file mode 100644 index a07fbbf60f..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/cmp/trait.PartialOrd.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl PartialOrd<Condition> for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl PartialOrd<FeeRate> for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl PartialOrd<SignerOrdering> for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl PartialOrd<TxOrdering> for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/convert/trait.AsRef.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/convert/trait.AsRef.js deleted file mode 100644 index cf12c34f1d..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/convert/trait.AsRef.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl AsRef<[u8]> for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/convert/trait.From.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/convert/trait.From.js deleted file mode 100644 index 2f08ca5d8e..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/convert/trait.From.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<AddressValidatorError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<PolicyError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<SignerError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<EsploraError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<CompactFiltersError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Client> for ElectrumBlockchain","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<ParseIntError> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<SystemTimeError> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<PolicyError> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<bool> for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl From<SatisfiableItem> for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl From<Hash> for SignerId<DescriptorPublicKey>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl From<Fingerprint> for SignerId<DescriptorPublicKey>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl From<HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>> for SignersContainer<DescriptorPublicKey>","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/default/trait.Default.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/default/trait.Default.js deleted file mode 100644 index 521ae3ac3c..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/default/trait.Default.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Default for Mempool","synthetic":false,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Default for MemoryDatabase","synthetic":false,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Default for PKOrF","synthetic":false,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Default for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Default for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Default for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Default for DumbCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Default for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk: Default + MiniscriptKey> Default for SignersContainer<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Cs: Default + CoinSelectionAlgorithm> Default for TxBuilder<Cs>","synthetic":false,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Default for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Default for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/fmt/trait.Debug.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/fmt/trait.Debug.js deleted file mode 100644 index 74c7308e86..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/fmt/trait.Debug.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Debug for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl Debug for EsploraBlockchain","synthetic":false,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Debug for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Debug for Mempool","synthetic":false,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Debug for Peer","synthetic":false,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Debug for CompactFiltersBlockchain","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Debug for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Debug for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Debug for MemoryDatabase","synthetic":false,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Debug for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl Debug for PKOrF","synthetic":false,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Debug for SatisfiableItem","synthetic":false,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Debug for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Debug for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Debug for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Debug for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl Debug for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl Debug for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Debug for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl Debug for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Debug for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Debug for CoinSelectionResult","synthetic":false,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Debug for DumbCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Debug for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl<Pk: Debug + MiniscriptKey> Debug for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Debug for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Debug for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk: Debug + MiniscriptKey> Debug for SignersContainer<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Cs: Debug + CoinSelectionAlgorithm> Debug for TxBuilder<Cs>","synthetic":false,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Debug for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Debug for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/fmt/trait.Display.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/fmt/trait.Display.js deleted file mode 100644 index e2ed5553a9..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/fmt/trait.Display.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Display for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl Display for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Display for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Display for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl Display for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl Display for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Display for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/hash/trait.Hash.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/hash/trait.Hash.js deleted file mode 100644 index a5da8ca7bd..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/hash/trait.Hash.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Hash for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Hash for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Hash for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl<Pk: Hash + MiniscriptKey> Hash for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Hash for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Hash for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Copy.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Copy.js deleted file mode 100644 index 5f551c2945..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Copy.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Copy for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Copy for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Copy for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl Copy for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Copy for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Copy for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Freeze.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Freeze.js deleted file mode 100644 index 23dc06ecd5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Freeze.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Freeze for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Freeze for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl Freeze for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Freeze for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Freeze for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl Freeze for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl Freeze for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Freeze for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Freeze for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl !Freeze for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Freeze for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Freeze for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl !Freeze for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Freeze for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Freeze for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Freeze for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Freeze for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Freeze for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Freeze for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Freeze for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Freeze for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Freeze for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Freeze for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Freeze for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !Freeze for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Freeze for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Freeze for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Freeze for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Freeze for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Freeze for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> Freeze for SignersContainer<Pk>","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> Freeze for SignerId<Pk> where
        <Pk as MiniscriptKey>::Hash: Freeze, 
    ","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Freeze for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> Freeze for TxBuilder<Cs> where
        Cs: Freeze, 
    ","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Freeze for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Freeze for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Send.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Send.js deleted file mode 100644 index 764c51c5e0..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Send.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Send for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Send for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl Send for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Send for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Send for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl Send for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl Send for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Send for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Send for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Send for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Send for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Send for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Send for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Send for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Send for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Send for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl !Send for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Send for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Send for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Send for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Send for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Send for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Send for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Send for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !Send for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Send for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Send for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Send for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Send for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Send for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> !Send for SignersContainer<Pk>","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> Send for SignerId<Pk> where
        <Pk as MiniscriptKey>::Hash: Send
    ","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Send for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> Send for TxBuilder<Cs> where
        Cs: Send
    ","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Send for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Send for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.StructuralEq.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.StructuralEq.js deleted file mode 100644 index 9aa523c03e..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.StructuralEq.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl StructuralEq for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl StructuralEq for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl StructuralEq for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl StructuralEq for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl StructuralEq for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl StructuralEq for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: MiniscriptKey> StructuralEq for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl StructuralEq for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl StructuralEq for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl StructuralEq for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl StructuralEq for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.StructuralPartialEq.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.StructuralPartialEq.js deleted file mode 100644 index f0eb276a1d..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.StructuralPartialEq.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl StructuralPartialEq for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl StructuralPartialEq for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl StructuralPartialEq for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl StructuralPartialEq for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl StructuralPartialEq for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl StructuralPartialEq for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl StructuralPartialEq for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl<Pk: MiniscriptKey> StructuralPartialEq for SignerId<Pk>","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl StructuralPartialEq for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl StructuralPartialEq for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl StructuralPartialEq for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl StructuralPartialEq for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Sync.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Sync.js deleted file mode 100644 index 1fd8f87484..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Sync.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Sync for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Sync for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl Sync for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Sync for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Sync for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl Sync for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl Sync for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Sync for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Sync for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Sync for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Sync for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Sync for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Sync for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Sync for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Sync for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Sync for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl !Sync for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Sync for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Sync for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Sync for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Sync for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Sync for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Sync for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Sync for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !Sync for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Sync for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Sync for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Sync for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Sync for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Sync for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> !Sync for SignersContainer<Pk>","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> Sync for SignerId<Pk> where
        <Pk as MiniscriptKey>::Hash: Sync
    ","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Sync for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> Sync for TxBuilder<Cs> where
        Cs: Sync
    ","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Sync for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Sync for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Unpin.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Unpin.js deleted file mode 100644 index 8cc0048d2d..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/marker/trait.Unpin.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Unpin for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Unpin for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl Unpin for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Unpin for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Unpin for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl Unpin for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl Unpin for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Unpin for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Unpin for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Unpin for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Unpin for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl Unpin for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Unpin for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Unpin for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Unpin for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Unpin for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Unpin for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Unpin for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Unpin for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Unpin for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Unpin for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Unpin for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Unpin for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Unpin for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> Unpin for Wallet<B, D> where
        B: Unpin,
        D: Unpin
    ","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Unpin for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Unpin for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Unpin for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl Unpin for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Unpin for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> Unpin for SignersContainer<Pk> where
        <Pk as MiniscriptKey>::Hash: Unpin
    ","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> Unpin for SignerId<Pk> where
        <Pk as MiniscriptKey>::Hash: Unpin
    ","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Unpin for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> Unpin for TxBuilder<Cs> where
        Cs: Unpin
    ","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Unpin for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Unpin for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/str/trait.FromStr.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/str/trait.FromStr.js deleted file mode 100644 index fd4b285a22..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/core/str/trait.FromStr.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl FromStr for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/serde/de/trait.Deserialize.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/serde/de/trait.Deserialize.js deleted file mode 100644 index b54d94401d..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/serde/de/trait.Deserialize.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl<'de> Deserialize<'de> for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl<'de> Deserialize<'de> for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl<'de> Deserialize<'de> for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl<'de> Deserialize<'de> for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/serde/ser/trait.Serialize.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/serde/ser/trait.Serialize.js deleted file mode 100644 index 87f639e005..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/serde/ser/trait.Serialize.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Serialize for PKOrF","synthetic":false,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl Serialize for SatisfiableItem","synthetic":false,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Serialize for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Serialize for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Serialize for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Serialize for ScriptType","synthetic":false,"types":["bdk::types::ScriptType"]},{"text":"impl Serialize for UTXO","synthetic":false,"types":["bdk::types::UTXO"]},{"text":"impl Serialize for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Serialize for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/error/trait.Error.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/error/trait.Error.js deleted file mode 100644 index 7326983fef..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/error/trait.Error.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Error for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl Error for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Error for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Error for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl Error for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl Error for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Error for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/panic/trait.RefUnwindSafe.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/panic/trait.RefUnwindSafe.js deleted file mode 100644 index 29deba8e41..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/panic/trait.RefUnwindSafe.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl RefUnwindSafe for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl RefUnwindSafe for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl RefUnwindSafe for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl !RefUnwindSafe for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl RefUnwindSafe for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl RefUnwindSafe for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl RefUnwindSafe for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl RefUnwindSafe for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl RefUnwindSafe for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl RefUnwindSafe for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl !RefUnwindSafe for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl !RefUnwindSafe for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl RefUnwindSafe for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl !RefUnwindSafe for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl !RefUnwindSafe for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl !RefUnwindSafe for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl !RefUnwindSafe for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl RefUnwindSafe for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl RefUnwindSafe for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl RefUnwindSafe for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl RefUnwindSafe for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl RefUnwindSafe for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl RefUnwindSafe for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl RefUnwindSafe for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !RefUnwindSafe for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl RefUnwindSafe for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl RefUnwindSafe for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl RefUnwindSafe for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl RefUnwindSafe for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl RefUnwindSafe for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> !RefUnwindSafe for SignersContainer<Pk>","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> RefUnwindSafe for SignerId<Pk> where
        <Pk as MiniscriptKey>::Hash: RefUnwindSafe
    ","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl RefUnwindSafe for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> RefUnwindSafe for TxBuilder<Cs> where
        Cs: RefUnwindSafe
    ","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl RefUnwindSafe for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl RefUnwindSafe for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/panic/trait.UnwindSafe.js b/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/panic/trait.UnwindSafe.js deleted file mode 100644 index 1aa1c54fb5..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/implementors/std/panic/trait.UnwindSafe.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl UnwindSafe for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl UnwindSafe for UTXO","synthetic":true,"types":["bdk::types::UTXO"]},{"text":"impl UnwindSafe for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl !UnwindSafe for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl UnwindSafe for ScriptType","synthetic":true,"types":["bdk::types::ScriptType"]},{"text":"impl UnwindSafe for OfflineBlockchain","synthetic":true,"types":["bdk::blockchain::OfflineBlockchain"]},{"text":"impl UnwindSafe for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl UnwindSafe for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl UnwindSafe for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl UnwindSafe for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl !UnwindSafe for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::EsploraBlockchain"]},{"text":"impl !UnwindSafe for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl UnwindSafe for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl !UnwindSafe for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl !UnwindSafe for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl !UnwindSafe for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl !UnwindSafe for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl UnwindSafe for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl UnwindSafe for PKOrF","synthetic":true,"types":["bdk::descriptor::policy::PKOrF"]},{"text":"impl UnwindSafe for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl UnwindSafe for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl UnwindSafe for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl UnwindSafe for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl UnwindSafe for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<B, D> !UnwindSafe for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl UnwindSafe for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl UnwindSafe for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl UnwindSafe for DumbCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::DumbCoinSelection"]},{"text":"impl UnwindSafe for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl UnwindSafe for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl<Pk> !UnwindSafe for SignersContainer<Pk>","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl<Pk> UnwindSafe for SignerId<Pk> where
        <Pk as MiniscriptKey>::Hash: UnwindSafe
    ","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl UnwindSafe for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl<Cs> UnwindSafe for TxBuilder<Cs> where
        Cs: UnwindSafe
    ","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl UnwindSafe for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl UnwindSafe for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/light.css b/static/docs-rs/bdk/0.1.0-beta.1/light.css deleted file mode 100644 index 824281ebe9..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/light.css +++ /dev/null @@ -1 +0,0 @@ - body{background-color:white;color:black;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:black;}h1.fqn{border-bottom-color:#D5D5D5;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){border-bottom-color:#DDDDDD;}.in-band{background-color:white;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#F5F5F5;}pre{background-color:#F5F5F5;}.sidebar{background-color:#F1F1F1;}*{scrollbar-color:rgba(36,37,39,0.6) #e6e6e6;}.sidebar{scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;}::-webkit-scrollbar-track{background-color:#ecebeb;}::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar::-webkit-scrollbar-track{background-color:#dcdcdc;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar .current{background-color:#fff;}.source .sidebar{background-color:#fff;}.sidebar .location{border-color:#000;background-color:#fff;color:#333;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#F5F5F5;}.line-numbers span{color:#c67e2d;}.line-numbers .line-highlighted{background-color:#f6fdb0 !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#ddd;}.docblock table,.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#4E4C4C;}.content .highlighted{color:#000 !important;background-color:#ccc;}.content .highlighted a,.content .highlighted span{color:#000 !important;}.content .highlighted.trait{background-color:#c7b6ff;}.content .highlighted.traitalias{background-color:#c7b6ff;}.content .highlighted.mod,.content .highlighted.externcrate{background-color:#afc6e4;}.content .highlighted.enum{background-color:#b4d1b9;}.content .highlighted.struct{background-color:#e7b1a0;}.content .highlighted.union{background-color:#b7bd49;}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{background-color:#c6afb3;}.content .highlighted.type{background-color:#ffc891;}.content .highlighted.foreigntype{background-color:#f5c4ff;}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{background-color:#8ce488;}.content .highlighted.constant,.content .highlighted.static{background-color:#c3e0ff;}.content .highlighted.primitive{background-color:#9aecff;}.content .highlighted.keyword{background-color:#f99650;}.content .stability::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#508157;}.content span.struct,.content a.struct,.block a.current.struct{color:#ad448e;}.content span.type,.content a.type,.block a.current.type{color:#ba5d00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#cd00e2;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#068000;}.content span.union,.content a.union,.block a.current.union{color:#767b27;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#546e8a;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#2c8093;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#4d76ae;}.content span.trait,.content a.trait,.block a.current.trait{color:#7c5af3;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#6841f1;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#9a6e31;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}pre.rust .comment{color:#8E908C;}pre.rust .doccomment{color:#4D4D4C;}nav:not(.sidebar){border-bottom-color:#e0e0e0;}nav.main .current{border-top-color:#000;border-bottom-color:#000;}nav.main .separator{border:1px solid #000;}a{color:#000;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.stability a{color:#3873AD;}.stab.internal a{color:#304FFE;}a.test-arrow{color:#f5f5f5;}.collapse-toggle{color:#999;}#crate-search{color:#555;background-color:white;border-color:#e0e0e0;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input{color:#555;background-color:white;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input:focus{border-color:#66afe9;}.search-focus:disabled{background-color:#e6e6e6;}#crate-search+.search-input:focus{box-shadow:0 0 8px #078dd8;}.module-item .stab{color:#000;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;}.stab.internal{background:#FFB9B3;border-color:#B71C1C;}.stab.deprecated{background:#F3DFFF;border-color:#7F0087;}.stab.portability{background:#C4ECFF;border-color:#7BA5DB;}.stab.portability>code{color:#000;}#help>div{background:#e9e9e9;border-color:#bfbfbf;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:black;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#8959A8;}pre.rust .kw-2,pre.rust .prelude-ty{color:#4271AE;}pre.rust .number,pre.rust .string{color:#718C00;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#C82829;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#B76514;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#c7c7c7;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label{color:#999;}:target>code,:target>.in-band{background:#FDFFD3;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.5);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.5);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.5);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip .tooltiptext{background-color:#000;color:#fff;}.tooltip .tooltiptext::after{border-color:transparent black transparent transparent;}#titles>div:not(.selected){background-color:#e6e6e6;border-top-color:#e6e6e6;}#titles>div:hover,#titles>div.selected{border-top-color:#0089ff;}#titles>div>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#F1F1F1;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#F1F1F1;border-right-color:#000;}#sidebar-filler{background-color:#F1F1F1;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu{border-color:#e0e0e0;background-color:#fff;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus{border-color:#717171;}#theme-choices{border-color:#ccc;background-color:#fff;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#eee;}@media (max-width:700px){#theme-picker{background:#fff;}}#all-types{background-color:#fff;}#all-types:hover{background-color:#f9f9f9;}.search-results td span.alias{color:#000;}.search-results td span.grey{color:#999;}#sidebar-toggle{background-color:#F1F1F1;}#sidebar-toggle:hover{background-color:#E0E0E0;}#source-sidebar{background-color:#F1F1F1;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#E0E0E0;}div.files>.selected{background-color:#fff;}.setting-line>.title{border-bottom-color:#D5D5D5;} \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/main.js b/static/docs-rs/bdk/0.1.0-beta.1/main.js deleted file mode 100644 index 0bdb14b511..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/main.js +++ /dev/null @@ -1,7 +0,0 @@ -if(!String.prototype.startsWith){String.prototype.startsWith=function(searchString,position){position=position||0;return this.indexOf(searchString,position)===position}}if(!String.prototype.endsWith){String.prototype.endsWith=function(suffix,length){var l=length||this.length;return this.indexOf(suffix,l-suffix.length)!==-1}}if(!DOMTokenList.prototype.add){DOMTokenList.prototype.add=function(className){if(className&&!hasClass(this,className)){if(this.className&&this.className.length>0){this.className+=" "+className}else{this.className=className}}}}if(!DOMTokenList.prototype.remove){DOMTokenList.prototype.remove=function(className){if(className&&this.className){this.className=(" "+this.className+" ").replace(" "+className+" "," ").trim()}}}function getSearchInput(){return document.getElementsByClassName("search-input")[0]}function getSearchElement(){return document.getElementById("search")}function focusSearchBar(){getSearchInput().focus()}function defocusSearchBar(){getSearchInput().blur()}(function(){"use strict";var itemTypes=["mod","externcrate","import","struct","enum","fn","type","static","trait","impl","tymethod","method","structfield","variant","macro","primitive","associatedtype","constant","associatedconstant","union","foreigntype","keyword","existential","attr","derive","traitalias"];var disableShortcuts=getCurrentValue("rustdoc-disable-shortcuts")==="true";var search_input=getSearchInput();var searchTimeout=null;var currentTab=0;var mouseMovedAfterSearch=true;var titleBeforeSearch=document.title;function clearInputTimeout(){if(searchTimeout!==null){clearTimeout(searchTimeout);searchTimeout=null}}function getPageId(){if(window.location.hash){var tmp=window.location.hash.replace(/^#/,"");if(tmp.length>0){return tmp}}return null}function showSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){addClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];if(sidebar){addClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(!filler){var div=document.createElement("div");div.id="sidebar-filler";sidebar.appendChild(div)}}var themePickers=document.getElementsByClassName("theme-picker");if(themePickers&&themePickers.length>0){themePickers[0].style.display="none"}}function hideSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){removeClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(filler){filler.remove()}document.getElementsByTagName("body")[0].style.marginTop="";var themePickers=document.getElementsByClassName("theme-picker");if(themePickers&&themePickers.length>0){themePickers[0].style.display=null}}function showSearchResults(search){if(search===null||typeof search==='undefined'){search=getSearchElement()}addClass(main,"hidden");removeClass(search,"hidden");mouseMovedAfterSearch=false}function hideSearchResults(search){if(search===null||typeof search==='undefined'){search=getSearchElement()}addClass(search,"hidden");removeClass(main,"hidden")}var TY_PRIMITIVE=itemTypes.indexOf("primitive");var TY_KEYWORD=itemTypes.indexOf("keyword");function getQueryStringParams(){var params={};window.location.search.substring(1).split("&").map(function(s){var pair=s.split("=");params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params}function browserSupportsHistoryApi(){return window.history&&typeof window.history.pushState==="function"}function isHidden(elem){return elem.offsetHeight===0}var main=document.getElementById("main");var savedHash="";function handleHashes(ev){var elem;var search=getSearchElement();if(ev!==null&&search&&!hasClass(search,"hidden")&&ev.newURL){hideSearchResults(search);var hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(browserSupportsHistoryApi()){history.replaceState(hash,"","?search=#"+hash)}elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}if(savedHash!==window.location.hash){savedHash=window.location.hash;if(savedHash.length===0){return}elem=document.getElementById(savedHash.slice(1));if(!elem||!isHidden(elem)){return}var parent=elem.parentNode;if(parent&&hasClass(parent,"impl-items")){onEachLazy(parent.getElementsByClassName("collapsed"),function(e){if(e.parentNode===parent){e.click();return true}});if(isHidden(elem)){if(hasClass(parent.lastElementChild,"collapse-toggle")){parent.lastElementChild.click()}}}}}function highlightSourceLines(match,ev){if(typeof match==="undefined"){hideSidebar();match=window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/)}if(!match){return}var from=parseInt(match[1],10);var to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(to0){collapseDocs(collapses[0],"show")}}}}function getVirtualKey(ev){if("key"in ev&&typeof ev.key!="undefined"){return ev.key}var c=ev.charCode||ev.keyCode;if(c==27){return"Escape"}return String.fromCharCode(c)}function getHelpElement(){return document.getElementById("help")}function displayHelp(display,ev,help){help=help?help:getHelpElement();if(display===true){if(hasClass(help,"hidden")){ev.preventDefault();removeClass(help,"hidden");addClass(document.body,"blur")}}else if(hasClass(help,"hidden")===false){ev.preventDefault();addClass(help,"hidden");removeClass(document.body,"blur")}}function handleEscape(ev){var help=getHelpElement();var search=getSearchElement();if(hasClass(help,"hidden")===false){displayHelp(false,ev,help)}else if(hasClass(search,"hidden")===false){clearInputTimeout();ev.preventDefault();hideSearchResults(search);document.title=titleBeforeSearch}defocusSearchBar()}function handleShortcut(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts===true){return}if(document.activeElement.tagName==="INPUT"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":displayHelp(false,ev);ev.preventDefault();focusSearchBar();break;case"+":case"-":ev.preventDefault();toggleAllDocs();break;case"?":if(ev.shiftKey){displayHelp(true,ev)}break}}}function findParentElement(elem,tagName){do{if(elem&&elem.tagName===tagName){return elem}elem=elem.parentNode}while(elem);return null}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);function resetMouseMoved(ev){mouseMovedAfterSearch=true}document.addEventListener("mousemove",resetMouseMoved);var handleSourceHighlight=(function(){var prev_line_id=0;var set_fragment=function(name){var x=window.scrollX,y=window.scrollY;if(browserSupportsHistoryApi()){history.replaceState(null,null,"#"+name);highlightSourceLines()}else{location.replace("#"+name)}window.scrollTo(x,y)};return function(ev){var cur_line_id=parseInt(ev.target.id,10);ev.preventDefault();if(ev.shiftKey&&prev_line_id){if(prev_line_id>cur_line_id){var tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());document.addEventListener("click",function(ev){if(hasClass(ev.target,"collapse-toggle")){collapseDocs(ev.target,"toggle")}else if(hasClass(ev.target.parentNode,"collapse-toggle")){collapseDocs(ev.target.parentNode,"toggle")}else if(ev.target.tagName==="SPAN"&&hasClass(ev.target.parentNode,"line-numbers")){handleSourceHighlight(ev)}else if(hasClass(getHelpElement(),"hidden")===false){var help=getHelpElement();var is_inside_help_popup=ev.target!==help&&help.contains(ev.target);if(is_inside_help_popup===false){addClass(help,"hidden");removeClass(document.body,"blur")}}else{var a=findParentElement(ev.target,"A");if(a&&a.hash){expandSection(a.hash.replace(/^#/,""))}}});(function(){var x=document.getElementsByClassName("version-selector");if(x.length>0){x[0].onchange=function(){var i,match,url=document.location.href,stripped="",len=rootPath.match(/\.\.\//g).length+1;for(i=0;i-1){var obj=searchIndex[results[i].id];obj.lev=results[i].lev;if(isType!==true||obj.type){var res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=obj.displayPath+obj.name;obj.fullPath+="|"+obj.ty;obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}}return out}function sortResults(results,isType){var ar=[];for(var entry in results){if(hasOwnProperty(results,entry)){ar.push(results[entry])}}results=ar;var i;var nresults=results.length;for(i=0;ib?+1:-1)}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}if((aaa.item.ty===TY_PRIMITIVE&&bbb.item.ty!==TY_KEYWORD)||(aaa.item.ty===TY_KEYWORD&&bbb.item.ty!==TY_PRIMITIVE)){return-1}if((bbb.item.ty===TY_PRIMITIVE&&aaa.item.ty!==TY_PRIMITIVE)||(bbb.item.ty===TY_KEYWORD&&aaa.item.ty!==TY_KEYWORD)){return 1}a=(aaa.item.desc==="");b=(bbb.item.desc==="");if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});var length=results.length;for(i=0;i"));return{name:val.substring(0,val.indexOf("<")),generics:values.split(/\s*,\s*/),}}return{name:val,generics:[],}}function getObjectFromId(id){if(typeof id==="number"){return searchIndex[id]}return{'name':id}}function checkGenerics(obj,val){var lev_distance=MAX_LEV_DISTANCE+1;if(val.generics.length>0){if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>=val.generics.length){var elems=obj[GENERICS_DATA].slice(0);var total=0;var done=0;var vlength=val.generics.length;for(var y=0;yGENERICS_DATA&&obj[GENERICS_DATA].length>=val.generics.length){var elems=obj[GENERICS_DATA].slice(0);var allFound=true;for(var y=0;allFound===true&&yGENERICS_DATA&&obj[GENERICS_DATA].length!==0){var tmp_lev=checkGenerics(obj,val);if(tmp_lev<=MAX_LEV_DISTANCE){return tmp_lev}}else{return 0}}if(literalSearch===true){if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>0){var length=obj[GENERICS_DATA].length;for(x=0;xGENERICS_DATA&&obj[GENERICS_DATA].length>0){var olength=obj[GENERICS_DATA].length;for(x=0;x0){var length=obj.type[INPUTS_DATA].length;for(var i=0;iOUTPUT_DATA){var ret=obj.type[OUTPUT_DATA];if(typeof ret[0]==="string"){ret=[ret]}for(var x=0;xlength){return MAX_LEV_DISTANCE+1}for(var i=0;ilength){break}var lev_total=0;var aborted=false;for(var x=0;xMAX_LEV_DISTANCE){aborted=true;break}lev_total+=lev}if(aborted===false){ret_lev=Math.min(ret_lev,Math.round(lev_total/clength))}}return ret_lev}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER)return true;if(filter===type)return true;var name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function generateId(ty){if(ty.parent&&ty.parent.name){return itemTypes[ty.ty]+ty.path+ty.parent.name+ty.name}return itemTypes[ty.ty]+ty.path+ty.name}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,desc:item.desc,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,}}function handleAliases(ret,query,filterCrates){var aliases=[];var crateAliases=[];var i;if(filterCrates!==undefined){if(ALIASES[filterCrates]&&ALIASES[filterCrates][query.search]){for(i=0;iMAX_RESULTS){ret.others.pop()}};onEach(aliases,pushFunc);onEach(crateAliases,pushFunc)}var nSearchWords=searchWords.length;var i;var ty;var fullId;var returned;var in_args;if((val.charAt(0)==="\""||val.charAt(0)==="'")&&val.charAt(val.length-1)===val.charAt(0)){val=extractGenerics(val.substr(1,val.length-2));for(i=0;i")>-1){var trimmer=function(s){return s.trim()};var parts=val.split("->").map(trimmer);var input=parts[0];var inputs=input.split(",").map(trimmer).sort();for(i=0;i1?paths.length-1:1);var lev;for(j=0;j1){lev=checkPath(contains,paths[paths.length-1],ty);if(lev>MAX_LEV_DISTANCE){continue}else if(lev>0){lev_add=lev/10}}returned=MAX_LEV_DISTANCE+1;in_args=MAX_LEV_DISTANCE+1;var index=-1;lev=MAX_LEV_DISTANCE+1;fullId=generateId(ty);if(searchWords[j].indexOf(split[i])>-1||searchWords[j].indexOf(val)>-1||searchWords[j].replace(/_/g,"").indexOf(val)>-1){if(typePassesFilter(typeFilter,ty.ty)&&results[fullId]===undefined){index=searchWords[j].replace(/_/g,"").indexOf(val)}}if((lev=levenshtein(searchWords[j],val))<=MAX_LEV_DISTANCE){if(typePassesFilter(typeFilter,ty.ty)===false){lev=MAX_LEV_DISTANCE+1}else{lev+=1}}in_args=findArg(ty,valGenerics,false,typeFilter);returned=checkReturned(ty,valGenerics,false,typeFilter);lev+=lev_add;if(lev>0&&val.length>3&&searchWords[j].indexOf(val)>-1){if(val.length<6){lev-=1}else{lev=0}}if(in_args<=MAX_LEV_DISTANCE){if(results_in_args[fullId]===undefined){results_in_args[fullId]={id:j,index:index,lev:in_args,}}results_in_args[fullId].lev=Math.min(results_in_args[fullId].lev,in_args)}if(returned<=MAX_LEV_DISTANCE){if(results_returned[fullId]===undefined){results_returned[fullId]={id:j,index:index,lev:returned,}}results_returned[fullId].lev=Math.min(results_returned[fullId].lev,returned)}if(index!==-1||lev<=MAX_LEV_DISTANCE){if(index!==-1&&paths.length<2){lev=0}if(results[fullId]===undefined){results[fullId]={id:j,index:index,lev:lev,}}results[fullId].lev=Math.min(results[fullId].lev,lev)}}}var ret={"in_args":sortResults(results_in_args,true),"returned":sortResults(results_returned,true),"others":sortResults(results),};handleAliases(ret,query,filterCrates);return ret}function validateResult(name,path,keys,parent){for(var i=0;i-1||path.indexOf(keys[i])>-1||(parent!==undefined&&parent.name!==undefined&&parent.name.toLowerCase().indexOf(keys[i])>-1)||levenshtein(name,keys[i])<=MAX_LEV_DISTANCE)){return false}}return true}function getQuery(raw){var matches,type,query;query=raw;matches=query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);if(matches){type=matches[1].replace(/^const$/,"constant");query=query.substring(matches[0].length)}return{raw:raw,query:query,type:type,id:query+type}}function initSearchNav(){var hoverTimeout;var click_func=function(e){var el=e.target;while(el.tagName!=="TR"){el=el.parentNode}var dst=e.target.getElementsByTagName("a");if(dst.length<1){return}dst=dst[0];if(window.location.pathname===dst.pathname){hideSearchResults();document.location.href=dst.href}};var mouseover_func=function(e){if(mouseMovedAfterSearch){var el=e.target;while(el.tagName!=="TR"){el=el.parentNode}clearTimeout(hoverTimeout);hoverTimeout=setTimeout(function(){onEachLazy(document.getElementsByClassName("search-results"),function(e){onEachLazy(e.getElementsByClassName("result"),function(i_e){removeClass(i_e,"highlighted")})});addClass(el,"highlighted")},20)}};onEachLazy(document.getElementsByClassName("search-results"),function(e){onEachLazy(e.getElementsByClassName("result"),function(i_e){i_e.onclick=click_func;i_e.onmouseover=mouseover_func})});search_input.onkeydown=function(e){var actives=[[],[],[]];var current=0;onEachLazy(document.getElementById("results").childNodes,function(e){onEachLazy(e.getElementsByClassName("highlighted"),function(e){actives[current].push(e)});current+=1});if(e.which===38){if(!actives[currentTab].length||!actives[currentTab][0].previousElementSibling){return}addClass(actives[currentTab][0].previousElementSibling,"highlighted");removeClass(actives[currentTab][0],"highlighted");e.preventDefault()}else if(e.which===40){if(!actives[currentTab].length){var results=document.getElementById("results").childNodes;if(results.length>0){var res=results[currentTab].getElementsByClassName("result");if(res.length>0){addClass(res[0],"highlighted")}}}else if(actives[currentTab][0].nextElementSibling){addClass(actives[currentTab][0].nextElementSibling,"highlighted");removeClass(actives[currentTab][0],"highlighted")}e.preventDefault()}else if(e.which===13){if(actives[currentTab].length){document.location.href=actives[currentTab][0].getElementsByTagName("a")[0].href}}else if(e.which===9){if(e.shiftKey){printTab(currentTab>0?currentTab-1:2)}else{printTab(currentTab>1?0:currentTab+1)}e.preventDefault()}else if(e.which===16){}else if(actives[currentTab].length>0){removeClass(actives[currentTab][0],"highlighted")}}}function buildHrefAndPath(item){var displayPath;var href;var type=itemTypes[item.ty];var name=item.name;var path=item.path;if(type==="mod"){displayPath=path+"::";href=rootPath+path.replace(/::/g,"/")+"/"+name+"/index.html"}else if(type==="primitive"||type==="keyword"){displayPath="";href=rootPath+path.replace(/::/g,"/")+"/"+type+"."+name+".html"}else if(type==="externcrate"){displayPath="";href=rootPath+name+"/index.html"}else if(item.parent!==undefined){var myparent=item.parent;var anchor="#"+type+"."+name;var parentType=itemTypes[myparent.ty];var pageType=parentType;var pageName=myparent.name;if(parentType==="primitive"){displayPath=myparent.name+"::"}else if(type==="structfield"&&parentType==="variant"){var splitPath=item.path.split("::");var enumName=splitPath.pop();path=splitPath.join("::");displayPath=path+"::"+enumName+"::"+myparent.name+"::";anchor="#variant."+myparent.name+".field."+name;pageType="enum";pageName=enumName}else{displayPath=path+"::"+myparent.name+"::"}href=rootPath+path.replace(/::/g,"/")+"/"+pageType+"."+pageName+".html"+anchor}else{displayPath=item.path+"::";href=rootPath+item.path.replace(/::/g,"/")+"/"+type+"."+name+".html"}return[displayPath,href]}function escape(content){var h1=document.createElement("h1");h1.textContent=content;return h1.innerHTML}function pathSplitter(path){var tmp=""+path.replace(/::/g,"::");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}function addTab(array,query,display){var extraStyle="";if(display===false){extraStyle=" style=\"display: none;\""}var output="";var duplicates={};var length=0;if(array.length>0){output="";array.forEach(function(item){var name,type;name=item.name;type=itemTypes[item.ty];if(item.is_alias!==true){if(duplicates[item.fullPath]){return}duplicates[item.fullPath]=true}length+=1;output+=""});output+="
    "+""+(item.is_alias===true?(""+item.alias+"  - see "):"")+item.displayPath+""+name+""+""+""+escape(item.desc)+" 
    "}else{output="
    No results :(
    "+"Try on DuckDuckGo?

    "+"Or try looking in one of these:
    "}return[output,length]}function makeTabHeader(tabNb,text,nbElems){if(currentTab===tabNb){return"
    "+text+"
    ("+nbElems+")
    "}return"
    "+text+"
    ("+nbElems+")
    "}function showResults(results){if(results.others.length===1&&getCurrentValue("rustdoc-go-to-only-result")==="true"){var elem=document.createElement("a");elem.href=results.others[0].href;elem.style.display="none";document.body.appendChild(elem);elem.click()}var query=getQuery(search_input.value);currentResults=query.id;var ret_others=addTab(results.others,query);var ret_in_args=addTab(results.in_args,query,false);var ret_returned=addTab(results.returned,query,false);var output="

    Results for "+escape(query.query)+(query.type?" (type: "+escape(query.type)+")":"")+"

    "+"
    "+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
    "+ret_others[0]+ret_in_args[0]+ret_returned[0]+"
    ";var search=getSearchElement();search.innerHTML=output;showSearchResults(search);var tds=search.getElementsByTagName("td");var td_width=0;if(tds.length>0){td_width=tds[0].offsetWidth}var width=search.offsetWidth-40-td_width;onEachLazy(search.getElementsByClassName("desc"),function(e){e.style.width=width+"px"});initSearchNav();var elems=document.getElementById("titles").childNodes;elems[0].onclick=function(){printTab(0)};elems[1].onclick=function(){printTab(1)};elems[2].onclick=function(){printTab(2)};printTab(currentTab)}function execSearch(query,searchWords,filterCrates){function getSmallest(arrays,positions,notDuplicates){var start=null;for(var it=0;itpositions[it]&&(start===null||start>arrays[it][positions[it]].lev)&&!notDuplicates[arrays[it][positions[it]].fullPath]){start=arrays[it][positions[it]].lev}}return start}function mergeArrays(arrays){var ret=[];var positions=[];var notDuplicates={};for(var x=0;xpositions[x]&&arrays[x][positions[x]].lev===smallest&&!notDuplicates[arrays[x][positions[x]].fullPath]){ret.push(arrays[x][positions[x]]);notDuplicates[arrays[x][positions[x]].fullPath]=true;positions[x]+=1}}}return ret}var queries=query.raw.split(",");var results={"in_args":[],"returned":[],"others":[],};for(var i=0;i1){return{"in_args":mergeArrays(results.in_args),"returned":mergeArrays(results.returned),"others":mergeArrays(results.others),}}return{"in_args":results.in_args[0],"returned":results.returned[0],"others":results.others[0],}}function getFilterCrates(){var elem=document.getElementById("crate-search");if(elem&&elem.value!=="All crates"&&hasOwnProperty(rawSearchIndex,elem.value)){return elem.value}return undefined}function search(e,forced){var params=getQueryStringParams();var query=getQuery(search_input.value.trim());if(e){e.preventDefault()}if(query.query.length===0){return}if(forced!==true&&query.id===currentResults){if(query.query.length>0){putBackSearch(search_input)}return}document.title="Results for "+query.query+" - Rust";if(browserSupportsHistoryApi()){if(!history.state&&!params.search){history.pushState(query,"","?search="+encodeURIComponent(query.raw))}else{history.replaceState(query,"","?search="+encodeURIComponent(query.raw))}}var filterCrates=getFilterCrates();showResults(execSearch(query,index,filterCrates))}function buildIndex(rawSearchIndex){searchIndex=[];var searchWords=[];var i;var currentIndex=0;for(var crate in rawSearchIndex){if(!hasOwnProperty(rawSearchIndex,crate)){continue}var crateSize=0;searchWords.push(crate);searchIndex.push({crate:crate,ty:1,name:crate,path:"",desc:rawSearchIndex[crate].doc,type:null,});currentIndex+=1;var items=rawSearchIndex[crate].i;var paths=rawSearchIndex[crate].p;var aliases=rawSearchIndex[crate].a;var len=paths.length;for(i=0;i0){search_input.value=params.search;search(e)}else{search_input.value="";hideSearchResults()}})}search()}index=buildIndex(rawSearchIndex);startSearch();if(rootPath==="../"||rootPath==="./"){var sidebar=document.getElementsByClassName("sidebar-elems")[0];if(sidebar){var div=document.createElement("div");div.className="block crate";div.innerHTML="

    Crates

    ";var ul=document.createElement("ul");div.appendChild(ul);var crates=[];for(var crate in rawSearchIndex){if(!hasOwnProperty(rawSearchIndex,crate)){continue}crates.push(crate)}crates.sort();for(var i=0;i"+""+"
    "+code.outerHTML+"
    ";list.appendChild(display)}}};if(window.pending_implementors){window.register_implementors(window.pending_implementors)}function labelForToggleButton(sectionIsCollapsed){if(sectionIsCollapsed){return"+"}return"\u2212"}function onEveryMatchingChild(elem,className,func){if(elem&&className&&func){var length=elem.childNodes.length;var nodes=elem.childNodes;for(var i=0;i"+labelForToggleButton(sectionIsCollapsed)+"
    ]";return toggle}function createToggle(toggle,otherMessage,fontSize,extraClass,show){var span=document.createElement("span");span.className="toggle-label";if(show){span.style.display="none"}if(!otherMessage){span.innerHTML=" Expand description"}else{span.innerHTML=otherMessage}if(fontSize){span.style.fontSize=fontSize}var mainToggle=toggle.cloneNode(true);mainToggle.appendChild(span);var wrapper=document.createElement("div");wrapper.className="toggle-wrapper";if(!show){addClass(wrapper,"collapsed");var inner=mainToggle.getElementsByClassName("inner");if(inner&&inner.length>0){inner[0].innerHTML="+"}}if(extraClass){addClass(wrapper,extraClass)}wrapper.appendChild(mainToggle);return wrapper}(function(){var toggle=createSimpleToggle(false);var hideMethodDocs=getCurrentValue("rustdoc-auto-hide-method-docs")==="true";var pageId=getPageId();var func=function(e){var next=e.nextElementSibling;if(!next){return}if(hasClass(next,"docblock")===true||(hasClass(next,"stability")===true&&hasClass(next.nextElementSibling,"docblock")===true)){var newToggle=toggle.cloneNode(true);insertAfter(newToggle,e.childNodes[e.childNodes.length-1]);if(hideMethodDocs===true&&hasClass(e,"method")===true){collapseDocs(newToggle,"hide",pageId)}}};var funcImpl=function(e){var next=e.nextElementSibling;if(next&&hasClass(next,"docblock")){next=next.nextElementSibling}if(!next){return}if(hasClass(e,"impl")&&(next.getElementsByClassName("method").length>0||next.getElementsByClassName("associatedconstant").length>0)){insertAfter(toggle.cloneNode(true),e.childNodes[e.childNodes.length-1])}};onEachLazy(document.getElementsByClassName("method"),func);onEachLazy(document.getElementsByClassName("associatedconstant"),func);onEachLazy(document.getElementsByClassName("impl"),funcImpl);var impl_call=function(){};if(hideMethodDocs===true){impl_call=function(e,newToggle){if(e.id.match(/^impl(?:-\d+)?$/)===null){if(hasClass(e,"impl")===true){collapseDocs(newToggle,"hide",pageId)}}}}var newToggle=document.createElement("a");newToggle.href="javascript:void(0)";newToggle.className="collapse-toggle hidden-default collapsed";newToggle.innerHTML="["+labelForToggleButton(true)+"] Show hidden undocumented items";function toggleClicked(){if(hasClass(this,"collapsed")){removeClass(this,"collapsed");onEachLazy(this.parentNode.getElementsByClassName("hidden"),function(x){if(hasClass(x,"content")===false){removeClass(x,"hidden");addClass(x,"x")}},true);this.innerHTML="["+labelForToggleButton(false)+"] Hide undocumented items"}else{addClass(this,"collapsed");onEachLazy(this.parentNode.getElementsByClassName("x"),function(x){if(hasClass(x,"content")===false){addClass(x,"hidden");removeClass(x,"x")}},true);this.innerHTML="["+labelForToggleButton(true)+"] Show hidden undocumented items"}}onEachLazy(document.getElementsByClassName("impl-items"),function(e){onEachLazy(e.getElementsByClassName("associatedconstant"),func);var hiddenElems=e.getElementsByClassName("hidden");var needToggle=false;var hlength=hiddenElems.length;for(var i=0;iLoading search results...";showSearchResults(search)}var sidebar_menu=document.getElementsByClassName("sidebar-menu")[0];if(sidebar_menu){sidebar_menu.onclick=function(){var sidebar=document.getElementsByClassName("sidebar")[0];if(hasClass(sidebar,"mobile")===true){hideSidebar()}else{showSidebar()}}}window.onresize=function(){hideSidebar()};if(main){onEachLazy(main.getElementsByClassName("loading-content"),function(e){e.remove()});onEachLazy(main.childNodes,function(e){if(e.tagName==="H2"||e.tagName==="H3"){var nextTagName=e.nextElementSibling.tagName;if(nextTagName=="H2"||nextTagName=="H3"){e.nextElementSibling.style.display="flex"}else{e.nextElementSibling.style.display="block"}}})}window.addSearchOptions=function(crates){var elem=document.getElementById("crate-search");if(!elem){return}var crates_text=[];if(Object.keys(crates).length>1){for(var crate in crates){if(hasOwnProperty(crates,crate)){crates_text.push(crate)}}}crates_text.sort(function(a,b){var lower_a=a.toLowerCase();var lower_b=b.toLowerCase();if(lower_alower_b){return 1}return 0});var savedCrate=getCurrentValue("rustdoc-saved-filter-crate");for(var i=0;i"
    "+x[0]+"
    "+x[1]+"
    ").join("");var div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

    Keyboard Shortcuts

    "+shortcuts+"
    ";var infos=["Prefix searches with a type followed by a colon (e.g., fn:) to \ - restrict the search to a given type.","Accepted types are: fn, mod, struct, \ - enum, trait, type, macro, \ - and const.","Search functions by type signature (e.g., vec -> usize or \ - * -> vec)","Search multiple things at once by splitting your query with comma (e.g., \ - str,u8 or String,struct:Vec,test)","You can look for items with an exact name by putting double quotes around \ - your request: \"string\"","Look for items inside another one by searching for a path: vec::Vec",].map(x=>"

    "+x+"

    ").join("");var div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

    Search Tricks

    "+infos;container.appendChild(div_shortcuts);container.appendChild(div_infos);popup.appendChild(container);insertAfter(popup,getSearchElement())}onHashChange(null);window.onhashchange=onHashChange;buildHelperPopup()}());window.onunload=function(){} \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/normalize.css b/static/docs-rs/bdk/0.1.0-beta.1/normalize.css deleted file mode 100644 index 45b6cb2638..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/normalize.css +++ /dev/null @@ -1,2 +0,0 @@ -/*! normalize.css v3.0.0 | MIT License | git.io/normalize */ -html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/noscript.css b/static/docs-rs/bdk/0.1.0-beta.1/noscript.css deleted file mode 100644 index 351b41cf8e..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/noscript.css +++ /dev/null @@ -1 +0,0 @@ -#main>h2+div,#main>h2+h3,#main>h3+div{display:block;}.loading-content{display:none;}#main>h2+div,#main>h3+div{display:block;}#main>h2+h3{display:flex;} \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/rust-logo.png b/static/docs-rs/bdk/0.1.0-beta.1/rust-logo.png deleted file mode 100644 index 74b4bd6950..0000000000 Binary files a/static/docs-rs/bdk/0.1.0-beta.1/rust-logo.png and /dev/null differ diff --git a/static/docs-rs/bdk/0.1.0-beta.1/rustdoc.css b/static/docs-rs/bdk/0.1.0-beta.1/rustdoc.css deleted file mode 100644 index cbf40b2271..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/rustdoc.css +++ /dev/null @@ -1 +0,0 @@ - @font-face {font-family:'Fira Sans';font-style:normal;font-weight:400;src:local('Fira Sans'),url("FiraSans-Regular.woff") format('woff');}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:500;src:local('Fira Sans Medium'),url("FiraSans-Medium.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:normal;font-weight:400;src:local('Source Serif Pro'),url("SourceSerifPro-Regular.ttf.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:italic;font-weight:400;src:local('Source Serif Pro Italic'),url("SourceSerifPro-It.ttf.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:normal;font-weight:700;src:local('Source Serif Pro Bold'),url("SourceSerifPro-Bold.ttf.woff") format('woff');}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("SourceCodePro-Regular.woff") format('woff');}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("SourceCodePro-Semibold.woff") format('woff');}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}html{content:"";}@media (prefers-color-scheme:light){html{content:"light";}}@media (prefers-color-scheme:dark){html{content:"dark";}}body{font:16px/1.4 "Source Serif Pro",serif;margin:0;position:relative;padding:10px 15px 20px 15px;-webkit-font-feature-settings:"kern","liga";-moz-font-feature-settings:"kern","liga";font-feature-settings:"kern","liga";}h1{font-size:1.5em;}h2{font-size:1.4em;}h3{font-size:1.3em;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod):not(.important),h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){font-weight:500;margin:20px 0 15px 0;padding-bottom:6px;}h1.fqn{border-bottom:1px dashed;margin-top:0;}h1.fqn>.in-band>a:hover{text-decoration:underline;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){border-bottom:1px solid;}h3.impl,h3.method,h4.method,h3.type,h4.type,h4.associatedconstant{flex-basis:100%;font-weight:600;margin-top:16px;margin-bottom:10px;position:relative;}h3.impl,h3.method,h3.type{padding-left:15px;}h1,h2,h3,h4,.sidebar,a.source,.search-input,.content table :not(code)>a,.collapse-toggle,div.item-list .out-of-band,#source-sidebar,#sidebar-toggle{font-family:"Fira Sans",sans-serif;}ol,ul{padding-left:25px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:.6em;}p{margin:0 0 .6em 0;}summary{outline:none;}code,pre,a.test-arrow{font-family:"Source Code Pro",monospace;}.docblock code,.docblock-short code{border-radius:3px;padding:0 0.1em;}.docblock pre code,.docblock-short pre code{padding:0;}pre{padding:14px;}.source .content pre{padding:20px;}img{max-width:100%;}li{position:relative;}.source .content{margin-top:50px;max-width:none;overflow:visible;margin-left:0px;min-width:70em;}nav.sub{font-size:16px;text-transform:uppercase;}.sidebar{width:200px;position:fixed;left:0;top:0;bottom:0;overflow:auto;}*{scrollbar-width:initial;}.sidebar{scrollbar-width:thin;}::-webkit-scrollbar{width:12px;}.sidebar::-webkit-scrollbar{width:8px;}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0;}.sidebar .block>ul>li{margin-right:-10px;}.content,nav{max-width:960px;}.hidden{display:none !important;}.logo-container{height:100px;width:100px;position:relative;margin:20px auto;display:block;margin-top:10px;}.logo-container>img{max-width:100px;max-height:100px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);display:block;}.sidebar .location{border:1px solid;font-size:17px;margin:30px 10px 20px 10px;text-align:center;word-wrap:break-word;}.sidebar .version{font-size:15px;text-align:center;border-bottom:1px solid;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;}.location:empty{border:none;}.location a:first-child{font-weight:500;}.block{padding:0;margin-bottom:14px;}.block h2,.block h3{margin-top:0;margin-bottom:8px;text-align:center;}.block ul,.block li{margin:0 10px;padding:0;list-style:none;}.block a{display:block;text-overflow:ellipsis;overflow:hidden;line-height:15px;padding:7px 5px;font-size:14px;font-weight:300;transition:border 500ms ease-out;}.sidebar-title{border-top:1px solid;border-bottom:1px solid;text-align:center;font-size:17px;margin-bottom:5px;}.sidebar-links{margin-bottom:15px;}.sidebar-links>a{padding-left:10px;width:100%;}.sidebar-menu{display:none;}.content{padding:15px 0;}.source .content pre.rust{white-space:pre;overflow:auto;padding-left:0;}.rustdoc:not(.source) .example-wrap{display:inline-flex;margin-bottom:10px;position:relative;}.example-wrap{width:100%;}.example-wrap>pre.line-number{overflow:initial;border:1px solid;border-top-left-radius:5px;border-bottom-left-radius:5px;padding:13px 8px;text-align:right;}.rustdoc:not(.source) .example-wrap>pre.rust{width:100%;overflow-x:auto;}.rustdoc:not(.source) .example-wrap>pre{margin:0;}#search{margin-left:230px;position:relative;}#results{position:absolute;right:0;left:0;overflow:auto;}#results>table{width:100%;table-layout:fixed;}.content pre.line-numbers{float:left;border:none;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}.line-numbers span{cursor:pointer;}.docblock-short p{display:inline;}.docblock-short.nowrap{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.docblock-short p{overflow:hidden;text-overflow:ellipsis;margin:0;}.docblock code,.docblock-short code{white-space:pre-wrap;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom:1px solid;}#main>.docblock h1{font-size:1.3em;}#main>.docblock h2{font-size:1.15em;}#main>.docblock h3,#main>.docblock h4,#main>.docblock h5{font-size:1em;}#main>h2+div,#main>h2+h3,#main>h3+div{display:none;flex-wrap:wrap;}.docblock h1{font-size:1em;}.docblock h2{font-size:0.95em;}.docblock h3,.docblock h4,.docblock h5{font-size:0.9em;}.docblock{margin-left:24px;position:relative;}.content .out-of-band{float:right;font-size:23px;margin:0px;padding:0px;font-weight:normal;}h3.impl>.out-of-band{font-size:21px;}h4.method>.out-of-band{font-size:19px;}h4>code,h3>code,.invisible>code{max-width:calc(100% - 41px);display:block;}.invisible{width:100%;display:inline-block;}.content .in-band{margin:0px;padding:0px;}.in-band>code{display:inline-block;}#main{position:relative;}#main>.since{top:inherit;font-family:"Fira Sans",sans-serif;}.content table:not(.table-display){border-spacing:0 5px;}.content td{vertical-align:top;}.content td:first-child{padding-right:20px;}.content td p:first-child{margin-top:0;}.content td h1,.content td h2{margin-left:0;font-size:1.1em;}.content tr:first-child td{border-top:0;}.docblock table{margin:.5em 0;width:calc(100% - 2px);border:1px dashed;}.docblock table td{padding:.5em;border:1px dashed;}.docblock table th{padding:.5em;text-align:left;border:1px solid;}.fields+table{margin-bottom:1em;}.content .item-list{list-style-type:none;padding:0;}.content .multi-column{-moz-column-count:5;-moz-column-gap:2.5em;-webkit-column-count:5;-webkit-column-gap:2.5em;column-count:5;column-gap:2.5em;}.content .multi-column li{width:100%;display:inline-block;}.content .method{font-size:1em;position:relative;}.content .method .where,.content .fn .where,.content .where.fmt-newline{display:block;font-size:0.8em;}.content .methods>div{margin-left:40px;margin-bottom:15px;}.content .docblock>.impl-items{margin-left:20px;margin-top:-34px;}.content .docblock>.impl-items>h4{border-bottom:0;}.content .docblock>.impl-items .table-display{margin:0;}.content .docblock>.impl-items table td{padding:0;}.toggle-wrapper.marg-left>.collapse-toggle{left:-24px;}.content .docblock>.impl-items .table-display,.impl-items table td{border:none;}.content .stability code{font-size:90%;}.content .stability{position:relative;margin-left:33px;margin-top:-13px;}.sub-variant>div>.stability{margin-top:initial;}.content .stability::before{content:'⬑';font-size:25px;position:absolute;top:-6px;left:-19px;}.content .impl-items .method,.content .impl-items>.type,.impl-items>.associatedconstant{margin-left:20px;}.content .impl-items .docblock,.content .impl-items .stability{margin-bottom:.6em;}.content .impl-items>.stability{margin-left:40px;}.methods>.stability,.content .impl-items>.stability{margin-top:-8px;}.impl-items{flex-basis:100%;}#main>.stability{margin-top:0;}nav:not(.sidebar){border-bottom:1px solid;padding-bottom:10px;margin-bottom:10px;}nav.main{padding:20px 0;text-align:center;}nav.main .current{border-top:1px solid;border-bottom:1px solid;}nav.main .separator{border:1px solid;display:inline-block;height:23px;margin:0 20px;}nav.sum{text-align:right;}nav.sub form{display:inline;}nav.sub,.content{margin-left:230px;}a{text-decoration:none;background:transparent;}.small-section-header:hover>.anchor{display:initial;}.in-band:hover>.anchor,.impl:hover>.anchor{display:inline-block;position:absolute;}.anchor{display:none;position:absolute;left:-7px;}.anchor.field{left:-5px;}.small-section-header>.anchor{left:-28px;padding-right:10px;}.anchor:before{content:'\2002\00a7\2002';}.docblock a:not(.srclink):not(.test-arrow):hover,.docblock-short a:not(.srclink):not(.test-arrow):hover,.stability a{text-decoration:underline;}.invisible>.srclink,h4>code+.srclink{position:absolute;top:0;right:0;font-size:17px;font-weight:normal;}.block a.current.crate{font-weight:500;}.search-container{position:relative;}.search-container>div{display:inline-flex;width:calc(100% - 34px);}#crate-search{margin-top:5px;padding:6px;padding-right:19px;flex:none;border:0;border-right:0;border-radius:4px 0 0 4px;outline:none;cursor:pointer;border-right:1px solid;-moz-appearance:none;-webkit-appearance:none;text-indent:0.01px;text-overflow:"";background-repeat:no-repeat;background-color:transparent;background-size:20px;background-position:calc(100% - 1px) 56%;}.search-container>.top-button{position:absolute;right:0;top:10px;}.search-input{-moz-box-sizing:border-box !important;box-sizing:border-box !important;outline:none;border:none;border-radius:1px;margin-top:5px;padding:10px 16px;font-size:17px;transition:border-color 300ms ease;transition:border-radius 300ms ease-in-out;transition:box-shadow 300ms ease-in-out;width:100%;}#crate-search+.search-input{border-radius:0 1px 1px 0;width:calc(100% - 32px);}.search-input:focus{border-radius:2px;border:0;outline:0;}.search-results .desc{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;display:block;}.search-results a{display:block;}.content .search-results td:first-child{padding-right:0;width:50%;}.content .search-results td:first-child a{padding-right:10px;}.content .search-results td:first-child a:after{clear:both;content:"";display:block;}.content .search-results td:first-child a span{float:left;}tr.result span.primitive::after{content:' (primitive type)';font-style:italic;}tr.result span.keyword::after{content:' (keyword)';font-style:italic;}body.blur>:not(#help){filter:blur(8px);-webkit-filter:blur(8px);opacity:.7;}#help{width:100%;height:100vh;position:fixed;top:0;left:0;display:flex;justify-content:center;align-items:center;}#help>div{flex:0 0 auto;box-shadow:0 0 6px rgba(0,0,0,.2);width:550px;height:auto;border:1px solid;}#help dt{float:left;clear:left;display:block;}#help dd{margin:5px 35px;}#help .infos{padding-left:0;}#help h1,#help h2{margin-top:0;}#help>div div{width:50%;float:left;padding:20px;padding-left:17px;}.stab{display:table;border-width:1px;border-style:solid;padding:3px;margin-bottom:5px;font-size:90%;}.stab p{display:inline;}.stab summary{display:list-item;}.stab .emoji{font-size:1.5em;}.module-item .stab{border-radius:3px;display:inline-block;font-size:80%;line-height:1.2;margin-bottom:0;margin-right:.3em;padding:2px;vertical-align:text-bottom;}.module-item.unstable{opacity:0.65;}.since{font-weight:normal;font-size:initial;position:absolute;right:0;top:0;}.impl-items .since,.impl .since{flex-grow:0;padding-left:12px;padding-right:2px;position:initial;}.impl-items .srclink,.impl .srclink{flex-grow:0;font-size:17px;font-weight:normal;}.impl-items code,.impl code{flex-grow:1;}.impl-items h4,h4.impl,h3.impl{display:flex;flex-basis:100%;font-size:16px;margin-bottom:12px;justify-content:space-between;}.variants_table{width:100%;}.variants_table tbody tr td:first-child{width:1%;}td.summary-column{width:100%;}.summary{padding-right:0px;}pre.rust .question-mark{font-weight:bold;}a.test-arrow{display:inline-block;position:absolute;padding:5px 10px 5px 10px;border-radius:5px;font-size:130%;top:5px;right:5px;z-index:1;}a.test-arrow:hover{text-decoration:none;}.section-header:hover a:before{position:absolute;left:-25px;padding-right:10px;content:'\2002\00a7\2002';}.section-header:hover a{text-decoration:none;}.section-header a{color:inherit;}.collapse-toggle{font-weight:300;position:absolute;left:-23px;top:0;}h3>.collapse-toggle,h4>.collapse-toggle{font-size:0.8em;top:5px;}.toggle-wrapper>.collapse-toggle{left:-24px;margin-top:0px;}.toggle-wrapper{position:relative;margin-top:0;}.toggle-wrapper.collapsed{height:25px;transition:height .2s;margin-bottom:.6em;}.collapse-toggle>.inner{display:inline-block;width:1.2ch;text-align:center;}.collapse-toggle.hidden-default{position:relative;margin-left:20px;}.since+.srclink{display:table-cell;padding-left:10px;}.item-spacer{width:100%;height:12px;}.out-of-band>span.since{position:initial;font-size:20px;margin-right:5px;}.toggle-wrapper>.collapse-toggle{left:0;}.variant+.toggle-wrapper+.docblock>p{margin-top:5px;}.sub-variant,.sub-variant>h3{margin-top:1px !important;}#main>.sub-variant>h3{font-size:15px;margin-left:25px;margin-bottom:5px;}.sub-variant>div{margin-left:20px;margin-bottom:10px;}.sub-variant>div>span{display:block;position:relative;}.toggle-label{display:inline-block;margin-left:4px;margin-top:3px;}.enum>.toggle-wrapper+.docblock,.struct>.toggle-wrapper+.docblock{margin-left:30px;margin-bottom:20px;margin-top:5px;}.docblock>.section-header:first-child{margin-left:15px;margin-top:0;}.docblock>.section-header:first-child:hover>a:before{left:-10px;}.enum>.collapsed,.struct>.collapsed{margin-bottom:25px;}#main>.variant,#main>.structfield{display:block;}.attributes{display:block;margin-top:0px !important;margin-right:0px;margin-bottom:0px !important;margin-left:30px;}.toggle-attributes.collapsed{margin-bottom:0;}.impl-items>.toggle-attributes{margin-left:20px;}.impl-items .attributes{font-weight:500;}:target>code{opacity:1;}.information{position:absolute;left:-25px;margin-top:7px;z-index:1;}.tooltip{position:relative;display:inline-block;cursor:pointer;}.tooltip .tooltiptext{width:120px;display:none;text-align:center;padding:5px 3px 3px 3px;border-radius:6px;margin-left:5px;top:-5px;left:105%;z-index:10;font-size:16px;}.tooltip:hover .tooltiptext{display:inline;}.tooltip .tooltiptext::after{content:" ";position:absolute;top:50%;left:16px;margin-top:-5px;border-width:5px;border-style:solid;}.tooltip.compile_fail,.tooltip.should_panic,.tooltip.ignore{font-weight:bold;font-size:20px;}.tooltip .tooltiptext{border:1px solid;font-weight:normal;}pre.rust{position:relative;tab-size:4;-moz-tab-size:4;}.search-failed{text-align:center;margin-top:20px;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#titles{height:35px;}#titles>div{float:left;width:33.3%;text-align:center;font-size:18px;cursor:pointer;border-top:2px solid;}#titles>div:not(:last-child){margin-right:1px;width:calc(33.3% - 1px);}#titles>div>div.count{display:inline-block;font-size:16px;}#all-types{text-align:center;border:1px solid;margin:0 10px;margin-bottom:10px;display:block;border-radius:7px;}#all-types>p{margin:5px 0;}#sidebar-toggle{position:fixed;top:30px;left:300px;z-index:10;padding:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;cursor:pointer;font-weight:bold;transition:left .5s;font-size:1.2em;border:1px solid;border-left:0;}#source-sidebar{position:fixed;top:0;bottom:0;left:0;width:300px;z-index:1;overflow:auto;transition:left .5s;border-right:1px solid;}#source-sidebar>.title{font-size:1.5em;text-align:center;border-bottom:1px solid;margin-bottom:6px;}.theme-picker{position:absolute;left:211px;top:19px;}.theme-picker button{outline:none;}#settings-menu{position:absolute;right:0;top:10px;outline:none;}#theme-picker,#settings-menu{padding:4px;width:27px;height:29px;border:1px solid;border-radius:3px;cursor:pointer;}#theme-choices{display:none;position:absolute;left:0;top:28px;border:1px solid;border-radius:3px;z-index:1;cursor:pointer;}#theme-choices>button{border:none;width:100%;padding:4px;text-align:center;background:rgba(0,0,0,0);}#theme-choices>button:not(:first-child){border-top:1px solid;}@media (max-width:700px){body{padding-top:0px;}.rustdoc>.sidebar{height:45px;min-height:40px;margin:0;margin-left:-15px;padding:0 15px;position:static;z-index:11;}.sidebar>.location{float:right;margin:0px;margin-top:2px;padding:3px 10px 1px 10px;min-height:39px;background:inherit;text-align:left;font-size:24px;}.sidebar .location:empty{padding:0;}.sidebar .logo-container{width:35px;height:35px;margin-top:5px;margin-bottom:5px;float:left;margin-left:50px;}.sidebar .logo-container>img{max-width:35px;max-height:35px;}.sidebar-menu{position:fixed;z-index:10;font-size:2rem;cursor:pointer;width:45px;left:0;text-align:center;display:block;border-bottom:1px solid;border-right:1px solid;height:45px;}.rustdoc.source>.sidebar>.sidebar-menu{display:none;}.sidebar-elems{position:fixed;z-index:1;left:0;top:45px;bottom:0;overflow-y:auto;border-right:1px solid;display:none;}.sidebar>.block.version{border-bottom:none;margin-top:12px;}nav.sub{width:calc(100% - 32px);float:right;}.content{margin-left:0px;}#main{margin-top:45px;padding:0;}.content .in-band{width:100%;}.content h4>.out-of-band{position:inherit;}.toggle-wrapper>.collapse-toggle{left:0px;}.toggle-wrapper{height:1.5em;}#search{margin-left:0;}.content .impl-items .method,.content .impl-items>.type,.impl-items>.associatedconstant{display:flex;}.anchor{display:none !important;}h1.fqn{overflow:initial;}.theme-picker{left:10px;top:54px;z-index:1;}#titles>div>div.count{float:left;width:100%;}#titles{height:50px;}.sidebar.mobile{position:fixed;width:100%;margin-left:0;background-color:rgba(0,0,0,0);height:100%;}.sidebar{width:calc(100% + 30px);}.show-it{display:block;width:246px;}.show-it>.block.items{margin:8px 0;}.show-it>.block.items>ul{margin:0;}.show-it>.block.items>ul>li{text-align:center;margin:2px 0;}.show-it>.block.items>ul>li>a{font-size:21px;}#sidebar-filler{position:fixed;left:45px;width:calc(100% - 45px);top:0;height:45px;z-index:-1;border-bottom:1px solid;}.collapse-toggle{left:-20px;}.impl>.collapse-toggle{left:-10px;}#all-types{margin:10px;}#sidebar-toggle{top:100px;width:30px;font-size:1.5rem;text-align:center;padding:0;}#source-sidebar{z-index:11;}#main>.line-numbers{margin-top:0;}}@media print{nav.sub,.content .out-of-band,.collapse-toggle{display:none;}}@media (max-width:416px){#titles{height:73px;}#titles>div{height:73px;}}h3.important{margin:0;margin-bottom:13px;font-size:19px;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px;border-radius:3px;box-shadow:inset 0 -1px 0;cursor:default;}.hidden-by-impl-hider,.hidden-by-usual-hider{display:none !important;}#implementations-list>h3>span.in-band{width:100%;}.table-display{width:100%;border:0;border-collapse:collapse;border-spacing:0;font-size:16px;}.table-display tr td:first-child{padding-right:0;}.table-display tr td:last-child{float:right;}.table-display .out-of-band{position:relative;font-size:19px;display:block;}#implementors-list>.impl-items .table-display .out-of-band{font-size:17px;}.table-display td:hover .anchor{display:block;top:2px;left:-5px;}#main>ul{padding-left:10px;}#main>ul>li{list-style:none;}.non-exhaustive{margin-bottom:1em;}div.children{padding-left:27px;display:none;}div.name{cursor:pointer;position:relative;margin-left:16px;}div.files>a{display:block;padding:0 3px;}div.files>a:hover,div.name:hover{background-color:#a14b4b;}div.name.expand+.children{display:block;}div.name::before{content:"\25B6";padding-left:4px;font-size:0.7em;position:absolute;left:-16px;top:4px;}div.name.expand::before{transform:rotate(90deg);left:-15px;top:2px;}.type-decl>pre>.toggle-wrapper.toggle-attributes.top-attr{margin-left:0 !important;}.type-decl>pre>.docblock.attributes.top-attr{margin-left:1.8em !important;}.type-decl>pre>.toggle-attributes{margin-left:2.2em;}.type-decl>pre>.docblock.attributes{margin-left:4em;} \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/search-index.js b/static/docs-rs/bdk/0.1.0-beta.1/search-index.js deleted file mode 100644 index ee6d03afb2..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/search-index.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchIndex = JSON.parse('{\ -"bdk":{"doc":"","i":[[3,"FeeRate","bdk","Fee rate",null,null],[3,"UTXO","","A wallet unspent output",null,null],[12,"outpoint","","",0,null],[12,"txout","","",0,null],[12,"is_internal","","",0,null],[3,"TransactionDetails","","A wallet transaction",null,null],[12,"transaction","","",1,null],[12,"txid","","",1,null],[12,"timestamp","","",1,null],[12,"received","","",1,null],[12,"sent","","",1,null],[12,"fees","","",1,null],[12,"height","","",1,null],[4,"Error","","Errors that can be thrown by the `Wallet`",null,null],[13,"KeyMismatch","","",2,null],[13,"MissingInputUTXO","","",2,null],[13,"InvalidU32Bytes","","",2,null],[13,"Generic","","",2,null],[13,"ScriptDoesntHaveAddressForm","","",2,null],[13,"SendAllMultipleOutputs","","",2,null],[13,"NoAddressees","","",2,null],[13,"OutputBelowDustLimit","","",2,null],[13,"InsufficientFunds","","",2,null],[13,"InvalidAddressNetwork","","",2,null],[13,"UnknownUTXO","","",2,null],[13,"DifferentTransactions","","",2,null],[13,"TransactionNotFound","","",2,null],[13,"TransactionConfirmed","","",2,null],[13,"IrreplaceableTransaction","","",2,null],[13,"FeeRateTooLow","","",2,null],[12,"required","bdk::Error","",3,null],[13,"ChecksumMismatch","bdk","",2,null],[13,"DifferentDescriptorStructure","","",2,null],[13,"SpendingPolicyRequired","","",2,null],[13,"InvalidPolicyPathError","","",2,null],[13,"Signer","","",2,null],[13,"Uncapable","","",2,null],[13,"OfflineClient","","",2,null],[13,"InvalidProgressValue","","",2,null],[13,"ProgressUpdateError","","",2,null],[13,"MissingCachedAddresses","","",2,null],[13,"InvalidOutpoint","","",2,null],[13,"Descriptor","","",2,null],[13,"AddressValidator","","",2,null],[13,"Encode","","",2,null],[13,"Miniscript","","",2,null],[13,"BIP32","","",2,null],[13,"Secp256k1","","",2,null],[13,"JSON","","",2,null],[13,"Hex","","",2,null],[13,"PSBT","","",2,null],[13,"Electrum","","",2,null],[13,"Esplora","","",2,null],[13,"CompactFilters","","",2,null],[13,"Sled","","",2,null],[4,"ScriptType","","Types of script",null,null],[13,"External","","",4,null],[13,"Internal","","",4,null],[0,"blockchain","","Blockchain backends",null,null],[3,"OfflineBlockchain","bdk::blockchain","Type that only implements [`Blockchain`] and is always…",null,null],[3,"NoopProgress","","Type that implements [`Progress`] and drops every update…",null,null],[3,"LogProgress","","Type that implements [`Progress`] and logs at level `INFO`…",null,null],[4,"Capability","","Capabilities that can be supported by a [`Blockchain`]…",null,null],[13,"FullHistory","","Can recover the full history of a wallet and not only the…",5,null],[13,"GetAnyTx","","Can fetch any historical transaction given its txid",5,null],[13,"AccurateFees","","Can compute accurate fees for the transactions found…",5,null],[5,"progress","","Shortcut to create a [`channel`] (pair of [`Sender`] and…",null,[[]]],[5,"noop_progress","","Create a new instance of [`NoopProgress`]",null,[[],["noopprogress",3]]],[5,"log_progress","","Create a nwe instance of [`LogProgress`]",null,[[],["logprogress",3]]],[0,"electrum","","Electrum",null,null],[3,"ElectrumBlockchain","bdk::blockchain::electrum","Wrapper over an Electrum Client that implements the…",null,null],[0,"esplora","bdk::blockchain","Esplora",null,null],[3,"EsploraBlockchain","bdk::blockchain::esplora","Structure that implements the logic to sync with Esplora",null,null],[4,"EsploraError","","Errors that can happen during a sync with…",null,null],[13,"Reqwest","","Error with the HTTP call",6,null],[13,"Parsing","","Invalid number returned",6,null],[13,"BitcoinEncoding","","Invalid Bitcoin data returned",6,null],[13,"TransactionNotFound","","Transaction not found",6,null],[11,"new","","Create a new instance of the client from a base URL",7,[[]]],[0,"compact_filters","bdk::blockchain","Compact Filters",null,null],[3,"Mempool","bdk::blockchain::compact_filters","Container for unconfirmed, but valid Bitcoin transactions",null,null],[3,"Peer","","A Bitcoin peer",null,null],[3,"CompactFiltersBlockchain","","Structure implementing the required blockchain traits",null,null],[4,"CompactFiltersError","","An error that can occur during sync with a…",null,null],[13,"InvalidResponse","","A peer sent an invalid or unexpected response",8,null],[13,"InvalidHeaders","","The headers returned are invalid",8,null],[13,"InvalidFilterHeader","","The compact filter headers returned are invalid",8,null],[13,"InvalidFilter","","The compact filter returned is invalid",8,null],[13,"MissingBlock","","The peer is missing a block in the valid chain",8,null],[13,"DataCorruption","","The data stored in the block filters storage are corrupted",8,null],[13,"NotConnected","","A peer is not connected",8,null],[13,"Timeout","","A peer took too long to reply to one of our messages",8,null],[13,"NoPeers","","No peers have been specified",8,null],[13,"DB","","Internal database error",8,null],[13,"IO","","Internal I/O error",8,null],[13,"BIP158","","Invalid BIP158 filter",8,null],[13,"Time","","Internal system time error",8,null],[13,"Global","","Wrapper for [`crate::error::Error`]",8,null],[11,"add_tx","","Add a transaction to the mempool",9,[[["transaction",3]]]],[11,"get_tx","","Look-up a transaction in the mempool given an…",9,[[["inventory",4]],[["option",4],["transaction",3]]]],[11,"has_tx","","Return whether or not the mempool contains a transaction…",9,[[["txid",3]]]],[11,"iter_txs","","Return the list of transactions contained in the mempool",9,[[],[["transaction",3],["vec",3]]]],[11,"connect","","Connect to a peer over a plaintext TCP connection",10,[[["tosocketaddrs",8],["network",4],["arc",3],["mempool",3]],[["result",4],["compactfilterserror",4]]]],[11,"connect_proxy","","Connect to a peer through a SOCKS5 proxy, optionally by…",10,[[["tosocketaddrs",8],["option",4],["totargetaddr",8],["arc",3],["mempool",3],["network",4]],[["result",4],["compactfilterserror",4]]]],[11,"get_version","","Return the [`VersionMessage`] sent by the peer",10,[[],["versionmessage",3]]],[11,"get_network","","Return the Bitcoin [`Network`] in use",10,[[],["network",4]]],[11,"get_mempool","","Return the mempool used by this peer",10,[[],[["arc",3],["mempool",3]]]],[11,"is_connected","","Return whether or not the peer is still connected",10,[[]]],[11,"send","","Send a raw Bitcoin message to the peer",10,[[["networkmessage",4]],[["compactfilterserror",4],["result",4]]]],[11,"recv","","Waits for a specific incoming Bitcoin message, optionally…",10,[[["option",4],["duration",3]],[["option",4],["compactfilterserror",4],["result",4]]]],[11,"new","","Construct a new instance given a list of peers, a path to…",11,[[["asref",8],["path",3],["option",4],["vec",3],["peer",3]],[["result",4],["compactfilterserror",4]]]],[6,"ProgressData","bdk::blockchain","Data sent with a progress update over a [`channel`]",null,null],[8,"BlockchainMarker","","Marker trait for a blockchain backend",null,null],[8,"Blockchain","","Trait that defines the actions that must be supported by a…",null,null],[10,"get_capabilities","","Return the set of [`Capability`] supported by this backend",12,[[],[["capability",4],["hashset",3]]]],[10,"setup","","Setup the backend and populate the internal database for…",12,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"sync","","Populate the internal database with transactions and UTXOs",12,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[10,"get_tx","","Fetch a transaction from the blockchain given its txid",12,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[10,"broadcast","","Broadcast a transaction",12,[[["transaction",3]],[["error",4],["result",4]]]],[10,"get_height","","Return the current height",12,[[],[["result",4],["error",4]]]],[10,"estimate_fee","","Estimate the fee rate required to confirm a transaction in…",12,[[],[["feerate",3],["error",4],["result",4]]]],[8,"Progress","","Trait for types that can receive and process progress…",null,null],[10,"update","","Send a new progress update",13,[[["string",3],["option",4]],[["error",4],["result",4]]]],[0,"database","bdk","Database types",null,null],[0,"memory","bdk::database","In-memory ephemeral database",null,null],[3,"MemoryDatabase","bdk::database::memory","In-memory ephemeral database",null,null],[11,"new","","Create a new empty database",14,[[]]],[8,"BatchOperations","bdk::database","Trait for operations that can be batched",null,null],[10,"set_script_pubkey","","Store a script_pubkey along with its script type and child…",15,[[["scripttype",4],["script",3]],[["error",4],["result",4]]]],[10,"set_utxo","","Store a [`UTXO`]",15,[[["utxo",3]],[["error",4],["result",4]]]],[10,"set_raw_tx","","Store a raw transaction",15,[[["transaction",3]],[["error",4],["result",4]]]],[10,"set_tx","","Store the metadata of a transaction",15,[[["transactiondetails",3]],[["error",4],["result",4]]]],[10,"set_last_index","","Store the last derivation index for a given script type",15,[[["scripttype",4]],[["error",4],["result",4]]]],[10,"del_script_pubkey_from_path","","Delete a script_pubkey given the script type and its child…",15,[[["scripttype",4]],[["error",4],["option",4],["result",4]]]],[10,"del_path_from_script_pubkey","","Delete the data related to a specific script_pubkey,…",15,[[["script",3]],[["option",4],["error",4],["result",4]]]],[10,"del_utxo","","Delete a [`UTXO`] given its [`OutPoint`]",15,[[["outpoint",3]],[["result",4],["error",4],["option",4]]]],[10,"del_raw_tx","","Delete a raw transaction given its [`Txid`]",15,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[10,"del_tx","","Delete the metadata of a transaction and optionally the…",15,[[["txid",3]],[["option",4],["error",4],["result",4]]]],[10,"del_last_index","","Delete the last derivation index for a script type",15,[[["scripttype",4]],[["result",4],["option",4],["error",4]]]],[8,"Database","","Trait for reading data from a database",null,null],[10,"check_descriptor_checksum","","Read and checks the descriptor checksum for a given script…",16,[[["scripttype",4],["asref",8]],[["error",4],["result",4]]]],[10,"iter_script_pubkeys","","Return the list of script_pubkeys",16,[[["option",4],["scripttype",4]],[["result",4],["vec",3],["error",4]]]],[10,"iter_utxos","","Return the list of [`UTXO`]s",16,[[],[["result",4],["vec",3],["error",4]]]],[10,"iter_raw_txs","","Return the list of raw transactions",16,[[],[["error",4],["vec",3],["result",4]]]],[10,"iter_txs","","Return the list of transactions metadata",16,[[],[["vec",3],["result",4],["error",4]]]],[10,"get_script_pubkey_from_path","","Fetch a script_pubkey given the script type and child number",16,[[["scripttype",4]],[["error",4],["option",4],["result",4]]]],[10,"get_path_from_script_pubkey","","Fetch the script type and child number of a given…",16,[[["script",3]],[["option",4],["error",4],["result",4]]]],[10,"get_utxo","","Fetch a [`UTXO`] given its [`OutPoint`]",16,[[["outpoint",3]],[["result",4],["error",4],["option",4]]]],[10,"get_raw_tx","","Fetch a raw transaction given its [`Txid`]",16,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[10,"get_tx","","Fetch the transaction metadata and optionally also the raw…",16,[[["txid",3]],[["option",4],["error",4],["result",4]]]],[10,"get_last_index","","Return the last defivation index for a script type",16,[[["scripttype",4]],[["result",4],["option",4],["error",4]]]],[10,"increment_last_index","","Increment the last derivation index for a script type and…",16,[[["scripttype",4]],[["result",4],["error",4]]]],[8,"BatchDatabase","","Trait for a database that supports batch operations",null,null],[16,"Batch","","Container for the operations",17,null],[10,"begin_batch","","Create a new batch container",17,[[]]],[10,"commit_batch","","Consume and apply a batch of operations",17,[[],[["error",4],["result",4]]]],[0,"descriptor","bdk","Descriptors",null,null],[4,"Descriptor","bdk::descriptor","Script descriptor",null,null],[13,"Bare","","A raw scriptpubkey (including pay-to-pubkey) under Legacy…",18,null],[13,"Pk","","Pay-to-Pubkey",18,null],[13,"Pkh","","Pay-to-PubKey-Hash",18,null],[13,"Wpkh","","Pay-to-Witness-PubKey-Hash",18,null],[13,"ShWpkh","","Pay-to-Witness-PubKey-Hash inside P2SH",18,null],[13,"Sh","","Pay-to-ScriptHash with Legacy context",18,null],[13,"Wsh","","Pay-to-Witness-ScriptHash with Segwitv0 context",18,null],[13,"ShWsh","","P2SH-P2WSH with Segwitv0 context",18,null],[4,"Legacy","","Legacy ScriptContext",null,null],[3,"Miniscript","","Top-level script AST type",null,null],[12,"node","","A node in the Abstract Syntax Tree(",19,null],[12,"ty","","The correctness and malleability type information for the…",19,null],[12,"ext","","Additional information helpful for extra analysis.",19,null],[8,"MiniscriptKey","","Public key trait which can be converted to Hash type",null,null],[11,"is_uncompressed","","Check if the publicKey is uncompressed. The default…",20,[[]]],[16,"Hash","","The associated Hash type with the publicKey",20,null],[10,"to_pubkeyhash","","Converts an object to PublicHash",20,[[]]],[8,"ScriptContext","","",null,null],[10,"check_frag_non_malleable","","Depending on ScriptContext, fragments can be malleable.…",21,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[10,"check_frag_validity","","Depending on script Context, some of the Terminals might…",21,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[4,"Segwitv0","","Segwitv0 ScriptContext",null,null],[4,"Terminal","","All AST elements",null,null],[13,"True","","`1`",22,null],[13,"False","","`0`",22,null],[13,"PkK","","``",22,null],[13,"PkH","","`DUP HASH160 EQUALVERIFY`",22,null],[13,"After","","`n CHECKLOCKTIMEVERIFY`",22,null],[13,"Older","","`n CHECKSEQUENCEVERIFY`",22,null],[13,"Sha256","","`SIZE 32 EQUALVERIFY SHA256 EQUAL`",22,null],[13,"Hash256","","`SIZE 32 EQUALVERIFY HASH256 EQUAL`",22,null],[13,"Ripemd160","","`SIZE 32 EQUALVERIFY RIPEMD160 EQUAL`",22,null],[13,"Hash160","","`SIZE 32 EQUALVERIFY HASH160 EQUAL`",22,null],[13,"Alt","","`TOALTSTACK [E] FROMALTSTACK`",22,null],[13,"Swap","","`SWAP [E1]`",22,null],[13,"Check","","`[Kt]/[Ke] CHECKSIG`",22,null],[13,"DupIf","","`DUP IF [V] ENDIF`",22,null],[13,"Verify","","[T] VERIFY",22,null],[13,"NonZero","","SIZE 0NOTEQUAL IF [Fn] ENDIF",22,null],[13,"ZeroNotEqual","","[X] 0NOTEQUAL",22,null],[13,"AndV","","[V] [T]/[V]/[F]/[Kt]",22,null],[13,"AndB","","[E] [W] BOOLAND",22,null],[13,"AndOr","","[various] NOTIF [various] ELSE [various] ENDIF",22,null],[13,"OrB","","[E] [W] BOOLOR",22,null],[13,"OrD","","[E] IFDUP NOTIF [T]/[E] ENDIF",22,null],[13,"OrC","","[E] NOTIF [V] ENDIF",22,null],[13,"OrI","","IF [various] ELSE [various] ENDIF",22,null],[13,"Thresh","","[E] ([W] ADD)* k EQUAL",22,null],[13,"Multi","","k ()* n CHECKMULTISIG",22,null],[8,"ToPublicKey","","Trait describing public key types which can be converted…",null,null],[10,"to_public_key","","Converts an object to a public key",23,[[],["publickey",3]]],[11,"serialized_len","","Computes the size of a public key when serialized in a…",23,[[]]],[10,"hash_to_hash160","","Converts a hashed version of the public key to a `hash160`…",23,[[],["hash",3]]],[0,"checksum","","Descriptor checksum",null,null],[5,"get_checksum","bdk::descriptor::checksum","Compute the checksum of a descriptor",null,[[],[["result",4],["string",3],["error",4]]]],[0,"error","bdk::descriptor","Descriptor errors",null,null],[4,"Error","bdk::descriptor::error","Errors related to the parsing and usage of descriptors",null,null],[13,"InternalError","","",24,null],[13,"InvalidPrefix","","",24,null],[13,"HardenedDerivationOnXpub","","",24,null],[13,"MalformedInput","","",24,null],[13,"KeyParsingError","","",24,null],[13,"Policy","","",24,null],[13,"InputIndexDoesntExist","","",24,null],[13,"MissingPublicKey","","",24,null],[13,"MissingDetails","","",24,null],[13,"InvalidDescriptorCharacter","","",24,null],[13,"CantDeriveWithMiniscript","","",24,null],[13,"BIP32","","",24,null],[13,"Base58","","",24,null],[13,"PK","","",24,null],[13,"Miniscript","","",24,null],[13,"Hex","","",24,null],[0,"policy","bdk::descriptor","Descriptor policy",null,null],[3,"PKOrF","bdk::descriptor::policy","Raw public key or extended key fingerprint",null,null],[3,"Policy","","Descriptor spending policy",null,null],[12,"id","","Identifier for this policy node",25,null],[12,"item","","Type of this policy node",25,null],[12,"satisfaction","","How a much given PSBT already satisfies this polcy node…",25,null],[12,"contribution","","How the wallet\'s descriptor can satisfy this policy node",25,null],[3,"Condition","","An extra condition that must be satisfied but that is out…",null,null],[12,"csv","","",26,null],[12,"timelock","","",26,null],[4,"SatisfiableItem","","An item that need to be satisfied",null,null],[13,"Signature","","",27,null],[13,"SignatureKey","","",27,null],[13,"SHA256Preimage","","",27,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","",28,null],[13,"HASH256Preimage","bdk::descriptor::policy","",27,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","",29,null],[13,"RIPEMD160Preimage","bdk::descriptor::policy","",27,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","",30,null],[13,"HASH160Preimage","bdk::descriptor::policy","",27,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","",31,null],[13,"AbsoluteTimelock","bdk::descriptor::policy","",27,null],[12,"value","bdk::descriptor::policy::SatisfiableItem","",32,null],[13,"RelativeTimelock","bdk::descriptor::policy","",27,null],[12,"value","bdk::descriptor::policy::SatisfiableItem","",33,null],[13,"Thresh","bdk::descriptor::policy","",27,null],[12,"items","bdk::descriptor::policy::SatisfiableItem","",34,null],[12,"threshold","","",34,null],[13,"Multisig","bdk::descriptor::policy","",27,null],[12,"keys","bdk::descriptor::policy::SatisfiableItem","",35,null],[12,"threshold","","",35,null],[4,"Satisfaction","bdk::descriptor::policy","Represent if and how much a policy item is satisfied by…",null,null],[13,"Partial","","Only a partial satisfaction of some kind of threshold policy",36,null],[12,"n","bdk::descriptor::policy::Satisfaction","Total number of items",37,null],[12,"m","","Threshold",37,null],[12,"items","","The items that can be satisfied by the descriptor",37,null],[12,"conditions","","Extra conditions that also need to be satisfied",37,null],[13,"PartialComplete","bdk::descriptor::policy","Can reach the threshold of some kind of threshold policy",36,null],[12,"n","bdk::descriptor::policy::Satisfaction","Total number of items",38,null],[12,"m","","Threshold",38,null],[12,"items","","The items that can be satisfied by the descriptor",38,null],[12,"conditions","","Extra conditions that also need to be satisfied",38,null],[13,"Complete","bdk::descriptor::policy","Can satisfy the policy item",36,null],[12,"condition","bdk::descriptor::policy::Satisfaction","Extra conditions that also need to be satisfied",39,null],[13,"None","bdk::descriptor::policy","Cannot satisfy or contribute to the policy item",36,null],[4,"PolicyError","","Errors that can happen while extracting and manipulating…",null,null],[13,"NotEnoughItemsSelected","","",40,null],[13,"TooManyItemsSelected","","",40,null],[13,"IndexOutOfRange","","",40,null],[13,"AddOnLeaf","","",40,null],[13,"AddOnPartialComplete","","",40,null],[13,"MixedTimelockUnits","","",40,null],[13,"IncompatibleConditions","","",40,null],[6,"ConditionMap","","",null,null],[6,"FoldedConditionMap","","",null,null],[11,"is_leaf","","",27,[[]]],[11,"id","","",27,[[],["string",3]]],[11,"is_leaf","","",36,[[]]],[11,"is_null","","",26,[[]]],[11,"requires_path","","Return whether or not a specific path in the policy tree…",25,[[]]],[11,"get_condition","","Return the conditions that are set by the spending policy…",25,[[["btreemap",3]],[["policyerror",4],["result",4],["condition",3]]]],[6,"ExtendedDescriptor","bdk::descriptor","Alias for a [`Descriptor`] that can contain extended keys…",null,null],[6,"HDKeyPaths","","Alias for the type of maps that represent derivation paths…",null,null],[8,"ExtractPolicy","","Trait implemented on [`Descriptor`]s to add a method to…",null,null],[10,"extract_policy","","",41,[[["signerscontainer",3],["arc",3]],[["error",4],["result",4],["option",4]]]],[11,"as_byte","bdk","",4,[[]]],[11,"is_internal","","",4,[[]]],[11,"from_btc_per_kvb","","Create a new instance of [`FeeRate`] given a float fee…",42,[[]]],[11,"from_sat_per_vb","","Create a new instance of [`FeeRate`] given a float fee…",42,[[]]],[11,"default_min_relay_fee","","Create a new [`FeeRate`] with the default min relay fee…",42,[[]]],[11,"as_sat_vb","","Return the value as satoshi/vbyte",42,[[]]],[0,"wallet","","Wallet",null,null],[3,"Wallet","bdk::wallet","A Bitcoin wallet",null,null],[0,"address_validator","","Address validation callbacks",null,null],[4,"AddressValidatorError","bdk::wallet::address_validator","Errors that can be returned to fail the validation of an…",null,null],[13,"UserRejected","","",43,null],[13,"ConnectionError","","",43,null],[13,"TimeoutError","","",43,null],[13,"InvalidScript","","",43,null],[13,"Message","","",43,null],[8,"AddressValidator","","Trait to build address validators",null,null],[10,"validate","","Validate or inspect an address",44,[[["scripttype",4],["script",3],["hdkeypaths",6]],[["result",4],["addressvalidatorerror",4]]]],[0,"coin_selection","bdk::wallet","Coin selection",null,null],[3,"CoinSelectionResult","bdk::wallet::coin_selection","Result of a successful coin selection",null,null],[12,"txin","","List of inputs to use, with the respective previous…",45,null],[12,"selected_amount","","Sum of the selected inputs\' value",45,null],[12,"fee_amount","","Total fee amount in satoshi",45,null],[3,"DumbCoinSelection","","Simple and dumb coin selection",null,null],[6,"DefaultCoinSelectionAlgorithm","","Default coin selection algorithm used by `TxBuilder` if…",null,null],[8,"CoinSelectionAlgorithm","","Trait for generalized coin selection algorithms",null,null],[10,"coin_select","","Perform the coin selection",46,[[["feerate",3],["vec",3],["utxo",3]],[["coinselectionresult",3],["error",4],["result",4]]]],[0,"export","bdk::wallet","Wallet export",null,null],[3,"WalletExport","bdk::wallet::export","Structure that contains the export of a wallet",null,null],[12,"blockheight","","Earliest block to rescan when looking for the wallet\'s…",47,null],[12,"label","","Arbitrary label for the wallet",47,null],[11,"export_wallet","","Export a wallet",47,[[["wallet",3]],["result",4]]],[11,"descriptor","","Return the external descriptor",47,[[],["string",3]]],[11,"change_descriptor","","Return the internal descriptor, if present",47,[[],[["string",3],["option",4]]]],[0,"signer","bdk::wallet","Generalized signers",null,null],[3,"SignerOrdering","bdk::wallet::signer","Defines the order in which signers are called",null,null],[12,"0","","",48,null],[3,"SignersContainer","","Container for multiple signers",null,null],[4,"SignerId","","Identifier of a signer in the `SignersContainers`. Used as…",null,null],[13,"PkHash","","",49,null],[13,"Fingerprint","","",49,null],[4,"SignerError","","Signing error",null,null],[13,"MissingKey","","The private key is missing for the required public key",50,null],[13,"UserCanceled","","The user canceled the operation",50,null],[13,"MissingSighash","","The sighash is missing in the PSBT input",50,null],[13,"InputIndexOutOfRange","","Input index is out of range",50,null],[13,"MissingNonWitnessUtxo","","The `non_witness_utxo` field of the transaction is…",50,null],[13,"InvalidNonWitnessUtxo","","The `non_witness_utxo` specified is invalid",50,null],[13,"MissingWitnessUtxo","","The `witness_utxo` field of the transaction is required to…",50,null],[13,"MissingWitnessScript","","The `witness_script` field of the transaction is requied…",50,null],[13,"MissingHDKeypath","","The fingerprint and derivation path are missing from the…",50,null],[8,"Signer","","Trait for signers",null,null],[10,"sign","","Sign a PSBT",51,[[["partiallysignedtransaction",3],["option",4]],[["result",4],["signererror",4]]]],[10,"sign_whole_tx","","Return whether or not the signer signs the whole…",51,[[]]],[11,"descriptor_secret_key","","Return the secret key for the signer",51,[[],[["descriptorsecretkey",4],["option",4]]]],[11,"as_key_map","","",52,[[],["keymap",6]]],[11,"new","","Default constructor",52,[[]]],[11,"add_external","","Adds an external signer to the container for the specified…",52,[[["signerid",4],["signerordering",3],["arc",3],["box",3]],[["arc",3],["option",4]]]],[11,"remove","","Removes a signer from the container and returns it",52,[[["signerid",4],["signerordering",3]],[["arc",3],["option",4]]]],[11,"ids","","Returns the list of identifiers of all the signers in the…",52,[[],[["vec",3],["signerid",4]]]],[11,"signers","","Returns the list of signers in the container, sorted by…",52,[[],[["vec",3],["arc",3]]]],[11,"find","","Finds the signer with lowest ordering for a given id in…",52,[[["signerid",4]],[["option",4],["arc",3]]]],[0,"time","bdk::wallet","Cross-platform time",null,null],[5,"get_timestamp","bdk::wallet::time","Return the current timestamp in seconds",null,[[]]],[0,"tx_builder","bdk::wallet","Transaction builder",null,null],[3,"TxBuilder","bdk::wallet::tx_builder","A transaction builder",null,null],[4,"TxOrdering","","Ordering of the transaction\'s inputs and outputs",null,null],[13,"Shuffle","","Randomized (default)",53,null],[13,"Untouched","","Unchanged",53,null],[13,"BIP69Lexicographic","","BIP69 / Lexicographic",53,null],[4,"ChangeSpendPolicy","","Policy regarding the use of change outputs when creating a…",null,null],[13,"ChangeAllowed","","Use both change and non-change outputs (default)",54,null],[13,"OnlyChange","","Only use change outputs (see…",54,null],[13,"ChangeForbidden","","Only use non-change outputs (see…",54,null],[11,"new","","Create an empty builder",55,[[]]],[11,"with_recipients","","Create a builder starting from a list of recipients",55,[[["vec",3]]]],[11,"set_recipients","","Replace the recipients already added with a new list",55,[[["vec",3]]]],[11,"add_recipient","","Add a recipient to the internal list",55,[[["script",3]]]],[11,"send_all","","Send all the selected utxos to a single output",55,[[]]],[11,"fee_rate","","Set a custom fee rate",55,[[["feerate",3]]]],[11,"policy_path","","Set the policy path to use while creating the transaction",55,[[["vec",3],["string",3],["btreemap",3]]]],[11,"utxos","","Replace the internal list of utxos that must be spent with…",55,[[["vec",3],["outpoint",3]]]],[11,"add_utxo","","Add a utxo to the internal list of utxos that must be spent",55,[[["outpoint",3]]]],[11,"unspendable","","Replace the internal list of unspendable utxos with a new…",55,[[["vec",3],["outpoint",3]]]],[11,"add_unspendable","","Add a utxo to the internal list of unspendable utxos",55,[[["outpoint",3]]]],[11,"sighash","","Sign with a specific sig hash",55,[[["sighashtype",4]]]],[11,"ordering","","Choose the ordering for inputs and outputs of the…",55,[[["txordering",4]]]],[11,"nlocktime","","Use a specific nLockTime while creating the transaction",55,[[]]],[11,"enable_rbf","","Enable signaling RBF",55,[[]]],[11,"enable_rbf_with_sequence","","Enable signaling RBF with a specific nSequence value",55,[[]]],[11,"version","","Build a transaction with a specific version",55,[[]]],[11,"do_not_spend_change","","Do not spend change outputs",55,[[]]],[11,"only_spend_change","","Only spend change outputs",55,[[]]],[11,"change_policy","","Set a specific [`ChangeSpendPolicy`]. See…",55,[[["changespendpolicy",4]]]],[11,"force_non_witness_utxo","","Fill-in the `psbt::Input::non_witness_utxo` field even if…",55,[[]]],[11,"coin_selection","","Choose the coin selection algorithm",55,[[["coinselectionalgorithm",8]],[["txbuilder",3],["coinselectionalgorithm",8]]]],[11,"sort_tx","","",53,[[["transaction",3]]]],[6,"OfflineWallet","bdk::wallet","Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]",null,null],[8,"IsDust","","Trait to check if a value is below the dust limit",null,null],[10,"is_dust","","Check whether or not a value is below dust limit",56,[[]]],[11,"new_offline","","Create a new \\\"offline\\\" wallet",57,[[["option",4],["network",4]],[["error",4],["result",4]]]],[11,"get_new_address","","Return a newly generated address using the external…",57,[[],[["address",3],["result",4],["error",4]]]],[11,"is_mine","","Return whether or not a `script` is part of this wallet…",57,[[["script",3]],[["error",4],["result",4]]]],[11,"list_unspent","","Return the list of unspent outputs of this wallet",57,[[],[["result",4],["vec",3],["error",4]]]],[11,"list_transactions","","Return the list of transactions made and received by the…",57,[[],[["vec",3],["result",4],["error",4]]]],[11,"get_balance","","Return the balance, meaning the sum of this wallet\'s…",57,[[],[["result",4],["error",4]]]],[11,"add_signer","","Add an external signer",57,[[["scripttype",4],["signerid",4],["signerordering",3],["descriptorpublickey",4],["arc",3],["box",3]]]],[11,"add_address_validator","","Add an address validator",57,[[["arc",3],["box",3]]]],[11,"create_tx","","Create a new transaction following the options specified…",57,[[["txbuilder",3],["coinselectionalgorithm",8]],[["error",4],["result",4]]]],[11,"bump_fee","","Bump the fee of a transaction following the options…",57,[[["txid",3],["txbuilder",3],["coinselectionalgorithm",8]],[["error",4],["result",4]]]],[11,"sign","","Sign a transaction with all the wallet\'s signers, in the…",57,[[["psbt",3],["option",4]],[["result",4],["error",4]]]],[11,"policies","","Return the spending policies for the wallet\'s descriptor",57,[[["scripttype",4]],[["result",4],["option",4],["error",4]]]],[11,"public_descriptor","","Return the \\\"public\\\" version of the wallet\'s descriptor,…",57,[[["scripttype",4]],[["option",4],["result",4],["error",4]]]],[11,"finalize_psbt","","Try to finalize a PSBT",57,[[["psbt",3],["option",4]],[["result",4],["error",4]]]],[11,"new","","Create a new \\\"online\\\" wallet",57,[[["option",4],["network",4]],[["error",4],["result",4]]]],[11,"sync","","Sync the internal database with the blockchain",57,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"client","","Return a reference to the internal blockchain client",57,[[],["option",4]]],[11,"broadcast","","Broadcast a transaction to the network",57,[[["transaction",3]],[["result",4],["txid",3],["error",4]]]],[11,"from","bdk","",42,[[]]],[11,"into","","",42,[[]]],[11,"to_owned","","",42,[[]]],[11,"clone_into","","",42,[[]]],[11,"try_from","","",42,[[],["result",4]]],[11,"try_into","","",42,[[],["result",4]]],[11,"borrow","","",42,[[]]],[11,"borrow_mut","","",42,[[]]],[11,"type_id","","",42,[[],["typeid",3]]],[11,"vzip","","",42,[[]]],[11,"from","","",0,[[]]],[11,"into","","",0,[[]]],[11,"to_owned","","",0,[[]]],[11,"clone_into","","",0,[[]]],[11,"try_from","","",0,[[],["result",4]]],[11,"try_into","","",0,[[],["result",4]]],[11,"borrow","","",0,[[]]],[11,"borrow_mut","","",0,[[]]],[11,"type_id","","",0,[[],["typeid",3]]],[11,"equivalent","","",0,[[]]],[11,"vzip","","",0,[[]]],[11,"from","","",1,[[]]],[11,"into","","",1,[[]]],[11,"to_owned","","",1,[[]]],[11,"clone_into","","",1,[[]]],[11,"try_from","","",1,[[],["result",4]]],[11,"try_into","","",1,[[],["result",4]]],[11,"borrow","","",1,[[]]],[11,"borrow_mut","","",1,[[]]],[11,"type_id","","",1,[[],["typeid",3]]],[11,"equivalent","","",1,[[]]],[11,"vzip","","",1,[[]]],[11,"from","","",2,[[]]],[11,"into","","",2,[[]]],[11,"to_string","","",2,[[],["string",3]]],[11,"try_from","","",2,[[],["result",4]]],[11,"try_into","","",2,[[],["result",4]]],[11,"borrow","","",2,[[]]],[11,"borrow_mut","","",2,[[]]],[11,"type_id","","",2,[[],["typeid",3]]],[11,"vzip","","",2,[[]]],[11,"from","","",4,[[]]],[11,"into","","",4,[[]]],[11,"to_owned","","",4,[[]]],[11,"clone_into","","",4,[[]]],[11,"try_from","","",4,[[],["result",4]]],[11,"try_into","","",4,[[],["result",4]]],[11,"borrow","","",4,[[]]],[11,"borrow_mut","","",4,[[]]],[11,"type_id","","",4,[[],["typeid",3]]],[11,"write_base32","","",4,[[],["result",4]]],[11,"base32_len","","",4,[[]]],[11,"check_base32","","",4,[[],[["result",4],["vec",3]]]],[11,"equivalent","","",4,[[]]],[11,"vzip","","",4,[[]]],[11,"from","bdk::blockchain","",58,[[]]],[11,"into","","",58,[[]]],[11,"try_from","","",58,[[],["result",4]]],[11,"try_into","","",58,[[],["result",4]]],[11,"borrow","","",58,[[]]],[11,"borrow_mut","","",58,[[]]],[11,"type_id","","",58,[[],["typeid",3]]],[11,"vzip","","",58,[[]]],[11,"from","","",59,[[]]],[11,"into","","",59,[[]]],[11,"to_owned","","",59,[[]]],[11,"clone_into","","",59,[[]]],[11,"try_from","","",59,[[],["result",4]]],[11,"try_into","","",59,[[],["result",4]]],[11,"borrow","","",59,[[]]],[11,"borrow_mut","","",59,[[]]],[11,"type_id","","",59,[[],["typeid",3]]],[11,"vzip","","",59,[[]]],[11,"from","","",60,[[]]],[11,"into","","",60,[[]]],[11,"to_owned","","",60,[[]]],[11,"clone_into","","",60,[[]]],[11,"try_from","","",60,[[],["result",4]]],[11,"try_into","","",60,[[],["result",4]]],[11,"borrow","","",60,[[]]],[11,"borrow_mut","","",60,[[]]],[11,"type_id","","",60,[[],["typeid",3]]],[11,"vzip","","",60,[[]]],[11,"from","","",5,[[]]],[11,"into","","",5,[[]]],[11,"to_owned","","",5,[[]]],[11,"clone_into","","",5,[[]]],[11,"try_from","","",5,[[],["result",4]]],[11,"try_into","","",5,[[],["result",4]]],[11,"borrow","","",5,[[]]],[11,"borrow_mut","","",5,[[]]],[11,"type_id","","",5,[[],["typeid",3]]],[11,"equivalent","","",5,[[]]],[11,"vzip","","",5,[[]]],[11,"from","bdk::blockchain::electrum","",61,[[]]],[11,"into","","",61,[[]]],[11,"try_from","","",61,[[],["result",4]]],[11,"try_into","","",61,[[],["result",4]]],[11,"borrow","","",61,[[]]],[11,"borrow_mut","","",61,[[]]],[11,"type_id","","",61,[[],["typeid",3]]],[11,"vzip","","",61,[[]]],[11,"from","bdk::blockchain::esplora","",7,[[]]],[11,"into","","",7,[[]]],[11,"try_from","","",7,[[],["result",4]]],[11,"try_into","","",7,[[],["result",4]]],[11,"borrow","","",7,[[]]],[11,"borrow_mut","","",7,[[]]],[11,"type_id","","",7,[[],["typeid",3]]],[11,"vzip","","",7,[[]]],[11,"from","","",6,[[]]],[11,"into","","",6,[[]]],[11,"to_string","","",6,[[],["string",3]]],[11,"try_from","","",6,[[],["result",4]]],[11,"try_into","","",6,[[],["result",4]]],[11,"borrow","","",6,[[]]],[11,"borrow_mut","","",6,[[]]],[11,"type_id","","",6,[[],["typeid",3]]],[11,"vzip","","",6,[[]]],[11,"from","bdk::blockchain::compact_filters","",9,[[]]],[11,"into","","",9,[[]]],[11,"try_from","","",9,[[],["result",4]]],[11,"try_into","","",9,[[],["result",4]]],[11,"borrow","","",9,[[]]],[11,"borrow_mut","","",9,[[]]],[11,"type_id","","",9,[[],["typeid",3]]],[11,"vzip","","",9,[[]]],[11,"from","","",10,[[]]],[11,"into","","",10,[[]]],[11,"try_from","","",10,[[],["result",4]]],[11,"try_into","","",10,[[],["result",4]]],[11,"borrow","","",10,[[]]],[11,"borrow_mut","","",10,[[]]],[11,"type_id","","",10,[[],["typeid",3]]],[11,"vzip","","",10,[[]]],[11,"from","","",11,[[]]],[11,"into","","",11,[[]]],[11,"try_from","","",11,[[],["result",4]]],[11,"try_into","","",11,[[],["result",4]]],[11,"borrow","","",11,[[]]],[11,"borrow_mut","","",11,[[]]],[11,"type_id","","",11,[[],["typeid",3]]],[11,"vzip","","",11,[[]]],[11,"from","","",8,[[]]],[11,"into","","",8,[[]]],[11,"to_string","","",8,[[],["string",3]]],[11,"try_from","","",8,[[],["result",4]]],[11,"try_into","","",8,[[],["result",4]]],[11,"borrow","","",8,[[]]],[11,"borrow_mut","","",8,[[]]],[11,"type_id","","",8,[[],["typeid",3]]],[11,"vzip","","",8,[[]]],[11,"from","bdk::database::memory","",14,[[]]],[11,"into","","",14,[[]]],[11,"try_from","","",14,[[],["result",4]]],[11,"try_into","","",14,[[],["result",4]]],[11,"borrow","","",14,[[]]],[11,"borrow_mut","","",14,[[]]],[11,"type_id","","",14,[[],["typeid",3]]],[11,"vzip","","",14,[[]]],[11,"from","bdk::descriptor","",18,[[]]],[11,"into","","",18,[[]]],[11,"to_owned","","",18,[[]]],[11,"clone_into","","",18,[[]]],[11,"to_string","","",18,[[],["string",3]]],[11,"try_from","","",18,[[],["result",4]]],[11,"try_into","","",18,[[],["result",4]]],[11,"borrow","","",18,[[]]],[11,"borrow_mut","","",18,[[]]],[11,"type_id","","",18,[[],["typeid",3]]],[11,"equivalent","","",18,[[]]],[11,"vzip","","",18,[[]]],[11,"from","","",62,[[]]],[11,"into","","",62,[[]]],[11,"to_owned","","",62,[[]]],[11,"clone_into","","",62,[[]]],[11,"try_from","","",62,[[],["result",4]]],[11,"try_into","","",62,[[],["result",4]]],[11,"borrow","","",62,[[]]],[11,"borrow_mut","","",62,[[]]],[11,"type_id","","",62,[[],["typeid",3]]],[11,"equivalent","","",62,[[]]],[11,"vzip","","",62,[[]]],[11,"from","","",19,[[]]],[11,"into","","",19,[[]]],[11,"to_owned","","",19,[[]]],[11,"clone_into","","",19,[[]]],[11,"to_string","","",19,[[],["string",3]]],[11,"try_from","","",19,[[],["result",4]]],[11,"try_into","","",19,[[],["result",4]]],[11,"borrow","","",19,[[]]],[11,"borrow_mut","","",19,[[]]],[11,"type_id","","",19,[[],["typeid",3]]],[11,"equivalent","","",19,[[]]],[11,"vzip","","",19,[[]]],[11,"from","","",63,[[]]],[11,"into","","",63,[[]]],[11,"to_owned","","",63,[[]]],[11,"clone_into","","",63,[[]]],[11,"try_from","","",63,[[],["result",4]]],[11,"try_into","","",63,[[],["result",4]]],[11,"borrow","","",63,[[]]],[11,"borrow_mut","","",63,[[]]],[11,"type_id","","",63,[[],["typeid",3]]],[11,"equivalent","","",63,[[]]],[11,"vzip","","",63,[[]]],[11,"from","","",22,[[]]],[11,"into","","",22,[[]]],[11,"to_owned","","",22,[[]]],[11,"clone_into","","",22,[[]]],[11,"to_string","","",22,[[],["string",3]]],[11,"try_from","","",22,[[],["result",4]]],[11,"try_into","","",22,[[],["result",4]]],[11,"borrow","","",22,[[]]],[11,"borrow_mut","","",22,[[]]],[11,"type_id","","",22,[[],["typeid",3]]],[11,"equivalent","","",22,[[]]],[11,"vzip","","",22,[[]]],[11,"from","bdk::descriptor::error","",24,[[]]],[11,"into","","",24,[[]]],[11,"to_string","","",24,[[],["string",3]]],[11,"try_from","","",24,[[],["result",4]]],[11,"try_into","","",24,[[],["result",4]]],[11,"borrow","","",24,[[]]],[11,"borrow_mut","","",24,[[]]],[11,"type_id","","",24,[[],["typeid",3]]],[11,"vzip","","",24,[[]]],[11,"from","bdk::descriptor::policy","",64,[[]]],[11,"into","","",64,[[]]],[11,"to_owned","","",64,[[]]],[11,"clone_into","","",64,[[]]],[11,"try_from","","",64,[[],["result",4]]],[11,"try_into","","",64,[[],["result",4]]],[11,"borrow","","",64,[[]]],[11,"borrow_mut","","",64,[[]]],[11,"type_id","","",64,[[],["typeid",3]]],[11,"vzip","","",64,[[]]],[11,"from","","",25,[[]]],[11,"into","","",25,[[]]],[11,"to_owned","","",25,[[]]],[11,"clone_into","","",25,[[]]],[11,"try_from","","",25,[[],["result",4]]],[11,"try_into","","",25,[[],["result",4]]],[11,"borrow","","",25,[[]]],[11,"borrow_mut","","",25,[[]]],[11,"type_id","","",25,[[],["typeid",3]]],[11,"vzip","","",25,[[]]],[11,"from","","",26,[[]]],[11,"into","","",26,[[]]],[11,"to_owned","","",26,[[]]],[11,"clone_into","","",26,[[]]],[11,"try_from","","",26,[[],["result",4]]],[11,"try_into","","",26,[[],["result",4]]],[11,"borrow","","",26,[[]]],[11,"borrow_mut","","",26,[[]]],[11,"type_id","","",26,[[],["typeid",3]]],[11,"equivalent","","",26,[[]]],[11,"vzip","","",26,[[]]],[11,"from","","",27,[[]]],[11,"into","","",27,[[]]],[11,"to_owned","","",27,[[]]],[11,"clone_into","","",27,[[]]],[11,"try_from","","",27,[[],["result",4]]],[11,"try_into","","",27,[[],["result",4]]],[11,"borrow","","",27,[[]]],[11,"borrow_mut","","",27,[[]]],[11,"type_id","","",27,[[],["typeid",3]]],[11,"vzip","","",27,[[]]],[11,"from","","",36,[[]]],[11,"into","","",36,[[]]],[11,"to_owned","","",36,[[]]],[11,"clone_into","","",36,[[]]],[11,"try_from","","",36,[[],["result",4]]],[11,"try_into","","",36,[[],["result",4]]],[11,"borrow","","",36,[[]]],[11,"borrow_mut","","",36,[[]]],[11,"type_id","","",36,[[],["typeid",3]]],[11,"vzip","","",36,[[]]],[11,"from","","",40,[[]]],[11,"into","","",40,[[]]],[11,"to_string","","",40,[[],["string",3]]],[11,"try_from","","",40,[[],["result",4]]],[11,"try_into","","",40,[[],["result",4]]],[11,"borrow","","",40,[[]]],[11,"borrow_mut","","",40,[[]]],[11,"type_id","","",40,[[],["typeid",3]]],[11,"vzip","","",40,[[]]],[11,"from","bdk::wallet","",57,[[]]],[11,"into","","",57,[[]]],[11,"try_from","","",57,[[],["result",4]]],[11,"try_into","","",57,[[],["result",4]]],[11,"borrow","","",57,[[]]],[11,"borrow_mut","","",57,[[]]],[11,"type_id","","",57,[[],["typeid",3]]],[11,"vzip","","",57,[[]]],[11,"from","bdk::wallet::address_validator","",43,[[]]],[11,"into","","",43,[[]]],[11,"to_owned","","",43,[[]]],[11,"clone_into","","",43,[[]]],[11,"to_string","","",43,[[],["string",3]]],[11,"try_from","","",43,[[],["result",4]]],[11,"try_into","","",43,[[],["result",4]]],[11,"borrow","","",43,[[]]],[11,"borrow_mut","","",43,[[]]],[11,"type_id","","",43,[[],["typeid",3]]],[11,"equivalent","","",43,[[]]],[11,"vzip","","",43,[[]]],[11,"from","bdk::wallet::coin_selection","",45,[[]]],[11,"into","","",45,[[]]],[11,"try_from","","",45,[[],["result",4]]],[11,"try_into","","",45,[[],["result",4]]],[11,"borrow","","",45,[[]]],[11,"borrow_mut","","",45,[[]]],[11,"type_id","","",45,[[],["typeid",3]]],[11,"vzip","","",45,[[]]],[11,"from","","",65,[[]]],[11,"into","","",65,[[]]],[11,"try_from","","",65,[[],["result",4]]],[11,"try_into","","",65,[[],["result",4]]],[11,"borrow","","",65,[[]]],[11,"borrow_mut","","",65,[[]]],[11,"type_id","","",65,[[],["typeid",3]]],[11,"vzip","","",65,[[]]],[11,"from","bdk::wallet::export","",47,[[]]],[11,"into","","",47,[[]]],[11,"to_string","","",47,[[],["string",3]]],[11,"try_from","","",47,[[],["result",4]]],[11,"try_into","","",47,[[],["result",4]]],[11,"borrow","","",47,[[]]],[11,"borrow_mut","","",47,[[]]],[11,"type_id","","",47,[[],["typeid",3]]],[11,"vzip","","",47,[[]]],[11,"from","bdk::wallet::signer","",48,[[]]],[11,"into","","",48,[[]]],[11,"to_owned","","",48,[[]]],[11,"clone_into","","",48,[[]]],[11,"try_from","","",48,[[],["result",4]]],[11,"try_into","","",48,[[],["result",4]]],[11,"borrow","","",48,[[]]],[11,"borrow_mut","","",48,[[]]],[11,"type_id","","",48,[[],["typeid",3]]],[11,"equivalent","","",48,[[]]],[11,"vzip","","",48,[[]]],[11,"from","","",52,[[]]],[11,"into","","",52,[[]]],[11,"to_owned","","",52,[[]]],[11,"clone_into","","",52,[[]]],[11,"try_from","","",52,[[],["result",4]]],[11,"try_into","","",52,[[],["result",4]]],[11,"borrow","","",52,[[]]],[11,"borrow_mut","","",52,[[]]],[11,"type_id","","",52,[[],["typeid",3]]],[11,"vzip","","",52,[[]]],[11,"from","","",49,[[]]],[11,"into","","",49,[[]]],[11,"to_owned","","",49,[[]]],[11,"clone_into","","",49,[[]]],[11,"try_from","","",49,[[],["result",4]]],[11,"try_into","","",49,[[],["result",4]]],[11,"borrow","","",49,[[]]],[11,"borrow_mut","","",49,[[]]],[11,"type_id","","",49,[[],["typeid",3]]],[11,"equivalent","","",49,[[]]],[11,"vzip","","",49,[[]]],[11,"from","","",50,[[]]],[11,"into","","",50,[[]]],[11,"to_owned","","",50,[[]]],[11,"clone_into","","",50,[[]]],[11,"to_string","","",50,[[],["string",3]]],[11,"try_from","","",50,[[],["result",4]]],[11,"try_into","","",50,[[],["result",4]]],[11,"borrow","","",50,[[]]],[11,"borrow_mut","","",50,[[]]],[11,"type_id","","",50,[[],["typeid",3]]],[11,"equivalent","","",50,[[]]],[11,"vzip","","",50,[[]]],[11,"from","bdk::wallet::tx_builder","",55,[[]]],[11,"into","","",55,[[]]],[11,"try_from","","",55,[[],["result",4]]],[11,"try_into","","",55,[[],["result",4]]],[11,"borrow","","",55,[[]]],[11,"borrow_mut","","",55,[[]]],[11,"type_id","","",55,[[],["typeid",3]]],[11,"vzip","","",55,[[]]],[11,"from","","",53,[[]]],[11,"into","","",53,[[]]],[11,"to_owned","","",53,[[]]],[11,"clone_into","","",53,[[]]],[11,"try_from","","",53,[[],["result",4]]],[11,"try_into","","",53,[[],["result",4]]],[11,"borrow","","",53,[[]]],[11,"borrow_mut","","",53,[[]]],[11,"type_id","","",53,[[],["typeid",3]]],[11,"equivalent","","",53,[[]]],[11,"vzip","","",53,[[]]],[11,"from","","",54,[[]]],[11,"into","","",54,[[]]],[11,"to_owned","","",54,[[]]],[11,"clone_into","","",54,[[]]],[11,"try_from","","",54,[[],["result",4]]],[11,"try_into","","",54,[[],["result",4]]],[11,"borrow","","",54,[[]]],[11,"borrow_mut","","",54,[[]]],[11,"type_id","","",54,[[],["typeid",3]]],[11,"equivalent","","",54,[[]]],[11,"vzip","","",54,[[]]],[11,"eq","bdk::descriptor","",19,[[["miniscript",3]]]],[11,"eq","","",18,[[["descriptor",4]]]],[11,"ne","","",18,[[["descriptor",4]]]],[11,"eq","","",63,[[["segwitv0",4]]]],[11,"eq","","",22,[[["terminal",4]]]],[11,"ne","","",22,[[["terminal",4]]]],[11,"eq","","",62,[[["legacy",4]]]],[11,"check_frag_non_malleable","","",62,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_frag_validity","","",62,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_frag_non_malleable","","",63,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_frag_validity","","",63,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"cmp","","",22,[[["terminal",4]],["ordering",4]]],[11,"cmp","","",63,[[["segwitv0",4]],["ordering",4]]],[11,"cmp","","",62,[[["legacy",4]],["ordering",4]]],[11,"cmp","","",18,[[["descriptor",4]],["ordering",4]]],[11,"cmp","","",19,[[["miniscript",3]],["ordering",4]]],[11,"fmt","","",19,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",18,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",22,[[["formatter",3]],[["result",4],["error",3]]]],[11,"from_str","","",18,[[],[["error",4],["descriptor",4],["result",4]]]],[11,"from_str","","",19,[[],[["error",4],["miniscript",3],["result",4]]]],[11,"hash","","",19,[[]]],[11,"hash","","",22,[[]]],[11,"fmt","","",19,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",63,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",62,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",22,[[["formatter",3]],[["result",4],["error",3]]]],[11,"fmt","","",18,[[["formatter",3]],[["result",4],["error",3]]]],[11,"partial_cmp","","",19,[[["miniscript",3]],[["ordering",4],["option",4]]]],[11,"partial_cmp","","",63,[[["segwitv0",4]],[["ordering",4],["option",4]]]],[11,"partial_cmp","","",18,[[["descriptor",4]],[["ordering",4],["option",4]]]],[11,"lt","","",18,[[["descriptor",4]]]],[11,"le","","",18,[[["descriptor",4]]]],[11,"gt","","",18,[[["descriptor",4]]]],[11,"ge","","",18,[[["descriptor",4]]]],[11,"partial_cmp","","",22,[[["terminal",4]],[["ordering",4],["option",4]]]],[11,"lt","","",22,[[["terminal",4]]]],[11,"le","","",22,[[["terminal",4]]]],[11,"gt","","",22,[[["terminal",4]]]],[11,"ge","","",22,[[["terminal",4]]]],[11,"partial_cmp","","",62,[[["legacy",4]],[["ordering",4],["option",4]]]],[11,"from_tree","","Parse an expression tree into a Miniscript. As a general…",19,[[["tree",3]],[["error",4],["miniscript",3],["result",4]]]],[11,"from_tree","","",22,[[["tree",3]],[["error",4],["terminal",4],["result",4]]]],[11,"from_tree","","Parse an expression tree into a descriptor",18,[[["tree",3]],[["error",4],["descriptor",4],["result",4]]]],[11,"lift","","",18,[[],["policy",4]]],[11,"lift","","",19,[[],["policy",4]]],[11,"lift","","",22,[[],["policy",4]]],[11,"clone","","",18,[[],["descriptor",4]]],[11,"clone","","",19,[[],["miniscript",3]]],[11,"clone","","",62,[[],["legacy",4]]],[11,"clone","","",63,[[],["segwitv0",4]]],[11,"clone","","",22,[[],["terminal",4]]],[11,"update","bdk::blockchain","",59,[[["string",3],["option",4]],[["error",4],["result",4]]]],[11,"update","","",60,[[["string",3],["option",4]],[["error",4],["result",4]]]],[11,"set_script_pubkey","bdk::database::memory","",14,[[["scripttype",4],["script",3]],[["error",4],["result",4]]]],[11,"set_utxo","","",14,[[["utxo",3]],[["error",4],["result",4]]]],[11,"set_raw_tx","","",14,[[["transaction",3]],[["error",4],["result",4]]]],[11,"set_tx","","",14,[[["transactiondetails",3]],[["error",4],["result",4]]]],[11,"set_last_index","","",14,[[["scripttype",4]],[["error",4],["result",4]]]],[11,"del_script_pubkey_from_path","","",14,[[["scripttype",4]],[["error",4],["option",4],["result",4]]]],[11,"del_path_from_script_pubkey","","",14,[[["script",3]],[["option",4],["error",4],["result",4]]]],[11,"del_utxo","","",14,[[["outpoint",3]],[["result",4],["error",4],["option",4]]]],[11,"del_raw_tx","","",14,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"del_tx","","",14,[[["txid",3]],[["option",4],["error",4],["result",4]]]],[11,"del_last_index","","",14,[[["scripttype",4]],[["result",4],["option",4],["error",4]]]],[11,"check_descriptor_checksum","","",14,[[["scripttype",4],["asref",8]],[["error",4],["result",4]]]],[11,"iter_script_pubkeys","","",14,[[["option",4],["scripttype",4]],[["result",4],["vec",3],["error",4]]]],[11,"iter_utxos","","",14,[[],[["result",4],["vec",3],["error",4]]]],[11,"iter_raw_txs","","",14,[[],[["error",4],["vec",3],["result",4]]]],[11,"iter_txs","","",14,[[],[["vec",3],["result",4],["error",4]]]],[11,"get_script_pubkey_from_path","","",14,[[["scripttype",4]],[["error",4],["option",4],["result",4]]]],[11,"get_path_from_script_pubkey","","",14,[[["script",3]],[["option",4],["error",4],["result",4]]]],[11,"get_utxo","","",14,[[["outpoint",3]],[["result",4],["error",4],["option",4]]]],[11,"get_raw_tx","","",14,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"get_tx","","",14,[[["txid",3]],[["option",4],["error",4],["result",4]]]],[11,"get_last_index","","",14,[[["scripttype",4]],[["result",4],["option",4],["error",4]]]],[11,"increment_last_index","","",14,[[["scripttype",4]],[["result",4],["error",4]]]],[11,"begin_batch","","",14,[[]]],[11,"commit_batch","","",14,[[],[["error",4],["result",4]]]],[11,"extract_policy","bdk::descriptor","",19,[[["signerscontainer",3],["arc",3]],[["error",4],["result",4],["option",4]]]],[11,"extract_policy","","",18,[[["signerscontainer",3],["arc",3]],[["error",4],["result",4],["option",4]]]],[11,"coin_select","bdk::wallet::coin_selection","",65,[[["feerate",3],["vec",3],["utxo",3]],[["coinselectionresult",3],["error",4],["result",4]]]],[11,"get_capabilities","bdk::blockchain::electrum","",61,[[],[["capability",4],["hashset",3]]]],[11,"setup","","",61,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"get_tx","","",61,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"broadcast","","",61,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",61,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",61,[[],[["feerate",3],["error",4],["result",4]]]],[11,"get_capabilities","bdk::blockchain::esplora","",7,[[],[["capability",4],["hashset",3]]]],[11,"setup","","",7,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"get_tx","","",7,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"broadcast","","",7,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",7,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",7,[[],[["feerate",3],["error",4],["result",4]]]],[11,"get_capabilities","bdk::blockchain::compact_filters","",11,[[],[["capability",4],["hashset",3]]]],[11,"setup","","",11,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"get_tx","","",11,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"broadcast","","",11,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",11,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",11,[[],[["feerate",3],["error",4],["result",4]]]],[11,"as_ref","bdk","",4,[[]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["addressvalidatorerror",4]]]],[11,"from","","",2,[[["policyerror",4]]]],[11,"from","","",2,[[["signererror",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",3]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["esploraerror",4]]]],[11,"from","","",2,[[["error",4]]]],[11,"from","","",2,[[["compactfilterserror",4]]]],[11,"from","bdk::blockchain::electrum","",61,[[["client",4]]]],[11,"from","bdk::blockchain::esplora","",6,[[["error",3]]]],[11,"from","","",6,[[["parseinterror",3]]]],[11,"from","","",6,[[["error",4]]]],[11,"from","bdk::blockchain::compact_filters","",8,[[["error",3]]]],[11,"from","","",8,[[["error",3]]]],[11,"from","","",8,[[["error",4]]]],[11,"from","","",8,[[["systemtimeerror",3]]]],[11,"from","","",8,[[["error",4]]]],[11,"from","bdk::descriptor::error","",24,[[["error",4]]]],[11,"from","","",24,[[["error",4]]]],[11,"from","","",24,[[["error",4]]]],[11,"from","","",24,[[["error",4]]]],[11,"from","","",24,[[["error",4]]]],[11,"from","","",24,[[["policyerror",4]]]],[11,"from","bdk::descriptor::policy","",36,[[]]],[11,"from","","",25,[[["satisfiableitem",4]]]],[11,"from","bdk::wallet::signer","",49,[[["hash",3]],[["signerid",4],["descriptorpublickey",4]]]],[11,"from","","",49,[[["fingerprint",3]],[["signerid",4],["descriptorpublickey",4]]]],[11,"from","","",52,[[["keymap",6]],[["signerscontainer",3],["descriptorpublickey",4]]]],[11,"clone","bdk::blockchain","",5,[[],["capability",4]]],[11,"clone","","",59,[[],["noopprogress",3]]],[11,"clone","","",60,[[],["logprogress",3]]],[11,"clone","bdk::descriptor::policy","",64,[[],["pkorf",3]]],[11,"clone","","",27,[[],["satisfiableitem",4]]],[11,"clone","","",36,[[],["satisfaction",4]]],[11,"clone","","",25,[[],["policy",3]]],[11,"clone","","",26,[[],["condition",3]]],[11,"clone","bdk","",4,[[],["scripttype",4]]],[11,"clone","","",42,[[],["feerate",3]]],[11,"clone","","",0,[[],["utxo",3]]],[11,"clone","","",1,[[],["transactiondetails",3]]],[11,"clone","bdk::wallet::address_validator","",43,[[],["addressvalidatorerror",4]]],[11,"clone","bdk::wallet::signer","",49,[[],["signerid",4]]],[11,"clone","","",50,[[],["signererror",4]]],[11,"clone","","",48,[[],["signerordering",3]]],[11,"clone","","",52,[[],["signerscontainer",3]]],[11,"clone","bdk::wallet::tx_builder","",53,[[],["txordering",4]]],[11,"clone","","",54,[[],["changespendpolicy",4]]],[11,"default","bdk::blockchain::compact_filters","",9,[[],["mempool",3]]],[11,"default","bdk::database::memory","",14,[[],["memorydatabase",3]]],[11,"default","bdk::descriptor::policy","",64,[[],["pkorf",3]]],[11,"default","","",26,[[],["condition",3]]],[11,"default","bdk","",42,[[]]],[11,"default","","",1,[[],["transactiondetails",3]]],[11,"default","bdk::wallet::coin_selection","",65,[[],["dumbcoinselection",3]]],[11,"default","bdk::wallet::signer","",48,[[]]],[11,"default","","",52,[[],["signerscontainer",3]]],[11,"default","bdk::wallet::tx_builder","",55,[[],["txbuilder",3]]],[11,"default","","",53,[[]]],[11,"default","","",54,[[]]],[11,"cmp","bdk::descriptor::policy","",26,[[["condition",3]],["ordering",4]]],[11,"cmp","bdk::wallet::signer","",48,[[["signerordering",3]],["ordering",4]]],[11,"cmp","bdk::wallet::tx_builder","",53,[[["txordering",4]],["ordering",4]]],[11,"cmp","","",54,[[["changespendpolicy",4]],["ordering",4]]],[11,"eq","bdk::blockchain","",5,[[["capability",4]]]],[11,"eq","bdk::descriptor::policy","",26,[[["condition",3]]]],[11,"ne","","",26,[[["condition",3]]]],[11,"eq","bdk","",4,[[["scripttype",4]]]],[11,"eq","","",42,[[["feerate",3]]]],[11,"ne","","",42,[[["feerate",3]]]],[11,"eq","","",0,[[["utxo",3]]]],[11,"ne","","",0,[[["utxo",3]]]],[11,"eq","","",1,[[["transactiondetails",3]]]],[11,"ne","","",1,[[["transactiondetails",3]]]],[11,"eq","bdk::wallet::address_validator","",43,[[["addressvalidatorerror",4]]]],[11,"ne","","",43,[[["addressvalidatorerror",4]]]],[11,"eq","bdk::wallet::signer","",49,[[["signerid",4]]]],[11,"ne","","",49,[[["signerid",4]]]],[11,"eq","","",50,[[["signererror",4]]]],[11,"eq","","",48,[[["signerordering",3]]]],[11,"ne","","",48,[[["signerordering",3]]]],[11,"eq","bdk::wallet::tx_builder","",53,[[["txordering",4]]]],[11,"eq","","",54,[[["changespendpolicy",4]]]],[11,"partial_cmp","bdk::descriptor::policy","",26,[[["condition",3]],[["option",4],["ordering",4]]]],[11,"lt","","",26,[[["condition",3]]]],[11,"le","","",26,[[["condition",3]]]],[11,"gt","","",26,[[["condition",3]]]],[11,"ge","","",26,[[["condition",3]]]],[11,"partial_cmp","bdk","",42,[[["feerate",3]],[["option",4],["ordering",4]]]],[11,"lt","","",42,[[["feerate",3]]]],[11,"le","","",42,[[["feerate",3]]]],[11,"gt","","",42,[[["feerate",3]]]],[11,"ge","","",42,[[["feerate",3]]]],[11,"partial_cmp","bdk::wallet::signer","",48,[[["signerordering",3]],[["option",4],["ordering",4]]]],[11,"lt","","",48,[[["signerordering",3]]]],[11,"le","","",48,[[["signerordering",3]]]],[11,"gt","","",48,[[["signerordering",3]]]],[11,"ge","","",48,[[["signerordering",3]]]],[11,"partial_cmp","bdk::wallet::tx_builder","",53,[[["txordering",4]],[["option",4],["ordering",4]]]],[11,"partial_cmp","","",54,[[["changespendpolicy",4]],[["option",4],["ordering",4]]]],[11,"to_string","bdk::wallet::export","",47,[[],["string",3]]],[11,"fmt","bdk","",2,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::esplora","",7,[[["formatter",3]],["result",6]]],[11,"fmt","","",6,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::compact_filters","",9,[[["formatter",3]],["result",6]]],[11,"fmt","","",10,[[["formatter",3]],["result",6]]],[11,"fmt","","",11,[[["formatter",3]],["result",6]]],[11,"fmt","","",8,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain","",5,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::database::memory","",14,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::error","",24,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::policy","",64,[[["formatter",3]],["result",6]]],[11,"fmt","","",27,[[["formatter",3]],["result",6]]],[11,"fmt","","",36,[[["formatter",3]],["result",6]]],[11,"fmt","","",25,[[["formatter",3]],["result",6]]],[11,"fmt","","",26,[[["formatter",3]],["result",6]]],[11,"fmt","","",40,[[["formatter",3]],["result",6]]],[11,"fmt","bdk","",4,[[["formatter",3]],["result",6]]],[11,"fmt","","",42,[[["formatter",3]],["result",6]]],[11,"fmt","","",0,[[["formatter",3]],["result",6]]],[11,"fmt","","",1,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::address_validator","",43,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::coin_selection","",45,[[["formatter",3]],["result",6]]],[11,"fmt","","",65,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::export","",47,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::signer","",49,[[["formatter",3]],["result",6]]],[11,"fmt","","",50,[[["formatter",3]],["result",6]]],[11,"fmt","","",48,[[["formatter",3]],["result",6]]],[11,"fmt","","",52,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::tx_builder","",55,[[["formatter",3]],["result",6]]],[11,"fmt","","",53,[[["formatter",3]],["result",6]]],[11,"fmt","","",54,[[["formatter",3]],["result",6]]],[11,"fmt","bdk","",2,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::esplora","",6,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::compact_filters","",8,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::error","",24,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::policy","",40,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::address_validator","",43,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::signer","",50,[[["formatter",3]],["result",6]]],[11,"hash","bdk::blockchain","",5,[[]]],[11,"hash","bdk::descriptor::policy","",26,[[]]],[11,"hash","bdk","",4,[[]]],[11,"hash","bdk::wallet::signer","",49,[[]]],[11,"hash","bdk::wallet::tx_builder","",53,[[]]],[11,"hash","","",54,[[]]],[11,"from_str","bdk::wallet::export","",47,[[],["result",4]]],[11,"serialize","bdk::descriptor::policy","",64,[[],["result",4]]],[11,"serialize","","",27,[[],["result",4]]],[11,"serialize","","",36,[[],["result",4]]],[11,"serialize","","",25,[[],["result",4]]],[11,"serialize","","",26,[[],["result",4]]],[11,"serialize","bdk","",4,[[],["result",4]]],[11,"serialize","","",0,[[],["result",4]]],[11,"serialize","","",1,[[],["result",4]]],[11,"serialize","bdk::wallet::export","",47,[[],["result",4]]],[11,"deserialize","bdk","",4,[[],["result",4]]],[11,"deserialize","","",0,[[],["result",4]]],[11,"deserialize","","",1,[[],["result",4]]],[11,"deserialize","bdk::wallet::export","",47,[[],["result",4]]],[11,"translate_pk","bdk::descriptor","Convert a descriptor using abstract keys to one using…",18,[[],[["result",4],["descriptor",4]]]],[11,"address","","Computes the Bitcoin address of the descriptor, if one…",18,[[["network",4]],[["option",4],["address",3]]]],[11,"script_pubkey","","Computes the scriptpubkey of the descriptor",18,[[],["script",3]]],[11,"unsigned_script_sig","","Computes the scriptSig that will be in place for an…",18,[[],["script",3]]],[11,"witness_script","","Computes the \\\"witness script\\\" of the descriptor, i.e. the…",18,[[],["script",3]]],[11,"satisfy","","Attempts to produce a satisfying witness and scriptSig to…",18,[[["txin",3]],[["error",4],["result",4]]]],[11,"max_satisfaction_weight","","Computes an upper bound on the weight of a satisfying…",18,[[]]],[11,"derive","","Derives all wildcard keys in the descriptor using the…",18,[[],[["descriptor",4],["descriptorpublickey",4]]]],[11,"parse_secret","","",18,[[],[["error",4],["result",4]]]],[11,"to_string_with_secret","","",18,[[["hashmap",3]],["string",3]]],[11,"from_ast","","Add type information(Type and Extdata) to Miniscript based…",19,[[["terminal",4]],[["error",4],["miniscript",3],["result",4]]]],[11,"into_inner","","Extracts the `AstElem` representing the root of the…",19,[[],["terminal",4]]],[11,"as_inner","","",19,[[],["terminal",4]]],[11,"parse","","Attempt to parse a script into a Miniscript representation",19,[[["script",3]],[["error",4],["miniscript",3],["result",4]]]],[11,"encode","","Encode as a Bitcoin script",19,[[],["script",3]]],[11,"script_size","","Size, in bytes of the script-pubkey. If this Miniscript is…",19,[[]]],[11,"max_satisfaction_witness_elements","","Maximum number of witness elements used to satisfy the…",19,[[]]],[11,"max_satisfaction_size","","Maximum size, in bytes, of a satisfying witness. For…",19,[[]]],[11,"translate_pk","","This will panic if translatefpk returns an uncompressed…",19,[[],[["miniscript",3],["result",4]]]],[11,"satisfy","","Attempt to produce a satisfying witness for the witness…",19,[[],[["vec",3],["option",4]]]],[11,"translate_pk","","Convert an AST element with one public key type to one of…",22,[[],[["terminal",4],["result",4]]]],[11,"encode","","Encode the element as a fragment of Bitcoin Script. The…",22,[[["builder",3]],["builder",3]]],[11,"script_size","","Size, in bytes of the script-pubkey. If this Miniscript is…",22,[[]]],[11,"max_dissatisfaction_witness_elements","","Maximum number of witness elements used to dissatisfy the…",22,[[],["option",4]]],[11,"max_dissatisfaction_size","","Maximum dissatisfaction cost, in bytes, of a Miniscript…",22,[[],["option",4]]],[11,"max_satisfaction_witness_elements","","Maximum number of witness elements used to satisfy the…",22,[[]]],[11,"max_satisfaction_size","","Maximum size, in bytes, of a satisfying witness. For…",22,[[]]]],"p":[[3,"UTXO"],[3,"TransactionDetails"],[4,"Error"],[13,"FeeRateTooLow"],[4,"ScriptType"],[4,"Capability"],[4,"EsploraError"],[3,"EsploraBlockchain"],[4,"CompactFiltersError"],[3,"Mempool"],[3,"Peer"],[3,"CompactFiltersBlockchain"],[8,"Blockchain"],[8,"Progress"],[3,"MemoryDatabase"],[8,"BatchOperations"],[8,"Database"],[8,"BatchDatabase"],[4,"Descriptor"],[3,"Miniscript"],[8,"MiniscriptKey"],[8,"ScriptContext"],[4,"Terminal"],[8,"ToPublicKey"],[4,"Error"],[3,"Policy"],[3,"Condition"],[4,"SatisfiableItem"],[13,"SHA256Preimage"],[13,"HASH256Preimage"],[13,"RIPEMD160Preimage"],[13,"HASH160Preimage"],[13,"AbsoluteTimelock"],[13,"RelativeTimelock"],[13,"Thresh"],[13,"Multisig"],[4,"Satisfaction"],[13,"Partial"],[13,"PartialComplete"],[13,"Complete"],[4,"PolicyError"],[8,"ExtractPolicy"],[3,"FeeRate"],[4,"AddressValidatorError"],[8,"AddressValidator"],[3,"CoinSelectionResult"],[8,"CoinSelectionAlgorithm"],[3,"WalletExport"],[3,"SignerOrdering"],[4,"SignerId"],[4,"SignerError"],[8,"Signer"],[3,"SignersContainer"],[4,"TxOrdering"],[4,"ChangeSpendPolicy"],[3,"TxBuilder"],[8,"IsDust"],[3,"Wallet"],[3,"OfflineBlockchain"],[3,"NoopProgress"],[3,"LogProgress"],[3,"ElectrumBlockchain"],[4,"Legacy"],[4,"Segwitv0"],[3,"PKOrF"],[3,"DumbCoinSelection"]]}\ -}'); -addSearchOptions(searchIndex);initSearch(searchIndex); \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/settings.css b/static/docs-rs/bdk/0.1.0-beta.1/settings.css deleted file mode 100644 index 6ce7665866..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/settings.css +++ /dev/null @@ -1 +0,0 @@ -.setting-line{padding:5px;position:relative;}.setting-line>div{max-width:calc(100% - 74px);display:inline-block;vertical-align:top;font-size:17px;padding-top:2px;}.setting-line>.title{font-size:19px;width:100%;max-width:none;border-bottom:1px solid;}.toggle{position:relative;display:inline-block;width:45px;height:27px;margin-right:20px;}.toggle input{display:none;}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.3s;transition:.3s;}.slider:before{position:absolute;content:"";height:19px;width:19px;left:4px;bottom:4px;background-color:white;-webkit-transition:.3s;transition:.3s;}input:checked+.slider{background-color:#2196F3;}input:focus+.slider{box-shadow:0 0 1px #2196F3;}input:checked+.slider:before{-webkit-transform:translateX(19px);-ms-transform:translateX(19px);transform:translateX(19px);}.setting-line>.sub-settings{padding-left:42px;width:100%;display:block;} \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/settings.html b/static/docs-rs/bdk/0.1.0-beta.1/settings.html deleted file mode 100644 index 12a71ee2cf..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/settings.html +++ /dev/null @@ -1,2 +0,0 @@ -Rustdoc settings

    Rustdoc settings

    Auto-hide item declarations
    Auto-hide structs declaration
    Auto-hide enums declaration
    Auto-hide unions declaration
    Auto-hide traits declaration
    Auto-hide macros declaration
    -
    Auto-hide item attributes.
    Auto-hide item methods' documentation
    Auto-hide trait implementations documentation
    Directly go to item in search if there is only one result
    Show line numbers on code examples
    Disable keyboard shortcuts
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/settings.js b/static/docs-rs/bdk/0.1.0-beta.1/settings.js deleted file mode 100644 index 9930309054..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/settings.js +++ /dev/null @@ -1 +0,0 @@ -(function(){function changeSetting(settingName,isEnabled){updateLocalStorage('rustdoc-'+settingName,isEnabled)}function getSettingValue(settingName){return getCurrentValue('rustdoc-'+settingName)}function setEvents(){var elems=document.getElementsByClassName("slider");if(!elems||elems.length===0){return}for(var i=0;i"){sidebar.style.left="";this.style.left="";child.innerText="<";updateLocalStorage("rustdoc-source-sidebar-show","true")}else{sidebar.style.left="-300px";this.style.left="0";child.innerText=">";updateLocalStorage("rustdoc-source-sidebar-show","false")}}function createSidebarToggle(){var sidebarToggle=document.createElement("div");sidebarToggle.id="sidebar-toggle";sidebarToggle.onclick=toggleSidebar;var inner1=document.createElement("div");inner1.style.position="relative";var inner2=document.createElement("div");inner2.style.paddingTop="3px";if(getCurrentValue("rustdoc-source-sidebar-show")==="true"){inner2.innerText="<"}else{inner2.innerText=">";sidebarToggle.style.left="0"}inner1.appendChild(inner2);sidebarToggle.appendChild(inner1);return sidebarToggle}function createSourceSidebar(){if(window.rootPath.endsWith("/")===false){window.rootPath+="/"}var main=document.getElementById("main");var sidebarToggle=createSidebarToggle();main.insertBefore(sidebarToggle,main.firstChild);var sidebar=document.createElement("div");sidebar.id="source-sidebar";if(getCurrentValue("rustdoc-source-sidebar-show")!=="true"){sidebar.style.left="-300px"}var currentFile=getCurrentFilePath();var hasFoundFile=false;var title=document.createElement("div");title.className="title";title.innerText="Files";sidebar.appendChild(title);Object.keys(sourcesIndex).forEach(function(key){sourcesIndex[key].name=key;hasFoundFile=createDirEntry(sourcesIndex[key],sidebar,"",currentFile,hasFoundFile)});main.insertBefore(sidebar,main.firstChild)} \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/mod.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/mod.rs.html deleted file mode 100644 index 6fad4c357b..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/mod.rs.html +++ /dev/null @@ -1,1057 +0,0 @@ -mod.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Compact Filters
    -//!
    -//! This module contains a multithreaded implementation of an [`Blockchain`] backend that
    -//! uses BIP157 (aka "Neutrino") to populate the wallet's [database](crate::database::Database)
    -//! by downloading compact filters from the P2P network.
    -//!
    -//! Since there are currently very few peers "in the wild" that advertise the required service
    -//! flag, this implementation requires that one or more known peers are provided by the user.
    -//! No dns or other kinds of peer discovery are done internally.
    -//!
    -//! Moreover, this module doesn't currently support detecting and resolving conflicts between
    -//! messages received by different peers. Thus, it's recommended to use this module by only
    -//! connecting to a single peer at a time, optionally by opening multiple connections if it's
    -//! desirable to use multiple threads at once to sync in parallel.
    -//!
    -//! ## Example
    -//!
    -//! ```no_run
    -//! # use std::sync::Arc;
    -//! # use bitcoin::*;
    -//! # use bdk::*;
    -//! # use bdk::blockchain::compact_filters::*;
    -//! let num_threads = 4;
    -//!
    -//! let mempool = Arc::new(Mempool::default());
    -//! let peers = (0..num_threads)
    -//!     .map(|_| Peer::connect(
    -//!         "btcd-mainnet.lightning.computer:8333",
    -//!         Arc::clone(&mempool),
    -//!         Network::Bitcoin,
    -//!     ))
    -//!     .collect::<Result<_, _>>()?;
    -//! let blockchain = CompactFiltersBlockchain::new(peers, "./wallet-filters", Some(500_000))?;
    -//! # Ok::<(), bdk::error::Error>(())
    -//! ```
    -
    -use std::collections::HashSet;
    -use std::fmt;
    -use std::path::Path;
    -use std::sync::atomic::{AtomicUsize, Ordering};
    -use std::sync::{Arc, Mutex};
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -use bitcoin::network::message_blockdata::Inventory;
    -use bitcoin::{OutPoint, Transaction, Txid};
    -
    -use rocksdb::{Options, SliceTransform, DB};
    -
    -mod peer;
    -mod store;
    -mod sync;
    -
    -use super::{Blockchain, Capability, Progress};
    -use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
    -use crate::error::Error;
    -use crate::types::{ScriptType, TransactionDetails, UTXO};
    -use crate::FeeRate;
    -
    -use peer::*;
    -use store::*;
    -use sync::*;
    -
    -pub use peer::{Mempool, Peer};
    -
    -const SYNC_HEADERS_COST: f32 = 1.0;
    -const SYNC_FILTERS_COST: f32 = 11.6 * 1_000.0;
    -const PROCESS_BLOCKS_COST: f32 = 20_000.0;
    -
    -/// Structure implementing the required blockchain traits
    -///
    -/// ## Example
    -/// See the [`blockchain::compact_filters`](crate::blockchain::compact_filters) module for a usage example.
    -#[derive(Debug)]
    -pub struct CompactFiltersBlockchain {
    -    peers: Vec<Arc<Peer>>,
    -    headers: Arc<ChainStore<Full>>,
    -    skip_blocks: Option<usize>,
    -}
    -
    -impl CompactFiltersBlockchain {
    -    /// Construct a new instance given a list of peers, a path to store headers and block
    -    /// filters downloaded during the sync and optionally a number of blocks to ignore starting
    -    /// from the genesis while scanning for the wallet's outputs.
    -    ///
    -    /// For each [`Peer`] specified a new thread will be spawned to download and verify the filters
    -    /// in parallel. It's currently recommended to only connect to a single peer to avoid
    -    /// inconsistencies in the data returned, optionally with multiple connections in parallel to
    -    /// speed-up the sync process.
    -    pub fn new<P: AsRef<Path>>(
    -        peers: Vec<Peer>,
    -        storage_dir: P,
    -        skip_blocks: Option<usize>,
    -    ) -> Result<Self, CompactFiltersError> {
    -        if peers.is_empty() {
    -            return Err(CompactFiltersError::NoPeers);
    -        }
    -
    -        let mut opts = Options::default();
    -        opts.create_if_missing(true);
    -        opts.set_prefix_extractor(SliceTransform::create_fixed_prefix(16));
    -
    -        let network = peers[0].get_network();
    -
    -        let cfs = DB::list_cf(&opts, &storage_dir).unwrap_or(vec!["default".to_string()]);
    -        let db = DB::open_cf(&opts, &storage_dir, &cfs)?;
    -        let headers = Arc::new(ChainStore::new(db, network)?);
    -
    -        // try to recover partial snapshots
    -        for cf_name in &cfs {
    -            if !cf_name.starts_with("_headers:") {
    -                continue;
    -            }
    -
    -            info!("Trying to recover: {:?}", cf_name);
    -            headers.recover_snapshot(cf_name)?;
    -        }
    -
    -        Ok(CompactFiltersBlockchain {
    -            peers: peers.into_iter().map(Arc::new).collect(),
    -            headers,
    -            skip_blocks,
    -        })
    -    }
    -
    -    /// Process a transaction by looking for inputs that spend from a UTXO in the database or
    -    /// outputs that send funds to a know script_pubkey.
    -    fn process_tx<D: BatchDatabase>(
    -        &self,
    -        database: &mut D,
    -        tx: &Transaction,
    -        height: Option<u32>,
    -        timestamp: u64,
    -        internal_max_deriv: &mut Option<u32>,
    -        external_max_deriv: &mut Option<u32>,
    -    ) -> Result<(), Error> {
    -        let mut updates = database.begin_batch();
    -
    -        let mut incoming: u64 = 0;
    -        let mut outgoing: u64 = 0;
    -
    -        let mut inputs_sum: u64 = 0;
    -        let mut outputs_sum: u64 = 0;
    -
    -        // look for our own inputs
    -        for (i, input) in tx.input.iter().enumerate() {
    -            if let Some(previous_output) = database.get_previous_output(&input.previous_output)? {
    -                inputs_sum += previous_output.value;
    -
    -                if database.is_mine(&previous_output.script_pubkey)? {
    -                    outgoing += previous_output.value;
    -
    -                    debug!("{} input #{} is mine, removing from utxo", tx.txid(), i);
    -                    updates.del_utxo(&input.previous_output)?;
    -                }
    -            }
    -        }
    -
    -        for (i, output) in tx.output.iter().enumerate() {
    -            // to compute the fees later
    -            outputs_sum += output.value;
    -
    -            // this output is ours, we have a path to derive it
    -            if let Some((script_type, child)) =
    -                database.get_path_from_script_pubkey(&output.script_pubkey)?
    -            {
    -                debug!("{} output #{} is mine, adding utxo", tx.txid(), i);
    -                updates.set_utxo(&UTXO {
    -                    outpoint: OutPoint::new(tx.txid(), i as u32),
    -                    txout: output.clone(),
    -                    is_internal: script_type.is_internal(),
    -                })?;
    -                incoming += output.value;
    -
    -                if script_type == ScriptType::Internal
    -                    && (internal_max_deriv.is_none() || child > internal_max_deriv.unwrap_or(0))
    -                {
    -                    *internal_max_deriv = Some(child);
    -                } else if script_type == ScriptType::External
    -                    && (external_max_deriv.is_none() || child > external_max_deriv.unwrap_or(0))
    -                {
    -                    *external_max_deriv = Some(child);
    -                }
    -            }
    -        }
    -
    -        if incoming > 0 || outgoing > 0 {
    -            let tx = TransactionDetails {
    -                txid: tx.txid(),
    -                transaction: Some(tx.clone()),
    -                received: incoming,
    -                sent: outgoing,
    -                height,
    -                timestamp,
    -                fees: inputs_sum.checked_sub(outputs_sum).unwrap_or(0),
    -            };
    -
    -            info!("Saving tx {}", tx.txid);
    -            updates.set_tx(&tx)?;
    -        }
    -
    -        database.commit_batch(updates)?;
    -
    -        Ok(())
    -    }
    -}
    -
    -impl Blockchain for CompactFiltersBlockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        vec![Capability::FullHistory].into_iter().collect()
    -    }
    -
    -    fn setup<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        _stop_gap: Option<usize>, // TODO: move to electrum and esplora only
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        let first_peer = &self.peers[0];
    -
    -        let skip_blocks = self.skip_blocks.unwrap_or(0);
    -
    -        let cf_sync = Arc::new(CFSync::new(Arc::clone(&self.headers), skip_blocks, 0x00)?);
    -
    -        let initial_height = self.headers.get_height()?;
    -        let total_bundles = (first_peer.get_version().start_height as usize)
    -            .checked_sub(skip_blocks)
    -            .map(|x| x / 1000)
    -            .unwrap_or(0)
    -            + 1;
    -        let expected_bundles_to_sync = total_bundles
    -            .checked_sub(cf_sync.pruned_bundles()?)
    -            .unwrap_or(0);
    -
    -        let headers_cost = (first_peer.get_version().start_height as usize)
    -            .checked_sub(initial_height)
    -            .unwrap_or(0) as f32
    -            * SYNC_HEADERS_COST;
    -        let filters_cost = expected_bundles_to_sync as f32 * SYNC_FILTERS_COST;
    -
    -        let total_cost = headers_cost + filters_cost + PROCESS_BLOCKS_COST;
    -
    -        if let Some(snapshot) = sync::sync_headers(
    -            Arc::clone(&first_peer),
    -            Arc::clone(&self.headers),
    -            |new_height| {
    -                let local_headers_cost =
    -                    new_height.checked_sub(initial_height).unwrap_or(0) as f32 * SYNC_HEADERS_COST;
    -                progress_update.update(
    -                    local_headers_cost / total_cost * 100.0,
    -                    Some(format!("Synced headers to {}", new_height)),
    -                )
    -            },
    -        )? {
    -            if snapshot.work()? > self.headers.work()? {
    -                info!("Applying snapshot with work: {}", snapshot.work()?);
    -                self.headers.apply_snapshot(snapshot)?;
    -            }
    -        }
    -
    -        let synced_height = self.headers.get_height()?;
    -        let buried_height = synced_height
    -            .checked_sub(sync::BURIED_CONFIRMATIONS)
    -            .unwrap_or(0);
    -        info!("Synced headers to height: {}", synced_height);
    -
    -        cf_sync.prepare_sync(Arc::clone(&first_peer))?;
    -
    -        let all_scripts = Arc::new(
    -            database
    -                .iter_script_pubkeys(None)?
    -                .into_iter()
    -                .map(|s| s.to_bytes())
    -                .collect::<Vec<_>>(),
    -        );
    -
    -        let last_synced_block = Arc::new(Mutex::new(synced_height));
    -        let synced_bundles = Arc::new(AtomicUsize::new(0));
    -        let progress_update = Arc::new(Mutex::new(progress_update));
    -
    -        let mut threads = Vec::with_capacity(self.peers.len());
    -        for peer in &self.peers {
    -            let cf_sync = Arc::clone(&cf_sync);
    -            let peer = Arc::clone(&peer);
    -            let headers = Arc::clone(&self.headers);
    -            let all_scripts = Arc::clone(&all_scripts);
    -            let last_synced_block = Arc::clone(&last_synced_block);
    -            let progress_update = Arc::clone(&progress_update);
    -            let synced_bundles = Arc::clone(&synced_bundles);
    -
    -            let thread = std::thread::spawn(move || {
    -                cf_sync.capture_thread_for_sync(
    -                    peer,
    -                    |block_hash, filter| {
    -                        if !filter
    -                            .match_any(block_hash, &mut all_scripts.iter().map(AsRef::as_ref))?
    -                        {
    -                            return Ok(false);
    -                        }
    -
    -                        let block_height = headers.get_height_for(block_hash)?.unwrap_or(0);
    -                        let saved_correct_block = match headers.get_full_block(block_height)? {
    -                            Some(block) if &block.block_hash() == block_hash => true,
    -                            _ => false,
    -                        };
    -
    -                        if saved_correct_block {
    -                            Ok(false)
    -                        } else {
    -                            let mut last_synced_block = last_synced_block.lock().unwrap();
    -
    -                            // If we download a block older than `last_synced_block`, we update it so that
    -                            // we know to delete and re-process all txs starting from that height
    -                            if block_height < *last_synced_block {
    -                                *last_synced_block = block_height;
    -                            }
    -
    -                            Ok(true)
    -                        }
    -                    },
    -                    |index| {
    -                        let synced_bundles = synced_bundles.fetch_add(1, Ordering::SeqCst);
    -                        let local_filters_cost = synced_bundles as f32 * SYNC_FILTERS_COST;
    -                        progress_update.lock().unwrap().update(
    -                            (headers_cost + local_filters_cost) / total_cost * 100.0,
    -                            Some(format!(
    -                                "Synced filters {} - {}",
    -                                index * 1000 + 1,
    -                                (index + 1) * 1000
    -                            )),
    -                        )
    -                    },
    -                )
    -            });
    -
    -            threads.push(thread);
    -        }
    -
    -        for t in threads {
    -            t.join().unwrap()?;
    -        }
    -
    -        progress_update.lock().unwrap().update(
    -            (headers_cost + filters_cost) / total_cost * 100.0,
    -            Some("Processing downloaded blocks and mempool".into()),
    -        )?;
    -
    -        // delete all txs newer than last_synced_block
    -        let last_synced_block = *last_synced_block.lock().unwrap();
    -        log::debug!(
    -            "Dropping transactions newer than `last_synced_block` = {}",
    -            last_synced_block
    -        );
    -        let mut updates = database.begin_batch();
    -        for details in database.iter_txs(false)? {
    -            match details.height {
    -                Some(height) if (height as usize) < last_synced_block => continue,
    -                _ => updates.del_tx(&details.txid, false)?,
    -            };
    -        }
    -        database.commit_batch(updates)?;
    -
    -        first_peer.ask_for_mempool()?;
    -
    -        let mut internal_max_deriv = None;
    -        let mut external_max_deriv = None;
    -
    -        for (height, block) in self.headers.iter_full_blocks()? {
    -            for tx in &block.txdata {
    -                self.process_tx(
    -                    database,
    -                    tx,
    -                    Some(height as u32),
    -                    0,
    -                    &mut internal_max_deriv,
    -                    &mut external_max_deriv,
    -                )?;
    -            }
    -        }
    -        for tx in first_peer.get_mempool().iter_txs().iter() {
    -            self.process_tx(
    -                database,
    -                tx,
    -                None,
    -                0,
    -                &mut internal_max_deriv,
    -                &mut external_max_deriv,
    -            )?;
    -        }
    -
    -        let current_ext = database.get_last_index(ScriptType::External)?.unwrap_or(0);
    -        let first_ext_new = external_max_deriv.map(|x| x + 1).unwrap_or(0);
    -        if first_ext_new > current_ext {
    -            info!("Setting external index to {}", first_ext_new);
    -            database.set_last_index(ScriptType::External, first_ext_new)?;
    -        }
    -
    -        let current_int = database.get_last_index(ScriptType::Internal)?.unwrap_or(0);
    -        let first_int_new = internal_max_deriv.map(|x| x + 1).unwrap_or(0);
    -        if first_int_new > current_int {
    -            info!("Setting internal index to {}", first_int_new);
    -            database.set_last_index(ScriptType::Internal, first_int_new)?;
    -        }
    -
    -        info!("Dropping blocks until {}", buried_height);
    -        self.headers.delete_blocks_until(buried_height)?;
    -
    -        progress_update
    -            .lock()
    -            .unwrap()
    -            .update(100.0, Some("Done".into()))?;
    -
    -        Ok(())
    -    }
    -
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        Ok(self.peers[0]
    -            .get_mempool()
    -            .get_tx(&Inventory::Transaction(*txid)))
    -    }
    -
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        self.peers[0].broadcast_tx(tx.clone())?;
    -
    -        Ok(())
    -    }
    -
    -    fn get_height(&self) -> Result<u32, Error> {
    -        Ok(self.headers.get_height()? as u32)
    -    }
    -
    -    fn estimate_fee(&self, _target: usize) -> Result<FeeRate, Error> {
    -        // TODO
    -        Ok(FeeRate::default())
    -    }
    -}
    -
    -/// An error that can occur during sync with a [`CompactFiltersBlockchain`]
    -#[derive(Debug)]
    -pub enum CompactFiltersError {
    -    /// A peer sent an invalid or unexpected response
    -    InvalidResponse,
    -    /// The headers returned are invalid
    -    InvalidHeaders,
    -    /// The compact filter headers returned are invalid
    -    InvalidFilterHeader,
    -    /// The compact filter returned is invalid
    -    InvalidFilter,
    -    /// The peer is missing a block in the valid chain
    -    MissingBlock,
    -    /// The data stored in the block filters storage are corrupted
    -    DataCorruption,
    -
    -    /// A peer is not connected
    -    NotConnected,
    -    /// A peer took too long to reply to one of our messages
    -    Timeout,
    -
    -    /// No peers have been specified
    -    NoPeers,
    -
    -    /// Internal database error
    -    DB(rocksdb::Error),
    -    /// Internal I/O error
    -    IO(std::io::Error),
    -    /// Invalid BIP158 filter
    -    BIP158(bitcoin::util::bip158::Error),
    -    /// Internal system time error
    -    Time(std::time::SystemTimeError),
    -
    -    /// Wrapper for [`crate::error::Error`]
    -    Global(Box<crate::error::Error>),
    -}
    -
    -impl fmt::Display for CompactFiltersError {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for CompactFiltersError {}
    -
    -macro_rules! impl_error {
    -    ( $from:ty, $to:ident ) => {
    -        impl std::convert::From<$from> for CompactFiltersError {
    -            fn from(err: $from) -> Self {
    -                CompactFiltersError::$to(err)
    -            }
    -        }
    -    };
    -}
    -
    -impl_error!(rocksdb::Error, DB);
    -impl_error!(std::io::Error, IO);
    -impl_error!(bitcoin::util::bip158::Error, BIP158);
    -impl_error!(std::time::SystemTimeError, Time);
    -
    -impl From<crate::error::Error> for CompactFiltersError {
    -    fn from(err: crate::error::Error) -> Self {
    -        CompactFiltersError::Global(Box::new(err))
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/peer.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/peer.rs.html deleted file mode 100644 index cdec7c7773..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/peer.rs.html +++ /dev/null @@ -1,1103 +0,0 @@ -peer.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use std::collections::HashMap;
    -use std::net::{TcpStream, ToSocketAddrs};
    -use std::sync::{Arc, Condvar, Mutex, RwLock};
    -use std::thread;
    -use std::time::{Duration, SystemTime, UNIX_EPOCH};
    -
    -use socks::{Socks5Stream, ToTargetAddr};
    -
    -use rand::{thread_rng, Rng};
    -
    -use bitcoin::consensus::Encodable;
    -use bitcoin::hash_types::BlockHash;
    -use bitcoin::hashes::Hash;
    -use bitcoin::network::constants::ServiceFlags;
    -use bitcoin::network::message::{NetworkMessage, RawNetworkMessage};
    -use bitcoin::network::message_blockdata::*;
    -use bitcoin::network::message_filter::*;
    -use bitcoin::network::message_network::VersionMessage;
    -use bitcoin::network::stream_reader::StreamReader;
    -use bitcoin::network::Address;
    -use bitcoin::{Block, Network, Transaction, Txid};
    -
    -use super::CompactFiltersError;
    -
    -type ResponsesMap = HashMap<&'static str, Arc<(Mutex<Vec<NetworkMessage>>, Condvar)>>;
    -
    -pub(crate) const TIMEOUT_SECS: u64 = 30;
    -
    -/// Container for unconfirmed, but valid Bitcoin transactions
    -///
    -/// It is normally shared between [`Peer`]s with the use of [`Arc`], so that transactions are not
    -/// duplicated in memory.
    -#[derive(Debug, Default)]
    -pub struct Mempool {
    -    txs: RwLock<HashMap<Txid, Transaction>>,
    -}
    -
    -impl Mempool {
    -    /// Add a transaction to the mempool
    -    ///
    -    /// Note that this doesn't propagate the transaction to other
    -    /// peers. To do that, [`broadcast`](crate::blockchain::Blockchain::broadcast) should be used.
    -    pub fn add_tx(&self, tx: Transaction) {
    -        self.txs.write().unwrap().insert(tx.txid(), tx);
    -    }
    -
    -    /// Look-up a transaction in the mempool given an [`Inventory`] request
    -    pub fn get_tx(&self, inventory: &Inventory) -> Option<Transaction> {
    -        let txid = match inventory {
    -            Inventory::Error | Inventory::Block(_) | Inventory::WitnessBlock(_) => return None,
    -            Inventory::Transaction(txid) => *txid,
    -            Inventory::WitnessTransaction(wtxid) => Txid::from_inner(wtxid.into_inner()),
    -        };
    -        self.txs.read().unwrap().get(&txid).cloned()
    -    }
    -
    -    /// Return whether or not the mempool contains a transaction with a given txid
    -    pub fn has_tx(&self, txid: &Txid) -> bool {
    -        self.txs.read().unwrap().contains_key(txid)
    -    }
    -
    -    /// Return the list of transactions contained in the mempool
    -    pub fn iter_txs(&self) -> Vec<Transaction> {
    -        self.txs.read().unwrap().values().cloned().collect()
    -    }
    -}
    -
    -/// A Bitcoin peer
    -#[derive(Debug)]
    -pub struct Peer {
    -    writer: Arc<Mutex<TcpStream>>,
    -    responses: Arc<RwLock<ResponsesMap>>,
    -
    -    reader_thread: thread::JoinHandle<()>,
    -    connected: Arc<RwLock<bool>>,
    -
    -    mempool: Arc<Mempool>,
    -
    -    version: VersionMessage,
    -    network: Network,
    -}
    -
    -impl Peer {
    -    /// Connect to a peer over a plaintext TCP connection
    -    ///
    -    /// This function internally spawns a new thread that will monitor incoming messages from the
    -    /// peer, and optionally reply to some of them transparently, like [pings](NetworkMessage::Ping)
    -    pub fn connect<A: ToSocketAddrs>(
    -        address: A,
    -        mempool: Arc<Mempool>,
    -        network: Network,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let stream = TcpStream::connect(address)?;
    -
    -        Peer::from_stream(stream, mempool, network)
    -    }
    -
    -    /// Connect to a peer through a SOCKS5 proxy, optionally by using some credentials, specified
    -    /// as a tuple of `(username, password)`
    -    ///
    -    /// This function internally spawns a new thread that will monitor incoming messages from the
    -    /// peer, and optionally reply to some of them transparently, like [pings](NetworkMessage::Ping)
    -    pub fn connect_proxy<T: ToTargetAddr, P: ToSocketAddrs>(
    -        target: T,
    -        proxy: P,
    -        credentials: Option<(&str, &str)>,
    -        mempool: Arc<Mempool>,
    -        network: Network,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let socks_stream = if let Some((username, password)) = credentials {
    -            Socks5Stream::connect_with_password(proxy, target, username, password)?
    -        } else {
    -            Socks5Stream::connect(proxy, target)?
    -        };
    -
    -        Peer::from_stream(socks_stream.into_inner(), mempool, network)
    -    }
    -
    -    /// Create a [`Peer`] from an already connected TcpStream
    -    fn from_stream(
    -        stream: TcpStream,
    -        mempool: Arc<Mempool>,
    -        network: Network,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let writer = Arc::new(Mutex::new(stream.try_clone()?));
    -        let responses: Arc<RwLock<ResponsesMap>> = Arc::new(RwLock::new(HashMap::new()));
    -        let connected = Arc::new(RwLock::new(true));
    -
    -        let mut locked_writer = writer.lock().unwrap();
    -
    -        let reader_thread_responses = Arc::clone(&responses);
    -        let reader_thread_writer = Arc::clone(&writer);
    -        let reader_thread_mempool = Arc::clone(&mempool);
    -        let reader_thread_connected = Arc::clone(&connected);
    -        let reader_thread = thread::spawn(move || {
    -            Self::reader_thread(
    -                network,
    -                stream,
    -                reader_thread_responses,
    -                reader_thread_writer,
    -                reader_thread_mempool,
    -                reader_thread_connected,
    -            )
    -        });
    -
    -        let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() as i64;
    -        let nonce = thread_rng().gen();
    -        let receiver = Address::new(&locked_writer.peer_addr()?, ServiceFlags::NONE);
    -        let sender = Address {
    -            services: ServiceFlags::NONE,
    -            address: [0u16; 8],
    -            port: 0,
    -        };
    -
    -        Self::_send(
    -            &mut locked_writer,
    -            network.magic(),
    -            NetworkMessage::Version(VersionMessage::new(
    -                ServiceFlags::WITNESS,
    -                timestamp,
    -                receiver,
    -                sender,
    -                nonce,
    -                "MagicalBitcoinWallet".into(),
    -                0,
    -            )),
    -        )?;
    -        let version = if let NetworkMessage::Version(version) =
    -            Self::_recv(&responses, "version", None)?.unwrap()
    -        {
    -            version
    -        } else {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        };
    -
    -        if let NetworkMessage::Verack = Self::_recv(&responses, "verack", None)?.unwrap() {
    -            Self::_send(&mut locked_writer, network.magic(), NetworkMessage::Verack)?;
    -        } else {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        }
    -
    -        std::mem::drop(locked_writer);
    -
    -        Ok(Peer {
    -            writer,
    -            reader_thread,
    -            responses,
    -            connected,
    -            mempool,
    -            network,
    -            version,
    -        })
    -    }
    -
    -    /// Send a Bitcoin network message
    -    fn _send(
    -        writer: &mut TcpStream,
    -        magic: u32,
    -        payload: NetworkMessage,
    -    ) -> Result<(), CompactFiltersError> {
    -        log::trace!("==> {:?}", payload);
    -
    -        let raw_message = RawNetworkMessage { magic, payload };
    -
    -        raw_message
    -            .consensus_encode(writer)
    -            .map_err(|_| CompactFiltersError::DataCorruption)?;
    -
    -        Ok(())
    -    }
    -
    -    /// Wait for a specific incoming Bitcoin message, optionally with a timeout
    -    fn _recv(
    -        responses: &Arc<RwLock<ResponsesMap>>,
    -        wait_for: &'static str,
    -        timeout: Option<Duration>,
    -    ) -> Result<Option<NetworkMessage>, CompactFiltersError> {
    -        let message_resp = {
    -            let mut lock = responses.write().unwrap();
    -            let message_resp = lock.entry(wait_for).or_default();
    -            Arc::clone(&message_resp)
    -        };
    -
    -        let (lock, cvar) = &*message_resp;
    -
    -        let mut messages = lock.lock().unwrap();
    -        while messages.is_empty() {
    -            match timeout {
    -                None => messages = cvar.wait(messages).unwrap(),
    -                Some(t) => {
    -                    let result = cvar.wait_timeout(messages, t).unwrap();
    -                    if result.1.timed_out() {
    -                        return Ok(None);
    -                    }
    -
    -                    messages = result.0;
    -                }
    -            }
    -        }
    -
    -        Ok(messages.pop())
    -    }
    -
    -    /// Return the [`VersionMessage`] sent by the peer
    -    pub fn get_version(&self) -> &VersionMessage {
    -        &self.version
    -    }
    -
    -    /// Return the Bitcoin [`Network`] in use
    -    pub fn get_network(&self) -> Network {
    -        self.network
    -    }
    -
    -    /// Return the mempool used by this peer
    -    pub fn get_mempool(&self) -> Arc<Mempool> {
    -        Arc::clone(&self.mempool)
    -    }
    -
    -    /// Return whether or not the peer is still connected
    -    pub fn is_connected(&self) -> bool {
    -        *self.connected.read().unwrap()
    -    }
    -
    -    /// Internal function called once the `reader_thread` is spawned
    -    fn reader_thread(
    -        network: Network,
    -        connection: TcpStream,
    -        reader_thread_responses: Arc<RwLock<ResponsesMap>>,
    -        reader_thread_writer: Arc<Mutex<TcpStream>>,
    -        reader_thread_mempool: Arc<Mempool>,
    -        reader_thread_connected: Arc<RwLock<bool>>,
    -    ) {
    -        macro_rules! check_disconnect {
    -            ($call:expr) => {
    -                match $call {
    -                    Ok(good) => good,
    -                    Err(e) => {
    -                        log::debug!("Error {:?}", e);
    -                        *reader_thread_connected.write().unwrap() = false;
    -
    -                        break;
    -                    }
    -                }
    -            };
    -        }
    -
    -        let mut reader = StreamReader::new(connection, None);
    -        loop {
    -            let raw_message: RawNetworkMessage = check_disconnect!(reader.read_next());
    -
    -            let in_message = if raw_message.magic != network.magic() {
    -                continue;
    -            } else {
    -                raw_message.payload
    -            };
    -
    -            log::trace!("<== {:?}", in_message);
    -
    -            match in_message {
    -                NetworkMessage::Ping(nonce) => {
    -                    check_disconnect!(Self::_send(
    -                        &mut reader_thread_writer.lock().unwrap(),
    -                        network.magic(),
    -                        NetworkMessage::Pong(nonce),
    -                    ));
    -
    -                    continue;
    -                }
    -                NetworkMessage::Alert(_) => continue,
    -                NetworkMessage::GetData(ref inv) => {
    -                    let (found, not_found): (Vec<_>, Vec<_>) = inv
    -                        .into_iter()
    -                        .map(|item| (*item, reader_thread_mempool.get_tx(item)))
    -                        .partition(|(_, d)| d.is_some());
    -                    for (_, found_tx) in found {
    -                        check_disconnect!(Self::_send(
    -                            &mut reader_thread_writer.lock().unwrap(),
    -                            network.magic(),
    -                            NetworkMessage::Tx(found_tx.unwrap()),
    -                        ));
    -                    }
    -
    -                    if !not_found.is_empty() {
    -                        check_disconnect!(Self::_send(
    -                            &mut reader_thread_writer.lock().unwrap(),
    -                            network.magic(),
    -                            NetworkMessage::NotFound(
    -                                not_found.into_iter().map(|(i, _)| i).collect(),
    -                            ),
    -                        ));
    -                    }
    -                }
    -                _ => {}
    -            }
    -
    -            let message_resp = {
    -                let mut lock = reader_thread_responses.write().unwrap();
    -                let message_resp = lock.entry(in_message.cmd()).or_default();
    -                Arc::clone(&message_resp)
    -            };
    -
    -            let (lock, cvar) = &*message_resp;
    -            let mut messages = lock.lock().unwrap();
    -            messages.push(in_message);
    -            cvar.notify_all();
    -        }
    -    }
    -
    -    /// Send a raw Bitcoin message to the peer
    -    pub fn send(&self, payload: NetworkMessage) -> Result<(), CompactFiltersError> {
    -        let mut writer = self.writer.lock().unwrap();
    -        Self::_send(&mut writer, self.network.magic(), payload)
    -    }
    -
    -    /// Waits for a specific incoming Bitcoin message, optionally with a timeout
    -    pub fn recv(
    -        &self,
    -        wait_for: &'static str,
    -        timeout: Option<Duration>,
    -    ) -> Result<Option<NetworkMessage>, CompactFiltersError> {
    -        Self::_recv(&self.responses, wait_for, timeout)
    -    }
    -}
    -
    -pub trait CompactFiltersPeer {
    -    fn get_cf_checkpt(
    -        &self,
    -        filter_type: u8,
    -        stop_hash: BlockHash,
    -    ) -> Result<CFCheckpt, CompactFiltersError>;
    -    fn get_cf_headers(
    -        &self,
    -        filter_type: u8,
    -        start_height: u32,
    -        stop_hash: BlockHash,
    -    ) -> Result<CFHeaders, CompactFiltersError>;
    -    fn get_cf_filters(
    -        &self,
    -        filter_type: u8,
    -        start_height: u32,
    -        stop_hash: BlockHash,
    -    ) -> Result<(), CompactFiltersError>;
    -    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError>;
    -}
    -
    -impl CompactFiltersPeer for Peer {
    -    fn get_cf_checkpt(
    -        &self,
    -        filter_type: u8,
    -        stop_hash: BlockHash,
    -    ) -> Result<CFCheckpt, CompactFiltersError> {
    -        self.send(NetworkMessage::GetCFCheckpt(GetCFCheckpt {
    -            filter_type,
    -            stop_hash,
    -        }))?;
    -
    -        let response = self
    -            .recv("cfcheckpt", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -            .ok_or(CompactFiltersError::Timeout)?;
    -        let response = match response {
    -            NetworkMessage::CFCheckpt(response) => response,
    -            _ => return Err(CompactFiltersError::InvalidResponse),
    -        };
    -
    -        if response.filter_type != filter_type {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        }
    -
    -        Ok(response)
    -    }
    -
    -    fn get_cf_headers(
    -        &self,
    -        filter_type: u8,
    -        start_height: u32,
    -        stop_hash: BlockHash,
    -    ) -> Result<CFHeaders, CompactFiltersError> {
    -        self.send(NetworkMessage::GetCFHeaders(GetCFHeaders {
    -            filter_type,
    -            start_height,
    -            stop_hash,
    -        }))?;
    -
    -        let response = self
    -            .recv("cfheaders", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -            .ok_or(CompactFiltersError::Timeout)?;
    -        let response = match response {
    -            NetworkMessage::CFHeaders(response) => response,
    -            _ => return Err(CompactFiltersError::InvalidResponse),
    -        };
    -
    -        if response.filter_type != filter_type {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        }
    -
    -        Ok(response)
    -    }
    -
    -    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError> {
    -        let response = self
    -            .recv("cfilter", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -            .ok_or(CompactFiltersError::Timeout)?;
    -        let response = match response {
    -            NetworkMessage::CFilter(response) => response,
    -            _ => return Err(CompactFiltersError::InvalidResponse),
    -        };
    -
    -        Ok(response)
    -    }
    -
    -    fn get_cf_filters(
    -        &self,
    -        filter_type: u8,
    -        start_height: u32,
    -        stop_hash: BlockHash,
    -    ) -> Result<(), CompactFiltersError> {
    -        self.send(NetworkMessage::GetCFilters(GetCFilters {
    -            filter_type,
    -            start_height,
    -            stop_hash,
    -        }))?;
    -
    -        Ok(())
    -    }
    -}
    -
    -pub trait InvPeer {
    -    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError>;
    -    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError>;
    -    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError>;
    -}
    -
    -impl InvPeer for Peer {
    -    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError> {
    -        self.send(NetworkMessage::GetData(vec![Inventory::WitnessBlock(
    -            block_hash,
    -        )]))?;
    -
    -        match self.recv("block", Some(Duration::from_secs(TIMEOUT_SECS)))? {
    -            None => Ok(None),
    -            Some(NetworkMessage::Block(response)) => Ok(Some(response)),
    -            _ => Err(CompactFiltersError::InvalidResponse),
    -        }
    -    }
    -
    -    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError> {
    -        self.send(NetworkMessage::MemPool)?;
    -        let inv = match self.recv("inv", Some(Duration::from_secs(5)))? {
    -            None => return Ok(()), // empty mempool
    -            Some(NetworkMessage::Inv(inv)) => inv,
    -            _ => return Err(CompactFiltersError::InvalidResponse),
    -        };
    -
    -        let getdata = inv
    -            .iter()
    -            .cloned()
    -            .filter(|item| match item {
    -                Inventory::Transaction(txid) if !self.mempool.has_tx(txid) => true,
    -                _ => false,
    -            })
    -            .collect::<Vec<_>>();
    -        let num_txs = getdata.len();
    -        self.send(NetworkMessage::GetData(getdata))?;
    -
    -        for _ in 0..num_txs {
    -            let tx = self
    -                .recv("tx", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -                .ok_or(CompactFiltersError::Timeout)?;
    -            let tx = match tx {
    -                NetworkMessage::Tx(tx) => tx,
    -                _ => return Err(CompactFiltersError::InvalidResponse),
    -            };
    -
    -            self.mempool.add_tx(tx);
    -        }
    -
    -        Ok(())
    -    }
    -
    -    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError> {
    -        self.mempool.add_tx(tx.clone());
    -        self.send(NetworkMessage::Tx(tx))?;
    -
    -        Ok(())
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/store.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/store.rs.html deleted file mode 100644 index 64172790be..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/store.rs.html +++ /dev/null @@ -1,1811 +0,0 @@ -store.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use std::convert::TryInto;
    -use std::fmt;
    -use std::io::{Read, Write};
    -use std::marker::PhantomData;
    -use std::ops::Deref;
    -use std::sync::Arc;
    -use std::sync::RwLock;
    -
    -use rand::distributions::Alphanumeric;
    -use rand::{thread_rng, Rng};
    -
    -use rocksdb::{Direction, IteratorMode, ReadOptions, WriteBatch, DB};
    -
    -use bitcoin::consensus::{deserialize, encode::VarInt, serialize, Decodable, Encodable};
    -use bitcoin::hash_types::FilterHash;
    -use bitcoin::hashes::hex::FromHex;
    -use bitcoin::hashes::{sha256d, Hash};
    -use bitcoin::util::bip158::BlockFilter;
    -use bitcoin::util::uint::Uint256;
    -use bitcoin::Block;
    -use bitcoin::BlockHash;
    -use bitcoin::BlockHeader;
    -use bitcoin::Network;
    -
    -use super::CompactFiltersError;
    -
    -lazy_static! {
    -    static ref MAINNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A29AB5F49FFFF001D1DAC2B7C0101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
    -    static ref TESTNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4ADAE5494DFFFF001D1AA4AE180101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
    -    static ref REGTEST_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4ADAE5494DFFFF7F20020000000101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
    -}
    -
    -pub trait StoreType: Default + fmt::Debug {}
    -
    -#[derive(Default, Debug)]
    -pub struct Full;
    -impl StoreType for Full {}
    -#[derive(Default, Debug)]
    -pub struct Snapshot;
    -impl StoreType for Snapshot {}
    -
    -pub enum StoreEntry {
    -    BlockHeader(Option<usize>),
    -    Block(Option<usize>),
    -    BlockHeaderIndex(Option<BlockHash>),
    -    CFilterTable((u8, Option<usize>)),
    -}
    -
    -impl StoreEntry {
    -    pub fn get_prefix(&self) -> Vec<u8> {
    -        match self {
    -            StoreEntry::BlockHeader(_) => b"z",
    -            StoreEntry::Block(_) => b"x",
    -            StoreEntry::BlockHeaderIndex(_) => b"i",
    -            StoreEntry::CFilterTable(_) => b"t",
    -        }
    -        .to_vec()
    -    }
    -
    -    pub fn get_key(&self) -> Vec<u8> {
    -        let mut prefix = self.get_prefix();
    -        match self {
    -            StoreEntry::BlockHeader(Some(height)) => {
    -                prefix.extend_from_slice(&height.to_be_bytes())
    -            }
    -            StoreEntry::Block(Some(height)) => prefix.extend_from_slice(&height.to_be_bytes()),
    -            StoreEntry::BlockHeaderIndex(Some(hash)) => {
    -                prefix.extend_from_slice(&hash.into_inner())
    -            }
    -            StoreEntry::CFilterTable((filter_type, bundle_index)) => {
    -                prefix.push(*filter_type);
    -                if let Some(bundle_index) = bundle_index {
    -                    prefix.extend_from_slice(&bundle_index.to_be_bytes());
    -                }
    -            }
    -            _ => {}
    -        }
    -
    -        prefix
    -    }
    -}
    -
    -pub trait SerializeDb: Sized {
    -    fn serialize(&self) -> Vec<u8>;
    -    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError>;
    -}
    -
    -impl<T> SerializeDb for T
    -where
    -    T: Encodable + Decodable,
    -{
    -    fn serialize(&self) -> Vec<u8> {
    -        serialize(self)
    -    }
    -
    -    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError> {
    -        Ok(deserialize(data).map_err(|_| CompactFiltersError::DataCorruption)?)
    -    }
    -}
    -
    -impl Encodable for FilterHeader {
    -    fn consensus_encode<W: Write>(
    -        &self,
    -        mut e: W,
    -    ) -> Result<usize, bitcoin::consensus::encode::Error> {
    -        let mut written = self.prev_header_hash.consensus_encode(&mut e)?;
    -        written += self.filter_hash.consensus_encode(&mut e)?;
    -        Ok(written)
    -    }
    -}
    -
    -impl Decodable for FilterHeader {
    -    fn consensus_decode<D: Read>(mut d: D) -> Result<Self, bitcoin::consensus::encode::Error> {
    -        let prev_header_hash = FilterHeaderHash::consensus_decode(&mut d)?;
    -        let filter_hash = FilterHash::consensus_decode(&mut d)?;
    -
    -        Ok(FilterHeader {
    -            prev_header_hash,
    -            filter_hash,
    -        })
    -    }
    -}
    -
    -impl Encodable for BundleStatus {
    -    fn consensus_encode<W: Write>(
    -        &self,
    -        mut e: W,
    -    ) -> Result<usize, bitcoin::consensus::encode::Error> {
    -        let mut written = 0;
    -
    -        match self {
    -            BundleStatus::Init => {
    -                written += 0x00u8.consensus_encode(&mut e)?;
    -            }
    -            BundleStatus::CFHeaders { cf_headers } => {
    -                written += 0x01u8.consensus_encode(&mut e)?;
    -                written += VarInt(cf_headers.len() as u64).consensus_encode(&mut e)?;
    -                for header in cf_headers {
    -                    written += header.consensus_encode(&mut e)?;
    -                }
    -            }
    -            BundleStatus::CFilters { cf_filters } => {
    -                written += 0x02u8.consensus_encode(&mut e)?;
    -                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
    -                for filter in cf_filters {
    -                    written += filter.consensus_encode(&mut e)?;
    -                }
    -            }
    -            BundleStatus::Processed { cf_filters } => {
    -                written += 0x03u8.consensus_encode(&mut e)?;
    -                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
    -                for filter in cf_filters {
    -                    written += filter.consensus_encode(&mut e)?;
    -                }
    -            }
    -            BundleStatus::Pruned => {
    -                written += 0x04u8.consensus_encode(&mut e)?;
    -            }
    -            BundleStatus::Tip { cf_filters } => {
    -                written += 0x05u8.consensus_encode(&mut e)?;
    -                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
    -                for filter in cf_filters {
    -                    written += filter.consensus_encode(&mut e)?;
    -                }
    -            }
    -        }
    -
    -        Ok(written)
    -    }
    -}
    -
    -impl Decodable for BundleStatus {
    -    fn consensus_decode<D: Read>(mut d: D) -> Result<Self, bitcoin::consensus::encode::Error> {
    -        let byte_type = u8::consensus_decode(&mut d)?;
    -        match byte_type {
    -            0x00 => Ok(BundleStatus::Init),
    -            0x01 => {
    -                let num = VarInt::consensus_decode(&mut d)?;
    -                let num = num.0 as usize;
    -
    -                let mut cf_headers = Vec::with_capacity(num);
    -                for _ in 0..num {
    -                    cf_headers.push(FilterHeader::consensus_decode(&mut d)?);
    -                }
    -
    -                Ok(BundleStatus::CFHeaders { cf_headers })
    -            }
    -            0x02 => {
    -                let num = VarInt::consensus_decode(&mut d)?;
    -                let num = num.0 as usize;
    -
    -                let mut cf_filters = Vec::with_capacity(num);
    -                for _ in 0..num {
    -                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
    -                }
    -
    -                Ok(BundleStatus::CFilters { cf_filters })
    -            }
    -            0x03 => {
    -                let num = VarInt::consensus_decode(&mut d)?;
    -                let num = num.0 as usize;
    -
    -                let mut cf_filters = Vec::with_capacity(num);
    -                for _ in 0..num {
    -                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
    -                }
    -
    -                Ok(BundleStatus::Processed { cf_filters })
    -            }
    -            0x04 => Ok(BundleStatus::Pruned),
    -            0x05 => {
    -                let num = VarInt::consensus_decode(&mut d)?;
    -                let num = num.0 as usize;
    -
    -                let mut cf_filters = Vec::with_capacity(num);
    -                for _ in 0..num {
    -                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
    -                }
    -
    -                Ok(BundleStatus::Tip { cf_filters })
    -            }
    -            _ => Err(bitcoin::consensus::encode::Error::ParseFailed(
    -                "Invalid byte type",
    -            )),
    -        }
    -    }
    -}
    -
    -pub struct ChainStore<T: StoreType> {
    -    store: Arc<RwLock<DB>>,
    -    cf_name: String,
    -    min_height: usize,
    -    network: Network,
    -    phantom: PhantomData<T>,
    -}
    -
    -impl ChainStore<Full> {
    -    pub fn new(store: DB, network: Network) -> Result<Self, CompactFiltersError> {
    -        let genesis = match network {
    -            Network::Bitcoin => MAINNET_GENESIS.deref(),
    -            Network::Testnet => TESTNET_GENESIS.deref(),
    -            Network::Regtest => REGTEST_GENESIS.deref(),
    -        };
    -
    -        let cf_name = "default".to_string();
    -        let cf_handle = store.cf_handle(&cf_name).unwrap();
    -
    -        let genesis_key = StoreEntry::BlockHeader(Some(0)).get_key();
    -
    -        if store.get_pinned_cf(cf_handle, &genesis_key)?.is_none() {
    -            let mut batch = WriteBatch::default();
    -            batch.put_cf(
    -                cf_handle,
    -                genesis_key,
    -                (genesis.header, genesis.header.work()).serialize(),
    -            );
    -            batch.put_cf(
    -                cf_handle,
    -                StoreEntry::BlockHeaderIndex(Some(genesis.block_hash())).get_key(),
    -                &0usize.to_be_bytes(),
    -            );
    -            store.write(batch)?;
    -        }
    -
    -        Ok(ChainStore {
    -            store: Arc::new(RwLock::new(store)),
    -            cf_name,
    -            min_height: 0,
    -            network,
    -            phantom: PhantomData,
    -        })
    -    }
    -
    -    pub fn get_locators(&self) -> Result<Vec<(BlockHash, usize)>, CompactFiltersError> {
    -        let mut step = 1;
    -        let mut index = self.get_height()?;
    -        let mut answer = Vec::new();
    -
    -        let store_read = self.store.read().unwrap();
    -        let cf_handle = store_read.cf_handle(&self.cf_name).unwrap();
    -
    -        loop {
    -            if answer.len() > 10 {
    -                step *= 2;
    -            }
    -
    -            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(
    -                &store_read
    -                    .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(index)).get_key())?
    -                    .unwrap(),
    -            )?;
    -            answer.push((header.block_hash(), index));
    -
    -            if let Some(new_index) = index.checked_sub(step) {
    -                index = new_index;
    -            } else {
    -                break;
    -            }
    -        }
    -
    -        Ok(answer)
    -    }
    -
    -    pub fn start_snapshot(&self, from: usize) -> Result<ChainStore<Snapshot>, CompactFiltersError> {
    -        let new_cf_name: String = thread_rng().sample_iter(&Alphanumeric).take(16).collect();
    -        let new_cf_name = format!("_headers:{}", new_cf_name);
    -
    -        let mut write_store = self.store.write().unwrap();
    -
    -        write_store.create_cf(&new_cf_name, &Default::default())?;
    -
    -        let cf_handle = write_store.cf_handle(&self.cf_name).unwrap();
    -        let new_cf_handle = write_store.cf_handle(&new_cf_name).unwrap();
    -
    -        let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(
    -            &write_store
    -                .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
    -                .ok_or(CompactFiltersError::DataCorruption)?,
    -        )?;
    -
    -        let mut batch = WriteBatch::default();
    -        batch.put_cf(
    -            new_cf_handle,
    -            StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
    -            &from.to_be_bytes(),
    -        );
    -        batch.put_cf(
    -            new_cf_handle,
    -            StoreEntry::BlockHeader(Some(from)).get_key(),
    -            (header, work).serialize(),
    -        );
    -        write_store.write(batch)?;
    -
    -        let store = Arc::clone(&self.store);
    -        Ok(ChainStore {
    -            store,
    -            cf_name: new_cf_name,
    -            min_height: from,
    -            network: self.network,
    -            phantom: PhantomData,
    -        })
    -    }
    -
    -    pub fn recover_snapshot(&self, cf_name: &str) -> Result<(), CompactFiltersError> {
    -        let mut write_store = self.store.write().unwrap();
    -        let snapshot_cf_handle = write_store.cf_handle(cf_name).unwrap();
    -
    -        let prefix = StoreEntry::BlockHeader(None).get_key();
    -        let mut iterator = write_store.prefix_iterator_cf(snapshot_cf_handle, prefix);
    -
    -        let min_height = match iterator
    -            .next()
    -            .and_then(|(k, _)| k[1..].try_into().ok())
    -            .map(|bytes| usize::from_be_bytes(bytes))
    -        {
    -            None => {
    -                std::mem::drop(iterator);
    -                write_store.drop_cf(cf_name).ok();
    -
    -                return Ok(());
    -            }
    -            Some(x) => x,
    -        };
    -        std::mem::drop(iterator);
    -        std::mem::drop(write_store);
    -
    -        let snapshot = ChainStore {
    -            store: Arc::clone(&self.store),
    -            cf_name: cf_name.into(),
    -            min_height,
    -            network: self.network,
    -            phantom: PhantomData,
    -        };
    -        if snapshot.work()? > self.work()? {
    -            self.apply_snapshot(snapshot)?;
    -        }
    -
    -        Ok(())
    -    }
    -
    -    pub fn apply_snapshot(
    -        &self,
    -        snaphost: ChainStore<Snapshot>,
    -    ) -> Result<(), CompactFiltersError> {
    -        let mut batch = WriteBatch::default();
    -
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -        let snapshot_cf_handle = read_store.cf_handle(&snaphost.cf_name).unwrap();
    -
    -        let from_key = StoreEntry::BlockHeader(Some(snaphost.min_height)).get_key();
    -        let to_key = StoreEntry::BlockHeader(Some(usize::MAX)).get_key();
    -
    -        let mut opts = ReadOptions::default();
    -        opts.set_iterate_upper_bound(to_key.clone());
    -
    -        log::debug!("Removing items");
    -        batch.delete_range_cf(cf_handle, &from_key, &to_key);
    -        for (_, v) in read_store.iterator_cf_opt(
    -            cf_handle,
    -            opts,
    -            IteratorMode::From(&from_key, Direction::Forward),
    -        ) {
    -            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
    -
    -            batch.delete_cf(
    -                cf_handle,
    -                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
    -            );
    -        }
    -
    -        // Delete full blocks overriden by snapshot
    -        let from_key = StoreEntry::Block(Some(snaphost.min_height)).get_key();
    -        let to_key = StoreEntry::Block(Some(usize::MAX)).get_key();
    -        batch.delete_range(&from_key, &to_key);
    -
    -        log::debug!("Copying over new items");
    -        for (k, v) in read_store.iterator_cf(snapshot_cf_handle, IteratorMode::Start) {
    -            batch.put_cf(cf_handle, k, v);
    -        }
    -
    -        read_store.write(batch)?;
    -
    -        std::mem::drop(snapshot_cf_handle);
    -        std::mem::drop(cf_handle);
    -        std::mem::drop(read_store);
    -
    -        self.store.write().unwrap().drop_cf(&snaphost.cf_name)?;
    -
    -        Ok(())
    -    }
    -
    -    pub fn get_height_for(
    -        &self,
    -        block_hash: &BlockHash,
    -    ) -> Result<Option<usize>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let key = StoreEntry::BlockHeaderIndex(Some(block_hash.clone())).get_key();
    -        let data = read_store.get_pinned_cf(cf_handle, key)?;
    -        Ok(data
    -            .map(|data| {
    -                Ok::<_, CompactFiltersError>(usize::from_be_bytes(
    -                    data.as_ref()
    -                        .try_into()
    -                        .map_err(|_| CompactFiltersError::DataCorruption)?,
    -                ))
    -            })
    -            .transpose()?)
    -    }
    -
    -    pub fn get_block_hash(&self, height: usize) -> Result<Option<BlockHash>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let key = StoreEntry::BlockHeader(Some(height)).get_key();
    -        let data = read_store.get_pinned_cf(cf_handle, key)?;
    -        Ok(data
    -            .map(|data| {
    -                let (header, _): (BlockHeader, Uint256) =
    -                    deserialize(&data).map_err(|_| CompactFiltersError::DataCorruption)?;
    -                Ok::<_, CompactFiltersError>(header.block_hash())
    -            })
    -            .transpose()?)
    -    }
    -
    -    pub fn save_full_block(&self, block: &Block, height: usize) -> Result<(), CompactFiltersError> {
    -        let key = StoreEntry::Block(Some(height)).get_key();
    -        self.store.read().unwrap().put(key, block.serialize())?;
    -
    -        Ok(())
    -    }
    -
    -    pub fn get_full_block(&self, height: usize) -> Result<Option<Block>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -
    -        let key = StoreEntry::Block(Some(height)).get_key();
    -        let opt_block = read_store.get_pinned(key)?;
    -
    -        Ok(opt_block
    -            .map(|data| deserialize(&data))
    -            .transpose()
    -            .map_err(|_| CompactFiltersError::DataCorruption)?)
    -    }
    -
    -    pub fn delete_blocks_until(&self, height: usize) -> Result<(), CompactFiltersError> {
    -        let from_key = StoreEntry::Block(Some(0)).get_key();
    -        let to_key = StoreEntry::Block(Some(height)).get_key();
    -
    -        let mut batch = WriteBatch::default();
    -        batch.delete_range(&from_key, &to_key);
    -
    -        self.store.read().unwrap().write(batch)?;
    -
    -        Ok(())
    -    }
    -
    -    pub fn iter_full_blocks(&self) -> Result<Vec<(usize, Block)>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -
    -        let prefix = StoreEntry::Block(None).get_key();
    -
    -        let iterator = read_store.prefix_iterator(&prefix);
    -        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
    -        // have the right prefix
    -        iterator
    -            .filter(|(k, _)| k.starts_with(&prefix))
    -            .map(|(k, v)| {
    -                let height: usize = usize::from_be_bytes(
    -                    k[1..]
    -                        .try_into()
    -                        .map_err(|_| CompactFiltersError::DataCorruption)?,
    -                );
    -                let block = SerializeDb::deserialize(&v)?;
    -
    -                Ok((height, block))
    -            })
    -            .collect::<Result<_, _>>()
    -    }
    -}
    -
    -impl<T: StoreType> ChainStore<T> {
    -    pub fn work(&self) -> Result<Uint256, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let prefix = StoreEntry::BlockHeader(None).get_key();
    -        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
    -
    -        Ok(iterator
    -            .last()
    -            .map(|(_, v)| -> Result<_, CompactFiltersError> {
    -                let (_, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
    -
    -                Ok(work)
    -            })
    -            .transpose()?
    -            .unwrap_or_default())
    -    }
    -
    -    pub fn get_height(&self) -> Result<usize, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let prefix = StoreEntry::BlockHeader(None).get_key();
    -        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
    -
    -        Ok(iterator
    -            .last()
    -            .map(|(k, _)| -> Result<_, CompactFiltersError> {
    -                let height = usize::from_be_bytes(
    -                    k[1..]
    -                        .try_into()
    -                        .map_err(|_| CompactFiltersError::DataCorruption)?,
    -                );
    -
    -                Ok(height)
    -            })
    -            .transpose()?
    -            .unwrap_or_default())
    -    }
    -
    -    pub fn get_tip_hash(&self) -> Result<Option<BlockHash>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let prefix = StoreEntry::BlockHeader(None).get_key();
    -        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
    -
    -        Ok(iterator
    -            .last()
    -            .map(|(_, v)| -> Result<_, CompactFiltersError> {
    -                let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
    -
    -                Ok(header.block_hash())
    -            })
    -            .transpose()?)
    -    }
    -
    -    pub fn apply(
    -        &mut self,
    -        from: usize,
    -        headers: Vec<BlockHeader>,
    -    ) -> Result<BlockHash, CompactFiltersError> {
    -        let mut batch = WriteBatch::default();
    -
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let (mut last_hash, mut accumulated_work) = read_store
    -            .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
    -            .map(|result| {
    -                let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&result)?;
    -                Ok::<_, CompactFiltersError>((header.block_hash(), work))
    -            })
    -            .transpose()?
    -            .ok_or(CompactFiltersError::DataCorruption)?;
    -
    -        for (index, header) in headers.into_iter().enumerate() {
    -            if header.prev_blockhash != last_hash {
    -                return Err(CompactFiltersError::InvalidHeaders);
    -            }
    -
    -            last_hash = header.block_hash();
    -            accumulated_work = accumulated_work + header.work();
    -
    -            let height = from + index + 1;
    -            batch.put_cf(
    -                cf_handle,
    -                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
    -                &(height).to_be_bytes(),
    -            );
    -            batch.put_cf(
    -                cf_handle,
    -                StoreEntry::BlockHeader(Some(height)).get_key(),
    -                (header, accumulated_work).serialize(),
    -            );
    -        }
    -
    -        std::mem::drop(cf_handle);
    -        std::mem::drop(read_store);
    -
    -        self.store.write().unwrap().write(batch)?;
    -        Ok(last_hash)
    -    }
    -}
    -
    -impl<T: StoreType> fmt::Debug for ChainStore<T> {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        f.debug_struct(&format!("ChainStore<{:?}>", T::default()))
    -            .field("cf_name", &self.cf_name)
    -            .field("min_height", &self.min_height)
    -            .field("network", &self.network)
    -            .field("headers_height", &self.get_height())
    -            .field("tip_hash", &self.get_tip_hash())
    -            .finish()
    -    }
    -}
    -
    -pub type FilterHeaderHash = FilterHash;
    -
    -#[derive(Debug, Clone)]
    -pub struct FilterHeader {
    -    prev_header_hash: FilterHeaderHash,
    -    filter_hash: FilterHash,
    -}
    -
    -impl FilterHeader {
    -    fn header_hash(&self) -> FilterHeaderHash {
    -        let mut hash_data = self.filter_hash.into_inner().to_vec();
    -        hash_data.extend_from_slice(&self.prev_header_hash);
    -        sha256d::Hash::hash(&hash_data).into()
    -    }
    -}
    -
    -pub enum BundleStatus {
    -    Init,
    -    CFHeaders { cf_headers: Vec<FilterHeader> },
    -    CFilters { cf_filters: Vec<Vec<u8>> },
    -    Processed { cf_filters: Vec<Vec<u8>> },
    -    Tip { cf_filters: Vec<Vec<u8>> },
    -    Pruned,
    -}
    -
    -pub struct CFStore {
    -    store: Arc<RwLock<DB>>,
    -    filter_type: u8,
    -}
    -
    -type BundleEntry = (BundleStatus, FilterHeaderHash);
    -
    -impl CFStore {
    -    pub fn new(
    -        headers_store: &ChainStore<Full>,
    -        filter_type: u8,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let cf_store = CFStore {
    -            store: Arc::clone(&headers_store.store),
    -            filter_type,
    -        };
    -
    -        let genesis = match headers_store.network {
    -            Network::Bitcoin => MAINNET_GENESIS.deref(),
    -            Network::Testnet => TESTNET_GENESIS.deref(),
    -            Network::Regtest => REGTEST_GENESIS.deref(),
    -        };
    -
    -        let filter = BlockFilter::new_script_filter(genesis, |utxo| {
    -            Err(bitcoin::util::bip158::Error::UtxoMissing(*utxo))
    -        })?;
    -        let first_key = StoreEntry::CFilterTable((filter_type, Some(0))).get_key();
    -
    -        // Add the genesis' filter
    -        {
    -            let read_store = cf_store.store.read().unwrap();
    -            if read_store.get_pinned(&first_key)?.is_none() {
    -                read_store.put(
    -                    &first_key,
    -                    (BundleStatus::Init, filter.filter_id(&FilterHash::default())).serialize(),
    -                )?;
    -            }
    -        }
    -
    -        Ok(cf_store)
    -    }
    -
    -    pub fn get_filter_type(&self) -> u8 {
    -        self.filter_type
    -    }
    -
    -    pub fn get_bundles(&self) -> Result<Vec<BundleEntry>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -
    -        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
    -        let iterator = read_store.prefix_iterator(&prefix);
    -
    -        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
    -        // have the right prefix
    -        iterator
    -            .filter(|(k, _)| k.starts_with(&prefix))
    -            .map(|(_, data)| BundleEntry::deserialize(&data))
    -            .collect::<Result<_, _>>()
    -    }
    -
    -    pub fn get_checkpoints(&self) -> Result<Vec<FilterHash>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -
    -        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
    -        let iterator = read_store.prefix_iterator(&prefix);
    -
    -        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
    -        // have the right prefix
    -        Ok(iterator
    -            .filter(|(k, _)| k.starts_with(&prefix))
    -            .skip(1)
    -            .map(|(_, data)| Ok::<_, CompactFiltersError>(BundleEntry::deserialize(&data)?.1))
    -            .collect::<Result<_, _>>()?)
    -    }
    -
    -    pub fn replace_checkpoints(
    -        &self,
    -        checkpoints: Vec<FilterHash>,
    -    ) -> Result<(), CompactFiltersError> {
    -        let current_checkpoints = self.get_checkpoints()?;
    -
    -        let mut equal_bundles = 0;
    -        for (index, (our, their)) in current_checkpoints
    -            .iter()
    -            .zip(checkpoints.iter())
    -            .enumerate()
    -        {
    -            equal_bundles = index;
    -
    -            if our != their {
    -                break;
    -            }
    -        }
    -
    -        let read_store = self.store.read().unwrap();
    -        let mut batch = WriteBatch::default();
    -
    -        for (index, filter_hash) in checkpoints.iter().enumerate().skip(equal_bundles) {
    -            let key = StoreEntry::CFilterTable((self.filter_type, Some(index + 1))).get_key(); // +1 to skip the genesis' filter
    -
    -            if let Some((BundleStatus::Tip { .. }, _)) = read_store
    -                .get_pinned(&key)?
    -                .map(|data| BundleEntry::deserialize(&data))
    -                .transpose()?
    -            {
    -                println!("Keeping bundle #{} as Tip", index);
    -            } else {
    -                batch.put(&key, (BundleStatus::Init, *filter_hash).serialize());
    -            }
    -        }
    -
    -        read_store.write(batch)?;
    -
    -        Ok(())
    -    }
    -
    -    pub fn advance_to_cf_headers(
    -        &self,
    -        bundle: usize,
    -        checkpoint_hash: FilterHeaderHash,
    -        filter_headers: Vec<FilterHash>,
    -    ) -> Result<BundleStatus, CompactFiltersError> {
    -        let mut last_hash = checkpoint_hash;
    -        let cf_headers = filter_headers
    -            .into_iter()
    -            .map(|filter_hash| {
    -                let filter_header = FilterHeader {
    -                    prev_header_hash: last_hash,
    -                    filter_hash,
    -                };
    -                last_hash = filter_header.header_hash();
    -
    -                filter_header
    -            })
    -            .collect();
    -
    -        let read_store = self.store.read().unwrap();
    -
    -        let next_key = StoreEntry::CFilterTable((self.filter_type, Some(bundle + 1))).get_key(); // +1 to skip the genesis' filter
    -        if let Some((_, next_checkpoint)) = read_store
    -            .get_pinned(&next_key)?
    -            .map(|data| BundleEntry::deserialize(&data))
    -            .transpose()?
    -        {
    -            // check connection with the next bundle if present
    -            if last_hash != next_checkpoint {
    -                return Err(CompactFiltersError::InvalidFilterHeader);
    -            }
    -        }
    -
    -        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
    -        let value = (BundleStatus::CFHeaders { cf_headers }, checkpoint_hash);
    -
    -        read_store.put(key, value.serialize())?;
    -
    -        Ok(value.0)
    -    }
    -
    -    pub fn advance_to_cf_filters(
    -        &self,
    -        bundle: usize,
    -        checkpoint_hash: FilterHeaderHash,
    -        headers: Vec<FilterHeader>,
    -        filters: Vec<(usize, Vec<u8>)>,
    -    ) -> Result<BundleStatus, CompactFiltersError> {
    -        let cf_filters = filters
    -            .into_iter()
    -            .zip(headers.iter())
    -            .map(|((_, filter_content), header)| {
    -                if header.filter_hash != sha256d::Hash::hash(&filter_content).into() {
    -                    return Err(CompactFiltersError::InvalidFilter);
    -                }
    -
    -                Ok::<_, CompactFiltersError>(filter_content)
    -            })
    -            .collect::<Result<_, _>>()?;
    -
    -        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
    -        let value = (BundleStatus::CFilters { cf_filters }, checkpoint_hash);
    -
    -        let read_store = self.store.read().unwrap();
    -        read_store.put(key, value.serialize())?;
    -
    -        Ok(value.0)
    -    }
    -
    -    pub fn prune_filters(
    -        &self,
    -        bundle: usize,
    -        checkpoint_hash: FilterHeaderHash,
    -    ) -> Result<BundleStatus, CompactFiltersError> {
    -        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
    -        let value = (BundleStatus::Pruned, checkpoint_hash);
    -
    -        let read_store = self.store.read().unwrap();
    -        read_store.put(key, value.serialize())?;
    -
    -        Ok(value.0)
    -    }
    -
    -    pub fn mark_as_tip(
    -        &self,
    -        bundle: usize,
    -        cf_filters: Vec<Vec<u8>>,
    -        checkpoint_hash: FilterHeaderHash,
    -    ) -> Result<BundleStatus, CompactFiltersError> {
    -        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
    -        let value = (BundleStatus::Tip { cf_filters }, checkpoint_hash);
    -
    -        let read_store = self.store.read().unwrap();
    -        read_store.put(key, value.serialize())?;
    -
    -        Ok(value.0)
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/sync.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/sync.rs.html deleted file mode 100644 index 29d89bdd81..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/compact_filters/sync.rs.html +++ /dev/null @@ -1,629 +0,0 @@ -sync.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use std::collections::{BTreeMap, HashMap, VecDeque};
    -use std::sync::{Arc, Mutex};
    -use std::time::Duration;
    -
    -use bitcoin::hash_types::{BlockHash, FilterHash};
    -use bitcoin::network::message::NetworkMessage;
    -use bitcoin::network::message_blockdata::GetHeadersMessage;
    -use bitcoin::util::bip158::BlockFilter;
    -
    -use super::peer::*;
    -use super::store::*;
    -use super::CompactFiltersError;
    -use crate::error::Error;
    -
    -pub(crate) const BURIED_CONFIRMATIONS: usize = 100;
    -
    -pub struct CFSync {
    -    headers_store: Arc<ChainStore<Full>>,
    -    cf_store: Arc<CFStore>,
    -    skip_blocks: usize,
    -    bundles: Mutex<VecDeque<(BundleStatus, FilterHash, usize)>>,
    -}
    -
    -impl CFSync {
    -    pub fn new(
    -        headers_store: Arc<ChainStore<Full>>,
    -        skip_blocks: usize,
    -        filter_type: u8,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let cf_store = Arc::new(CFStore::new(&headers_store, filter_type)?);
    -
    -        Ok(CFSync {
    -            headers_store,
    -            cf_store,
    -            skip_blocks,
    -            bundles: Mutex::new(VecDeque::new()),
    -        })
    -    }
    -
    -    pub fn pruned_bundles(&self) -> Result<usize, CompactFiltersError> {
    -        Ok(self
    -            .cf_store
    -            .get_bundles()?
    -            .into_iter()
    -            .skip(self.skip_blocks / 1000)
    -            .fold(0, |acc, (status, _)| match status {
    -                BundleStatus::Pruned => acc + 1,
    -                _ => acc,
    -            }))
    -    }
    -
    -    pub fn prepare_sync(&self, peer: Arc<Peer>) -> Result<(), CompactFiltersError> {
    -        let mut bundles_lock = self.bundles.lock().unwrap();
    -
    -        let resp = peer.get_cf_checkpt(
    -            self.cf_store.get_filter_type(),
    -            self.headers_store.get_tip_hash()?.unwrap(),
    -        )?;
    -        self.cf_store.replace_checkpoints(resp.filter_headers)?;
    -
    -        bundles_lock.clear();
    -        for (index, (status, checkpoint)) in self.cf_store.get_bundles()?.into_iter().enumerate() {
    -            bundles_lock.push_back((status, checkpoint, index));
    -        }
    -
    -        Ok(())
    -    }
    -
    -    pub fn capture_thread_for_sync<F, Q>(
    -        &self,
    -        peer: Arc<Peer>,
    -        process: F,
    -        completed_bundle: Q,
    -    ) -> Result<(), CompactFiltersError>
    -    where
    -        F: Fn(&BlockHash, &BlockFilter) -> Result<bool, CompactFiltersError>,
    -        Q: Fn(usize) -> Result<(), Error>,
    -    {
    -        let current_height = self.headers_store.get_height()?; // TODO: we should update it in case headers_store is also updated
    -
    -        loop {
    -            let (mut status, checkpoint, index) = match self.bundles.lock().unwrap().pop_front() {
    -                None => break,
    -                Some(x) => x,
    -            };
    -
    -            log::debug!(
    -                "Processing bundle #{} - height {} to {}",
    -                index,
    -                index * 1000 + 1,
    -                (index + 1) * 1000
    -            );
    -
    -            let process_received_filters =
    -                |expected_filters| -> Result<BTreeMap<usize, Vec<u8>>, CompactFiltersError> {
    -                    let mut filters_map = BTreeMap::new();
    -                    for _ in 0..expected_filters {
    -                        let filter = peer.pop_cf_filter_resp()?;
    -                        if filter.filter_type != self.cf_store.get_filter_type() {
    -                            return Err(CompactFiltersError::InvalidResponse);
    -                        }
    -
    -                        match self.headers_store.get_height_for(&filter.block_hash)? {
    -                            Some(height) => filters_map.insert(height, filter.filter),
    -                            None => return Err(CompactFiltersError::InvalidFilter),
    -                        };
    -                    }
    -
    -                    Ok(filters_map)
    -                };
    -
    -            let start_height = index * 1000 + 1;
    -            let mut already_processed = 0;
    -
    -            if start_height < self.skip_blocks {
    -                status = self.cf_store.prune_filters(index, checkpoint)?;
    -            }
    -
    -            let stop_height = std::cmp::min(current_height, start_height + 999);
    -            let stop_hash = self.headers_store.get_block_hash(stop_height)?.unwrap();
    -
    -            if let BundleStatus::Init = status {
    -                log::trace!("status: Init");
    -
    -                let resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
    -
    -                assert!(resp.previous_filter == checkpoint);
    -                status =
    -                    self.cf_store
    -                        .advance_to_cf_headers(index, checkpoint, resp.filter_hashes)?;
    -            }
    -            if let BundleStatus::Tip { cf_filters } = status {
    -                log::trace!("status: Tip (beginning) ");
    -
    -                already_processed = cf_filters.len();
    -                let headers_resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
    -
    -                let cf_headers = match self.cf_store.advance_to_cf_headers(
    -                    index,
    -                    checkpoint,
    -                    headers_resp.filter_hashes,
    -                )? {
    -                    BundleStatus::CFHeaders { cf_headers } => cf_headers,
    -                    _ => return Err(CompactFiltersError::InvalidResponse),
    -                };
    -
    -                peer.get_cf_filters(
    -                    self.cf_store.get_filter_type(),
    -                    (start_height + cf_filters.len()) as u32,
    -                    stop_hash,
    -                )?;
    -                let expected_filters = stop_height - start_height + 1 - cf_filters.len();
    -                let filters_map = process_received_filters(expected_filters)?;
    -                let filters = cf_filters
    -                    .into_iter()
    -                    .enumerate()
    -                    .chain(filters_map.into_iter())
    -                    .collect();
    -                status = self
    -                    .cf_store
    -                    .advance_to_cf_filters(index, checkpoint, cf_headers, filters)?;
    -            }
    -            if let BundleStatus::CFHeaders { cf_headers } = status {
    -                log::trace!("status: CFHeaders");
    -
    -                peer.get_cf_filters(
    -                    self.cf_store.get_filter_type(),
    -                    start_height as u32,
    -                    stop_hash,
    -                )?;
    -                let expected_filters = stop_height - start_height + 1;
    -                let filters_map = process_received_filters(expected_filters)?;
    -                status = self.cf_store.advance_to_cf_filters(
    -                    index,
    -                    checkpoint,
    -                    cf_headers,
    -                    filters_map.into_iter().collect(),
    -                )?;
    -            }
    -            if let BundleStatus::CFilters { cf_filters } = status {
    -                log::trace!("status: CFilters");
    -
    -                let last_sync_buried_height = (start_height + already_processed)
    -                    .checked_sub(BURIED_CONFIRMATIONS)
    -                    .unwrap_or(0);
    -
    -                for (filter_index, filter) in cf_filters.iter().enumerate() {
    -                    let height = filter_index + start_height;
    -
    -                    // do not download blocks that were already "buried" since the last sync
    -                    if height < last_sync_buried_height {
    -                        continue;
    -                    }
    -
    -                    let block_hash = self.headers_store.get_block_hash(height)?.unwrap();
    -
    -                    // TODO: also download random blocks?
    -                    if process(&block_hash, &BlockFilter::new(&filter))? {
    -                        log::debug!("Downloading block {}", block_hash);
    -
    -                        let block = peer
    -                            .get_block(block_hash)?
    -                            .ok_or(CompactFiltersError::MissingBlock)?;
    -                        self.headers_store.save_full_block(&block, height)?;
    -                    }
    -                }
    -
    -                status = BundleStatus::Processed { cf_filters };
    -            }
    -            if let BundleStatus::Processed { cf_filters } = status {
    -                log::trace!("status: Processed");
    -
    -                if current_height - stop_height > 1000 {
    -                    status = self.cf_store.prune_filters(index, checkpoint)?;
    -                } else {
    -                    status = self.cf_store.mark_as_tip(index, cf_filters, checkpoint)?;
    -                }
    -
    -                completed_bundle(index)?;
    -            }
    -            if let BundleStatus::Pruned = status {
    -                log::trace!("status: Pruned");
    -            }
    -            if let BundleStatus::Tip { .. } = status {
    -                log::trace!("status: Tip");
    -            }
    -        }
    -
    -        Ok(())
    -    }
    -}
    -
    -pub fn sync_headers<F>(
    -    peer: Arc<Peer>,
    -    store: Arc<ChainStore<Full>>,
    -    sync_fn: F,
    -) -> Result<Option<ChainStore<Snapshot>>, CompactFiltersError>
    -where
    -    F: Fn(usize) -> Result<(), Error>,
    -{
    -    let locators = store.get_locators()?;
    -    let locators_vec = locators.iter().map(|(hash, _)| hash).cloned().collect();
    -    let locators_map: HashMap<_, _> = locators.into_iter().collect();
    -
    -    peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
    -        locators_vec,
    -        Default::default(),
    -    )))?;
    -    let (mut snapshot, mut last_hash) = if let NetworkMessage::Headers(headers) = peer
    -        .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -        .ok_or(CompactFiltersError::Timeout)?
    -    {
    -        if headers.is_empty() {
    -            return Ok(None);
    -        }
    -
    -        match locators_map.get(&headers[0].prev_blockhash) {
    -            None => return Err(CompactFiltersError::InvalidHeaders),
    -            Some(from) => (
    -                store.start_snapshot(*from)?,
    -                headers[0].prev_blockhash.clone(),
    -            ),
    -        }
    -    } else {
    -        return Err(CompactFiltersError::InvalidResponse);
    -    };
    -
    -    let mut sync_height = store.get_height()?;
    -    while sync_height < peer.get_version().start_height as usize {
    -        peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
    -            vec![last_hash],
    -            Default::default(),
    -        )))?;
    -        if let NetworkMessage::Headers(headers) = peer
    -            .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -            .ok_or(CompactFiltersError::Timeout)?
    -        {
    -            let batch_len = headers.len();
    -            last_hash = snapshot.apply(sync_height, headers)?;
    -
    -            sync_height += batch_len;
    -            sync_fn(sync_height)?;
    -        } else {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        }
    -    }
    -
    -    Ok(Some(snapshot))
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/electrum.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/electrum.rs.html deleted file mode 100644 index c12b391f32..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/electrum.rs.html +++ /dev/null @@ -1,353 +0,0 @@ -electrum.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Electrum
    -//!
    -//! This module defines a [`Blockchain`] struct that wraps an [`electrum_client::Client`]
    -//! and implements the logic required to populate the wallet's [database](crate::database::Database) by
    -//! querying the inner client.
    -//!
    -//! ## Example
    -//!
    -//! ```no_run
    -//! # use bdk::blockchain::electrum::ElectrumBlockchain;
    -//! let client = electrum_client::Client::new("ssl://electrum.blockstream.info:50002", None)?;
    -//! let blockchain = ElectrumBlockchain::from(client);
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use std::collections::HashSet;
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -use bitcoin::{Script, Transaction, Txid};
    -
    -use electrum_client::{Client, ElectrumApi};
    -
    -use self::utils::{ELSGetHistoryRes, ELSListUnspentRes, ElectrumLikeSync};
    -use super::*;
    -use crate::database::BatchDatabase;
    -use crate::error::Error;
    -use crate::FeeRate;
    -
    -/// Wrapper over an Electrum Client that implements the required blockchain traits
    -///
    -/// ## Example
    -/// See the [`blockchain::electrum`](crate::blockchain::electrum) module for a usage example.
    -pub struct ElectrumBlockchain(Client);
    -
    -#[cfg(test)]
    -#[cfg(feature = "test-electrum")]
    -#[bdk_blockchain_tests(crate)]
    -fn local_electrs() -> ElectrumBlockchain {
    -    ElectrumBlockchain::from(Client::new(&testutils::get_electrum_url(), None).unwrap())
    -}
    -
    -impl std::convert::From<Client> for ElectrumBlockchain {
    -    fn from(client: Client) -> Self {
    -        ElectrumBlockchain(client)
    -    }
    -}
    -
    -impl Blockchain for ElectrumBlockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        vec![
    -            Capability::FullHistory,
    -            Capability::GetAnyTx,
    -            Capability::AccurateFees,
    -        ]
    -        .into_iter()
    -        .collect()
    -    }
    -
    -    fn setup<D: BatchDatabase, P: Progress>(
    -        &self,
    -        stop_gap: Option<usize>,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        self.0
    -            .electrum_like_setup(stop_gap, database, progress_update)
    -    }
    -
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        Ok(self.0.transaction_get(txid).map(Option::Some)?)
    -    }
    -
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        Ok(self.0.transaction_broadcast(tx).map(|_| ())?)
    -    }
    -
    -    fn get_height(&self) -> Result<u32, Error> {
    -        // TODO: unsubscribe when added to the client, or is there a better call to use here?
    -
    -        Ok(self
    -            .0
    -            .block_headers_subscribe()
    -            .map(|data| data.height as u32)?)
    -    }
    -
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
    -        Ok(FeeRate::from_btc_per_kvb(
    -            self.0.estimate_fee(target)? as f32
    -        ))
    -    }
    -}
    -
    -impl ElectrumLikeSync for Client {
    -    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
    -        &self,
    -        scripts: I,
    -    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error> {
    -        self.batch_script_get_history(scripts)
    -            .map(|v| {
    -                v.into_iter()
    -                    .map(|v| {
    -                        v.into_iter()
    -                            .map(
    -                                |electrum_client::GetHistoryRes {
    -                                     height, tx_hash, ..
    -                                 }| ELSGetHistoryRes {
    -                                    height,
    -                                    tx_hash,
    -                                },
    -                            )
    -                            .collect()
    -                    })
    -                    .collect()
    -            })
    -            .map_err(Error::Electrum)
    -    }
    -
    -    fn els_batch_script_list_unspent<'s, I: IntoIterator<Item = &'s Script>>(
    -        &self,
    -        scripts: I,
    -    ) -> Result<Vec<Vec<ELSListUnspentRes>>, Error> {
    -        self.batch_script_list_unspent(scripts)
    -            .map(|v| {
    -                v.into_iter()
    -                    .map(|v| {
    -                        v.into_iter()
    -                            .map(
    -                                |electrum_client::ListUnspentRes {
    -                                     height,
    -                                     tx_hash,
    -                                     tx_pos,
    -                                     ..
    -                                 }| ELSListUnspentRes {
    -                                    height,
    -                                    tx_hash,
    -                                    tx_pos,
    -                                },
    -                            )
    -                            .collect()
    -                    })
    -                    .collect()
    -            })
    -            .map_err(Error::Electrum)
    -    }
    -
    -    fn els_transaction_get(&self, txid: &Txid) -> Result<Transaction, Error> {
    -        self.transaction_get(txid).map_err(Error::Electrum)
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/esplora.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/esplora.rs.html deleted file mode 100644 index 635d250df6..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/esplora.rs.html +++ /dev/null @@ -1,765 +0,0 @@ -esplora.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Esplora
    -//!
    -//! This module defines a [`Blockchain`] struct that can query an Esplora backend
    -//! populate the wallet's [database](crate::database::Database) by
    -//!
    -//! ## Example
    -//!
    -//! ```no_run
    -//! # use bdk::blockchain::esplora::EsploraBlockchain;
    -//! let blockchain = EsploraBlockchain::new("https://blockstream.info/testnet/api");
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use std::collections::{HashMap, HashSet};
    -use std::fmt;
    -
    -use futures::stream::{self, StreamExt, TryStreamExt};
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -use serde::Deserialize;
    -
    -use reqwest::{Client, StatusCode};
    -
    -use bitcoin::consensus::{deserialize, serialize};
    -use bitcoin::hashes::hex::ToHex;
    -use bitcoin::hashes::{sha256, Hash};
    -use bitcoin::{Script, Transaction, Txid};
    -
    -use self::utils::{ELSGetHistoryRes, ELSListUnspentRes, ElectrumLikeSync};
    -use super::*;
    -use crate::database::BatchDatabase;
    -use crate::error::Error;
    -use crate::FeeRate;
    -
    -#[derive(Debug)]
    -struct UrlClient {
    -    url: String,
    -    // We use the async client instead of the blocking one because it automatically uses `fetch`
    -    // when the target platform is wasm32.
    -    client: Client,
    -}
    -
    -/// Structure that implements the logic to sync with Esplora
    -///
    -/// ## Example
    -/// See the [`blockchain::esplora`](crate::blockchain::esplora) module for a usage example.
    -#[derive(Debug)]
    -pub struct EsploraBlockchain(UrlClient);
    -
    -impl std::convert::From<UrlClient> for EsploraBlockchain {
    -    fn from(url_client: UrlClient) -> Self {
    -        EsploraBlockchain(url_client)
    -    }
    -}
    -
    -impl EsploraBlockchain {
    -    /// Create a new instance of the client from a base URL
    -    pub fn new(base_url: &str) -> Self {
    -        EsploraBlockchain(UrlClient {
    -            url: base_url.to_string(),
    -            client: Client::new(),
    -        })
    -    }
    -}
    -
    -#[maybe_async]
    -impl Blockchain for EsploraBlockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        vec![
    -            Capability::FullHistory,
    -            Capability::GetAnyTx,
    -            Capability::AccurateFees,
    -        ]
    -        .into_iter()
    -        .collect()
    -    }
    -
    -    fn setup<D: BatchDatabase, P: Progress>(
    -        &self,
    -        stop_gap: Option<usize>,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        maybe_await!(self
    -            .0
    -            .electrum_like_setup(stop_gap, database, progress_update))
    -    }
    -
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        Ok(await_or_block!(self.0._get_tx(txid))?)
    -    }
    -
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        Ok(await_or_block!(self.0._broadcast(tx))?)
    -    }
    -
    -    fn get_height(&self) -> Result<u32, Error> {
    -        Ok(await_or_block!(self.0._get_height())?)
    -    }
    -
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
    -        let estimates = await_or_block!(self.0._get_fee_estimates())?;
    -
    -        let fee_val = estimates
    -            .into_iter()
    -            .map(|(k, v)| Ok::<_, std::num::ParseIntError>((k.parse::<usize>()?, v)))
    -            .collect::<Result<Vec<_>, _>>()
    -            .map_err(|e| Error::Generic(e.to_string()))?
    -            .into_iter()
    -            .take_while(|(k, _)| k <= &target)
    -            .map(|(_, v)| v)
    -            .last()
    -            .unwrap_or(1.0);
    -
    -        Ok(FeeRate::from_sat_per_vb(fee_val as f32))
    -    }
    -}
    -
    -impl UrlClient {
    -    fn script_to_scripthash(script: &Script) -> String {
    -        sha256::Hash::hash(script.as_bytes()).into_inner().to_hex()
    -    }
    -
    -    async fn _get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, EsploraError> {
    -        let resp = self
    -            .client
    -            .get(&format!("{}/tx/{}/raw", self.url, txid))
    -            .send()
    -            .await?;
    -
    -        if let StatusCode::NOT_FOUND = resp.status() {
    -            return Ok(None);
    -        }
    -
    -        Ok(Some(deserialize(&resp.error_for_status()?.bytes().await?)?))
    -    }
    -
    -    async fn _broadcast(&self, transaction: &Transaction) -> Result<(), EsploraError> {
    -        self.client
    -            .post(&format!("{}/tx", self.url))
    -            .body(serialize(transaction).to_hex())
    -            .send()
    -            .await?
    -            .error_for_status()?;
    -
    -        Ok(())
    -    }
    -
    -    async fn _get_height(&self) -> Result<u32, EsploraError> {
    -        let req = self
    -            .client
    -            .get(&format!("{}/blocks/tip/height", self.url))
    -            .send()
    -            .await?;
    -
    -        Ok(req.error_for_status()?.text().await?.parse()?)
    -    }
    -
    -    async fn _script_get_history(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Vec<ELSGetHistoryRes>, EsploraError> {
    -        let mut result = Vec::new();
    -        let scripthash = Self::script_to_scripthash(script);
    -
    -        // Add the unconfirmed transactions first
    -        result.extend(
    -            self.client
    -                .get(&format!(
    -                    "{}/scripthash/{}/txs/mempool",
    -                    self.url, scripthash
    -                ))
    -                .send()
    -                .await?
    -                .error_for_status()?
    -                .json::<Vec<EsploraGetHistory>>()
    -                .await?
    -                .into_iter()
    -                .map(|x| ELSGetHistoryRes {
    -                    tx_hash: x.txid,
    -                    height: x.status.block_height.unwrap_or(0) as i32,
    -                }),
    -        );
    -
    -        debug!(
    -            "Found {} mempool txs for {} - {:?}",
    -            result.len(),
    -            scripthash,
    -            script
    -        );
    -
    -        // Then go through all the pages of confirmed transactions
    -        let mut last_txid = String::new();
    -        loop {
    -            let response = self
    -                .client
    -                .get(&format!(
    -                    "{}/scripthash/{}/txs/chain/{}",
    -                    self.url, scripthash, last_txid
    -                ))
    -                .send()
    -                .await?
    -                .error_for_status()?
    -                .json::<Vec<EsploraGetHistory>>()
    -                .await?;
    -            let len = response.len();
    -            if let Some(elem) = response.last() {
    -                last_txid = elem.txid.to_hex();
    -            }
    -
    -            debug!("... adding {} confirmed transactions", len);
    -
    -            result.extend(response.into_iter().map(|x| ELSGetHistoryRes {
    -                tx_hash: x.txid,
    -                height: x.status.block_height.unwrap_or(0) as i32,
    -            }));
    -
    -            if len < 25 {
    -                break;
    -            }
    -        }
    -
    -        Ok(result)
    -    }
    -
    -    async fn _script_list_unspent(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Vec<ELSListUnspentRes>, EsploraError> {
    -        Ok(self
    -            .client
    -            .get(&format!(
    -                "{}/scripthash/{}/utxo",
    -                self.url,
    -                Self::script_to_scripthash(script)
    -            ))
    -            .send()
    -            .await?
    -            .error_for_status()?
    -            .json::<Vec<EsploraListUnspent>>()
    -            .await?
    -            .into_iter()
    -            .map(|x| ELSListUnspentRes {
    -                tx_hash: x.txid,
    -                height: x.status.block_height.unwrap_or(0),
    -                tx_pos: x.vout,
    -            })
    -            .collect())
    -    }
    -
    -    async fn _get_fee_estimates(&self) -> Result<HashMap<String, f64>, EsploraError> {
    -        Ok(self
    -            .client
    -            .get(&format!("{}/fee-estimates", self.url,))
    -            .send()
    -            .await?
    -            .error_for_status()?
    -            .json::<HashMap<String, f64>>()
    -            .await?)
    -    }
    -}
    -
    -#[maybe_async]
    -impl ElectrumLikeSync for UrlClient {
    -    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
    -        &self,
    -        scripts: I,
    -    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error> {
    -        let future = async {
    -            Ok(stream::iter(scripts)
    -                .then(|script| self._script_get_history(&script))
    -                .try_collect()
    -                .await?)
    -        };
    -
    -        await_or_block!(future)
    -    }
    -
    -    fn els_batch_script_list_unspent<'s, I: IntoIterator<Item = &'s Script>>(
    -        &self,
    -        scripts: I,
    -    ) -> Result<Vec<Vec<ELSListUnspentRes>>, Error> {
    -        let future = async {
    -            Ok(stream::iter(scripts)
    -                .then(|script| self._script_list_unspent(&script))
    -                .try_collect()
    -                .await?)
    -        };
    -
    -        await_or_block!(future)
    -    }
    -
    -    fn els_transaction_get(&self, txid: &Txid) -> Result<Transaction, Error> {
    -        Ok(await_or_block!(self._get_tx(txid))?
    -            .ok_or_else(|| EsploraError::TransactionNotFound(*txid))?)
    -    }
    -}
    -
    -#[derive(Deserialize)]
    -struct EsploraGetHistoryStatus {
    -    block_height: Option<usize>,
    -}
    -
    -#[derive(Deserialize)]
    -struct EsploraGetHistory {
    -    txid: Txid,
    -    status: EsploraGetHistoryStatus,
    -}
    -
    -#[derive(Deserialize)]
    -struct EsploraListUnspent {
    -    txid: Txid,
    -    vout: usize,
    -    status: EsploraGetHistoryStatus,
    -}
    -
    -/// Errors that can happen during a sync with [`EsploraBlockchain`]
    -#[derive(Debug)]
    -pub enum EsploraError {
    -    /// Error with the HTTP call
    -    Reqwest(reqwest::Error),
    -    /// Invalid number returned
    -    Parsing(std::num::ParseIntError),
    -    /// Invalid Bitcoin data returned
    -    BitcoinEncoding(bitcoin::consensus::encode::Error),
    -
    -    /// Transaction not found
    -    TransactionNotFound(Txid),
    -}
    -
    -impl fmt::Display for EsploraError {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for EsploraError {}
    -
    -impl From<reqwest::Error> for EsploraError {
    -    fn from(other: reqwest::Error) -> Self {
    -        EsploraError::Reqwest(other)
    -    }
    -}
    -
    -impl From<std::num::ParseIntError> for EsploraError {
    -    fn from(other: std::num::ParseIntError) -> Self {
    -        EsploraError::Parsing(other)
    -    }
    -}
    -
    -impl From<bitcoin::consensus::encode::Error> for EsploraError {
    -    fn from(other: bitcoin::consensus::encode::Error) -> Self {
    -        EsploraError::BitcoinEncoding(other)
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/mod.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/mod.rs.html deleted file mode 100644 index a059a898bb..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/mod.rs.html +++ /dev/null @@ -1,509 +0,0 @@ -mod.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Blockchain backends
    -//!
    -//! This module provides the implementation of a few commonly-used backends like
    -//! [Electrum](crate::blockchain::electrum), [Esplora](crate::blockchain::esplora) and
    -//! [Compact Filters/Neutrino](crate::blockchain::compact_filters), along with a generalized trait
    -//! [`Blockchain`] that can be implemented to build customized backends.
    -
    -use std::collections::HashSet;
    -use std::ops::Deref;
    -use std::sync::mpsc::{channel, Receiver, Sender};
    -use std::sync::Arc;
    -
    -use bitcoin::{Transaction, Txid};
    -
    -use crate::database::BatchDatabase;
    -use crate::error::Error;
    -use crate::FeeRate;
    -
    -pub(crate) mod utils;
    -
    -#[cfg(feature = "electrum")]
    -#[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
    -pub mod electrum;
    -#[cfg(feature = "electrum")]
    -pub use self::electrum::ElectrumBlockchain;
    -
    -#[cfg(feature = "esplora")]
    -#[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
    -pub mod esplora;
    -#[cfg(feature = "esplora")]
    -pub use self::esplora::EsploraBlockchain;
    -
    -#[cfg(feature = "compact_filters")]
    -#[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
    -pub mod compact_filters;
    -#[cfg(feature = "compact_filters")]
    -pub use self::compact_filters::CompactFiltersBlockchain;
    -
    -/// Capabilities that can be supported by a [`Blockchain`] backend
    -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
    -pub enum Capability {
    -    /// Can recover the full history of a wallet and not only the set of currently spendable UTXOs
    -    FullHistory,
    -    /// Can fetch any historical transaction given its txid
    -    GetAnyTx,
    -    /// Can compute accurate fees for the transactions found during sync
    -    AccurateFees,
    -}
    -
    -/// Marker trait for a blockchain backend
    -///
    -/// This is a marker trait for blockchain types. It is automatically implemented for types that
    -/// implement [`Blockchain`], so as a user of the library you won't have to implement this
    -/// manually.
    -///
    -/// Users of the library will probably never have to implement this trait manually, but they
    -/// could still need to import it to define types and structs with generics;
    -/// Implementing only the marker trait is pointless, since [`OfflineBlockchain`]
    -/// already does that, and whenever [`Blockchain`] is implemented, the marker trait is also
    -/// automatically implemented by the library.
    -pub trait BlockchainMarker {}
    -
    -/// The [`BlockchainMarker`] marker trait is automatically implemented for [`Blockchain`] types
    -impl<T: Blockchain> BlockchainMarker for T {}
    -
    -/// Type that only implements [`Blockchain`] and is always "offline"
    -pub struct OfflineBlockchain;
    -impl BlockchainMarker for OfflineBlockchain {}
    -
    -/// Trait that defines the actions that must be supported by a blockchain backend
    -#[maybe_async]
    -pub trait Blockchain: BlockchainMarker {
    -    /// Return the set of [`Capability`] supported by this backend
    -    fn get_capabilities(&self) -> HashSet<Capability>;
    -
    -    /// Setup the backend and populate the internal database for the first time
    -    ///
    -    /// This method is the equivalent of [`Blockchain::sync`], but it's guaranteed to only be
    -    /// called once, at the first [`Wallet::sync`](crate::wallet::Wallet::sync).
    -    ///
    -    /// The rationale behind the distinction between `sync` and `setup` is that some custom backends
    -    /// might need to perform specific actions only the first time they are synced.
    -    ///
    -    /// For types that do not have that distinction, only this method can be implemented, since
    -    /// [`Blockchain::sync`] defaults to calling this internally if not overridden.
    -    fn setup<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        stop_gap: Option<usize>,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error>;
    -    /// Populate the internal database with transactions and UTXOs
    -    ///
    -    /// If not overridden, it defaults to calling [`Blockchain::setup`] internally.
    -    ///
    -    /// This method should implement the logic required to iterate over the list of the wallet's
    -    /// script_pubkeys using [`Database::iter_script_pubkeys`] and look for relevant transactions
    -    /// in the blockchain to populate the database with [`BatchOperations::set_tx`] and
    -    /// [`BatchOperations::set_utxo`].
    -    ///
    -    /// This method should also take care of removing UTXOs that are seen as spent in the
    -    /// blockchain, using [`BatchOperations::del_utxo`].
    -    ///
    -    /// The `progress_update` object can be used to give the caller updates about the progress by using
    -    /// [`Progress::update`].
    -    ///
    -    /// [`Database::iter_script_pubkeys`]: crate::database::Database::iter_script_pubkeys
    -    /// [`BatchOperations::set_tx`]: crate::database::BatchOperations::set_tx
    -    /// [`BatchOperations::set_utxo`]: crate::database::BatchOperations::set_utxo
    -    /// [`BatchOperations::del_utxo`]: crate::database::BatchOperations::del_utxo
    -    fn sync<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        stop_gap: Option<usize>,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        maybe_await!(self.setup(stop_gap, database, progress_update))
    -    }
    -
    -    /// Fetch a transaction from the blockchain given its txid
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
    -    /// Broadcast a transaction
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error>;
    -
    -    /// Return the current height
    -    fn get_height(&self) -> Result<u32, Error>;
    -    /// Estimate the fee rate required to confirm a transaction in a given `target` of blocks
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>;
    -}
    -
    -/// Data sent with a progress update over a [`channel`]
    -pub type ProgressData = (f32, Option<String>);
    -
    -/// Trait for types that can receive and process progress updates during [`Blockchain::sync`] and
    -/// [`Blockchain::setup`]
    -pub trait Progress: Send {
    -    /// Send a new progress update
    -    ///
    -    /// The `progress` value should be in the range 0.0 - 100.0, and the `message` value is an
    -    /// optional text message that can be displayed to the user.
    -    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error>;
    -}
    -
    -/// Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]
    -pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>) {
    -    channel()
    -}
    -
    -impl Progress for Sender<ProgressData> {
    -    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
    -        if progress < 0.0 || progress > 100.0 {
    -            return Err(Error::InvalidProgressValue(progress));
    -        }
    -
    -        self.send((progress, message))
    -            .map_err(|_| Error::ProgressUpdateError)
    -    }
    -}
    -
    -/// Type that implements [`Progress`] and drops every update received
    -#[derive(Clone)]
    -pub struct NoopProgress;
    -
    -/// Create a new instance of [`NoopProgress`]
    -pub fn noop_progress() -> NoopProgress {
    -    NoopProgress
    -}
    -
    -impl Progress for NoopProgress {
    -    fn update(&self, _progress: f32, _message: Option<String>) -> Result<(), Error> {
    -        Ok(())
    -    }
    -}
    -
    -/// Type that implements [`Progress`] and logs at level `INFO` every update received
    -#[derive(Clone)]
    -pub struct LogProgress;
    -
    -/// Create a nwe instance of [`LogProgress`]
    -pub fn log_progress() -> LogProgress {
    -    LogProgress
    -}
    -
    -impl Progress for LogProgress {
    -    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
    -        log::info!("Sync {:.3}%: `{}`", progress, message.unwrap_or("".into()));
    -
    -        Ok(())
    -    }
    -}
    -
    -#[maybe_async]
    -impl<T: Blockchain> Blockchain for Arc<T> {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        maybe_await!(self.deref().get_capabilities())
    -    }
    -
    -    fn setup<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        stop_gap: Option<usize>,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        maybe_await!(self.deref().setup(stop_gap, database, progress_update))
    -    }
    -
    -    fn sync<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        stop_gap: Option<usize>,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        maybe_await!(self.deref().sync(stop_gap, database, progress_update))
    -    }
    -
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        maybe_await!(self.deref().get_tx(txid))
    -    }
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        maybe_await!(self.deref().broadcast(tx))
    -    }
    -
    -    fn get_height(&self) -> Result<u32, Error> {
    -        maybe_await!(self.deref().get_height())
    -    }
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
    -        maybe_await!(self.deref().estimate_fee(target))
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/utils.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/utils.rs.html deleted file mode 100644 index 6983da4834..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/blockchain/utils.rs.html +++ /dev/null @@ -1,719 +0,0 @@ -utils.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use std::cmp;
    -use std::collections::{HashSet, VecDeque};
    -use std::convert::TryFrom;
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -use bitcoin::{Address, Network, OutPoint, Script, Transaction, Txid};
    -
    -use super::*;
    -use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
    -use crate::error::Error;
    -use crate::types::{ScriptType, TransactionDetails, UTXO};
    -use crate::wallet::utils::ChunksIterator;
    -
    -#[derive(Debug)]
    -pub struct ELSGetHistoryRes {
    -    pub height: i32,
    -    pub tx_hash: Txid,
    -}
    -
    -#[derive(Debug)]
    -pub struct ELSListUnspentRes {
    -    pub height: usize,
    -    pub tx_hash: Txid,
    -    pub tx_pos: usize,
    -}
    -
    -/// Implements the synchronization logic for an Electrum-like client.
    -#[maybe_async]
    -pub trait ElectrumLikeSync {
    -    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
    -        &self,
    -        scripts: I,
    -    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error>;
    -
    -    fn els_batch_script_list_unspent<'s, I: IntoIterator<Item = &'s Script>>(
    -        &self,
    -        scripts: I,
    -    ) -> Result<Vec<Vec<ELSListUnspentRes>>, Error>;
    -
    -    fn els_transaction_get(&self, txid: &Txid) -> Result<Transaction, Error>;
    -
    -    // Provided methods down here...
    -
    -    fn electrum_like_setup<D: BatchDatabase, P: Progress>(
    -        &self,
    -        stop_gap: Option<usize>,
    -        database: &mut D,
    -        _progress_update: P,
    -    ) -> Result<(), Error> {
    -        // TODO: progress
    -
    -        let stop_gap = stop_gap.unwrap_or(20);
    -        let batch_query_size = 20;
    -
    -        // check unconfirmed tx, delete so they are retrieved later
    -        let mut del_batch = database.begin_batch();
    -        for tx in database.iter_txs(false)? {
    -            if tx.height.is_none() {
    -                del_batch.del_tx(&tx.txid, false)?;
    -            }
    -        }
    -        database.commit_batch(del_batch)?;
    -
    -        // maximum derivation index for a change address that we've seen during sync
    -        let mut change_max_deriv = None;
    -
    -        let mut already_checked: HashSet<Script> = HashSet::new();
    -        let mut to_check_later = VecDeque::with_capacity(batch_query_size);
    -
    -        // insert the first chunk
    -        let mut iter_scriptpubkeys = database
    -            .iter_script_pubkeys(Some(ScriptType::External))?
    -            .into_iter();
    -        let chunk: Vec<Script> = iter_scriptpubkeys.by_ref().take(batch_query_size).collect();
    -        for item in chunk.into_iter().rev() {
    -            to_check_later.push_front(item);
    -        }
    -
    -        let mut iterating_external = true;
    -        let mut index = 0;
    -        let mut last_found = None;
    -        while !to_check_later.is_empty() {
    -            trace!("to_check_later size {}", to_check_later.len());
    -
    -            let until = cmp::min(to_check_later.len(), batch_query_size);
    -            let chunk: Vec<Script> = to_check_later.drain(..until).collect();
    -            let call_result = maybe_await!(self.els_batch_script_get_history(chunk.iter()))?;
    -
    -            for (script, history) in chunk.into_iter().zip(call_result.into_iter()) {
    -                trace!("received history for {:?}, size {}", script, history.len());
    -
    -                if !history.is_empty() {
    -                    last_found = Some(index);
    -
    -                    let mut check_later_scripts = maybe_await!(self.check_history(
    -                        database,
    -                        script,
    -                        history,
    -                        &mut change_max_deriv
    -                    ))?
    -                    .into_iter()
    -                    .filter(|x| already_checked.insert(x.clone()))
    -                    .collect();
    -                    to_check_later.append(&mut check_later_scripts);
    -                }
    -
    -                index += 1;
    -            }
    -
    -            match iterating_external {
    -                true if index - last_found.unwrap_or(0) >= stop_gap => iterating_external = false,
    -                true => {
    -                    trace!("pushing one more batch from `iter_scriptpubkeys`. index = {}, last_found = {:?}, stop_gap = {}", index, last_found, stop_gap);
    -
    -                    let chunk: Vec<Script> =
    -                        iter_scriptpubkeys.by_ref().take(batch_query_size).collect();
    -                    for item in chunk.into_iter().rev() {
    -                        to_check_later.push_front(item);
    -                    }
    -                }
    -                _ => {}
    -            }
    -        }
    -
    -        // check utxo
    -        // TODO: try to minimize network requests and re-use scripts if possible
    -        let mut batch = database.begin_batch();
    -        for chunk in ChunksIterator::new(database.iter_utxos()?.into_iter(), batch_query_size) {
    -            let scripts: Vec<_> = chunk.iter().map(|u| &u.txout.script_pubkey).collect();
    -            let call_result = maybe_await!(self.els_batch_script_list_unspent(scripts))?;
    -
    -            // check which utxos are actually still unspent
    -            for (utxo, list_unspent) in chunk.into_iter().zip(call_result.iter()) {
    -                debug!(
    -                    "outpoint {:?} is unspent for me, list unspent is {:?}",
    -                    utxo.outpoint, list_unspent
    -                );
    -
    -                let mut spent = true;
    -                for unspent in list_unspent {
    -                    let res_outpoint = OutPoint::new(unspent.tx_hash, unspent.tx_pos as u32);
    -                    if utxo.outpoint == res_outpoint {
    -                        spent = false;
    -                        break;
    -                    }
    -                }
    -                if spent {
    -                    info!("{} not anymore unspent, removing", utxo.outpoint);
    -                    batch.del_utxo(&utxo.outpoint)?;
    -                }
    -            }
    -        }
    -
    -        let current_ext = database.get_last_index(ScriptType::External)?.unwrap_or(0);
    -        let first_ext_new = last_found.map(|x| x + 1).unwrap_or(0) as u32;
    -        if first_ext_new > current_ext {
    -            info!("Setting external index to {}", first_ext_new);
    -            database.set_last_index(ScriptType::External, first_ext_new)?;
    -        }
    -
    -        let current_int = database.get_last_index(ScriptType::Internal)?.unwrap_or(0);
    -        let first_int_new = change_max_deriv.map(|x| x + 1).unwrap_or(0);
    -        if first_int_new > current_int {
    -            info!("Setting internal index to {}", first_int_new);
    -            database.set_last_index(ScriptType::Internal, first_int_new)?;
    -        }
    -
    -        database.commit_batch(batch)?;
    -
    -        Ok(())
    -    }
    -
    -    fn check_tx_and_descendant<D: BatchDatabase>(
    -        &self,
    -        database: &mut D,
    -        txid: &Txid,
    -        height: Option<u32>,
    -        cur_script: &Script,
    -        change_max_deriv: &mut Option<u32>,
    -    ) -> Result<Vec<Script>, Error> {
    -        debug!(
    -            "check_tx_and_descendant of {}, height: {:?}, script: {}",
    -            txid, height, cur_script
    -        );
    -        let mut updates = database.begin_batch();
    -        let tx = match database.get_tx(&txid, true)? {
    -            Some(mut saved_tx) => {
    -                // update the height if it's different (in case of reorg)
    -                if saved_tx.height != height {
    -                    info!(
    -                        "updating height from {:?} to {:?} for tx {}",
    -                        saved_tx.height, height, txid
    -                    );
    -                    saved_tx.height = height;
    -                    updates.set_tx(&saved_tx)?;
    -                }
    -
    -                debug!("already have {} in db, returning the cached version", txid);
    -
    -                // unwrap since we explicitly ask for the raw_tx, if it's not present something
    -                // went wrong
    -                saved_tx.transaction.unwrap()
    -            }
    -            None => {
    -                let fetched_tx = maybe_await!(self.els_transaction_get(&txid))?;
    -                database.set_raw_tx(&fetched_tx)?;
    -
    -                fetched_tx
    -            }
    -        };
    -
    -        let mut incoming: u64 = 0;
    -        let mut outgoing: u64 = 0;
    -
    -        let mut inputs_sum: u64 = 0;
    -        let mut outputs_sum: u64 = 0;
    -
    -        // look for our own inputs
    -        for (i, input) in tx.input.iter().enumerate() {
    -            // the fact that we visit addresses in a BFS fashion starting from the external addresses
    -            // should ensure that this query is always consistent (i.e. when we get to call this all
    -            // the transactions at a lower depth have already been indexed, so if an outpoint is ours
    -            // we are guaranteed to have it in the db).
    -            if let Some(previous_output) = database.get_previous_output(&input.previous_output)? {
    -                inputs_sum += previous_output.value;
    -
    -                if database.is_mine(&previous_output.script_pubkey)? {
    -                    outgoing += previous_output.value;
    -
    -                    debug!("{} input #{} is mine, removing from utxo", txid, i);
    -                    updates.del_utxo(&input.previous_output)?;
    -                }
    -            } else {
    -                // The input is not ours, but we still need to count it for the fees. so fetch the
    -                // tx (from the database or from network) and check it
    -                let tx = match database.get_tx(&input.previous_output.txid, true)? {
    -                    Some(saved_tx) => saved_tx.transaction.unwrap(),
    -                    None => {
    -                        let fetched_tx =
    -                            maybe_await!(self.els_transaction_get(&input.previous_output.txid))?;
    -                        database.set_raw_tx(&fetched_tx)?;
    -
    -                        fetched_tx
    -                    }
    -                };
    -
    -                inputs_sum += tx.output[input.previous_output.vout as usize].value;
    -            }
    -        }
    -
    -        let mut to_check_later = vec![];
    -        for (i, output) in tx.output.iter().enumerate() {
    -            // to compute the fees later
    -            outputs_sum += output.value;
    -
    -            // this output is ours, we have a path to derive it
    -            if let Some((script_type, child)) =
    -                database.get_path_from_script_pubkey(&output.script_pubkey)?
    -            {
    -                debug!("{} output #{} is mine, adding utxo", txid, i);
    -                updates.set_utxo(&UTXO {
    -                    outpoint: OutPoint::new(tx.txid(), i as u32),
    -                    txout: output.clone(),
    -                    is_internal: script_type.is_internal(),
    -                })?;
    -                incoming += output.value;
    -
    -                if output.script_pubkey != *cur_script {
    -                    debug!("{} output #{} script {} was not current script, adding script to be checked later", txid, i, output.script_pubkey);
    -                    to_check_later.push(output.script_pubkey.clone())
    -                }
    -
    -                // derive as many change addrs as external addresses that we've seen
    -                if script_type == ScriptType::Internal
    -                    && (change_max_deriv.is_none() || child > change_max_deriv.unwrap_or(0))
    -                {
    -                    *change_max_deriv = Some(child);
    -                }
    -            }
    -        }
    -
    -        let tx = TransactionDetails {
    -            txid: tx.txid(),
    -            transaction: Some(tx),
    -            received: incoming,
    -            sent: outgoing,
    -            height,
    -            timestamp: 0,
    -            fees: inputs_sum - outputs_sum,
    -        };
    -        info!("Saving tx {}", txid);
    -        updates.set_tx(&tx)?;
    -
    -        database.commit_batch(updates)?;
    -
    -        Ok(to_check_later)
    -    }
    -
    -    fn check_history<D: BatchDatabase>(
    -        &self,
    -        database: &mut D,
    -        script_pubkey: Script,
    -        txs: Vec<ELSGetHistoryRes>,
    -        change_max_deriv: &mut Option<u32>,
    -    ) -> Result<Vec<Script>, Error> {
    -        let mut to_check_later = Vec::new();
    -
    -        debug!(
    -            "history of {} script {} has {} tx",
    -            Address::from_script(&script_pubkey, Network::Testnet).unwrap(),
    -            script_pubkey,
    -            txs.len()
    -        );
    -
    -        for tx in txs {
    -            let height: Option<u32> = match tx.height {
    -                0 | -1 => None,
    -                x => u32::try_from(x).ok(),
    -            };
    -
    -            to_check_later.extend_from_slice(&maybe_await!(self.check_tx_and_descendant(
    -                database,
    -                &tx.tx_hash,
    -                height,
    -                &script_pubkey,
    -                change_max_deriv,
    -            ))?);
    -        }
    -
    -        Ok(to_check_later)
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/keyvalue.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/keyvalue.rs.html deleted file mode 100644 index 8e338397ad..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/keyvalue.rs.html +++ /dev/null @@ -1,965 +0,0 @@ -keyvalue.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use std::convert::TryInto;
    -
    -use sled::{Batch, Tree};
    -
    -use bitcoin::consensus::encode::{deserialize, serialize};
    -use bitcoin::hash_types::Txid;
    -use bitcoin::{OutPoint, Script, Transaction};
    -
    -use crate::database::memory::MapKey;
    -use crate::database::{BatchDatabase, BatchOperations, Database};
    -use crate::error::Error;
    -use crate::types::*;
    -
    -macro_rules! impl_batch_operations {
    -    ( { $($after_insert:tt)* }, $process_delete:ident ) => {
    -        fn set_script_pubkey(&mut self, script: &Script, script_type: ScriptType, path: u32) -> Result<(), Error> {
    -            let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
    -            self.insert(key, serialize(script))$($after_insert)*;
    -
    -            let key = MapKey::Script(Some(script)).as_map_key();
    -            let value = json!({
    -                "t": script_type,
    -                "p": path,
    -            });
    -            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
    -            let key = MapKey::UTXO(Some(&utxo.outpoint)).as_map_key();
    -            let value = json!({
    -                "t": utxo.txout,
    -                "i": utxo.is_internal,
    -            });
    -            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
    -            let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
    -            let value = serialize(transaction);
    -            self.insert(key, value)$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
    -            let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
    -
    -            // remove the raw tx from the serialized version
    -            let mut value = serde_json::to_value(transaction)?;
    -            value["transaction"] = serde_json::Value::Null;
    -            let value = serde_json::to_vec(&value)?;
    -
    -            self.insert(key, value)$($after_insert)*;
    -
    -            // insert the raw_tx if present
    -            if let Some(ref tx) = transaction.transaction {
    -                self.set_raw_tx(tx)?;
    -            }
    -
    -            Ok(())
    -        }
    -
    -        fn set_last_index(&mut self, script_type: ScriptType, value: u32) -> Result<(), Error> {
    -            let key = MapKey::LastIndex(script_type).as_map_key();
    -            self.insert(key, &value.to_be_bytes())$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn del_script_pubkey_from_path(&mut self, script_type: ScriptType, path: u32) -> Result<Option<Script>, Error> {
    -            let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
    -        }
    -
    -        fn del_path_from_script_pubkey(&mut self, script: &Script) -> Result<Option<(ScriptType, u32)>, Error> {
    -            let key = MapKey::Script(Some(script)).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            match res {
    -                None => Ok(None),
    -                Some(b) => {
    -                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
    -                    let st = serde_json::from_value(val["t"].take())?;
    -                    let path = serde_json::from_value(val["p"].take())?;
    -
    -                    Ok(Some((st, path)))
    -                }
    -            }
    -        }
    -
    -        fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
    -            let key = MapKey::UTXO(Some(outpoint)).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            match res {
    -                None => Ok(None),
    -                Some(b) => {
    -                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
    -                    let txout = serde_json::from_value(val["t"].take())?;
    -                    let is_internal = serde_json::from_value(val["i"].take())?;
    -
    -                    Ok(Some(UTXO { outpoint: outpoint.clone(), txout, is_internal }))
    -                }
    -            }
    -        }
    -
    -        fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -            let key = MapKey::RawTx(Some(txid)).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
    -        }
    -
    -        fn del_tx(&mut self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -            let raw_tx = if include_raw {
    -                self.del_raw_tx(txid)?
    -            } else {
    -                None
    -            };
    -
    -            let key = MapKey::Transaction(Some(txid)).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            match res {
    -                None => Ok(None),
    -                Some(b) => {
    -                    let mut val: TransactionDetails = serde_json::from_slice(&b)?;
    -                    val.transaction = raw_tx;
    -
    -                    Ok(Some(val))
    -                }
    -            }
    -        }
    -
    -        fn del_last_index(&mut self, script_type: ScriptType) -> Result<Option<u32>, Error> {
    -            let key = MapKey::LastIndex(script_type).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            match res {
    -                None => Ok(None),
    -                Some(b) => {
    -                    let array: [u8; 4] = b.as_ref().try_into().map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
    -                    let val = u32::from_be_bytes(array);
    -                    Ok(Some(val))
    -                }
    -            }
    -        }
    -    }
    -}
    -
    -macro_rules! process_delete_tree {
    -    ($res:expr) => {
    -        $res?
    -    };
    -}
    -impl BatchOperations for Tree {
    -    impl_batch_operations!({?}, process_delete_tree);
    -}
    -
    -macro_rules! process_delete_batch {
    -    ($res:expr) => {
    -        None as Option<sled::IVec>
    -    };
    -}
    -#[allow(unused_variables)]
    -impl BatchOperations for Batch {
    -    impl_batch_operations!({}, process_delete_batch);
    -}
    -
    -impl Database for Tree {
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        script_type: ScriptType,
    -        bytes: B,
    -    ) -> Result<(), Error> {
    -        let key = MapKey::DescriptorChecksum(script_type).as_map_key();
    -
    -        let prev = self.get(&key)?.map(|x| x.to_vec());
    -        if let Some(val) = prev {
    -            if val == bytes.as_ref() {
    -                Ok(())
    -            } else {
    -                Err(Error::ChecksumMismatch)
    -            }
    -        } else {
    -            self.insert(&key, bytes.as_ref())?;
    -            Ok(())
    -        }
    -    }
    -
    -    fn iter_script_pubkeys(&self, script_type: Option<ScriptType>) -> Result<Vec<Script>, Error> {
    -        let key = MapKey::Path((script_type, None)).as_map_key();
    -        self.scan_prefix(key)
    -            .map(|x| -> Result<_, Error> {
    -                let (_, v) = x?;
    -                Ok(deserialize(&v)?)
    -            })
    -            .collect()
    -    }
    -
    -    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error> {
    -        let key = MapKey::UTXO(None).as_map_key();
    -        self.scan_prefix(key)
    -            .map(|x| -> Result<_, Error> {
    -                let (k, v) = x?;
    -                let outpoint = deserialize(&k[1..])?;
    -
    -                let mut val: serde_json::Value = serde_json::from_slice(&v)?;
    -                let txout = serde_json::from_value(val["t"].take())?;
    -                let is_internal = serde_json::from_value(val["i"].take())?;
    -
    -                Ok(UTXO {
    -                    outpoint,
    -                    txout,
    -                    is_internal,
    -                })
    -            })
    -            .collect()
    -    }
    -
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
    -        let key = MapKey::RawTx(None).as_map_key();
    -        self.scan_prefix(key)
    -            .map(|x| -> Result<_, Error> {
    -                let (_, v) = x?;
    -                Ok(deserialize(&v)?)
    -            })
    -            .collect()
    -    }
    -
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        let key = MapKey::Transaction(None).as_map_key();
    -        self.scan_prefix(key)
    -            .map(|x| -> Result<_, Error> {
    -                let (k, v) = x?;
    -                let mut txdetails: TransactionDetails = serde_json::from_slice(&v)?;
    -                if include_raw {
    -                    let txid = deserialize(&k[1..])?;
    -                    txdetails.transaction = self.get_raw_tx(&txid)?;
    -                }
    -
    -                Ok(txdetails)
    -            })
    -            .collect()
    -    }
    -
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        script_type: ScriptType,
    -        path: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
    -        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
    -    }
    -
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(ScriptType, u32)>, Error> {
    -        let key = MapKey::Script(Some(script)).as_map_key();
    -        self.get(key)?
    -            .map(|b| -> Result<_, Error> {
    -                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
    -                let st = serde_json::from_value(val["t"].take())?;
    -                let path = serde_json::from_value(val["p"].take())?;
    -
    -                Ok((st, path))
    -            })
    -            .transpose()
    -    }
    -
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
    -        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
    -        self.get(key)?
    -            .map(|b| -> Result<_, Error> {
    -                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
    -                let txout = serde_json::from_value(val["t"].take())?;
    -                let is_internal = serde_json::from_value(val["i"].take())?;
    -
    -                Ok(UTXO {
    -                    outpoint: outpoint.clone(),
    -                    txout,
    -                    is_internal,
    -                })
    -            })
    -            .transpose()
    -    }
    -
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        let key = MapKey::RawTx(Some(txid)).as_map_key();
    -        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
    -    }
    -
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -        let key = MapKey::Transaction(Some(txid)).as_map_key();
    -        self.get(key)?
    -            .map(|b| -> Result<_, Error> {
    -                let mut txdetails: TransactionDetails = serde_json::from_slice(&b)?;
    -                if include_raw {
    -                    txdetails.transaction = self.get_raw_tx(&txid)?;
    -                }
    -
    -                Ok(txdetails)
    -            })
    -            .transpose()
    -    }
    -
    -    fn get_last_index(&self, script_type: ScriptType) -> Result<Option<u32>, Error> {
    -        let key = MapKey::LastIndex(script_type).as_map_key();
    -        self.get(key)?
    -            .map(|b| -> Result<_, Error> {
    -                let array: [u8; 4] = b
    -                    .as_ref()
    -                    .try_into()
    -                    .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
    -                let val = u32::from_be_bytes(array);
    -                Ok(val)
    -            })
    -            .transpose()
    -    }
    -
    -    // inserts 0 if not present
    -    fn increment_last_index(&mut self, script_type: ScriptType) -> Result<u32, Error> {
    -        let key = MapKey::LastIndex(script_type).as_map_key();
    -        self.update_and_fetch(key, |prev| {
    -            let new = match prev {
    -                Some(b) => {
    -                    let array: [u8; 4] = b.try_into().unwrap_or([0; 4]);
    -                    let val = u32::from_be_bytes(array);
    -
    -                    val + 1
    -                }
    -                None => 0,
    -            };
    -
    -            Some(new.to_be_bytes().to_vec())
    -        })?
    -        .map_or(Ok(0), |b| -> Result<_, Error> {
    -            let array: [u8; 4] = b
    -                .as_ref()
    -                .try_into()
    -                .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
    -            let val = u32::from_be_bytes(array);
    -            Ok(val)
    -        })
    -    }
    -}
    -
    -impl BatchDatabase for Tree {
    -    type Batch = sled::Batch;
    -
    -    fn begin_batch(&self) -> Self::Batch {
    -        sled::Batch::default()
    -    }
    -
    -    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
    -        Ok(self.apply_batch(batch)?)
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::sync::{Arc, Condvar, Mutex, Once};
    -    use std::time::{SystemTime, UNIX_EPOCH};
    -
    -    use sled::{Db, Tree};
    -
    -    static mut COUNT: usize = 0;
    -
    -    lazy_static! {
    -        static ref DB: Arc<(Mutex<Option<Db>>, Condvar)> =
    -            Arc::new((Mutex::new(None), Condvar::new()));
    -        static ref INIT: Once = Once::new();
    -    }
    -
    -    fn get_tree() -> Tree {
    -        unsafe {
    -            let cloned = DB.clone();
    -            let (mutex, cvar) = &*cloned;
    -
    -            INIT.call_once(|| {
    -                let mut db = mutex.lock().unwrap();
    -
    -                let time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
    -                let mut dir = std::env::temp_dir();
    -                dir.push(format!("mbw_{}", time.as_nanos()));
    -
    -                *db = Some(sled::open(dir).unwrap());
    -                cvar.notify_all();
    -            });
    -
    -            let mut db = mutex.lock().unwrap();
    -            while !db.is_some() {
    -                db = cvar.wait(db).unwrap();
    -            }
    -
    -            COUNT += 1;
    -
    -            db.as_ref()
    -                .unwrap()
    -                .open_tree(format!("tree_{}", COUNT))
    -                .unwrap()
    -        }
    -    }
    -
    -    #[test]
    -    fn test_script_pubkey() {
    -        crate::database::test::test_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_batch_script_pubkey() {
    -        crate::database::test::test_batch_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_iter_script_pubkey() {
    -        crate::database::test::test_iter_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_script_pubkey() {
    -        crate::database::test::test_del_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_utxo() {
    -        crate::database::test::test_utxo(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_raw_tx() {
    -        crate::database::test::test_raw_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_tx() {
    -        crate::database::test::test_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_last_index() {
    -        crate::database::test::test_last_index(get_tree());
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/memory.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/memory.rs.html deleted file mode 100644 index 7f900ff53a..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/memory.rs.html +++ /dev/null @@ -1,1119 +0,0 @@ -memory.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! In-memory ephemeral database
    -//!
    -//! This module defines an in-memory database type called [`MemoryDatabase`] that is based on a
    -//! [`BTreeMap`].
    -
    -use std::collections::BTreeMap;
    -use std::ops::Bound::{Excluded, Included};
    -
    -use bitcoin::consensus::encode::{deserialize, serialize};
    -use bitcoin::hash_types::Txid;
    -use bitcoin::{OutPoint, Script, Transaction};
    -
    -use crate::database::{BatchDatabase, BatchOperations, Database};
    -use crate::error::Error;
    -use crate::types::*;
    -
    -// path -> script       p{i,e}<path> -> script
    -// script -> path       s<script> -> {i,e}<path>
    -// outpoint             u<outpoint> -> txout
    -// rawtx                r<txid> -> tx
    -// transactions         t<txid> -> tx details
    -// deriv indexes        c{i,e} -> u32
    -// descriptor checksum  d{i,e} -> vec<u8>
    -
    -pub(crate) enum MapKey<'a> {
    -    Path((Option<ScriptType>, Option<u32>)),
    -    Script(Option<&'a Script>),
    -    UTXO(Option<&'a OutPoint>),
    -    RawTx(Option<&'a Txid>),
    -    Transaction(Option<&'a Txid>),
    -    LastIndex(ScriptType),
    -    DescriptorChecksum(ScriptType),
    -}
    -
    -impl MapKey<'_> {
    -    pub fn as_prefix(&self) -> Vec<u8> {
    -        match self {
    -            MapKey::Path((st, _)) => {
    -                let mut v = b"p".to_vec();
    -                if let Some(st) = st {
    -                    v.push(st.as_byte());
    -                }
    -                v
    -            }
    -            MapKey::Script(_) => b"s".to_vec(),
    -            MapKey::UTXO(_) => b"u".to_vec(),
    -            MapKey::RawTx(_) => b"r".to_vec(),
    -            MapKey::Transaction(_) => b"t".to_vec(),
    -            MapKey::LastIndex(st) => [b"c", st.as_ref()].concat(),
    -            MapKey::DescriptorChecksum(st) => [b"d", st.as_ref()].concat(),
    -        }
    -    }
    -
    -    fn serialize_content(&self) -> Vec<u8> {
    -        match self {
    -            MapKey::Path((_, Some(child))) => u32::from(*child).to_be_bytes().to_vec(),
    -            MapKey::Script(Some(s)) => serialize(*s),
    -            MapKey::UTXO(Some(s)) => serialize(*s),
    -            MapKey::RawTx(Some(s)) => serialize(*s),
    -            MapKey::Transaction(Some(s)) => serialize(*s),
    -            _ => vec![],
    -        }
    -    }
    -
    -    pub fn as_map_key(&self) -> Vec<u8> {
    -        let mut v = self.as_prefix();
    -        v.extend_from_slice(&self.serialize_content());
    -
    -        v
    -    }
    -}
    -
    -fn after(key: &Vec<u8>) -> Vec<u8> {
    -    let mut key = key.clone();
    -    let mut idx = key.len();
    -    while idx > 0 {
    -        if key[idx - 1] == 0xFF {
    -            idx -= 1;
    -            continue;
    -        } else {
    -            key[idx - 1] += 1;
    -            break;
    -        }
    -    }
    -
    -    key
    -}
    -
    -/// In-memory ephemeral database
    -///
    -/// This database can be used as a temporary storage for wallets that are not kept permanently on
    -/// a device, or on platforms that don't provide a filesystem, like `wasm32`.
    -///
    -/// Once it's dropped its content will be lost.
    -///
    -/// If you are looking for a permanent storage solution, you can try with the default key-value
    -/// database called [`sled`]. See the [`database`] module documentation for more defailts.
    -///
    -/// [`database`]: crate::database
    -#[derive(Debug, Default)]
    -pub struct MemoryDatabase {
    -    map: BTreeMap<Vec<u8>, Box<dyn std::any::Any>>,
    -    deleted_keys: Vec<Vec<u8>>,
    -}
    -
    -impl MemoryDatabase {
    -    /// Create a new empty database
    -    pub fn new() -> Self {
    -        MemoryDatabase {
    -            map: BTreeMap::new(),
    -            deleted_keys: Vec::new(),
    -        }
    -    }
    -}
    -
    -impl BatchOperations for MemoryDatabase {
    -    fn set_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -        script_type: ScriptType,
    -        path: u32,
    -    ) -> Result<(), Error> {
    -        let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
    -        self.map.insert(key, Box::new(script.clone()));
    -
    -        let key = MapKey::Script(Some(script)).as_map_key();
    -        let value = json!({
    -            "t": script_type,
    -            "p": path,
    -        });
    -        self.map.insert(key, Box::new(value));
    -
    -        Ok(())
    -    }
    -
    -    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
    -        let key = MapKey::UTXO(Some(&utxo.outpoint)).as_map_key();
    -        self.map
    -            .insert(key, Box::new((utxo.txout.clone(), utxo.is_internal)));
    -
    -        Ok(())
    -    }
    -    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
    -        let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
    -        self.map.insert(key, Box::new(transaction.clone()));
    -
    -        Ok(())
    -    }
    -    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
    -        let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
    -
    -        // insert the raw_tx if present
    -        if let Some(ref tx) = transaction.transaction {
    -            self.set_raw_tx(tx)?;
    -        }
    -
    -        // remove the raw tx from the serialized version
    -        let mut transaction = transaction.clone();
    -        transaction.transaction = None;
    -
    -        self.map.insert(key, Box::new(transaction));
    -
    -        Ok(())
    -    }
    -    fn set_last_index(&mut self, script_type: ScriptType, value: u32) -> Result<(), Error> {
    -        let key = MapKey::LastIndex(script_type).as_map_key();
    -        self.map.insert(key, Box::new(value));
    -
    -        Ok(())
    -    }
    -
    -    fn del_script_pubkey_from_path(
    -        &mut self,
    -        script_type: ScriptType,
    -        path: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
    -    }
    -    fn del_path_from_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -    ) -> Result<Option<(ScriptType, u32)>, Error> {
    -        let key = MapKey::Script(Some(script)).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        match res {
    -            None => Ok(None),
    -            Some(b) => {
    -                let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
    -                let st = serde_json::from_value(val["t"].take())?;
    -                let path = serde_json::from_value(val["p"].take())?;
    -
    -                Ok(Some((st, path)))
    -            }
    -        }
    -    }
    -    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
    -        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        match res {
    -            None => Ok(None),
    -            Some(b) => {
    -                let (txout, is_internal) = b.downcast_ref().cloned().unwrap();
    -                Ok(Some(UTXO {
    -                    outpoint: outpoint.clone(),
    -                    txout,
    -                    is_internal,
    -                }))
    -            }
    -        }
    -    }
    -    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        let key = MapKey::RawTx(Some(txid)).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
    -    }
    -    fn del_tx(
    -        &mut self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error> {
    -        let raw_tx = if include_raw {
    -            self.del_raw_tx(txid)?
    -        } else {
    -            None
    -        };
    -
    -        let key = MapKey::Transaction(Some(txid)).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        match res {
    -            None => Ok(None),
    -            Some(b) => {
    -                let mut val: TransactionDetails = b.downcast_ref().cloned().unwrap();
    -                val.transaction = raw_tx;
    -
    -                Ok(Some(val))
    -            }
    -        }
    -    }
    -    fn del_last_index(&mut self, script_type: ScriptType) -> Result<Option<u32>, Error> {
    -        let key = MapKey::LastIndex(script_type).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        match res {
    -            None => Ok(None),
    -            Some(b) => Ok(Some(*b.downcast_ref().unwrap())),
    -        }
    -    }
    -}
    -
    -impl Database for MemoryDatabase {
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        script_type: ScriptType,
    -        bytes: B,
    -    ) -> Result<(), Error> {
    -        let key = MapKey::DescriptorChecksum(script_type).as_map_key();
    -
    -        let prev = self
    -            .map
    -            .get(&key)
    -            .map(|x| x.downcast_ref::<Vec<u8>>().unwrap());
    -        if let Some(val) = prev {
    -            if val == &bytes.as_ref().to_vec() {
    -                Ok(())
    -            } else {
    -                Err(Error::ChecksumMismatch)
    -            }
    -        } else {
    -            self.map.insert(key, Box::new(bytes.as_ref().to_vec()));
    -            Ok(())
    -        }
    -    }
    -
    -    fn iter_script_pubkeys(&self, script_type: Option<ScriptType>) -> Result<Vec<Script>, Error> {
    -        let key = MapKey::Path((script_type, None)).as_map_key();
    -        self.map
    -            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
    -            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
    -            .collect()
    -    }
    -
    -    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error> {
    -        let key = MapKey::UTXO(None).as_map_key();
    -        self.map
    -            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
    -            .map(|(k, v)| {
    -                let outpoint = deserialize(&k[1..]).unwrap();
    -                let (txout, is_internal) = v.downcast_ref().cloned().unwrap();
    -                Ok(UTXO {
    -                    outpoint,
    -                    txout,
    -                    is_internal,
    -                })
    -            })
    -            .collect()
    -    }
    -
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
    -        let key = MapKey::RawTx(None).as_map_key();
    -        self.map
    -            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
    -            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
    -            .collect()
    -    }
    -
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        let key = MapKey::Transaction(None).as_map_key();
    -        self.map
    -            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
    -            .map(|(k, v)| {
    -                let mut txdetails: TransactionDetails = v.downcast_ref().cloned().unwrap();
    -                if include_raw {
    -                    let txid = deserialize(&k[1..])?;
    -                    txdetails.transaction = self.get_raw_tx(&txid)?;
    -                }
    -
    -                Ok(txdetails)
    -            })
    -            .collect()
    -    }
    -
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        script_type: ScriptType,
    -        path: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let key = MapKey::Path((Some(script_type), Some(path))).as_map_key();
    -        Ok(self
    -            .map
    -            .get(&key)
    -            .map(|b| b.downcast_ref().cloned().unwrap()))
    -    }
    -
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(ScriptType, u32)>, Error> {
    -        let key = MapKey::Script(Some(script)).as_map_key();
    -        Ok(self.map.get(&key).map(|b| {
    -            let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
    -            let st = serde_json::from_value(val["t"].take()).unwrap();
    -            let path = serde_json::from_value(val["p"].take()).unwrap();
    -
    -            (st, path)
    -        }))
    -    }
    -
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
    -        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
    -        Ok(self.map.get(&key).map(|b| {
    -            let (txout, is_internal) = b.downcast_ref().cloned().unwrap();
    -            UTXO {
    -                outpoint: outpoint.clone(),
    -                txout,
    -                is_internal,
    -            }
    -        }))
    -    }
    -
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        let key = MapKey::RawTx(Some(txid)).as_map_key();
    -        Ok(self
    -            .map
    -            .get(&key)
    -            .map(|b| b.downcast_ref().cloned().unwrap()))
    -    }
    -
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -        let key = MapKey::Transaction(Some(txid)).as_map_key();
    -        Ok(self.map.get(&key).map(|b| {
    -            let mut txdetails: TransactionDetails = b.downcast_ref().cloned().unwrap();
    -            if include_raw {
    -                txdetails.transaction = self.get_raw_tx(&txid).unwrap();
    -            }
    -
    -            txdetails
    -        }))
    -    }
    -
    -    fn get_last_index(&self, script_type: ScriptType) -> Result<Option<u32>, Error> {
    -        let key = MapKey::LastIndex(script_type).as_map_key();
    -        Ok(self.map.get(&key).map(|b| *b.downcast_ref().unwrap()))
    -    }
    -
    -    // inserts 0 if not present
    -    fn increment_last_index(&mut self, script_type: ScriptType) -> Result<u32, Error> {
    -        let key = MapKey::LastIndex(script_type).as_map_key();
    -        let value = self
    -            .map
    -            .entry(key.clone())
    -            .and_modify(|x| *x.downcast_mut::<u32>().unwrap() += 1)
    -            .or_insert(Box::<u32>::new(0))
    -            .downcast_mut()
    -            .unwrap();
    -
    -        Ok(*value)
    -    }
    -}
    -
    -impl BatchDatabase for MemoryDatabase {
    -    type Batch = Self;
    -
    -    fn begin_batch(&self) -> Self::Batch {
    -        MemoryDatabase::new()
    -    }
    -
    -    fn commit_batch(&mut self, mut batch: Self::Batch) -> Result<(), Error> {
    -        for key in batch.deleted_keys {
    -            self.map.remove(&key);
    -        }
    -
    -        Ok(self.map.append(&mut batch.map))
    -    }
    -}
    -
    -#[cfg(test)]
    -impl MemoryDatabase {
    -    // Artificially insert a tx in the database, as if we had found it with a `sync`
    -    pub fn received_tx(
    -        &mut self,
    -        tx_meta: testutils::TestIncomingTx,
    -        current_height: Option<u32>,
    -    ) -> bitcoin::Txid {
    -        use std::str::FromStr;
    -
    -        let tx = Transaction {
    -            version: 1,
    -            lock_time: 0,
    -            input: vec![],
    -            output: tx_meta
    -                .output
    -                .iter()
    -                .map(|out_meta| bitcoin::TxOut {
    -                    value: out_meta.value,
    -                    script_pubkey: bitcoin::Address::from_str(&out_meta.to_address)
    -                        .unwrap()
    -                        .script_pubkey(),
    -                })
    -                .collect(),
    -        };
    -
    -        let txid = tx.txid();
    -        let height = tx_meta
    -            .min_confirmations
    -            .map(|conf| current_height.unwrap().checked_sub(conf as u32).unwrap());
    -
    -        let tx_details = TransactionDetails {
    -            transaction: Some(tx.clone()),
    -            txid,
    -            timestamp: 0,
    -            height,
    -            received: 0,
    -            sent: 0,
    -            fees: 0,
    -        };
    -
    -        self.set_tx(&tx_details).unwrap();
    -        for (vout, out) in tx.output.iter().enumerate() {
    -            self.set_utxo(&UTXO {
    -                txout: out.clone(),
    -                outpoint: OutPoint {
    -                    txid,
    -                    vout: vout as u32,
    -                },
    -                is_internal: false,
    -            })
    -            .unwrap();
    -        }
    -
    -        txid
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use super::MemoryDatabase;
    -
    -    fn get_tree() -> MemoryDatabase {
    -        MemoryDatabase::new()
    -    }
    -
    -    #[test]
    -    fn test_script_pubkey() {
    -        crate::database::test::test_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_batch_script_pubkey() {
    -        crate::database::test::test_batch_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_iter_script_pubkey() {
    -        crate::database::test::test_iter_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_script_pubkey() {
    -        crate::database::test::test_del_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_utxo() {
    -        crate::database::test::test_utxo(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_raw_tx() {
    -        crate::database::test::test_raw_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_tx() {
    -        crate::database::test::test_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_last_index() {
    -        crate::database::test::test_last_index(get_tree());
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/mod.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/mod.rs.html deleted file mode 100644 index 5836fe48fd..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/database/mod.rs.html +++ /dev/null @@ -1,739 +0,0 @@ -mod.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Database types
    -//!
    -//! This module provides the implementation of some defaults database types, along with traits that
    -//! can be implemented externally to let [`Wallet`]s use customized databases.
    -//!
    -//! It's important to note that the databases defined here only contains "blockchain-related" data.
    -//! They can be seen more as a cache than a critical piece of storage that contains secrets and
    -//! keys.
    -//!
    -//! The currently recommended database is [`sled`], which is a pretty simple key-value embedded
    -//! database written in Rust. If the `key-value-db` feature is enabled (which by default is),
    -//! this library automatically implements all the required traits for [`sled::Tree`].
    -//!
    -//! [`Wallet`]: crate::wallet::Wallet
    -
    -use bitcoin::hash_types::Txid;
    -use bitcoin::{OutPoint, Script, Transaction, TxOut};
    -
    -use crate::error::Error;
    -use crate::types::*;
    -
    -#[cfg(feature = "key-value-db")]
    -pub(crate) mod keyvalue;
    -
    -pub mod memory;
    -pub use memory::MemoryDatabase;
    -
    -/// Trait for operations that can be batched
    -///
    -/// This trait defines the list of operations that must be implemented on the [`Database`] type and
    -/// the [`BatchDatabase::Batch`] type.
    -pub trait BatchOperations {
    -    /// Store a script_pubkey along with its script type and child number
    -    fn set_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -        script_type: ScriptType,
    -        child: u32,
    -    ) -> Result<(), Error>;
    -    /// Store a [`UTXO`]
    -    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>;
    -    /// Store a raw transaction
    -    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>;
    -    /// Store the metadata of a transaction
    -    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>;
    -    /// Store the last derivation index for a given script type
    -    fn set_last_index(&mut self, script_type: ScriptType, value: u32) -> Result<(), Error>;
    -
    -    /// Delete a script_pubkey given the script type and its child number
    -    fn del_script_pubkey_from_path(
    -        &mut self,
    -        script_type: ScriptType,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error>;
    -    /// Delete the data related to a specific script_pubkey, meaning the script type and the child
    -    /// number
    -    fn del_path_from_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -    ) -> Result<Option<(ScriptType, u32)>, Error>;
    -    /// Delete a [`UTXO`] given its [`OutPoint`]
    -    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>;
    -    /// Delete a raw transaction given its [`Txid`]
    -    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>;
    -    /// Delete the metadata of a transaction and optionally the raw transaction itself
    -    fn del_tx(
    -        &mut self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error>;
    -    /// Delete the last derivation index for a script type
    -    fn del_last_index(&mut self, script_type: ScriptType) -> Result<Option<u32>, Error>;
    -}
    -
    -/// Trait for reading data from a database
    -///
    -/// This traits defines the operations that can be used to read data out of a database
    -pub trait Database: BatchOperations {
    -    /// Read and checks the descriptor checksum for a given script type
    -    ///
    -    /// Should return [`Error::ChecksumMismatch`](crate::error::Error::ChecksumMismatch) if the
    -    /// checksum doesn't match. If there's no checksum in the database, simply store it for the
    -    /// next time.
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        script_type: ScriptType,
    -        bytes: B,
    -    ) -> Result<(), Error>;
    -
    -    /// Return the list of script_pubkeys
    -    fn iter_script_pubkeys(&self, script_type: Option<ScriptType>) -> Result<Vec<Script>, Error>;
    -    /// Return the list of [`UTXO`]s
    -    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error>;
    -    /// Return the list of raw transactions
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>;
    -    /// Return the list of transactions metadata
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error>;
    -
    -    /// Fetch a script_pubkey given the script type and child number
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        script_type: ScriptType,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error>;
    -    /// Fetch the script type and child number of a given script_pubkey
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(ScriptType, u32)>, Error>;
    -    /// Fetch a [`UTXO`] given its [`OutPoint`]
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>;
    -    /// Fetch a raw transaction given its [`Txid`]
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
    -    /// Fetch the transaction metadata and optionally also the raw transaction
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error>;
    -    /// Return the last defivation index for a script type
    -    fn get_last_index(&self, script_type: ScriptType) -> Result<Option<u32>, Error>;
    -
    -    /// Increment the last derivation index for a script type and returns it
    -    ///
    -    /// It should insert and return `0` if not present in the database
    -    fn increment_last_index(&mut self, script_type: ScriptType) -> Result<u32, Error>;
    -}
    -
    -/// Trait for a database that supports batch operations
    -///
    -/// This trait defines the methods to start and apply a batch of operations.
    -pub trait BatchDatabase: Database {
    -    /// Container for the operations
    -    type Batch: BatchOperations;
    -
    -    /// Create a new batch container
    -    fn begin_batch(&self) -> Self::Batch;
    -    /// Consume and apply a batch of operations
    -    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>;
    -}
    -
    -pub(crate) trait DatabaseUtils: Database {
    -    fn is_mine(&self, script: &Script) -> Result<bool, Error> {
    -        self.get_path_from_script_pubkey(script)
    -            .map(|o| o.is_some())
    -    }
    -
    -    fn get_raw_tx_or<F>(&self, txid: &Txid, f: F) -> Result<Option<Transaction>, Error>
    -    where
    -        F: FnOnce() -> Result<Option<Transaction>, Error>,
    -    {
    -        self.get_tx(txid, true)?
    -            .map(|t| t.transaction)
    -            .flatten()
    -            .map_or_else(f, |t| Ok(Some(t)))
    -    }
    -
    -    fn get_previous_output(&self, outpoint: &OutPoint) -> Result<Option<TxOut>, Error> {
    -        self.get_raw_tx(&outpoint.txid)?
    -            .map(|previous_tx| {
    -                if outpoint.vout as usize >= previous_tx.output.len() {
    -                    Err(Error::InvalidOutpoint(outpoint.clone()))
    -                } else {
    -                    Ok(previous_tx.output[outpoint.vout as usize].clone())
    -                }
    -            })
    -            .transpose()
    -    }
    -}
    -
    -impl<T: Database> DatabaseUtils for T {}
    -
    -#[cfg(test)]
    -pub mod test {
    -    use std::str::FromStr;
    -
    -    use bitcoin::consensus::encode::deserialize;
    -    use bitcoin::hashes::hex::*;
    -    use bitcoin::*;
    -
    -    use super::*;
    -
    -    pub fn test_script_pubkey<D: Database>(mut tree: D) {
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let script_type = ScriptType::External;
    -
    -        tree.set_script_pubkey(&script, script_type, path).unwrap();
    -
    -        assert_eq!(
    -            tree.get_script_pubkey_from_path(script_type, path).unwrap(),
    -            Some(script.clone())
    -        );
    -        assert_eq!(
    -            tree.get_path_from_script_pubkey(&script).unwrap(),
    -            Some((script_type, path.clone()))
    -        );
    -    }
    -
    -    pub fn test_batch_script_pubkey<D: BatchDatabase>(mut tree: D) {
    -        let mut batch = tree.begin_batch();
    -
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let script_type = ScriptType::External;
    -
    -        batch.set_script_pubkey(&script, script_type, path).unwrap();
    -
    -        assert_eq!(
    -            tree.get_script_pubkey_from_path(script_type, path).unwrap(),
    -            None
    -        );
    -        assert_eq!(tree.get_path_from_script_pubkey(&script).unwrap(), None);
    -
    -        tree.commit_batch(batch).unwrap();
    -
    -        assert_eq!(
    -            tree.get_script_pubkey_from_path(script_type, path).unwrap(),
    -            Some(script.clone())
    -        );
    -        assert_eq!(
    -            tree.get_path_from_script_pubkey(&script).unwrap(),
    -            Some((script_type, path.clone()))
    -        );
    -    }
    -
    -    pub fn test_iter_script_pubkey<D: Database>(mut tree: D) {
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let script_type = ScriptType::External;
    -
    -        tree.set_script_pubkey(&script, script_type, path).unwrap();
    -
    -        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 1);
    -    }
    -
    -    pub fn test_del_script_pubkey<D: Database>(mut tree: D) {
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let script_type = ScriptType::External;
    -
    -        tree.set_script_pubkey(&script, script_type, path).unwrap();
    -        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 1);
    -
    -        tree.del_script_pubkey_from_path(script_type, path).unwrap();
    -        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 0);
    -    }
    -
    -    pub fn test_utxo<D: Database>(mut tree: D) {
    -        let outpoint = OutPoint::from_str(
    -            "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0",
    -        )
    -        .unwrap();
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let txout = TxOut {
    -            value: 133742,
    -            script_pubkey: script,
    -        };
    -        let utxo = UTXO {
    -            txout,
    -            outpoint,
    -            is_internal: false,
    -        };
    -
    -        tree.set_utxo(&utxo).unwrap();
    -
    -        assert_eq!(tree.get_utxo(&outpoint).unwrap(), Some(utxo));
    -    }
    -
    -    pub fn test_raw_tx<D: Database>(mut tree: D) {
    -        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
    -        let tx: Transaction = deserialize(&hex_tx).unwrap();
    -
    -        tree.set_raw_tx(&tx).unwrap();
    -
    -        let txid = tx.txid();
    -
    -        assert_eq!(tree.get_raw_tx(&txid).unwrap(), Some(tx));
    -    }
    -
    -    pub fn test_tx<D: Database>(mut tree: D) {
    -        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
    -        let tx: Transaction = deserialize(&hex_tx).unwrap();
    -        let txid = tx.txid();
    -        let mut tx_details = TransactionDetails {
    -            transaction: Some(tx),
    -            txid,
    -            timestamp: 123456,
    -            received: 1337,
    -            sent: 420420,
    -            fees: 140,
    -            height: Some(1000),
    -        };
    -
    -        tree.set_tx(&tx_details).unwrap();
    -
    -        // get with raw tx too
    -        assert_eq!(
    -            tree.get_tx(&tx_details.txid, true).unwrap(),
    -            Some(tx_details.clone())
    -        );
    -        // get only raw_tx
    -        assert_eq!(
    -            tree.get_raw_tx(&tx_details.txid).unwrap(),
    -            tx_details.transaction
    -        );
    -
    -        // now get without raw_tx
    -        tx_details.transaction = None;
    -        assert_eq!(
    -            tree.get_tx(&tx_details.txid, false).unwrap(),
    -            Some(tx_details)
    -        );
    -    }
    -
    -    pub fn test_last_index<D: Database>(mut tree: D) {
    -        tree.set_last_index(ScriptType::External, 1337).unwrap();
    -
    -        assert_eq!(
    -            tree.get_last_index(ScriptType::External).unwrap(),
    -            Some(1337)
    -        );
    -        assert_eq!(tree.get_last_index(ScriptType::Internal).unwrap(), None);
    -
    -        let res = tree.increment_last_index(ScriptType::External).unwrap();
    -        assert_eq!(res, 1338);
    -        let res = tree.increment_last_index(ScriptType::Internal).unwrap();
    -        assert_eq!(res, 0);
    -
    -        assert_eq!(
    -            tree.get_last_index(ScriptType::External).unwrap(),
    -            Some(1338)
    -        );
    -        assert_eq!(tree.get_last_index(ScriptType::Internal).unwrap(), Some(0));
    -    }
    -
    -    // TODO: more tests...
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/checksum.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/checksum.rs.html deleted file mode 100644 index 33f8d47a15..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/checksum.rs.html +++ /dev/null @@ -1,191 +0,0 @@ -checksum.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Descriptor checksum
    -//!
    -//! This module contains a re-implementation of the function used by Bitcoin Core to calculate the
    -//! checksum of a descriptor
    -
    -use std::iter::FromIterator;
    -
    -use crate::descriptor::Error;
    -
    -const INPUT_CHARSET: &str =  "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
    -const CHECKSUM_CHARSET: &str = "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 of a descriptor
    -pub fn get_checksum(desc: &str) -> Result<String, Error> {
    -    let mut c = 1;
    -    let mut cls = 0;
    -    let mut clscount = 0;
    -    for ch in desc.chars() {
    -        let pos = INPUT_CHARSET
    -            .find(ch)
    -            .ok_or(Error::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 chars = Vec::with_capacity(8);
    -    for j in 0..8 {
    -        chars.push(
    -            CHECKSUM_CHARSET
    -                .chars()
    -                .nth(((c >> (5 * (7 - j))) & 31) as usize)
    -                .unwrap(),
    -        );
    -    }
    -
    -    Ok(String::from_iter(chars))
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/error.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/error.rs.html deleted file mode 100644 index 78518b4f6b..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/error.rs.html +++ /dev/null @@ -1,135 +0,0 @@ -error.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Descriptor errors
    -
    -/// Errors related to the parsing and usage of descriptors
    -#[derive(Debug)]
    -pub enum Error {
    -    InternalError,
    -    InvalidPrefix(Vec<u8>),
    -    HardenedDerivationOnXpub,
    -    MalformedInput,
    -    KeyParsingError(String),
    -
    -    Policy(crate::descriptor::policy::PolicyError),
    -
    -    InputIndexDoesntExist,
    -    MissingPublicKey,
    -    MissingDetails,
    -
    -    InvalidDescriptorCharacter(char),
    -
    -    CantDeriveWithMiniscript,
    -
    -    BIP32(bitcoin::util::bip32::Error),
    -    Base58(bitcoin::util::base58::Error),
    -    PK(bitcoin::util::key::Error),
    -    Miniscript(miniscript::Error),
    -    Hex(bitcoin::hashes::hex::Error),
    -}
    -
    -impl std::fmt::Display for Error {
    -    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for Error {}
    -
    -impl_error!(bitcoin::util::bip32::Error, BIP32);
    -impl_error!(bitcoin::util::base58::Error, Base58);
    -impl_error!(bitcoin::util::key::Error, PK);
    -impl_error!(miniscript::Error, Miniscript);
    -impl_error!(bitcoin::hashes::hex::Error, Hex);
    -impl_error!(crate::descriptor::policy::PolicyError, Policy);
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/mod.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/mod.rs.html deleted file mode 100644 index 2e600ffa85..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/mod.rs.html +++ /dev/null @@ -1,883 +0,0 @@ -mod.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Descriptors
    -//!
    -//! This module contains generic utilities to work with descriptors, plus some re-exported types
    -//! from [`miniscript`].
    -
    -use std::collections::{BTreeMap, HashMap};
    -use std::fmt;
    -use std::sync::Arc;
    -
    -use bitcoin::hashes::hash160;
    -use bitcoin::secp256k1::Secp256k1;
    -use bitcoin::util::bip32::{ChildNumber, DerivationPath, Fingerprint};
    -use bitcoin::util::psbt;
    -use bitcoin::{PublicKey, Script, TxOut};
    -
    -use miniscript::descriptor::{DescriptorPublicKey, DescriptorXKey, InnerXKey};
    -pub use miniscript::{
    -    Descriptor, Legacy, Miniscript, MiniscriptKey, ScriptContext, Segwitv0, Terminal, ToPublicKey,
    -};
    -
    -pub mod checksum;
    -pub mod error;
    -pub mod policy;
    -
    -pub use self::checksum::get_checksum;
    -use self::error::Error;
    -pub use self::policy::Policy;
    -use crate::wallet::signer::SignersContainer;
    -
    -/// Alias for a [`Descriptor`] that can contain extended keys using [`DescriptorPublicKey`]
    -pub type ExtendedDescriptor = Descriptor<DescriptorPublicKey>;
    -
    -/// Alias for the type of maps that represent derivation paths in a [`psbt::Input`] or
    -/// [`psbt::Output`]
    -///
    -/// [`psbt::Input`]: bitcoin::util::psbt::Input
    -/// [`psbt::Output`]: bitcoin::util::psbt::Output
    -pub type HDKeyPaths = BTreeMap<PublicKey, (Fingerprint, DerivationPath)>;
    -
    -/// Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]
    -pub trait ExtractPolicy {
    -    fn extract_policy(
    -        &self,
    -        signers: Arc<SignersContainer<DescriptorPublicKey>>,
    -    ) -> Result<Option<Policy>, Error>;
    -}
    -
    -pub(crate) trait XKeyUtils {
    -    fn full_path(&self, append: &[ChildNumber]) -> DerivationPath;
    -    fn root_fingerprint(&self) -> Fingerprint;
    -}
    -
    -impl<K: InnerXKey> XKeyUtils for DescriptorXKey<K> {
    -    fn full_path(&self, append: &[ChildNumber]) -> DerivationPath {
    -        let full_path = match &self.source {
    -            &Some((_, ref path)) => path
    -                .into_iter()
    -                .chain(self.derivation_path.into_iter())
    -                .cloned()
    -                .collect(),
    -            &None => self.derivation_path.clone(),
    -        };
    -
    -        if self.is_wildcard {
    -            full_path
    -                .into_iter()
    -                .chain(append.into_iter())
    -                .cloned()
    -                .collect()
    -        } else {
    -            full_path
    -        }
    -    }
    -
    -    fn root_fingerprint(&self) -> Fingerprint {
    -        match &self.source {
    -            &Some((fingerprint, _)) => fingerprint.clone(),
    -            &None => self.xkey.xkey_fingerprint(),
    -        }
    -    }
    -}
    -
    -pub(crate) trait DescriptorMeta: Sized {
    -    fn is_witness(&self) -> bool;
    -    fn get_hd_keypaths(&self, index: u32) -> Result<HDKeyPaths, Error>;
    -    fn is_fixed(&self) -> bool;
    -    fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths) -> Option<Self>;
    -    fn derive_from_psbt_input(&self, psbt_input: &psbt::Input, utxo: Option<TxOut>)
    -        -> Option<Self>;
    -}
    -
    -pub(crate) trait DescriptorScripts {
    -    fn psbt_redeem_script(&self) -> Option<Script>;
    -    fn psbt_witness_script(&self) -> Option<Script>;
    -}
    -
    -impl<T> DescriptorScripts for Descriptor<T>
    -where
    -    T: miniscript::MiniscriptKey + miniscript::ToPublicKey,
    -{
    -    fn psbt_redeem_script(&self) -> Option<Script> {
    -        match self {
    -            Descriptor::ShWpkh(_) => Some(self.witness_script()),
    -            Descriptor::ShWsh(ref script) => Some(script.encode().to_v0_p2wsh()),
    -            Descriptor::Sh(ref script) => Some(script.encode()),
    -            Descriptor::Bare(ref script) => Some(script.encode()),
    -            _ => None,
    -        }
    -    }
    -
    -    fn psbt_witness_script(&self) -> Option<Script> {
    -        match self {
    -            Descriptor::Wsh(ref script) => Some(script.encode()),
    -            Descriptor::ShWsh(ref script) => Some(script.encode()),
    -            _ => None,
    -        }
    -    }
    -}
    -
    -impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
    -    fn is_witness(&self) -> bool {
    -        match self {
    -            Descriptor::Bare(_) | Descriptor::Pk(_) | Descriptor::Pkh(_) | Descriptor::Sh(_) => {
    -                false
    -            }
    -            Descriptor::Wpkh(_)
    -            | Descriptor::ShWpkh(_)
    -            | Descriptor::Wsh(_)
    -            | Descriptor::ShWsh(_) => true,
    -        }
    -    }
    -
    -    fn get_hd_keypaths(&self, index: u32) -> Result<HDKeyPaths, Error> {
    -        let mut answer = BTreeMap::new();
    -
    -        let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
    -            match key {
    -                DescriptorPublicKey::PubKey(_) => {}
    -                DescriptorPublicKey::XPub(xpub) => {
    -                    let derive_path = if xpub.is_wildcard {
    -                        xpub.derivation_path
    -                            .into_iter()
    -                            .chain([ChildNumber::from_normal_idx(index)?].iter())
    -                            .cloned()
    -                            .collect()
    -                    } else {
    -                        xpub.derivation_path.clone()
    -                    };
    -                    let derived_pubkey = xpub
    -                        .xkey
    -                        .derive_pub(&Secp256k1::verification_only(), &derive_path)?;
    -
    -                    answer.insert(
    -                        derived_pubkey.public_key,
    -                        (
    -                            xpub.root_fingerprint(),
    -                            xpub.full_path(&[ChildNumber::from_normal_idx(index)?]),
    -                        ),
    -                    );
    -                }
    -            }
    -
    -            Ok(DummyKey::default())
    -        };
    -        let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
    -
    -        self.translate_pk(translatefpk, translatefpkh)?;
    -
    -        Ok(answer)
    -    }
    -
    -    fn is_fixed(&self) -> bool {
    -        let mut found_wildcard = false;
    -
    -        let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
    -            match key {
    -                DescriptorPublicKey::PubKey(_) => {}
    -                DescriptorPublicKey::XPub(xpub) => {
    -                    if xpub.is_wildcard {
    -                        found_wildcard = true;
    -                    }
    -                }
    -            }
    -
    -            Ok(DummyKey::default())
    -        };
    -        let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
    -
    -        self.translate_pk(translatefpk, translatefpkh).unwrap();
    -
    -        !found_wildcard
    -    }
    -
    -    fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths) -> Option<Self> {
    -        let index: HashMap<_, _> = hd_keypaths.values().cloned().collect();
    -
    -        let mut derive_path = None::<DerivationPath>;
    -        let translatefpk = |key: &DescriptorPublicKey| -> Result<_, Error> {
    -            if derive_path.is_some() {
    -                // already found a matching path, we are done
    -                return Ok(DummyKey::default());
    -            }
    -
    -            if let DescriptorPublicKey::XPub(xpub) = key {
    -                // Check if the key matches one entry in our `index`. If it does, `matches()` will
    -                // return the "prefix" that matched, so we remove that prefix from the full path
    -                // found in `index` and save it in `derive_path`
    -                let root_fingerprint = xpub.root_fingerprint();
    -                derive_path = index
    -                    .get_key_value(&root_fingerprint)
    -                    .and_then(|(fingerprint, path)| xpub.matches(*fingerprint, path))
    -                    .map(|prefix_path| prefix_path.into_iter().cloned().collect::<Vec<_>>())
    -                    .map(|prefix| {
    -                        index
    -                            .get(&xpub.root_fingerprint())
    -                            .unwrap()
    -                            .into_iter()
    -                            .skip(prefix.len())
    -                            .cloned()
    -                            .collect()
    -                    });
    -            }
    -
    -            Ok(DummyKey::default())
    -        };
    -        let translatefpkh = |_: &hash160::Hash| -> Result<_, Error> { Ok(DummyKey::default()) };
    -
    -        self.translate_pk(translatefpk, translatefpkh).unwrap();
    -
    -        derive_path.map(|path| self.derive(path.as_ref()))
    -    }
    -
    -    fn derive_from_psbt_input(
    -        &self,
    -        psbt_input: &psbt::Input,
    -        utxo: Option<TxOut>,
    -    ) -> Option<Self> {
    -        if let Some(derived) = self.derive_from_hd_keypaths(&psbt_input.hd_keypaths) {
    -            return Some(derived);
    -        } else if !self.is_fixed() {
    -            // If the descriptor is not fixed we can't brute-force the derivation address, so just
    -            // exit here
    -            return None;
    -        }
    -
    -        match self {
    -            Descriptor::Pk(_)
    -            | Descriptor::Pkh(_)
    -            | Descriptor::Wpkh(_)
    -            | Descriptor::ShWpkh(_)
    -                if utxo.is_some()
    -                    && self.script_pubkey() == utxo.as_ref().unwrap().script_pubkey =>
    -            {
    -                Some(self.clone())
    -            }
    -            Descriptor::Bare(ms) | Descriptor::Sh(ms)
    -                if psbt_input.redeem_script.is_some()
    -                    && &ms.encode() == psbt_input.redeem_script.as_ref().unwrap() =>
    -            {
    -                Some(self.clone())
    -            }
    -            Descriptor::Wsh(ms) | Descriptor::ShWsh(ms)
    -                if psbt_input.witness_script.is_some()
    -                    && &ms.encode() == psbt_input.witness_script.as_ref().unwrap() =>
    -            {
    -                Some(self.clone())
    -            }
    -            _ => None,
    -        }
    -    }
    -}
    -
    -#[derive(Debug, Clone, Hash, PartialEq, PartialOrd, Eq, Ord, Default)]
    -struct DummyKey();
    -
    -impl fmt::Display for DummyKey {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "DummyKey")
    -    }
    -}
    -
    -impl std::str::FromStr for DummyKey {
    -    type Err = ();
    -
    -    fn from_str(_: &str) -> Result<Self, Self::Err> {
    -        Ok(DummyKey::default())
    -    }
    -}
    -
    -impl miniscript::MiniscriptKey for DummyKey {
    -    type Hash = DummyKey;
    -
    -    fn to_pubkeyhash(&self) -> DummyKey {
    -        DummyKey::default()
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::str::FromStr;
    -
    -    use bitcoin::consensus::encode::deserialize;
    -    use bitcoin::hashes::hex::FromHex;
    -    use bitcoin::util::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::PartiallySignedTransaction = 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))
    -            .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::PartiallySignedTransaction = 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))
    -            .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::PartiallySignedTransaction = 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))
    -            .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::PartiallySignedTransaction = 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))
    -            .is_some());
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/policy.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/policy.rs.html deleted file mode 100644 index b094837b39..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/descriptor/policy.rs.html +++ /dev/null @@ -1,1593 +0,0 @@ -policy.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Descriptor policy
    -//!
    -//! This module implements the logic to extract and represent the spending policies of a descriptor
    -//! in a more human-readable format.
    -//!
    -//! ## Example
    -//!
    -//! ```
    -//! # use std::sync::Arc;
    -//! # use bdk::descriptor::*;
    -//! let desc = "wsh(and_v(v:pk(cV3oCth6zxZ1UVsHLnGothsWNsaoxRhC6aeNi5VbSdFpwUkgkEci),or_d(pk(cVMTy7uebJgvFaSBwcgvwk8qn8xSLc97dKow4MBetjrrahZoimm2),older(12960))))";
    -//!
    -//! let (extended_desc, key_map) = ExtendedDescriptor::parse_secret(desc)?;
    -//! println!("{:?}", extended_desc);
    -//!
    -//! let signers = Arc::new(key_map.into());
    -//! let policy = extended_desc.extract_policy(signers)?;
    -//! println!("policy: {}", serde_json::to_string(&policy)?);
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use std::cmp::max;
    -use std::collections::{BTreeMap, HashSet, VecDeque};
    -use std::fmt;
    -use std::sync::Arc;
    -
    -use serde::ser::SerializeMap;
    -use serde::{Serialize, Serializer};
    -
    -use bitcoin::hashes::*;
    -use bitcoin::util::bip32::Fingerprint;
    -use bitcoin::PublicKey;
    -
    -use miniscript::descriptor::DescriptorPublicKey;
    -use miniscript::{Descriptor, Miniscript, MiniscriptKey, ScriptContext, Terminal};
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -use crate::descriptor::ExtractPolicy;
    -use crate::wallet::signer::{SignerId, SignersContainer};
    -
    -use super::checksum::get_checksum;
    -use super::error::Error;
    -use super::XKeyUtils;
    -
    -/// Raw public key or extended key fingerprint
    -#[derive(Debug, Clone, Default, Serialize)]
    -pub struct PKOrF {
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    pubkey: Option<PublicKey>,
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    pubkey_hash: Option<hash160::Hash>,
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    fingerprint: Option<Fingerprint>,
    -}
    -
    -impl PKOrF {
    -    fn from_key(k: &DescriptorPublicKey) -> Self {
    -        match k {
    -            DescriptorPublicKey::PubKey(pubkey) => PKOrF {
    -                pubkey: Some(*pubkey),
    -                ..Default::default()
    -            },
    -            DescriptorPublicKey::XPub(xpub) => PKOrF {
    -                fingerprint: Some(xpub.root_fingerprint()),
    -                ..Default::default()
    -            },
    -        }
    -    }
    -
    -    fn from_key_hash(k: hash160::Hash) -> Self {
    -        PKOrF {
    -            pubkey_hash: Some(k),
    -            ..Default::default()
    -        }
    -    }
    -}
    -
    -/// An item that need to be satisfied
    -#[derive(Debug, Clone, Serialize)]
    -#[serde(tag = "type", rename_all = "UPPERCASE")]
    -pub enum SatisfiableItem {
    -    // Leaves
    -    Signature(PKOrF),
    -    SignatureKey(PKOrF),
    -    SHA256Preimage {
    -        hash: sha256::Hash,
    -    },
    -    HASH256Preimage {
    -        hash: sha256d::Hash,
    -    },
    -    RIPEMD160Preimage {
    -        hash: ripemd160::Hash,
    -    },
    -    HASH160Preimage {
    -        hash: hash160::Hash,
    -    },
    -    AbsoluteTimelock {
    -        value: u32,
    -    },
    -    RelativeTimelock {
    -        value: u32,
    -    },
    -
    -    // Complex item
    -    Thresh {
    -        items: Vec<Policy>,
    -        threshold: usize,
    -    },
    -    Multisig {
    -        keys: Vec<PKOrF>,
    -        threshold: usize,
    -    },
    -}
    -
    -impl SatisfiableItem {
    -    pub fn is_leaf(&self) -> bool {
    -        match self {
    -            SatisfiableItem::Thresh {
    -                items: _,
    -                threshold: _,
    -            } => false,
    -            _ => true,
    -        }
    -    }
    -
    -    pub fn id(&self) -> String {
    -        get_checksum(&serde_json::to_string(self).expect("Failed to serialize a SatisfiableItem"))
    -            .expect("Failed to compute a SatisfiableItem id")
    -    }
    -}
    -
    -fn combinations(vec: &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
    -}
    -
    -pub type ConditionMap = BTreeMap<usize, HashSet<Condition>>;
    -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, 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
    -        items: Vec<usize>,
    -        #[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(
    -            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 {
    -    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) -> Result<(), PolicyError> {
    -        // if partial try to bump it to a partialcomplete
    -        if let Satisfaction::Partial {
    -            n,
    -            m,
    -            items,
    -            conditions,
    -        } = 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 ([choosen 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 possibile options and check whether or not they are compatible.
    -                    .map(|i_vec| {
    -                        mix(i_vec
    -                            .iter()
    -                            .map(|i| {
    -                                conditions
    -                                    .get(i)
    -                                    .and_then(|set| Some(set.clone().into_iter().collect()))
    -                                    .unwrap_or(vec![])
    -                            })
    -                            .collect())
    -                        .into_iter()
    -                        .map(|x| (i_vec.clone(), x))
    -                        .collect::<Vec<(Vec<usize>, Vec<Condition>)>>()
    -                    })
    -                    // .inspect(|x: &Vec<(Vec<usize>, Vec<Condition>)>| println!("fetch {:?}", x))
    -                    // since the previous step can turn one item of the iterator into multiple ones, we call flatten to expand them out
    -                    .flatten()
    -                    // .inspect(|x| println!("flat {:?}", x))
    -                    // try to fold all the conditions for this specific combination of indexes/options. if they are not compatibile, 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,
    -                };
    -            }
    -        }
    -
    -        Ok(())
    -    }
    -}
    -
    -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, Serialize)]
    -pub struct Policy {
    -    /// Identifier for this policy node
    -    pub id: String,
    -
    -    /// Type of this policy node
    -    #[serde(flatten)]
    -    pub item: SatisfiableItem,
    -    /// How a much given PSBT already satisfies this polcy node **(currently unused)**
    -    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
    -#[derive(Hash, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default, Serialize)]
    -pub struct Condition {
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    pub csv: Option<u32>,
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    pub timelock: Option<u32>,
    -}
    -
    -impl Condition {
    -    fn merge_timelock(a: u32, b: u32) -> Result<u32, PolicyError> {
    -        const BLOCKS_TIMELOCK_THRESHOLD: u32 = 500000000;
    -
    -        if (a < BLOCKS_TIMELOCK_THRESHOLD) != (b < BLOCKS_TIMELOCK_THRESHOLD) {
    -            Err(PolicyError::MixedTimelockUnits)
    -        } else {
    -            Ok(max(a, b))
    -        }
    -    }
    -
    -    fn merge(mut self, other: &Condition) -> Result<Self, PolicyError> {
    -        match (self.csv, other.csv) {
    -            (Some(a), Some(b)) => self.csv = Some(Self::merge_timelock(a, b)?),
    -            (None, any) => self.csv = any,
    -            _ => {}
    -        }
    -
    -        match (self.timelock, other.timelock) {
    -            (Some(a), Some(b)) => self.timelock = Some(Self::merge_timelock(a, b)?),
    -            (None, any) => self.timelock = any,
    -            _ => {}
    -        }
    -
    -        Ok(self)
    -    }
    -
    -    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)]
    -pub enum PolicyError {
    -    NotEnoughItemsSelected(String),
    -    TooManyItemsSelected(String),
    -    IndexOutOfRange(usize),
    -    AddOnLeaf,
    -    AddOnPartialComplete,
    -    MixedTimelockUnits,
    -    IncompatibleConditions,
    -}
    -
    -impl fmt::Display for PolicyError {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for PolicyError {}
    -
    -impl Policy {
    -    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(),
    -        };
    -        for (index, item) in items.iter().enumerate() {
    -            contribution.add(&item.contribution, index)?;
    -        }
    -        contribution.finalize()?;
    -
    -        let mut policy: Policy = SatisfiableItem::Thresh { items, threshold }.into();
    -        policy.contribution = contribution;
    -
    -        Ok(Some(policy))
    -    }
    -
    -    fn make_multisig(
    -        keys: &Vec<DescriptorPublicKey>,
    -        signers: Arc<SignersContainer<DescriptorPublicKey>>,
    -        threshold: usize,
    -    ) -> Result<Option<Policy>, PolicyError> {
    -        if threshold == 0 {
    -            return Ok(None);
    -        }
    -
    -        let parsed_keys = keys.iter().map(|k| PKOrF::from_key(k)).collect();
    -
    -        let mut contribution = Satisfaction::Partial {
    -            n: keys.len(),
    -            m: threshold,
    -            items: vec![],
    -            conditions: Default::default(),
    -        };
    -        for (index, key) in keys.iter().enumerate() {
    -            if let Some(_) = signers.find(signer_id(key)) {
    -                contribution.add(
    -                    &Satisfaction::Complete {
    -                        condition: Default::default(),
    -                    },
    -                    index,
    -                )?;
    -            }
    -        }
    -        contribution.finalize()?;
    -
    -        let mut policy: Policy = SatisfiableItem::Multisig {
    -            keys: parsed_keys,
    -            threshold,
    -        }
    -        .into();
    -        policy.contribution = contribution;
    -
    -        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).into_iter().collect()
    -            }
    -            _ => vec![],
    -        };
    -        let selected = match path.get(&self.id) {
    -            _ if !default.is_empty() => &default,
    -            Some(arr) => arr,
    -            _ => &default,
    -        };
    -
    -        match &self.item {
    -            SatisfiableItem::Thresh { items, threshold } => {
    -                let mapped_req = items
    -                    .iter()
    -                    .map(|i| i.get_condition(path))
    -                    .collect::<Result<Vec<_>, _>>()?;
    -
    -                // if all the requirements are null we don't care about `selected` because there
    -                // are no requirements
    -                if mapped_req.iter().all(Condition::is_null) {
    -                    return Ok(Condition::default());
    -                }
    -
    -                // 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()));
    -                } else if selected.len() > *threshold {
    -                    return Err(PolicyError::TooManyItemsSelected(self.id.clone()));
    -                }
    -
    -                // check the selected items, see if there are conflicting requirements
    -                let mut requirements = Condition::default();
    -                for item_index in selected {
    -                    requirements = requirements.merge(
    -                        mapped_req
    -                            .get(*item_index)
    -                            .ok_or(PolicyError::IndexOutOfRange(*item_index))?,
    -                    )?;
    -                }
    -
    -                Ok(requirements)
    -            }
    -            _ if !selected.is_empty() => Err(PolicyError::TooManyItemsSelected(self.id.clone())),
    -            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) -> SignerId<DescriptorPublicKey> {
    -    match key {
    -        DescriptorPublicKey::PubKey(pubkey) => pubkey.to_pubkeyhash().into(),
    -        DescriptorPublicKey::XPub(xpub) => xpub.root_fingerprint().into(),
    -    }
    -}
    -
    -fn signature(
    -    key: &DescriptorPublicKey,
    -    signers: Arc<SignersContainer<DescriptorPublicKey>>,
    -) -> Policy {
    -    let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key(key)).into();
    -
    -    policy.contribution = if signers.find(signer_id(key)).is_some() {
    -        Satisfaction::Complete {
    -            condition: Default::default(),
    -        }
    -    } else {
    -        Satisfaction::None
    -    };
    -
    -    policy
    -}
    -
    -fn signature_key(
    -    key_hash: &<DescriptorPublicKey as MiniscriptKey>::Hash,
    -    signers: Arc<SignersContainer<DescriptorPublicKey>>,
    -) -> Policy {
    -    let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key_hash(*key_hash)).into();
    -
    -    if let Some(_) = signers.find(SignerId::PkHash(*key_hash)) {
    -        policy.contribution = Satisfaction::Complete {
    -            condition: Default::default(),
    -        }
    -    }
    -
    -    policy
    -}
    -
    -impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx> {
    -    fn extract_policy(
    -        &self,
    -        signers: Arc<SignersContainer<DescriptorPublicKey>>,
    -    ) -> Result<Option<Policy>, Error> {
    -        Ok(match &self.node {
    -            // Leaves
    -            Terminal::True | Terminal::False => None,
    -            Terminal::PkK(pubkey) => Some(signature(pubkey, Arc::clone(&signers))),
    -            Terminal::PkH(pubkey_hash) => Some(signature_key(pubkey_hash, Arc::clone(&signers))),
    -            Terminal::After(value) => {
    -                let mut policy: Policy = SatisfiableItem::AbsoluteTimelock { value: *value }.into();
    -                policy.contribution = Satisfaction::Complete {
    -                    condition: Condition {
    -                        timelock: Some(*value),
    -                        csv: None,
    -                    },
    -                };
    -
    -                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),
    -                    },
    -                };
    -
    -                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) => Policy::make_multisig(pks, Arc::clone(&signers), *k)?,
    -            // 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(Arc::clone(&signers))?,
    -            // Complex policies
    -            Terminal::AndV(a, b) | Terminal::AndB(a, b) => Policy::make_and(
    -                a.extract_policy(Arc::clone(&signers))?,
    -                b.extract_policy(Arc::clone(&signers))?,
    -            )?,
    -            Terminal::AndOr(x, y, z) => Policy::make_or(
    -                Policy::make_and(
    -                    x.extract_policy(Arc::clone(&signers))?,
    -                    y.extract_policy(Arc::clone(&signers))?,
    -                )?,
    -                z.extract_policy(Arc::clone(&signers))?,
    -            )?,
    -            Terminal::OrB(a, b)
    -            | Terminal::OrD(a, b)
    -            | Terminal::OrC(a, b)
    -            | Terminal::OrI(a, b) => Policy::make_or(
    -                a.extract_policy(Arc::clone(&signers))?,
    -                b.extract_policy(Arc::clone(&signers))?,
    -            )?,
    -            Terminal::Thresh(k, nodes) => {
    -                let mut threshold = *k;
    -                let mapped: Vec<_> = nodes
    -                    .iter()
    -                    .map(|n| n.extract_policy(Arc::clone(&signers)))
    -                    .collect::<Result<Vec<_>, _>>()?
    -                    .into_iter()
    -                    .filter_map(|x| x)
    -                    .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)?
    -            }
    -        })
    -    }
    -}
    -
    -impl ExtractPolicy for Descriptor<DescriptorPublicKey> {
    -    fn extract_policy(
    -        &self,
    -        signers: Arc<SignersContainer<DescriptorPublicKey>>,
    -    ) -> Result<Option<Policy>, Error> {
    -        match self {
    -            Descriptor::Pk(pubkey)
    -            | Descriptor::Pkh(pubkey)
    -            | Descriptor::Wpkh(pubkey)
    -            | Descriptor::ShWpkh(pubkey) => Ok(Some(signature(pubkey, signers))),
    -            Descriptor::Bare(inner) | Descriptor::Sh(inner) => Ok(inner.extract_policy(signers)?),
    -            Descriptor::Wsh(inner) | Descriptor::ShWsh(inner) => Ok(inner.extract_policy(signers)?),
    -        }
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/error.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/error.rs.html deleted file mode 100644 index 930ba161c0..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/error.rs.html +++ /dev/null @@ -1,283 +0,0 @@ -error.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use std::fmt;
    -
    -use bitcoin::{Address, OutPoint};
    -
    -/// Errors that can be thrown by the [`Wallet`](crate::wallet::Wallet)
    -#[derive(Debug)]
    -pub enum Error {
    -    KeyMismatch(bitcoin::secp256k1::PublicKey, bitcoin::secp256k1::PublicKey),
    -    MissingInputUTXO(usize),
    -    InvalidU32Bytes(Vec<u8>),
    -    Generic(String),
    -    ScriptDoesntHaveAddressForm,
    -    SendAllMultipleOutputs,
    -    NoAddressees,
    -    OutputBelowDustLimit(usize),
    -    InsufficientFunds,
    -    InvalidAddressNetwork(Address),
    -    UnknownUTXO,
    -    DifferentTransactions,
    -    TransactionNotFound,
    -    TransactionConfirmed,
    -    IrreplaceableTransaction,
    -    FeeRateTooLow {
    -        required: crate::types::FeeRate,
    -    },
    -
    -    ChecksumMismatch,
    -    DifferentDescriptorStructure,
    -
    -    SpendingPolicyRequired,
    -    InvalidPolicyPathError(crate::descriptor::policy::PolicyError),
    -
    -    Signer(crate::wallet::signer::SignerError),
    -
    -    // Blockchain interface errors
    -    Uncapable(crate::blockchain::Capability),
    -    OfflineClient,
    -    InvalidProgressValue(f32),
    -    ProgressUpdateError,
    -    MissingCachedAddresses,
    -    InvalidOutpoint(OutPoint),
    -
    -    Descriptor(crate::descriptor::error::Error),
    -    AddressValidator(crate::wallet::address_validator::AddressValidatorError),
    -
    -    Encode(bitcoin::consensus::encode::Error),
    -    Miniscript(miniscript::Error),
    -    BIP32(bitcoin::util::bip32::Error),
    -    Secp256k1(bitcoin::secp256k1::Error),
    -    JSON(serde_json::Error),
    -    Hex(bitcoin::hashes::hex::Error),
    -    PSBT(bitcoin::util::psbt::Error),
    -
    -    #[cfg(feature = "electrum")]
    -    Electrum(electrum_client::Error),
    -    #[cfg(feature = "esplora")]
    -    Esplora(crate::blockchain::esplora::EsploraError),
    -    #[cfg(feature = "compact_filters")]
    -    CompactFilters(crate::blockchain::compact_filters::CompactFiltersError),
    -    #[cfg(feature = "key-value-db")]
    -    Sled(sled::Error),
    -}
    -
    -impl fmt::Display for Error {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for Error {}
    -
    -macro_rules! impl_error {
    -    ( $from:ty, $to:ident ) => {
    -        impl std::convert::From<$from> for Error {
    -            fn from(err: $from) -> Self {
    -                Error::$to(err)
    -            }
    -        }
    -    };
    -}
    -
    -impl_error!(crate::descriptor::error::Error, Descriptor);
    -impl_error!(
    -    crate::wallet::address_validator::AddressValidatorError,
    -    AddressValidator
    -);
    -impl_error!(
    -    crate::descriptor::policy::PolicyError,
    -    InvalidPolicyPathError
    -);
    -impl_error!(crate::wallet::signer::SignerError, Signer);
    -
    -impl_error!(bitcoin::consensus::encode::Error, Encode);
    -impl_error!(miniscript::Error, Miniscript);
    -impl_error!(bitcoin::util::bip32::Error, BIP32);
    -impl_error!(bitcoin::secp256k1::Error, Secp256k1);
    -impl_error!(serde_json::Error, JSON);
    -impl_error!(bitcoin::hashes::hex::Error, Hex);
    -impl_error!(bitcoin::util::psbt::Error, PSBT);
    -
    -#[cfg(feature = "electrum")]
    -impl_error!(electrum_client::Error, Electrum);
    -#[cfg(feature = "esplora")]
    -impl_error!(crate::blockchain::esplora::EsploraError, Esplora);
    -#[cfg(feature = "key-value-db")]
    -impl_error!(sled::Error, Sled);
    -
    -#[cfg(feature = "compact_filters")]
    -impl From<crate::blockchain::compact_filters::CompactFiltersError> for Error {
    -    fn from(other: crate::blockchain::compact_filters::CompactFiltersError) -> Self {
    -        match other {
    -            crate::blockchain::compact_filters::CompactFiltersError::Global(e) => *e,
    -            err @ _ => Error::CompactFilters(err),
    -        }
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/lib.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/lib.rs.html deleted file mode 100644 index 01356c108c..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/lib.rs.html +++ /dev/null @@ -1,179 +0,0 @@ -lib.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -// only enables the `doc_cfg` feature when
    -// the `docsrs` configuration attribute is defined
    -#![cfg_attr(docsrs, feature(doc_cfg))]
    -// only enables the nightly `external_doc` feature when
    -// `test-md-docs` is enabled
    -#![cfg_attr(feature = "test-md-docs", feature(external_doc))]
    -
    -pub extern crate bitcoin;
    -extern crate log;
    -pub extern crate miniscript;
    -extern crate serde;
    -#[macro_use]
    -extern crate serde_json;
    -
    -#[cfg(any(target_arch = "wasm32", feature = "async-interface"))]
    -#[macro_use]
    -extern crate async_trait;
    -#[macro_use]
    -extern crate bdk_macros;
    -
    -#[cfg(any(test, feature = "compact_filters"))]
    -#[macro_use]
    -extern crate lazy_static;
    -
    -#[cfg(feature = "electrum")]
    -pub extern crate electrum_client;
    -
    -#[cfg(feature = "esplora")]
    -pub extern crate reqwest;
    -
    -#[cfg(feature = "key-value-db")]
    -pub extern crate sled;
    -
    -#[cfg(feature = "cli-utils")]
    -pub mod cli;
    -
    -#[cfg(test)]
    -#[macro_use]
    -extern crate testutils;
    -#[cfg(test)]
    -#[macro_use]
    -extern crate testutils_macros;
    -#[cfg(test)]
    -#[macro_use]
    -extern crate serial_test;
    -
    -#[macro_use]
    -pub(crate) mod error;
    -pub mod blockchain;
    -pub mod database;
    -pub mod descriptor;
    -#[cfg(feature = "test-md-docs")]
    -mod doctest;
    -pub(crate) mod psbt;
    -pub(crate) mod types;
    -pub mod wallet;
    -
    -pub use descriptor::HDKeyPaths;
    -pub use error::Error;
    -pub use types::*;
    -pub use wallet::address_validator;
    -pub use wallet::signer;
    -pub use wallet::tx_builder::TxBuilder;
    -pub use wallet::{OfflineWallet, Wallet};
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/psbt/mod.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/psbt/mod.rs.html deleted file mode 100644 index cd35634064..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/psbt/mod.rs.html +++ /dev/null @@ -1,107 +0,0 @@ -mod.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
    -use bitcoin::TxOut;
    -
    -pub trait PSBTUtils {
    -    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut>;
    -}
    -
    -impl PSBTUtils for PSBT {
    -    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut> {
    -        let tx = &self.global.unsigned_tx;
    -
    -        if input_index >= tx.input.len() {
    -            return None;
    -        }
    -
    -        if let Some(input) = self.inputs.get(input_index) {
    -            if let Some(wit_utxo) = &input.witness_utxo {
    -                Some(wit_utxo.clone())
    -            } else if let Some(in_tx) = &input.non_witness_utxo {
    -                Some(in_tx.output[tx.input[input_index].previous_output.vout as usize].clone())
    -            } else {
    -                None
    -            }
    -        } else {
    -            None
    -        }
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/types.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/types.rs.html deleted file mode 100644 index 8fe99a773d..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/types.rs.html +++ /dev/null @@ -1,227 +0,0 @@ -types.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use std::convert::AsRef;
    -
    -use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxOut};
    -use bitcoin::hash_types::Txid;
    -
    -use serde::{Deserialize, Serialize};
    -
    -/// Types of script
    -#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
    -pub enum ScriptType {
    -    External = 0,
    -    Internal = 1,
    -}
    -
    -impl ScriptType {
    -    pub fn as_byte(&self) -> u8 {
    -        match self {
    -            ScriptType::External => 'e' as u8,
    -            ScriptType::Internal => 'i' as u8,
    -        }
    -    }
    -
    -    pub fn is_internal(&self) -> bool {
    -        self == &ScriptType::Internal
    -    }
    -}
    -
    -impl AsRef<[u8]> for ScriptType {
    -    fn as_ref(&self) -> &[u8] {
    -        match self {
    -            ScriptType::External => b"e",
    -            ScriptType::Internal => b"i",
    -        }
    -    }
    -}
    -
    -/// Fee rate
    -#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
    -// Internally stored as satoshi/vbyte
    -pub struct FeeRate(f32);
    -
    -impl FeeRate {
    -    /// Create a new instance of [`FeeRate`] given a float fee rate in btc/kvbytes
    -    pub fn from_btc_per_kvb(btc_per_kvb: f32) -> Self {
    -        FeeRate(btc_per_kvb * 1e5)
    -    }
    -
    -    /// Create a new instance of [`FeeRate`] given a float fee rate in satoshi/vbyte
    -    pub fn from_sat_per_vb(sat_per_vb: f32) -> Self {
    -        FeeRate(sat_per_vb)
    -    }
    -
    -    /// Create a new [`FeeRate`] with the default min relay fee value
    -    pub fn default_min_relay_fee() -> Self {
    -        FeeRate(1.0)
    -    }
    -
    -    /// Return the value as satoshi/vbyte
    -    pub fn as_sat_vb(&self) -> f32 {
    -        self.0
    -    }
    -}
    -
    -impl std::default::Default for FeeRate {
    -    fn default() -> Self {
    -        FeeRate::default_min_relay_fee()
    -    }
    -}
    -
    -/// A wallet unspent output
    -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
    -pub struct UTXO {
    -    pub outpoint: OutPoint,
    -    pub txout: TxOut,
    -    pub is_internal: bool,
    -}
    -
    -/// A wallet transaction
    -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
    -pub struct TransactionDetails {
    -    pub transaction: Option<Transaction>,
    -    pub txid: Txid,
    -    pub timestamp: u64,
    -    pub received: u64,
    -    pub sent: u64,
    -    pub fees: u64,
    -    pub height: Option<u32>,
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/address_validator.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/address_validator.rs.html deleted file mode 100644 index c674ae642a..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/address_validator.rs.html +++ /dev/null @@ -1,327 +0,0 @@ -address_validator.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Address validation callbacks
    -//!
    -//! The typical usage of those callbacks is for displaying the newly-generated address on a
    -//! hardware wallet, so that the user can cross-check its correctness.
    -//!
    -//! More generally speaking though, these callbacks can also be used to "do something" every time
    -//! an address is generated, without necessarily checking or validating it.
    -//!
    -//! An address validator can be attached to a [`Wallet`](super::Wallet) by using the
    -//! [`Wallet::add_address_validator`](super::Wallet::add_address_validator) method, and
    -//! whenever a new address is generated (either explicitly by the user with
    -//! [`Wallet::get_new_address`](super::Wallet::get_new_address) or internally to create a change
    -//! address) all the attached validators will be polled, in sequence. All of them must complete
    -//! successfully to continue.
    -//!
    -//! ## Example
    -//!
    -//! ```
    -//! # use std::sync::Arc;
    -//! # use bitcoin::*;
    -//! # use bdk::address_validator::*;
    -//! # use bdk::database::*;
    -//! # use bdk::*;
    -//! struct PrintAddressAndContinue;
    -//!
    -//! impl AddressValidator for PrintAddressAndContinue {
    -//!     fn validate(
    -//!         &self,
    -//!         script_type: ScriptType,
    -//!         hd_keypaths: &HDKeyPaths,
    -//!         script: &Script
    -//!     ) -> Result<(), AddressValidatorError> {
    -//!         let address = Address::from_script(script, Network::Testnet)
    -//!             .as_ref()
    -//!             .map(Address::to_string)
    -//!             .unwrap_or(script.to_string());
    -//!         println!("New address of type {:?}: {}", script_type, address);
    -//!         println!("HD keypaths: {:#?}", hd_keypaths);
    -//!
    -//!         Ok(())
    -//!     }
    -//! }
    -//!
    -//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -//! let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -//! wallet.add_address_validator(Arc::new(Box::new(PrintAddressAndContinue)));
    -//!
    -//! let address = wallet.get_new_address()?;
    -//! println!("Address: {}", address);
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use std::fmt;
    -
    -use bitcoin::Script;
    -
    -use crate::descriptor::HDKeyPaths;
    -use crate::types::ScriptType;
    -
    -/// Errors that can be returned to fail the validation of an address
    -#[derive(Debug, Clone, PartialEq, Eq)]
    -pub enum AddressValidatorError {
    -    UserRejected,
    -    ConnectionError,
    -    TimeoutError,
    -    InvalidScript,
    -    Message(String),
    -}
    -
    -impl fmt::Display for AddressValidatorError {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for AddressValidatorError {}
    -
    -/// Trait to build address validators
    -///
    -/// All the address validators attached to a wallet with [`Wallet::add_address_validator`](super::Wallet::add_address_validator) will be polled
    -/// every time an address (external or internal) is generated by the wallet. Errors returned in the
    -/// validator will be propagated up to the original caller that triggered the address generation.
    -///
    -/// For a usage example see [this module](crate::address_validator)'s documentation.
    -pub trait AddressValidator {
    -    /// Validate or inspect an address
    -    fn validate(
    -        &self,
    -        script_type: ScriptType,
    -        hd_keypaths: &HDKeyPaths,
    -        script: &Script,
    -    ) -> Result<(), AddressValidatorError>;
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::sync::Arc;
    -
    -    use super::*;
    -    use crate::wallet::test::{get_funded_wallet, get_test_wpkh};
    -    use crate::wallet::TxBuilder;
    -
    -    struct TestValidator;
    -    impl AddressValidator for TestValidator {
    -        fn validate(
    -            &self,
    -            _script_type: ScriptType,
    -            _hd_keypaths: &HDKeyPaths,
    -            _script: &bitcoin::Script,
    -        ) -> Result<(), AddressValidatorError> {
    -            Err(AddressValidatorError::InvalidScript)
    -        }
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InvalidScript")]
    -    fn test_address_validator_external() {
    -        let (mut wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        wallet.add_address_validator(Arc::new(Box::new(TestValidator)));
    -
    -        wallet.get_new_address().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InvalidScript")]
    -    fn test_address_validator_internal() {
    -        let (mut wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        wallet.add_address_validator(Arc::new(Box::new(TestValidator)));
    -
    -        let addr = testutils!(@external descriptors, 10);
    -        wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/coin_selection.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/coin_selection.rs.html deleted file mode 100644 index f795967e71..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/coin_selection.rs.html +++ /dev/null @@ -1,701 +0,0 @@ -coin_selection.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Coin selection
    -//!
    -//! This module provides the trait [`CoinSelectionAlgorithm`] that can be implemented to
    -//! define custom coin selection algorithms.
    -//!
    -//! The coin selection algorithm is not globally part of a [`Wallet`](super::Wallet), instead it
    -//! is selected whenever a [`Wallet::create_tx`](super::Wallet::create_tx) call is made, through
    -//! the use of the [`TxBuilder`] structure, specifically with
    -//! [`TxBuilder::coin_selection`](super::tx_builder::TxBuilder::coin_selection) method.
    -//!
    -//! The [`DefaultCoinSelectionAlgorithm`] selects the default coin selection algorithm that
    -//! [`TxBuilder`] uses, if it's not explicitly overridden.
    -//!
    -//! [`TxBuilder`]: super::tx_builder::TxBuilder
    -//!
    -//! ## Example
    -//!
    -//! ```no_run
    -//! # use std::str::FromStr;
    -//! # use bitcoin::*;
    -//! # use bitcoin::consensus::serialize;
    -//! # use bdk::wallet::coin_selection::*;
    -//! # use bdk::*;
    -//! #[derive(Debug)]
    -//! struct AlwaysSpendEverything;
    -//!
    -//! impl CoinSelectionAlgorithm for AlwaysSpendEverything {
    -//!     fn coin_select(
    -//!         &self,
    -//!         utxos: Vec<UTXO>,
    -//!         _use_all_utxos: bool,
    -//!         fee_rate: FeeRate,
    -//!         amount_needed: u64,
    -//!         input_witness_weight: usize,
    -//!         fee_amount: f32,
    -//!     ) -> Result<CoinSelectionResult, bdk::Error> {
    -//!         let selected_amount = utxos.iter().fold(0, |acc, utxo| acc + utxo.txout.value);
    -//!         let all_utxos_selected = utxos
    -//!             .into_iter()
    -//!             .map(|utxo| {
    -//!                 (
    -//!                     TxIn {
    -//!                         previous_output: utxo.outpoint,
    -//!                         ..Default::default()
    -//!                     },
    -//!                     utxo.txout.script_pubkey,
    -//!                 )
    -//!             })
    -//!             .collect::<Vec<_>>();
    -//!         let additional_weight = all_utxos_selected.iter().fold(0, |acc, (txin, _)| {
    -//!             acc + serialize(txin).len() * 4 + input_witness_weight
    -//!         });
    -//!         let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0;
    -//!
    -//!         if (fee_amount + additional_fees).ceil() as u64 + amount_needed > selected_amount {
    -//!             return Err(bdk::Error::InsufficientFunds);
    -//!         }
    -//!
    -//!         Ok(CoinSelectionResult {
    -//!             txin: all_utxos_selected,
    -//!             selected_amount,
    -//!             fee_amount: fee_amount + additional_fees,
    -//!         })
    -//!     }
    -//! }
    -//!
    -//! # let wallet: OfflineWallet<_> = Wallet::new_offline("", None, Network::Testnet, bdk::database::MemoryDatabase::default())?;
    -//! // create wallet, sync, ...
    -//!
    -//! let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -//! let (psbt, details) = wallet.create_tx(
    -//!     TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
    -//!         .coin_selection(AlwaysSpendEverything),
    -//! )?;
    -//!
    -//! // inspect, sign, broadcast, ...
    -//!
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use bitcoin::consensus::encode::serialize;
    -use bitcoin::{Script, TxIn};
    -
    -use crate::error::Error;
    -use crate::types::{FeeRate, UTXO};
    -
    -/// Default coin selection algorithm used by [`TxBuilder`](super::tx_builder::TxBuilder) if not
    -/// overridden
    -pub type DefaultCoinSelectionAlgorithm = DumbCoinSelection;
    -
    -/// Result of a successful coin selection
    -#[derive(Debug)]
    -pub struct CoinSelectionResult {
    -    /// List of inputs to use, with the respective previous script_pubkey
    -    pub txin: Vec<(TxIn, Script)>,
    -    /// Sum of the selected inputs' value
    -    pub selected_amount: u64,
    -    /// Total fee amount in satoshi
    -    pub fee_amount: f32,
    -}
    -
    -/// 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: std::fmt::Debug {
    -    /// Perform the coin selection
    -    ///
    -    /// - `utxos`: the list of spendable UTXOs
    -    /// - `use_all_utxos`: if true all utxos should be spent unconditionally
    -    /// - `fee_rate`: fee rate to use
    -    /// - `amount_needed`: the amount in satoshi to select
    -    /// - `input_witness_weight`: the weight of an input's witness to keep into account for the fees
    -    /// - `fee_amount`: the amount of fees in satoshi already accumulated from adding outputs
    -    fn coin_select(
    -        &self,
    -        utxos: Vec<UTXO>,
    -        use_all_utxos: bool,
    -        fee_rate: FeeRate,
    -        amount_needed: u64,
    -        input_witness_weight: usize,
    -        fee_amount: f32,
    -    ) -> 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)]
    -pub struct DumbCoinSelection;
    -
    -impl CoinSelectionAlgorithm for DumbCoinSelection {
    -    fn coin_select(
    -        &self,
    -        mut utxos: Vec<UTXO>,
    -        use_all_utxos: bool,
    -        fee_rate: FeeRate,
    -        outgoing_amount: u64,
    -        input_witness_weight: usize,
    -        mut fee_amount: f32,
    -    ) -> Result<CoinSelectionResult, Error> {
    -        let mut txin = Vec::new();
    -        let calc_fee_bytes = |wu| (wu as f32) * fee_rate.as_sat_vb() / 4.0;
    -
    -        log::debug!(
    -            "outgoing_amount = `{}`, fee_amount = `{}`, fee_rate = `{:?}`",
    -            outgoing_amount,
    -            fee_amount,
    -            fee_rate
    -        );
    -
    -        // sort so that we pick them starting from the larger.
    -        utxos.sort_by(|a, b| a.txout.value.partial_cmp(&b.txout.value).unwrap());
    -
    -        let mut selected_amount: u64 = 0;
    -        while use_all_utxos || selected_amount < outgoing_amount + (fee_amount.ceil() as u64) {
    -            let utxo = match utxos.pop() {
    -                Some(utxo) => utxo,
    -                None if selected_amount < outgoing_amount + (fee_amount.ceil() as u64) => {
    -                    return Err(Error::InsufficientFunds)
    -                }
    -                None if use_all_utxos => break,
    -                None => return Err(Error::InsufficientFunds),
    -            };
    -
    -            let new_in = TxIn {
    -                previous_output: utxo.outpoint,
    -                script_sig: Script::default(),
    -                sequence: 0, // Let the caller choose the right nSequence
    -                witness: vec![],
    -            };
    -            fee_amount += calc_fee_bytes(serialize(&new_in).len() * 4 + input_witness_weight);
    -            log::debug!(
    -                "Selected {}, updated fee_amount = `{}`",
    -                new_in.previous_output,
    -                fee_amount
    -            );
    -
    -            txin.push((new_in, utxo.txout.script_pubkey));
    -            selected_amount += utxo.txout.value;
    -        }
    -
    -        Ok(CoinSelectionResult {
    -            txin,
    -            fee_amount,
    -            selected_amount,
    -        })
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::str::FromStr;
    -
    -    use bitcoin::{OutPoint, Script, TxOut};
    -
    -    use super::*;
    -    use crate::types::*;
    -
    -    const P2WPKH_WITNESS_SIZE: usize = 73 + 33 + 2;
    -
    -    fn get_test_utxos() -> Vec<UTXO> {
    -        vec![
    -            UTXO {
    -                outpoint: OutPoint::from_str(
    -                    "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:0",
    -                )
    -                .unwrap(),
    -                txout: TxOut {
    -                    value: 100_000,
    -                    script_pubkey: Script::new(),
    -                },
    -                is_internal: false,
    -            },
    -            UTXO {
    -                outpoint: OutPoint::from_str(
    -                    "65d92ddff6b6dc72c89624a6491997714b90f6004f928d875bc0fd53f264fa85:0",
    -                )
    -                .unwrap(),
    -                txout: TxOut {
    -                    value: 200_000,
    -                    script_pubkey: Script::new(),
    -                },
    -                is_internal: true,
    -            },
    -        ]
    -    }
    -
    -    #[test]
    -    fn test_dumb_coin_selection_success() {
    -        let utxos = get_test_utxos();
    -
    -        let result = DumbCoinSelection
    -            .coin_select(
    -                utxos,
    -                false,
    -                FeeRate::from_sat_per_vb(1.0),
    -                250_000,
    -                P2WPKH_WITNESS_SIZE,
    -                50.0,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.txin.len(), 2);
    -        assert_eq!(result.selected_amount, 300_000);
    -        assert_eq!(result.fee_amount, 186.0);
    -    }
    -
    -    #[test]
    -    fn test_dumb_coin_selection_use_all() {
    -        let utxos = get_test_utxos();
    -
    -        let result = DumbCoinSelection
    -            .coin_select(
    -                utxos,
    -                true,
    -                FeeRate::from_sat_per_vb(1.0),
    -                20_000,
    -                P2WPKH_WITNESS_SIZE,
    -                50.0,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.txin.len(), 2);
    -        assert_eq!(result.selected_amount, 300_000);
    -        assert_eq!(result.fee_amount, 186.0);
    -    }
    -
    -    #[test]
    -    fn test_dumb_coin_selection_use_only_necessary() {
    -        let utxos = get_test_utxos();
    -
    -        let result = DumbCoinSelection
    -            .coin_select(
    -                utxos,
    -                false,
    -                FeeRate::from_sat_per_vb(1.0),
    -                20_000,
    -                P2WPKH_WITNESS_SIZE,
    -                50.0,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.txin.len(), 1);
    -        assert_eq!(result.selected_amount, 200_000);
    -        assert_eq!(result.fee_amount, 118.0);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_dumb_coin_selection_insufficient_funds() {
    -        let utxos = get_test_utxos();
    -
    -        DumbCoinSelection
    -            .coin_select(
    -                utxos,
    -                false,
    -                FeeRate::from_sat_per_vb(1.0),
    -                500_000,
    -                P2WPKH_WITNESS_SIZE,
    -                50.0,
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_dumb_coin_selection_insufficient_funds_high_fees() {
    -        let utxos = get_test_utxos();
    -
    -        DumbCoinSelection
    -            .coin_select(
    -                utxos,
    -                false,
    -                FeeRate::from_sat_per_vb(1000.0),
    -                250_000,
    -                P2WPKH_WITNESS_SIZE,
    -                50.0,
    -            )
    -            .unwrap();
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/export.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/export.rs.html deleted file mode 100644 index eae5ac9953..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/export.rs.html +++ /dev/null @@ -1,683 +0,0 @@ -export.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! 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::database::*;
    -//! # use bdk::wallet::export::*;
    -//! # use bdk::*;
    -//! let import = r#"{
    -//!     "descriptor": "wpkh([c258d2e4\/84h\/1h\/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe\/0\/*)",
    -//!     "blockheight":1782088,
    -//!     "label":"testnet"
    -//! }"#;
    -//!
    -//! let import = WalletExport::from_str(import)?;
    -//! let wallet: OfflineWallet<_> = Wallet::new_offline(&import.descriptor(), import.change_descriptor().as_deref(), Network::Testnet, MemoryDatabase::default())?;
    -//! # Ok::<_, bdk::Error>(())
    -//! ```
    -//!
    -//! ### Export a `Wallet`
    -//! ```
    -//! # use bitcoin::*;
    -//! # use bdk::database::*;
    -//! # use bdk::wallet::export::*;
    -//! # use bdk::*;
    -//! let wallet: OfflineWallet<_> = Wallet::new_offline(
    -//!     "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
    -//!     Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
    -//!     Network::Testnet,
    -//!     MemoryDatabase::default()
    -//! )?;
    -//! let export = WalletExport::export_wallet(&wallet, "exported wallet", true)
    -//!     .map_err(ToString::to_string)
    -//!     .map_err(bdk::Error::Generic)?;
    -//!
    -//! println!("Exported: {}", export.to_string());
    -//! # Ok::<_, bdk::Error>(())
    -//! ```
    -
    -use std::str::FromStr;
    -
    -use serde::{Deserialize, Serialize};
    -
    -use miniscript::{Descriptor, ScriptContext, Terminal};
    -
    -use crate::blockchain::BlockchainMarker;
    -use crate::database::BatchDatabase;
    -use crate::wallet::Wallet;
    -
    -/// 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 WalletExport {
    -    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 ToString for WalletExport {
    -    fn to_string(&self) -> String {
    -        serde_json::to_string(self).unwrap()
    -    }
    -}
    -
    -impl FromStr for WalletExport {
    -    type Err = serde_json::Error;
    -
    -    fn from_str(s: &str) -> Result<Self, Self::Err> {
    -        serde_json::from_str(s)
    -    }
    -}
    -
    -impl WalletExport {
    -    /// 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<B: BlockchainMarker, D: BatchDatabase>(
    -        wallet: &Wallet<B, D>,
    -        label: &str,
    -        include_blockheight: bool,
    -    ) -> Result<Self, &'static str> {
    -        let descriptor = wallet
    -            .descriptor
    -            .to_string_with_secret(&wallet.signers.as_key_map());
    -        Self::is_compatible_with_core(&descriptor)?;
    -
    -        let blockheight = match wallet.database.borrow().iter_txs(false) {
    -            _ if !include_blockheight => 0,
    -            Err(_) => 0,
    -            Ok(txs) => {
    -                let mut heights = txs
    -                    .into_iter()
    -                    .map(|tx| tx.height.unwrap_or(0))
    -                    .collect::<Vec<_>>();
    -                heights.sort();
    -
    -                *heights.last().unwrap_or(&0)
    -            }
    -        };
    -
    -        let export = WalletExport {
    -            descriptor,
    -            label: label.into(),
    -            blockheight,
    -        };
    -
    -        if export.change_descriptor()
    -            != wallet
    -                .change_descriptor
    -                .as_ref()
    -                .map(|d| d.to_string_with_secret(&wallet.change_signers.as_key_map()))
    -        {
    -            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")
    -            }
    -        }
    -
    -        match Descriptor::<String>::from_str(descriptor).map_err(|_| "Invalid descriptor")? {
    -            Descriptor::Pk(_)
    -            | Descriptor::Pkh(_)
    -            | Descriptor::Wpkh(_)
    -            | Descriptor::ShWpkh(_) => Ok(()),
    -            Descriptor::Sh(ms) => check_ms(ms.node),
    -            Descriptor::Wsh(ms) | Descriptor::ShWsh(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 std::str::FromStr;
    -
    -    use bitcoin::{Network, Txid};
    -
    -    use super::*;
    -    use crate::database::{memory::MemoryDatabase, BatchOperations};
    -    use crate::types::TransactionDetails;
    -    use crate::wallet::{OfflineWallet, Wallet};
    -
    -    fn get_test_db() -> MemoryDatabase {
    -        let mut db = MemoryDatabase::new();
    -        db.set_tx(&TransactionDetails {
    -            transaction: None,
    -            txid: Txid::from_str(
    -                "4ddff1fa33af17f377f62b72357b43107c19110a8009b36fb832af505efed98a",
    -            )
    -            .unwrap(),
    -            timestamp: 12345678,
    -            received: 100_000,
    -            sent: 0,
    -            fees: 500,
    -            height: Some(5000),
    -        })
    -        .unwrap();
    -
    -        db
    -    }
    -
    -    #[test]
    -    fn test_export_bip44() {
    -        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
    -        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
    -
    -        let wallet: OfflineWallet<_> = Wallet::new_offline(
    -            descriptor,
    -            Some(change_descriptor),
    -            Network::Testnet,
    -            get_test_db(),
    -        )
    -        .unwrap();
    -        let export = WalletExport::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: OfflineWallet<_> =
    -            Wallet::new_offline(descriptor, None, Network::Testnet, get_test_db()).unwrap();
    -        WalletExport::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: OfflineWallet<_> = Wallet::new_offline(
    -            descriptor,
    -            Some(change_descriptor),
    -            Network::Testnet,
    -            get_test_db(),
    -        )
    -        .unwrap();
    -        WalletExport::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: OfflineWallet<_> = Wallet::new_offline(
    -            descriptor,
    -            Some(change_descriptor),
    -            Network::Testnet,
    -            get_test_db(),
    -        )
    -        .unwrap();
    -        let export = WalletExport::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: OfflineWallet<_> = Wallet::new_offline(
    -            descriptor,
    -            Some(change_descriptor),
    -            Network::Testnet,
    -            get_test_db(),
    -        )
    -        .unwrap();
    -        let export = WalletExport::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 = WalletExport::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/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/mod.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/mod.rs.html deleted file mode 100644 index 46a90673f2..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/mod.rs.html +++ /dev/null @@ -1,4881 +0,0 @@ -mod.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Wallet
    -//!
    -//! This module defines the [`Wallet`] structure.
    -
    -use std::cell::RefCell;
    -use std::collections::HashMap;
    -use std::collections::{BTreeMap, HashSet};
    -use std::ops::{Deref, DerefMut};
    -use std::sync::Arc;
    -
    -use bitcoin::consensus::encode::serialize;
    -use bitcoin::util::bip32::ChildNumber;
    -use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
    -use bitcoin::{Address, Network, OutPoint, Script, SigHashType, Transaction, TxOut, Txid};
    -
    -use miniscript::descriptor::DescriptorPublicKey;
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -pub mod address_validator;
    -pub mod coin_selection;
    -pub mod export;
    -mod rbf;
    -pub mod signer;
    -pub mod time;
    -pub mod tx_builder;
    -pub(crate) mod utils;
    -
    -pub use utils::IsDust;
    -
    -use address_validator::AddressValidator;
    -use signer::{Signer, SignerId, SignerOrdering, SignersContainer};
    -use tx_builder::TxBuilder;
    -use utils::{After, Older};
    -
    -use crate::blockchain::{Blockchain, BlockchainMarker, OfflineBlockchain, Progress};
    -use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
    -use crate::descriptor::{
    -    get_checksum, DescriptorMeta, DescriptorScripts, ExtendedDescriptor, ExtractPolicy, Policy,
    -};
    -use crate::error::Error;
    -use crate::psbt::PSBTUtils;
    -use crate::types::*;
    -
    -const CACHE_ADDR_BATCH_SIZE: u32 = 100;
    -
    -/// Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]
    -pub type OfflineWallet<D> = Wallet<OfflineBlockchain, D>;
    -
    -/// A Bitcoin wallet
    -///
    -/// A wallet takes descriptors, a [`database`](crate::database) and a
    -/// [`blockchain`](crate::blockchain) and implements the basic functions that a Bitcoin wallets
    -/// needs to operate, like [generating addresses](Wallet::get_new_address), [returning the balance](Wallet::get_balance),
    -/// [creating transactions](Wallet::create_tx), etc.
    -///
    -/// A wallet can be either "online" if the [`blockchain`](crate::blockchain) type provided
    -/// implements [`Blockchain`], or "offline" [`OfflineBlockchain`] is used. Offline wallets only expose
    -/// methods that don't need any interaction with the blockchain to work.
    -pub struct Wallet<B: BlockchainMarker, D: BatchDatabase> {
    -    descriptor: ExtendedDescriptor,
    -    change_descriptor: Option<ExtendedDescriptor>,
    -
    -    signers: Arc<SignersContainer<DescriptorPublicKey>>,
    -    change_signers: Arc<SignersContainer<DescriptorPublicKey>>,
    -
    -    address_validators: Vec<Arc<Box<dyn AddressValidator>>>,
    -
    -    network: Network,
    -
    -    current_height: Option<u32>,
    -
    -    client: Option<B>,
    -    database: RefCell<D>,
    -}
    -
    -// offline actions, always available
    -impl<B, D> Wallet<B, D>
    -where
    -    B: BlockchainMarker,
    -    D: BatchDatabase,
    -{
    -    /// Create a new "offline" wallet
    -    pub fn new_offline(
    -        descriptor: &str,
    -        change_descriptor: Option<&str>,
    -        network: Network,
    -        mut database: D,
    -    ) -> Result<Self, Error> {
    -        database.check_descriptor_checksum(
    -            ScriptType::External,
    -            get_checksum(descriptor)?.as_bytes(),
    -        )?;
    -        let (descriptor, keymap) = ExtendedDescriptor::parse_secret(descriptor)?;
    -        let signers = Arc::new(SignersContainer::from(keymap));
    -        let (change_descriptor, change_signers) = match change_descriptor {
    -            Some(desc) => {
    -                database.check_descriptor_checksum(
    -                    ScriptType::Internal,
    -                    get_checksum(desc)?.as_bytes(),
    -                )?;
    -
    -                let (change_descriptor, change_keymap) = ExtendedDescriptor::parse_secret(desc)?;
    -                let change_signers = Arc::new(SignersContainer::from(change_keymap));
    -                // if !parsed.same_structure(descriptor.as_ref()) {
    -                //     return Err(Error::DifferentDescriptorStructure);
    -                // }
    -
    -                (Some(change_descriptor), change_signers)
    -            }
    -            None => (None, Arc::new(SignersContainer::new())),
    -        };
    -
    -        Ok(Wallet {
    -            descriptor,
    -            change_descriptor,
    -            signers,
    -            change_signers,
    -            address_validators: Vec::new(),
    -
    -            network,
    -
    -            current_height: None,
    -
    -            client: None,
    -            database: RefCell::new(database),
    -        })
    -    }
    -
    -    /// Return a newly generated address using the external descriptor
    -    pub fn get_new_address(&self) -> Result<Address, Error> {
    -        let index = self.fetch_and_increment_index(ScriptType::External)?;
    -
    -        self.descriptor
    -            .derive(&[ChildNumber::from_normal_idx(index).unwrap()])
    -            .address(self.network)
    -            .ok_or(Error::ScriptDoesntHaveAddressForm)
    -    }
    -
    -    /// Return whether or not a `script` is part of this wallet (either internal or external)
    -    pub fn is_mine(&self, script: &Script) -> Result<bool, Error> {
    -        self.database.borrow().is_mine(script)
    -    }
    -
    -    /// Return the list of unspent outputs of this wallet
    -    ///
    -    /// Note that this methods only operate on the internal database, which first needs to be
    -    /// [`Wallet::sync`] manually.
    -    pub fn list_unspent(&self) -> Result<Vec<UTXO>, Error> {
    -        self.database.borrow().iter_utxos()
    -    }
    -
    -    /// Return the list of transactions made and received by the wallet
    -    ///
    -    /// Optionally fill the [`TransactionDetails::transaction`] field with the raw transaction if
    -    /// `include_raw` is `true`.
    -    ///
    -    /// Note that this methods only operate on the internal database, which first needs to be
    -    /// [`Wallet::sync`] manually.
    -    pub fn list_transactions(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        self.database.borrow().iter_txs(include_raw)
    -    }
    -
    -    /// Return the balance, meaning the sum of this wallet's unspent outputs' values
    -    ///
    -    /// Note that this methods only operate on the internal database, which first needs to be
    -    /// [`Wallet::sync`] manually.
    -    pub fn get_balance(&self) -> Result<u64, Error> {
    -        Ok(self
    -            .list_unspent()?
    -            .iter()
    -            .fold(0, |sum, i| sum + i.txout.value))
    -    }
    -
    -    /// Add an external signer
    -    ///
    -    /// See [the `signer` module](signer) for an example.
    -    pub fn add_signer(
    -        &mut self,
    -        script_type: ScriptType,
    -        id: SignerId<DescriptorPublicKey>,
    -        ordering: SignerOrdering,
    -        signer: Arc<Box<dyn Signer>>,
    -    ) {
    -        let signers = match script_type {
    -            ScriptType::External => Arc::make_mut(&mut self.signers),
    -            ScriptType::Internal => Arc::make_mut(&mut self.change_signers),
    -        };
    -
    -        signers.add_external(id, ordering, signer);
    -    }
    -
    -    /// Add an address validator
    -    ///
    -    /// See [the `address_validator` module](address_validator) for an example.
    -    pub fn add_address_validator(&mut self, validator: Arc<Box<dyn AddressValidator>>) {
    -        self.address_validators.push(validator);
    -    }
    -
    -    /// Create a new transaction following the options specified in the `builder`
    -    ///
    -    /// ## Example
    -    ///
    -    /// ```no_run
    -    /// # use std::str::FromStr;
    -    /// # use bitcoin::*;
    -    /// # use bdk::*;
    -    /// # use bdk::database::*;
    -    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -    /// let (psbt, details) = wallet.create_tx(
    -    ///     TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
    -    /// )?;
    -    /// // sign and broadcast ...
    -    /// # Ok::<(), bdk::Error>(())
    -    /// ```
    -    pub fn create_tx<Cs: coin_selection::CoinSelectionAlgorithm>(
    -        &self,
    -        builder: TxBuilder<Cs>,
    -    ) -> Result<(PSBT, TransactionDetails), Error> {
    -        if builder.recipients.is_empty() {
    -            return Err(Error::NoAddressees);
    -        }
    -
    -        // TODO: fetch both internal and external policies
    -        let policy = self
    -            .descriptor
    -            .extract_policy(Arc::clone(&self.signers))?
    -            .unwrap();
    -        if policy.requires_path() && builder.policy_path.is_none() {
    -            return Err(Error::SpendingPolicyRequired);
    -        }
    -        let requirements =
    -            policy.get_condition(builder.policy_path.as_ref().unwrap_or(&BTreeMap::new()))?;
    -        debug!("requirements: {:?}", requirements);
    -
    -        let version = match builder.version {
    -            Some(tx_builder::Version(0)) => {
    -                return Err(Error::Generic("Invalid version `0`".into()))
    -            }
    -            Some(tx_builder::Version(1)) if requirements.csv.is_some() => {
    -                return Err(Error::Generic(
    -                    "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
    -                        .into(),
    -                ))
    -            }
    -            Some(tx_builder::Version(x)) => x,
    -            None if requirements.csv.is_some() => 2,
    -            _ => 1,
    -        };
    -
    -        let lock_time = match builder.locktime {
    -            None => requirements.timelock.unwrap_or(0),
    -            Some(x) if requirements.timelock.is_none() => x,
    -            Some(x) if requirements.timelock.unwrap() <= x => x,
    -            Some(x) => return Err(Error::Generic(format!("TxBuilder requested timelock of `{}`, but at least `{}` is required to spend from this script", x, requirements.timelock.unwrap())))
    -        };
    -
    -        let n_sequence = match (builder.rbf, requirements.csv) {
    -            (None, Some(csv)) => csv,
    -            (Some(rbf), Some(csv)) if rbf < csv => return Err(Error::Generic(format!("Cannot enable RBF with nSequence `{}`, since at least `{}` is required to spend with OP_CSV", rbf, csv))),
    -            (None, _) if requirements.timelock.is_some() => 0xFFFFFFFE,
    -            (Some(rbf), _) if rbf >= 0xFFFFFFFE => return Err(Error::Generic("Cannot enable RBF with a nSequence >= 0xFFFFFFFE".into())),
    -            (Some(rbf), _) => rbf,
    -            (None, _) => 0xFFFFFFFF,
    -        };
    -
    -        let mut tx = Transaction {
    -            version,
    -            lock_time,
    -            input: vec![],
    -            output: vec![],
    -        };
    -
    -        let fee_rate = builder.fee_rate.unwrap_or_default();
    -        if builder.send_all && builder.recipients.len() != 1 {
    -            return Err(Error::SendAllMultipleOutputs);
    -        }
    -
    -        // we keep it as a float while we accumulate it, and only round it at the end
    -        let mut fee_amount: f32 = 0.0;
    -        let mut outgoing: u64 = 0;
    -        let mut received: u64 = 0;
    -
    -        let calc_fee_bytes = |wu| (wu as f32) * fee_rate.as_sat_vb() / 4.0;
    -        fee_amount += calc_fee_bytes(tx.get_weight());
    -
    -        for (index, (script_pubkey, satoshi)) in builder.recipients.iter().enumerate() {
    -            let value = match builder.send_all {
    -                true => 0,
    -                false if satoshi.is_dust() => return Err(Error::OutputBelowDustLimit(index)),
    -                false => *satoshi,
    -            };
    -
    -            if self.is_mine(script_pubkey)? {
    -                received += value;
    -            }
    -
    -            let new_out = TxOut {
    -                script_pubkey: script_pubkey.clone(),
    -                value,
    -            };
    -            fee_amount += calc_fee_bytes(serialize(&new_out).len() * 4);
    -
    -            tx.output.push(new_out);
    -
    -            outgoing += value;
    -        }
    -
    -        // TODO: use the right weight instead of the maximum, and only fall-back to it if the
    -        // script is unknown in the database
    -        let input_witness_weight = std::cmp::max(
    -            self.get_descriptor_for_script_type(ScriptType::Internal)
    -                .0
    -                .max_satisfaction_weight(),
    -            self.get_descriptor_for_script_type(ScriptType::External)
    -                .0
    -                .max_satisfaction_weight(),
    -        );
    -
    -        if builder.change_policy != tx_builder::ChangeSpendPolicy::ChangeAllowed
    -            && self.change_descriptor.is_none()
    -        {
    -            return Err(Error::Generic(
    -                "The `change_policy` can be set only if the wallet has a change_descriptor".into(),
    -            ));
    -        }
    -
    -        let (available_utxos, use_all_utxos) = self.get_available_utxos(
    -            builder.change_policy,
    -            &builder.utxos,
    -            &builder.unspendable,
    -            builder.send_all,
    -        )?;
    -        let coin_selection::CoinSelectionResult {
    -            txin,
    -            selected_amount,
    -            mut fee_amount,
    -        } = builder.coin_selection.coin_select(
    -            available_utxos,
    -            use_all_utxos,
    -            fee_rate,
    -            outgoing,
    -            input_witness_weight,
    -            fee_amount,
    -        )?;
    -        let (mut txin, prev_script_pubkeys): (Vec<_>, Vec<_>) = txin.into_iter().unzip();
    -        // map that allows us to lookup the prev_script_pubkey for a given previous_output
    -        let prev_script_pubkeys = txin
    -            .iter()
    -            .zip(prev_script_pubkeys.into_iter())
    -            .map(|(txin, script)| (txin.previous_output, script))
    -            .collect::<HashMap<_, _>>();
    -
    -        txin.iter_mut().for_each(|i| i.sequence = n_sequence);
    -        tx.input = txin;
    -
    -        // prepare the change output
    -        let change_output = match builder.send_all {
    -            true => None,
    -            false => {
    -                let change_script = self.get_change_address()?;
    -                let change_output = TxOut {
    -                    script_pubkey: change_script,
    -                    value: 0,
    -                };
    -
    -                // take the change into account for fees
    -                fee_amount += calc_fee_bytes(serialize(&change_output).len() * 4);
    -                Some(change_output)
    -            }
    -        };
    -
    -        let mut fee_amount = fee_amount.ceil() as u64;
    -        let change_val = selected_amount - outgoing - fee_amount;
    -        if !builder.send_all && !change_val.is_dust() {
    -            let mut change_output = change_output.unwrap();
    -            change_output.value = change_val;
    -            received += change_val;
    -
    -            tx.output.push(change_output);
    -        } else if builder.send_all && !change_val.is_dust() {
    -            // there's only one output, send everything to it
    -            tx.output[0].value = change_val;
    -
    -            // send_all to our address
    -            if self.is_mine(&tx.output[0].script_pubkey)? {
    -                received = change_val;
    -            }
    -        } else if !builder.send_all && change_val.is_dust() {
    -            // skip the change output because it's dust, this adds up to the fees
    -            fee_amount += change_val;
    -        } else if builder.send_all {
    -            // send_all but the only output would be below dust limit
    -            return Err(Error::InsufficientFunds); // TODO: or OutputBelowDustLimit?
    -        }
    -
    -        // sort input/outputs according to the chosen algorithm
    -        builder.ordering.sort_tx(&mut tx);
    -
    -        let txid = tx.txid();
    -        let psbt = self.complete_transaction(tx, prev_script_pubkeys, builder)?;
    -
    -        let transaction_details = TransactionDetails {
    -            transaction: None,
    -            txid,
    -            timestamp: time::get_timestamp(),
    -            received,
    -            sent: selected_amount,
    -            fees: fee_amount,
    -            height: None,
    -        };
    -
    -        Ok((psbt, transaction_details))
    -    }
    -
    -    /// Bump the fee of a transaction following the options specified in the `builder`
    -    ///
    -    /// Return an error if the transaction is already confirmed or doesn't explicitly signal RBF.
    -    ///
    -    /// **NOTE**: if the original transaction was made with [`TxBuilder::send_all`], the same
    -    /// option must be enabled when bumping its fees to correctly reduce the only output's value to
    -    /// increase the fees.
    -    ///
    -    /// ## Example
    -    ///
    -    /// ```no_run
    -    /// # use std::str::FromStr;
    -    /// # use bitcoin::*;
    -    /// # use bdk::*;
    -    /// # use bdk::database::*;
    -    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -    /// let txid = Txid::from_str("faff0a466b70f5d5f92bd757a92c1371d4838bdd5bc53a06764e2488e51ce8f8").unwrap();
    -    /// let (psbt, details) = wallet.bump_fee(
    -    ///     &txid,
    -    ///     TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(5.0)),
    -    /// )?;
    -    /// // sign and broadcast ...
    -    /// # Ok::<(), bdk::Error>(())
    -    /// ```
    -    // TODO: support for merging multiple transactions while bumping the fees
    -    // TODO: option to force addition of an extra output? seems bad for privacy to update the
    -    // change
    -    pub fn bump_fee<Cs: coin_selection::CoinSelectionAlgorithm>(
    -        &self,
    -        txid: &Txid,
    -        builder: TxBuilder<Cs>,
    -    ) -> Result<(PSBT, TransactionDetails), Error> {
    -        let mut details = match self.database.borrow().get_tx(&txid, true)? {
    -            None => return Err(Error::TransactionNotFound),
    -            Some(tx) if tx.transaction.is_none() => return Err(Error::TransactionNotFound),
    -            Some(tx) if tx.height.is_some() => return Err(Error::TransactionConfirmed),
    -            Some(tx) => tx,
    -        };
    -        let mut tx = details.transaction.take().unwrap();
    -        if !tx.input.iter().any(|txin| txin.sequence <= 0xFFFFFFFD) {
    -            return Err(Error::IrreplaceableTransaction);
    -        }
    -
    -        // the new tx must "pay for its bandwidth"
    -        let vbytes = tx.get_weight() as f32 / 4.0;
    -        let required_feerate = FeeRate::from_sat_per_vb(details.fees as f32 / vbytes + 1.0);
    -        let new_feerate = builder.fee_rate.unwrap_or_default();
    -
    -        if new_feerate < required_feerate {
    -            return Err(Error::FeeRateTooLow {
    -                required: required_feerate,
    -            });
    -        }
    -        let mut fee_difference =
    -            (new_feerate.as_sat_vb() * tx.get_weight() as f32 / 4.0).ceil() as u64 - details.fees;
    -
    -        if builder.send_all && tx.output.len() > 1 {
    -            return Err(Error::SendAllMultipleOutputs);
    -        }
    -
    -        // find the index of the output that we can update. either the change or the only one if
    -        // it's `send_all`
    -        let updatable_output = if builder.send_all {
    -            0
    -        } else {
    -            let mut change_output = None;
    -            for (index, txout) in tx.output.iter().enumerate() {
    -                // look for an output that we know and that has the right ScriptType. We use
    -                // `get_deget_descriptor_for` to find what's the ScriptType for `Internal`
    -                // addresses really is, because if there's no change_descriptor it's actually equal
    -                // to "External"
    -                let (_, change_type) = self.get_descriptor_for_script_type(ScriptType::Internal);
    -                match self
    -                    .database
    -                    .borrow()
    -                    .get_path_from_script_pubkey(&txout.script_pubkey)?
    -                {
    -                    Some((script_type, _)) if script_type == change_type => {
    -                        change_output = Some(index);
    -                        break;
    -                    }
    -                    _ => {}
    -                }
    -            }
    -
    -            // we need a change output, add one here and take into account the extra fees for it
    -            if change_output.is_none() {
    -                let change_script = self.get_change_address()?;
    -                let change_txout = TxOut {
    -                    script_pubkey: change_script,
    -                    value: 0,
    -                };
    -                fee_difference +=
    -                    (serialize(&change_txout).len() as f32 * new_feerate.as_sat_vb()).ceil() as u64;
    -                tx.output.push(change_txout);
    -
    -                change_output = Some(tx.output.len() - 1);
    -            }
    -
    -            change_output.unwrap()
    -        };
    -
    -        // if `builder.utxos` is Some(_) we have to add inputs and we skip down to the last branch
    -        match tx.output[updatable_output]
    -            .value
    -            .checked_sub(fee_difference)
    -        {
    -            Some(new_value) if !new_value.is_dust() && builder.utxos.is_none() => {
    -                // try to reduce the "updatable output" amount
    -                tx.output[updatable_output].value = new_value;
    -                if self.is_mine(&tx.output[updatable_output].script_pubkey)? {
    -                    details.received -= fee_difference;
    -                }
    -
    -                details.fees += fee_difference;
    -            }
    -            _ if builder.send_all && builder.utxos.is_none() => {
    -                // if the tx is "send_all" it doesn't make sense to either remove the only output
    -                // or add more inputs
    -                return Err(Error::InsufficientFunds);
    -            }
    -            _ => {
    -                // initially always remove the change output
    -                let mut removed_change_output = tx.output.remove(updatable_output);
    -                if self.is_mine(&removed_change_output.script_pubkey)? {
    -                    details.received -= removed_change_output.value;
    -                }
    -
    -                // we want to add more inputs if:
    -                // - builder.utxos tells us to do so
    -                // - the removed change value is lower than the fee_difference we want to add
    -                let needs_more_inputs =
    -                    builder.utxos.is_some() || removed_change_output.value <= fee_difference;
    -                let added_amount = if needs_more_inputs {
    -                    // TODO: use the right weight instead of the maximum, and only fall-back to it if the
    -                    // script is unknown in the database
    -                    let input_witness_weight = std::cmp::max(
    -                        self.get_descriptor_for_script_type(ScriptType::Internal)
    -                            .0
    -                            .max_satisfaction_weight(),
    -                        self.get_descriptor_for_script_type(ScriptType::External)
    -                            .0
    -                            .max_satisfaction_weight(),
    -                    );
    -
    -                    let (available_utxos, use_all_utxos) = self.get_available_utxos(
    -                        builder.change_policy,
    -                        &builder.utxos,
    -                        &builder.unspendable,
    -                        false,
    -                    )?;
    -                    let available_utxos = rbf::filter_available(
    -                        self.database.borrow().deref(),
    -                        available_utxos.into_iter(),
    -                    )?;
    -                    let coin_selection::CoinSelectionResult {
    -                        txin,
    -                        selected_amount,
    -                        fee_amount,
    -                    } = builder.coin_selection.coin_select(
    -                        available_utxos,
    -                        use_all_utxos,
    -                        new_feerate,
    -                        fee_difference
    -                            .checked_sub(removed_change_output.value)
    -                            .unwrap_or(0),
    -                        input_witness_weight,
    -                        0.0,
    -                    )?;
    -                    fee_difference += fee_amount.ceil() as u64;
    -
    -                    // add the new inputs
    -                    let (mut txin, _): (Vec<_>, Vec<_>) = txin.into_iter().unzip();
    -
    -                    // TODO: use tx_builder.sequence ??
    -                    // copy the n_sequence from the inputs that were already in the transaction
    -                    txin.iter_mut()
    -                        .for_each(|i| i.sequence = tx.input[0].sequence);
    -                    tx.input.extend_from_slice(&mut txin);
    -
    -                    details.sent += selected_amount;
    -                    selected_amount
    -                } else {
    -                    // otherwise just remove the output and add 0 new coins
    -                    0
    -                };
    -
    -                match (removed_change_output.value + added_amount).checked_sub(fee_difference) {
    -                    None => return Err(Error::InsufficientFunds),
    -                    Some(new_value) if new_value.is_dust() => {
    -                        // the change would be dust, add that to fees
    -                        details.fees += fee_difference + new_value;
    -                    }
    -                    Some(new_value) => {
    -                        // add the change back
    -                        removed_change_output.value = new_value;
    -                        tx.output.push(removed_change_output);
    -
    -                        details.received += new_value;
    -                        details.fees += fee_difference;
    -                    }
    -                }
    -            }
    -        };
    -
    -        // clear witnesses
    -        for input in &mut tx.input {
    -            input.script_sig = Script::default();
    -            input.witness = vec![];
    -        }
    -
    -        // sort input/outputs according to the chosen algorithm
    -        builder.ordering.sort_tx(&mut tx);
    -
    -        // TODO: check that we are not replacing more than 100 txs from mempool
    -
    -        details.txid = tx.txid();
    -        details.timestamp = time::get_timestamp();
    -
    -        let prev_script_pubkeys = tx
    -            .input
    -            .iter()
    -            .map(|txin| {
    -                Ok((
    -                    txin.previous_output.clone(),
    -                    self.database
    -                        .borrow()
    -                        .get_previous_output(&txin.previous_output)?,
    -                ))
    -            })
    -            .collect::<Result<Vec<_>, Error>>()?
    -            .into_iter()
    -            .filter_map(|(outpoint, txout)| match txout {
    -                Some(txout) => Some((outpoint, txout.script_pubkey)),
    -                None => None,
    -            })
    -            .collect();
    -        let psbt = self.complete_transaction(tx, prev_script_pubkeys, builder)?;
    -
    -        Ok((psbt, details))
    -    }
    -
    -    /// Sign a transaction with all the wallet's signers, in the order specified by every signer's
    -    /// [`SignerOrdering`]
    -    ///
    -    /// ## Example
    -    ///
    -    /// ```no_run
    -    /// # use std::str::FromStr;
    -    /// # use bitcoin::*;
    -    /// # use bdk::*;
    -    /// # use bdk::database::*;
    -    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -    /// # let (psbt, _) = wallet.create_tx(TxBuilder::new())?;
    -    /// let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
    -    /// # Ok::<(), bdk::Error>(())
    -    pub fn sign(&self, mut psbt: PSBT, assume_height: Option<u32>) -> Result<(PSBT, bool), Error> {
    -        // this helps us doing our job later
    -        self.add_input_hd_keypaths(&mut psbt)?;
    -
    -        for signer in self
    -            .signers
    -            .signers()
    -            .iter()
    -            .chain(self.change_signers.signers().iter())
    -        {
    -            if signer.sign_whole_tx() {
    -                signer.sign(&mut psbt, None)?;
    -            } else {
    -                for index in 0..psbt.inputs.len() {
    -                    signer.sign(&mut psbt, Some(index))?;
    -                }
    -            }
    -        }
    -
    -        // attempt to finalize
    -        self.finalize_psbt(psbt, assume_height)
    -    }
    -
    -    /// Return the spending policies for the wallet's descriptor
    -    pub fn policies(&self, script_type: ScriptType) -> Result<Option<Policy>, Error> {
    -        match (script_type, self.change_descriptor.as_ref()) {
    -            (ScriptType::External, _) => {
    -                Ok(self.descriptor.extract_policy(Arc::clone(&self.signers))?)
    -            }
    -            (ScriptType::Internal, None) => Ok(None),
    -            (ScriptType::Internal, Some(desc)) => {
    -                Ok(desc.extract_policy(Arc::clone(&self.change_signers))?)
    -            }
    -        }
    -    }
    -
    -    /// 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,
    -        script_type: ScriptType,
    -    ) -> Result<Option<ExtendedDescriptor>, Error> {
    -        match (script_type, self.change_descriptor.as_ref()) {
    -            (ScriptType::External, _) => Ok(Some(self.descriptor.clone())),
    -            (ScriptType::Internal, None) => Ok(None),
    -            (ScriptType::Internal, Some(desc)) => Ok(Some(desc.clone())),
    -        }
    -    }
    -
    -    /// Try to finalize a PSBT
    -    pub fn finalize_psbt(
    -        &self,
    -        mut psbt: PSBT,
    -        assume_height: Option<u32>,
    -    ) -> Result<(PSBT, bool), Error> {
    -        let mut tx = psbt.global.unsigned_tx.clone();
    -
    -        for (n, (input, psbt_input)) in tx.input.iter_mut().zip(psbt.inputs.iter()).enumerate() {
    -            // if the height is None in the database it means it's still unconfirmed, so consider
    -            // that as a very high value
    -            let create_height = self
    -                .database
    -                .borrow()
    -                .get_tx(&input.previous_output.txid, false)?
    -                .and_then(|tx| Some(tx.height.unwrap_or(std::u32::MAX)));
    -            let current_height = assume_height.or(self.current_height);
    -
    -            debug!(
    -                "Input #{} - {}, using `create_height` = {:?}, `current_height` = {:?}",
    -                n, input.previous_output, create_height, current_height
    -            );
    -
    -            // - Try to derive the descriptor by looking at the txout. If it's in our database, we
    -            //   know exactly which `script_type` 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 `hd_keypaths`,
    -            //   `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 = if let Some(desc) = psbt
    -                .get_utxo_for(n)
    -                .map(|txout| self.get_descriptor_for_txout(&txout))
    -                .transpose()?
    -                .flatten()
    -            {
    -                desc
    -            } else if let Some(desc) = self
    -                .descriptor
    -                .derive_from_psbt_input(psbt_input, psbt.get_utxo_for(n))
    -            {
    -                desc
    -            } else if let Some(desc) = self
    -                .change_descriptor
    -                .as_ref()
    -                .and_then(|desc| desc.derive_from_psbt_input(psbt_input, psbt.get_utxo_for(n)))
    -            {
    -                desc
    -            } else {
    -                debug!("Couldn't find the right derived descriptor for input {}", n);
    -                return Ok((psbt, false));
    -            };
    -
    -            match desc.satisfy(
    -                input,
    -                (
    -                    psbt_input.clone(),
    -                    After::new(current_height, false),
    -                    Older::new(current_height, create_height, false),
    -                ),
    -            ) {
    -                Ok(_) => continue,
    -                Err(e) => {
    -                    debug!("satisfy error {:?} for input {}", e, n);
    -                    return Ok((psbt, false));
    -                }
    -            }
    -        }
    -
    -        // consume tx to extract its input's script_sig and witnesses and move them into the psbt
    -        for (input, psbt_input) in tx.input.into_iter().zip(psbt.inputs.iter_mut()) {
    -            psbt_input.final_script_sig = Some(input.script_sig);
    -            psbt_input.final_script_witness = Some(input.witness);
    -        }
    -
    -        Ok((psbt, true))
    -    }
    -
    -    // Internals
    -
    -    fn get_descriptor_for_script_type(
    -        &self,
    -        script_type: ScriptType,
    -    ) -> (&ExtendedDescriptor, ScriptType) {
    -        let desc = match script_type {
    -            ScriptType::Internal if self.change_descriptor.is_some() => (
    -                self.change_descriptor.as_ref().unwrap(),
    -                ScriptType::Internal,
    -            ),
    -            _ => (&self.descriptor, ScriptType::External),
    -        };
    -
    -        desc
    -    }
    -
    -    fn get_descriptor_for_txout(&self, txout: &TxOut) -> Result<Option<ExtendedDescriptor>, Error> {
    -        Ok(self
    -            .database
    -            .borrow()
    -            .get_path_from_script_pubkey(&txout.script_pubkey)?
    -            .map(|(script_type, child)| (self.get_descriptor_for_script_type(script_type).0, child))
    -            .map(|(desc, child)| desc.derive(&[ChildNumber::from_normal_idx(child).unwrap()])))
    -    }
    -
    -    fn get_change_address(&self) -> Result<Script, Error> {
    -        let (desc, script_type) = self.get_descriptor_for_script_type(ScriptType::Internal);
    -        let index = self.fetch_and_increment_index(script_type)?;
    -
    -        Ok(desc
    -            .derive(&[ChildNumber::from_normal_idx(index).unwrap()])
    -            .script_pubkey())
    -    }
    -
    -    fn fetch_and_increment_index(&self, script_type: ScriptType) -> Result<u32, Error> {
    -        let (descriptor, script_type) = self.get_descriptor_for_script_type(script_type);
    -        let index = match descriptor.is_fixed() {
    -            true => 0,
    -            false => self
    -                .database
    -                .borrow_mut()
    -                .increment_last_index(script_type)?,
    -        };
    -
    -        if self
    -            .database
    -            .borrow()
    -            .get_script_pubkey_from_path(script_type, index)?
    -            .is_none()
    -        {
    -            self.cache_addresses(script_type, index, CACHE_ADDR_BATCH_SIZE)?;
    -        }
    -
    -        let hd_keypaths = descriptor.get_hd_keypaths(index)?;
    -        let script = descriptor
    -            .derive(&[ChildNumber::from_normal_idx(index).unwrap()])
    -            .script_pubkey();
    -        for validator in &self.address_validators {
    -            validator.validate(script_type, &hd_keypaths, &script)?;
    -        }
    -
    -        Ok(index)
    -    }
    -
    -    fn cache_addresses(
    -        &self,
    -        script_type: ScriptType,
    -        from: u32,
    -        mut count: u32,
    -    ) -> Result<(), Error> {
    -        let (descriptor, script_type) = self.get_descriptor_for_script_type(script_type);
    -        if descriptor.is_fixed() {
    -            if from > 0 {
    -                return Ok(());
    -            }
    -
    -            count = 1;
    -        }
    -
    -        let mut address_batch = self.database.borrow().begin_batch();
    -
    -        let start_time = time::Instant::new();
    -        for i in from..(from + count) {
    -            address_batch.set_script_pubkey(
    -                &descriptor
    -                    .derive(&[ChildNumber::from_normal_idx(i).unwrap()])
    -                    .script_pubkey(),
    -                script_type,
    -                i,
    -            )?;
    -        }
    -
    -        info!(
    -            "Derivation of {} addresses from {} took {} ms",
    -            count,
    -            from,
    -            start_time.elapsed().as_millis()
    -        );
    -
    -        self.database.borrow_mut().commit_batch(address_batch)?;
    -
    -        Ok(())
    -    }
    -
    -    fn get_available_utxos(
    -        &self,
    -        change_policy: tx_builder::ChangeSpendPolicy,
    -        utxo: &Option<Vec<OutPoint>>,
    -        unspendable: &Option<Vec<OutPoint>>,
    -        send_all: bool,
    -    ) -> Result<(Vec<UTXO>, bool), Error> {
    -        let unspendable_set = match unspendable {
    -            None => HashSet::new(),
    -            Some(vec) => vec.into_iter().collect(),
    -        };
    -
    -        match utxo {
    -            // with manual coin selection we always want to spend all the selected utxos, no matter
    -            // what (even if they are marked as unspendable)
    -            Some(raw_utxos) => {
    -                let full_utxos = raw_utxos
    -                    .iter()
    -                    .map(|u| self.database.borrow().get_utxo(&u))
    -                    .collect::<Result<Vec<_>, _>>()?;
    -                if !full_utxos.iter().all(|u| u.is_some()) {
    -                    return Err(Error::UnknownUTXO);
    -                }
    -
    -                Ok((full_utxos.into_iter().map(|x| x.unwrap()).collect(), true))
    -            }
    -            // otherwise limit ourselves to the spendable utxos for the selected policy, and the `send_all` setting
    -            None => {
    -                let utxos = self.list_unspent()?.into_iter();
    -                let utxos = change_policy.filter_utxos(utxos).into_iter();
    -
    -                Ok((
    -                    utxos
    -                        .filter(|u| !unspendable_set.contains(&u.outpoint))
    -                        .collect(),
    -                    send_all,
    -                ))
    -            }
    -        }
    -    }
    -
    -    fn complete_transaction<Cs: coin_selection::CoinSelectionAlgorithm>(
    -        &self,
    -        tx: Transaction,
    -        prev_script_pubkeys: HashMap<OutPoint, Script>,
    -        builder: TxBuilder<Cs>,
    -    ) -> Result<PSBT, Error> {
    -        let mut psbt = PSBT::from_unsigned_tx(tx)?;
    -
    -        // add metadata for the inputs
    -        for (psbt_input, input) in psbt
    -            .inputs
    -            .iter_mut()
    -            .zip(psbt.global.unsigned_tx.input.iter())
    -        {
    -            let prev_script = match prev_script_pubkeys.get(&input.previous_output) {
    -                Some(prev_script) => prev_script,
    -                None => continue,
    -            };
    -
    -            // Add sighash, default is obviously "ALL"
    -            psbt_input.sighash_type = builder.sighash.or(Some(SigHashType::All));
    -
    -            // Try to find the prev_script in our db to figure out if this is internal or external,
    -            // and the derivation index
    -            let (script_type, child) = match self
    -                .database
    -                .borrow()
    -                .get_path_from_script_pubkey(&prev_script)?
    -            {
    -                Some(x) => x,
    -                None => continue,
    -            };
    -
    -            let (desc, _) = self.get_descriptor_for_script_type(script_type);
    -            psbt_input.hd_keypaths = desc.get_hd_keypaths(child)?;
    -            let derived_descriptor = desc.derive(&[ChildNumber::from_normal_idx(child).unwrap()]);
    -
    -            psbt_input.redeem_script = derived_descriptor.psbt_redeem_script();
    -            psbt_input.witness_script = derived_descriptor.psbt_witness_script();
    -
    -            let prev_output = input.previous_output;
    -            if let Some(prev_tx) = self.database.borrow().get_raw_tx(&prev_output.txid)? {
    -                if derived_descriptor.is_witness() {
    -                    psbt_input.witness_utxo =
    -                        Some(prev_tx.output[prev_output.vout as usize].clone());
    -                }
    -                if !derived_descriptor.is_witness() || builder.force_non_witness_utxo {
    -                    psbt_input.non_witness_utxo = Some(prev_tx);
    -                }
    -            }
    -        }
    -
    -        // probably redundant but it doesn't hurt...
    -        self.add_input_hd_keypaths(&mut psbt)?;
    -
    -        // add metadata for the outputs
    -        for (psbt_output, tx_output) in psbt
    -            .outputs
    -            .iter_mut()
    -            .zip(psbt.global.unsigned_tx.output.iter())
    -        {
    -            if let Some((script_type, child)) = self
    -                .database
    -                .borrow()
    -                .get_path_from_script_pubkey(&tx_output.script_pubkey)?
    -            {
    -                let (desc, _) = self.get_descriptor_for_script_type(script_type);
    -                psbt_output.hd_keypaths = desc.get_hd_keypaths(child)?;
    -            }
    -        }
    -
    -        Ok(psbt)
    -    }
    -
    -    fn add_input_hd_keypaths(&self, psbt: &mut PSBT) -> Result<(), Error> {
    -        let mut input_utxos = Vec::with_capacity(psbt.inputs.len());
    -        for n in 0..psbt.inputs.len() {
    -            input_utxos.push(psbt.get_utxo_for(n).clone());
    -        }
    -
    -        // try to add hd_keypaths if we've already seen the output
    -        for (psbt_input, out) in psbt.inputs.iter_mut().zip(input_utxos.iter()) {
    -            if let Some(out) = out {
    -                if let Some((script_type, child)) = self
    -                    .database
    -                    .borrow()
    -                    .get_path_from_script_pubkey(&out.script_pubkey)?
    -                {
    -                    debug!("Found descriptor {:?}/{}", script_type, child);
    -
    -                    // merge hd_keypaths
    -                    let (desc, _) = self.get_descriptor_for_script_type(script_type);
    -                    let mut hd_keypaths = desc.get_hd_keypaths(child)?;
    -                    psbt_input.hd_keypaths.append(&mut hd_keypaths);
    -                }
    -            }
    -        }
    -
    -        Ok(())
    -    }
    -}
    -
    -impl<B, D> Wallet<B, D>
    -where
    -    B: Blockchain,
    -    D: BatchDatabase,
    -{
    -    /// Create a new "online" wallet
    -    #[maybe_async]
    -    pub fn new(
    -        descriptor: &str,
    -        change_descriptor: Option<&str>,
    -        network: Network,
    -        database: D,
    -        client: B,
    -    ) -> Result<Self, Error> {
    -        let mut wallet = Self::new_offline(descriptor, change_descriptor, network, database)?;
    -
    -        wallet.current_height = Some(maybe_await!(client.get_height())? as u32);
    -        wallet.client = Some(client);
    -
    -        Ok(wallet)
    -    }
    -
    -    /// Sync the internal database with the blockchain
    -    #[maybe_async]
    -    pub fn sync<P: 'static + Progress>(
    -        &self,
    -        progress_update: P,
    -        max_address_param: Option<u32>,
    -    ) -> Result<(), Error> {
    -        debug!("Begin sync...");
    -
    -        let mut run_setup = false;
    -
    -        let max_address = match self.descriptor.is_fixed() {
    -            true => 0,
    -            false => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
    -        };
    -        if self
    -            .database
    -            .borrow()
    -            .get_script_pubkey_from_path(ScriptType::External, max_address)?
    -            .is_none()
    -        {
    -            run_setup = true;
    -            self.cache_addresses(ScriptType::External, 0, max_address)?;
    -        }
    -
    -        if let Some(change_descriptor) = &self.change_descriptor {
    -            let max_address = match change_descriptor.is_fixed() {
    -                true => 0,
    -                false => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
    -            };
    -
    -            if self
    -                .database
    -                .borrow()
    -                .get_script_pubkey_from_path(
    -                    ScriptType::Internal,
    -                    max_address.checked_sub(1).unwrap_or(0),
    -                )?
    -                .is_none()
    -            {
    -                run_setup = true;
    -                self.cache_addresses(ScriptType::Internal, 0, max_address)?;
    -            }
    -        }
    -
    -        // TODO: what if i generate an address first and cache some addresses?
    -        // TODO: we should sync if generating an address triggers a new batch to be stored
    -        if run_setup {
    -            maybe_await!(self.client.as_ref().ok_or(Error::OfflineClient)?.setup(
    -                None,
    -                self.database.borrow_mut().deref_mut(),
    -                progress_update,
    -            ))
    -        } else {
    -            maybe_await!(self.client.as_ref().ok_or(Error::OfflineClient)?.sync(
    -                None,
    -                self.database.borrow_mut().deref_mut(),
    -                progress_update,
    -            ))
    -        }
    -    }
    -
    -    /// Return a reference to the internal blockchain client
    -    pub fn client(&self) -> Option<&B> {
    -        self.client.as_ref()
    -    }
    -
    -    /// Broadcast a transaction to the network
    -    #[maybe_async]
    -    pub fn broadcast(&self, tx: Transaction) -> Result<Txid, Error> {
    -        maybe_await!(self
    -            .client
    -            .as_ref()
    -            .ok_or(Error::OfflineClient)?
    -            .broadcast(&tx))?;
    -
    -        Ok(tx.txid())
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::str::FromStr;
    -
    -    use bitcoin::Network;
    -
    -    use crate::database::memory::MemoryDatabase;
    -    use crate::database::Database;
    -    use crate::types::ScriptType;
    -
    -    use super::*;
    -
    -    #[test]
    -    fn test_cache_addresses_fixed() {
    -        let db = MemoryDatabase::new();
    -        let wallet: OfflineWallet<_> = Wallet::new_offline(
    -            "wpkh(L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6)",
    -            None,
    -            Network::Testnet,
    -            db,
    -        )
    -        .unwrap();
    -
    -        assert_eq!(
    -            wallet.get_new_address().unwrap().to_string(),
    -            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
    -        );
    -        assert_eq!(
    -            wallet.get_new_address().unwrap().to_string(),
    -            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
    -        );
    -
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(ScriptType::External, 0)
    -            .unwrap()
    -            .is_some());
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(ScriptType::Internal, 0)
    -            .unwrap()
    -            .is_none());
    -    }
    -
    -    #[test]
    -    fn test_cache_addresses() {
    -        let db = MemoryDatabase::new();
    -        let wallet: OfflineWallet<_> = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
    -
    -        assert_eq!(
    -            wallet.get_new_address().unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -        assert_eq!(
    -            wallet.get_new_address().unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(ScriptType::External, CACHE_ADDR_BATCH_SIZE - 1)
    -            .unwrap()
    -            .is_some());
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(ScriptType::External, CACHE_ADDR_BATCH_SIZE)
    -            .unwrap()
    -            .is_none());
    -    }
    -
    -    #[test]
    -    fn test_cache_addresses_refill() {
    -        let db = MemoryDatabase::new();
    -        let wallet: OfflineWallet<_> = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
    -
    -        assert_eq!(
    -            wallet.get_new_address().unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(ScriptType::External, CACHE_ADDR_BATCH_SIZE - 1)
    -            .unwrap()
    -            .is_some());
    -
    -        for _ in 0..CACHE_ADDR_BATCH_SIZE {
    -            wallet.get_new_address().unwrap();
    -        }
    -
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(ScriptType::External, CACHE_ADDR_BATCH_SIZE * 2 - 1)
    -            .unwrap()
    -            .is_some());
    -    }
    -
    -    pub(crate) fn get_test_wpkh() -> &'static str {
    -        "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)"
    -    }
    -
    -    pub(crate) fn get_test_single_sig_csv() -> &'static str {
    -        // and(pk(Alice),older(6))
    -        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),older(6)))"
    -    }
    -
    -    pub(crate) fn get_test_single_sig_cltv() -> &'static str {
    -        // and(pk(Alice),after(100000))
    -        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(100000)))"
    -    }
    -
    -    pub(crate) fn get_funded_wallet(
    -        descriptor: &str,
    -    ) -> (
    -        OfflineWallet<MemoryDatabase>,
    -        (String, Option<String>),
    -        bitcoin::Txid,
    -    ) {
    -        let descriptors = testutils!(@descriptors (descriptor));
    -        let wallet: OfflineWallet<_> = Wallet::new_offline(
    -            &descriptors.0,
    -            None,
    -            Network::Regtest,
    -            MemoryDatabase::new(),
    -        )
    -        .unwrap();
    -
    -        let txid = wallet.database.borrow_mut().received_tx(
    -            testutils! {
    -                @tx ( (@external descriptors, 0) => 50_000 ) (@confirmations 1)
    -            },
    -            Some(100),
    -        );
    -
    -        (wallet, descriptors, txid)
    -    }
    -
    -    macro_rules! assert_fee_rate {
    -        ($tx:expr, $fees:expr, $fee_rate:expr $( ,@dust_change $( $dust_change:expr )* )* $( ,@add_signature $( $add_signature:expr )* )* ) => ({
    -            let mut tx = $tx.clone();
    -            $(
    -                $( $add_signature )*
    -                for txin in &mut tx.input {
    -                    txin.witness.push([0x00; 108].to_vec()); // fake signature
    -                }
    -            )*
    -
    -            #[allow(unused_mut)]
    -            #[allow(unused_assignments)]
    -            let mut dust_change = false;
    -            $(
    -                $( $dust_change )*
    -                dust_change = true;
    -            )*
    -
    -            let tx_fee_rate = $fees as f32 / (tx.get_weight() as f32 / 4.0);
    -            let fee_rate = $fee_rate.as_sat_vb();
    -
    -            if !dust_change {
    -                assert!((tx_fee_rate - fee_rate).abs() < 0.5, format!("Expected fee rate of {}, the tx has {}", fee_rate, tx_fee_rate));
    -            } else {
    -                assert!(tx_fee_rate >= fee_rate, format!("Expected fee rate of at least {}, the tx has {}", fee_rate, tx_fee_rate));
    -            }
    -        });
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "NoAddressees")]
    -    fn test_create_tx_empty_recipients() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        wallet
    -            .create_tx(TxBuilder::with_recipients(vec![]).version(0))
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "Invalid version `0`")]
    -    fn test_create_tx_version_0() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(0))
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
    -    )]
    -    fn test_create_tx_version_1_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
    -        let addr = wallet.get_new_address().unwrap();
    -        wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(1))
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_version() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(42))
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.version, 42);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_locktime() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.lock_time, 0);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_locktime_cltv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.lock_time, 100_000);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_locktime() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(630_000),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_locktime_compatible_with_cltv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(630_000),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "TxBuilder requested timelock of `50000`, but at least `100000` is required to spend from this script"
    -    )]
    -    fn test_create_tx_custom_locktime_incompatible_with_cltv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -        let addr = wallet.get_new_address().unwrap();
    -        wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(50000),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_no_rbf_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 6);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_with_default_rbf_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFD);
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "Cannot enable RBF with nSequence `3`, since at least `6` is required to spend with OP_CSV"
    -    )]
    -    fn test_create_tx_with_custom_rbf_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
    -        let addr = wallet.get_new_address().unwrap();
    -        wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
    -                    .enable_rbf_with_sequence(3),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_no_rbf_cltv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFE);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "Cannot enable RBF with a nSequence >= 0xFFFFFFFE")]
    -    fn test_create_tx_invalid_rbf_sequence() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
    -                    .enable_rbf_with_sequence(0xFFFFFFFE),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_rbf_sequence() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
    -                    .enable_rbf_with_sequence(0xDEADBEEF),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xDEADBEEF);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_sequence() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFF);
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "The `change_policy` can be set only if the wallet has a change_descriptor"
    -    )]
    -    fn test_create_tx_change_policy_no_internal() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
    -                    .do_not_spend_change(),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "SendAllMultipleOutputs")]
    -    fn test_create_tx_send_all_multiple_outputs() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![
    -                    (addr.script_pubkey(), 25_000),
    -                    (addr.script_pubkey(), 10_000),
    -                ])
    -                .send_all(),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_send_all() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, details) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
    -        assert_eq!(
    -            psbt.global.unsigned_tx.output[0].value,
    -            50_000 - details.fees
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_fee_rate() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, details) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
    -            .unwrap();
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::default(), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_fee_rate() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
    -                    .fee_rate(FeeRate::from_sat_per_vb(5.0))
    -                    .send_all(),
    -            )
    -            .unwrap();
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(5.0), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_add_change() {
    -        use super::tx_builder::TxOrdering;
    -
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
    -                    .ordering(TxOrdering::Untouched),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.output.len(), 2);
    -        assert_eq!(psbt.global.unsigned_tx.output[0].value, 25_000);
    -        assert_eq!(
    -            psbt.global.unsigned_tx.output[1].value,
    -            25_000 - details.fees
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_skip_change_dust() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                49_800,
    -            )]))
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
    -        assert_eq!(psbt.global.unsigned_tx.output[0].value, 49_800);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_create_tx_send_all_dust_amount() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        // very high fee rate, so that the only output would be below dust
    -        wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
    -                    .send_all()
    -                    .fee_rate(crate::FeeRate::from_sat_per_vb(453.0)),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_ordering_respected() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![
    -                    (addr.script_pubkey(), 30_000),
    -                    (addr.script_pubkey(), 10_000),
    -                ])
    -                .ordering(super::tx_builder::TxOrdering::BIP69Lexicographic),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.output.len(), 3);
    -        assert_eq!(
    -            psbt.global.unsigned_tx.output[0].value,
    -            10_000 - details.fees
    -        );
    -        assert_eq!(psbt.global.unsigned_tx.output[1].value, 10_000);
    -        assert_eq!(psbt.global.unsigned_tx.output[2].value, 30_000);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_sighash() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                30_000,
    -            )]))
    -            .unwrap();
    -
    -        assert_eq!(psbt.inputs[0].sighash_type, Some(bitcoin::SigHashType::All));
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_sighash() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 30_000)])
    -                    .sighash(bitcoin::SigHashType::Single),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(
    -            psbt.inputs[0].sighash_type,
    -            Some(bitcoin::SigHashType::Single)
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_input_hd_keypaths() {
    -        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
    -        use std::str::FromStr;
    -
    -        let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*)");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
    -            .unwrap();
    -
    -        assert_eq!(psbt.inputs[0].hd_keypaths.len(), 1);
    -        assert_eq!(
    -            psbt.inputs[0].hd_keypaths.values().nth(0).unwrap(),
    -            &(
    -                Fingerprint::from_str("d34db33f").unwrap(),
    -                DerivationPath::from_str("m/44'/0'/0'/0/0").unwrap()
    -            )
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_output_hd_keypaths() {
    -        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
    -        use std::str::FromStr;
    -
    -        let (wallet, descriptors, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/0/*)");
    -        // cache some addresses
    -        wallet.get_new_address().unwrap();
    -
    -        let addr = testutils!(@external descriptors, 5);
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
    -            .unwrap();
    -
    -        assert_eq!(psbt.outputs[0].hd_keypaths.len(), 1);
    -        assert_eq!(
    -            psbt.outputs[0].hd_keypaths.values().nth(0).unwrap(),
    -            &(
    -                Fingerprint::from_str("d34db33f").unwrap(),
    -                DerivationPath::from_str("m/44'/0'/0'/0/5").unwrap()
    -            )
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_set_redeem_script_p2sh() {
    -        use bitcoin::hashes::hex::FromHex;
    -
    -        let (wallet, _, _) =
    -            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
    -            .unwrap();
    -
    -        assert_eq!(
    -            psbt.inputs[0].redeem_script,
    -            Some(Script::from(
    -                Vec::<u8>::from_hex(
    -                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
    -                )
    -                .unwrap()
    -            ))
    -        );
    -        assert_eq!(psbt.inputs[0].witness_script, None);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_set_witness_script_p2wsh() {
    -        use bitcoin::hashes::hex::FromHex;
    -
    -        let (wallet, _, _) =
    -            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
    -            .unwrap();
    -
    -        assert_eq!(psbt.inputs[0].redeem_script, None);
    -        assert_eq!(
    -            psbt.inputs[0].witness_script,
    -            Some(Script::from(
    -                Vec::<u8>::from_hex(
    -                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
    -                )
    -                .unwrap()
    -            ))
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_set_redeem_witness_script_p2wsh_p2sh() {
    -        use bitcoin::hashes::hex::FromHex;
    -
    -        let (wallet, _, _) =
    -            get_funded_wallet("sh(wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)))");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
    -            .unwrap();
    -
    -        let script = Script::from(
    -            Vec::<u8>::from_hex(
    -                "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac",
    -            )
    -            .unwrap(),
    -        );
    -
    -        assert_eq!(psbt.inputs[0].redeem_script, Some(script.to_v0_p2wsh()));
    -        assert_eq!(psbt.inputs[0].witness_script, Some(script));
    -    }
    -
    -    #[test]
    -    fn test_create_tx_non_witness_utxo() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
    -            .unwrap();
    -
    -        assert!(psbt.inputs[0].non_witness_utxo.is_some());
    -        assert!(psbt.inputs[0].witness_utxo.is_none());
    -    }
    -
    -    #[test]
    -    fn test_create_tx_only_witness_utxo() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
    -            .unwrap();
    -
    -        assert!(psbt.inputs[0].non_witness_utxo.is_none());
    -        assert!(psbt.inputs[0].witness_utxo.is_some());
    -    }
    -
    -    #[test]
    -    fn test_create_tx_both_non_witness_utxo_and_witness_utxo() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
    -                    .force_non_witness_utxo()
    -                    .send_all(),
    -            )
    -            .unwrap();
    -
    -        assert!(psbt.inputs[0].non_witness_utxo.is_some());
    -        assert!(psbt.inputs[0].witness_utxo.is_some());
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "IrreplaceableTransaction")]
    -    fn test_bump_fee_irreplaceable_tx() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, mut details) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        wallet.bump_fee(&txid, TxBuilder::new()).unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "TransactionConfirmed")]
    -    fn test_bump_fee_confirmed_tx() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, mut details) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        details.height = Some(42);
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        wallet.bump_fee(&txid, TxBuilder::new()).unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "FeeRateTooLow")]
    -    fn test_bump_fee_low_fee_rate() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, mut details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(1.0)),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_reduce_change() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let (psbt, details) = wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(2.5)),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent);
    -        assert_eq!(
    -            details.received + details.fees,
    -            original_details.received + original_details.fees
    -        );
    -        assert!(details.fees > original_details.fees);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            25_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(2.5), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_reduce_send_all() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
    -                    .send_all()
    -                    .enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let (psbt, details) = wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new()
    -                    .send_all()
    -                    .fee_rate(FeeRate::from_sat_per_vb(2.5)),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent);
    -        assert!(details.fees > original_details.fees);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.output.len(), 1);
    -        assert_eq!(tx.output[0].value + details.fees, details.sent);
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(2.5), @add_signature);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_bump_fee_remove_send_all_output() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        // receive an extra tx, to make sure that in case of "send_all" we get an error and it
    -        // doesn't try to pick more inputs
    -        let incoming_txid = wallet.database.borrow_mut().received_tx(
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
    -                    .utxos(vec![OutPoint {
    -                        txid: incoming_txid,
    -                        vout: 0,
    -                    }])
    -                    .send_all()
    -                    .enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -        assert_eq!(original_details.sent, 25_000);
    -
    -        wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new()
    -                    .send_all()
    -                    .fee_rate(FeeRate::from_sat_per_vb(225.0)),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_add_input() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        wallet.database.borrow_mut().received_tx(
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let (psbt, details) = wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(50.0)),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fees + details.received, 30_000);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(50.0), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_no_change_add_input_and_change() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let incoming_txid = wallet.database.borrow_mut().received_tx(
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)])
    -                    .send_all()
    -                    .add_utxo(OutPoint {
    -                        txid: incoming_txid,
    -                        vout: 0,
    -                    })
    -                    .enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        // NOTE: we don't set "send_all" here. so we have a transaction with only one input, but
    -        // here we are allowed to add more, and we will also have to add a change
    -        let (psbt, details) = wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(50.0)),
    -            )
    -            .unwrap();
    -
    -        let original_send_all_amount = original_details.sent - original_details.fees;
    -        assert_eq!(details.sent, original_details.sent + 50_000);
    -        assert_eq!(
    -            details.received,
    -            75_000 - original_send_all_amount - details.fees
    -        );
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            original_send_all_amount
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            75_000 - original_send_all_amount - details.fees
    -        );
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(50.0), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_add_input_change_dust() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        wallet.database.borrow_mut().received_tx(
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        assert_eq!(tx.input.len(), 1);
    -        assert_eq!(tx.output.len(), 2);
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let (psbt, details) = wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(140.0)),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(original_details.received, 5_000 - original_details.fees);
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fees, 30_000);
    -        assert_eq!(details.received, 0);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 1);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(140.0), @dust_change, @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_force_add_input() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let incoming_txid = wallet.database.borrow_mut().received_tx(
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        // the new fee_rate is low enough that just reducing the change would be fine, but we force
    -        // the addition of an extra input with `add_utxo()`
    -        let (psbt, details) = wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new()
    -                    .add_utxo(OutPoint {
    -                        txid: incoming_txid,
    -                        vout: 0,
    -                    })
    -                    .fee_rate(FeeRate::from_sat_per_vb(5.0)),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fees + details.received, 30_000);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(5.0), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_xprv() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
    -            .unwrap();
    -
    -        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
    -        assert_eq!(finalized, true);
    -
    -        let extracted = signed_psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_wif() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
    -            .unwrap();
    -
    -        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
    -        assert_eq!(finalized, true);
    -
    -        let extracted = signed_psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_xprv_no_hd_keypaths() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (mut psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 0)]).send_all())
    -            .unwrap();
    -
    -        psbt.inputs[0].hd_keypaths.clear();
    -        assert_eq!(psbt.inputs[0].hd_keypaths.len(), 0);
    -
    -        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
    -        assert_eq!(finalized, true);
    -
    -        let extracted = signed_psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/rbf.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/rbf.rs.html deleted file mode 100644 index 2f536bf64b..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/rbf.rs.html +++ /dev/null @@ -1,257 +0,0 @@ -rbf.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use crate::database::Database;
    -use crate::error::Error;
    -use crate::types::*;
    -
    -/// Filters unspent utxos
    -pub(super) fn filter_available<I: Iterator<Item = UTXO>, D: Database>(
    -    database: &D,
    -    iter: I,
    -) -> Result<Vec<UTXO>, Error> {
    -    Ok(iter
    -        .map(|utxo| {
    -            Ok(match database.get_tx(&utxo.outpoint.txid, true)? {
    -                None => None,
    -                Some(tx) if tx.height.is_none() => None,
    -                Some(_) => Some(utxo),
    -            })
    -        })
    -        .collect::<Result<Vec<_>, Error>>()?
    -        .into_iter()
    -        .filter_map(|x| x)
    -        .collect())
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::str::FromStr;
    -
    -    use bitcoin::{OutPoint, Transaction, TxIn, TxOut, Txid};
    -
    -    use super::*;
    -    use crate::database::{BatchOperations, MemoryDatabase};
    -
    -    fn add_transaction(
    -        database: &mut MemoryDatabase,
    -        spend: Vec<OutPoint>,
    -        outputs: Vec<u64>,
    -    ) -> Txid {
    -        let tx = Transaction {
    -            version: 1,
    -            lock_time: 0,
    -            input: spend
    -                .iter()
    -                .cloned()
    -                .map(|previous_output| TxIn {
    -                    previous_output,
    -                    ..Default::default()
    -                })
    -                .collect(),
    -            output: outputs
    -                .iter()
    -                .cloned()
    -                .map(|value| TxOut {
    -                    value,
    -                    ..Default::default()
    -                })
    -                .collect(),
    -        };
    -        let txid = tx.txid();
    -
    -        for input in &spend {
    -            database.del_utxo(input).unwrap();
    -        }
    -        for vout in 0..outputs.len() {
    -            database
    -                .set_utxo(&UTXO {
    -                    txout: tx.output[vout].clone(),
    -                    outpoint: OutPoint {
    -                        txid,
    -                        vout: vout as u32,
    -                    },
    -                    is_internal: true,
    -                })
    -                .unwrap();
    -        }
    -        database
    -            .set_tx(&TransactionDetails {
    -                txid,
    -                transaction: Some(tx),
    -                height: None,
    -                ..Default::default()
    -            })
    -            .unwrap();
    -
    -        txid
    -    }
    -
    -    #[test]
    -    fn test_filter_available() {
    -        let mut database = MemoryDatabase::new();
    -        add_transaction(
    -            &mut database,
    -            vec![OutPoint::from_str(
    -                "aad194c72fd5cfd16d23da9462930ca91e35df1cfee05242b62f4034f50c3d41:5",
    -            )
    -            .unwrap()],
    -            vec![50_000],
    -        );
    -
    -        let filtered =
    -            filter_available(&database, database.iter_utxos().unwrap().into_iter()).unwrap();
    -        assert_eq!(filtered, &[]);
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/signer.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/signer.rs.html deleted file mode 100644 index 8678817881..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/signer.rs.html +++ /dev/null @@ -1,1029 +0,0 @@ -signer.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! 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 std::sync::Arc;
    -//! # use std::str::FromStr;
    -//! # use bitcoin::*;
    -//! # use bitcoin::util::psbt;
    -//! # use bitcoin::util::bip32::Fingerprint;
    -//! # use bdk::signer::*;
    -//! # use bdk::database::*;
    -//! # use bdk::*;
    -//! # #[derive(Debug)]
    -//! # struct CustomHSM;
    -//! # impl CustomHSM {
    -//! #     fn sign_input(&self, _psbt: &mut psbt::PartiallySignedTransaction, _input: usize) -> Result<(), SignerError> {
    -//! #         Ok(())
    -//! #     }
    -//! #     fn connect() -> Self {
    -//! #         CustomHSM
    -//! #     }
    -//! # }
    -//! #[derive(Debug)]
    -//! struct CustomSigner {
    -//!     device: CustomHSM,
    -//! }
    -//!
    -//! impl CustomSigner {
    -//!     fn connect() -> Self {
    -//!         CustomSigner { device: CustomHSM::connect() }
    -//!     }
    -//! }
    -//!
    -//! impl Signer for CustomSigner {
    -//!     fn sign(
    -//!         &self,
    -//!         psbt: &mut psbt::PartiallySignedTransaction,
    -//!         input_index: Option<usize>,
    -//!     ) -> Result<(), SignerError> {
    -//!         let input_index = input_index.ok_or(SignerError::InputIndexOutOfRange)?;
    -//!         self.device.sign_input(psbt, input_index)?;
    -//!
    -//!         Ok(())
    -//!     }
    -//!
    -//!     fn sign_whole_tx(&self) -> bool {
    -//!         false
    -//!     }
    -//! }
    -//!
    -//! let custom_signer = CustomSigner::connect();
    -//!
    -//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -//! let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -//! wallet.add_signer(
    -//!     ScriptType::External,
    -//!     Fingerprint::from_str("e30f11b8").unwrap().into(),
    -//!     SignerOrdering(200),
    -//!     Arc::new(Box::new(custom_signer))
    -//! );
    -//!
    -//! # Ok::<_, bdk::Error>(())
    -//! ```
    -
    -use std::cmp::Ordering;
    -use std::collections::BTreeMap;
    -use std::fmt;
    -use std::ops::Bound::Included;
    -use std::sync::Arc;
    -
    -use bitcoin::blockdata::opcodes;
    -use bitcoin::blockdata::script::Builder as ScriptBuilder;
    -use bitcoin::hashes::{hash160, Hash};
    -use bitcoin::secp256k1::{Message, Secp256k1};
    -use bitcoin::util::bip32::{ExtendedPrivKey, Fingerprint};
    -use bitcoin::util::{bip143, psbt};
    -use bitcoin::{PrivateKey, SigHash, SigHashType};
    -
    -use miniscript::descriptor::{DescriptorPublicKey, DescriptorSecretKey, DescriptorXKey, KeyMap};
    -use miniscript::{Legacy, MiniscriptKey, Segwitv0};
    -
    -use crate::descriptor::XKeyUtils;
    -
    -/// Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among
    -/// multiple of them
    -#[derive(Debug, Clone, PartialEq, Eq, Hash)]
    -pub enum SignerId<Pk: MiniscriptKey> {
    -    PkHash(<Pk as MiniscriptKey>::Hash),
    -    Fingerprint(Fingerprint),
    -}
    -
    -impl From<hash160::Hash> for SignerId<DescriptorPublicKey> {
    -    fn from(hash: hash160::Hash) -> SignerId<DescriptorPublicKey> {
    -        SignerId::PkHash(hash)
    -    }
    -}
    -
    -impl From<Fingerprint> for SignerId<DescriptorPublicKey> {
    -    fn from(fing: Fingerprint) -> SignerId<DescriptorPublicKey> {
    -        SignerId::Fingerprint(fing)
    -    }
    -}
    -
    -/// Signing error
    -#[derive(Debug, PartialEq, Eq, Clone)]
    -pub enum SignerError {
    -    /// The private key is missing for the required public key
    -    MissingKey,
    -    /// The user canceled the operation
    -    UserCanceled,
    -    /// The sighash is missing in the PSBT input
    -    MissingSighash,
    -    /// 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 requied to sign this input
    -    MissingWitnessScript,
    -    /// The fingerprint and derivation path are missing from the psbt input
    -    MissingHDKeypath,
    -}
    -
    -impl fmt::Display for SignerError {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for SignerError {}
    -
    -/// Trait for signers
    -///
    -/// This trait can be implemented to provide customized signers to the wallet. For an example see
    -/// [`this module`](crate::wallet::signer)'s documentation.
    -pub trait Signer: fmt::Debug {
    -    /// Sign a PSBT
    -    ///
    -    /// The `input_index` argument is only provided if the wallet doesn't declare to sign the whole
    -    /// transaction in one go (see [`Signer::sign_whole_tx`]). Otherwise its value is `None` and
    -    /// can be ignored.
    -    fn sign(
    -        &self,
    -        psbt: &mut psbt::PartiallySignedTransaction,
    -        input_index: Option<usize>,
    -    ) -> Result<(), SignerError>;
    -
    -    /// Return whether or not the signer signs the whole transaction in one go instead of every
    -    /// input individually
    -    fn sign_whole_tx(&self) -> bool;
    -
    -    /// 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
    -    }
    -}
    -
    -impl Signer for DescriptorXKey<ExtendedPrivKey> {
    -    fn sign(
    -        &self,
    -        psbt: &mut psbt::PartiallySignedTransaction,
    -        input_index: Option<usize>,
    -    ) -> Result<(), SignerError> {
    -        let input_index = input_index.unwrap();
    -        if input_index >= psbt.inputs.len() {
    -            return Err(SignerError::InputIndexOutOfRange);
    -        }
    -
    -        let deriv_path = match psbt.inputs[input_index]
    -            .hd_keypaths
    -            .iter()
    -            .filter_map(|(_, &(fingerprint, ref path))| self.matches(fingerprint.clone(), &path))
    -            .next()
    -        {
    -            Some(deriv_path) => deriv_path,
    -            None => return Ok(()), // TODO: should report an error maybe?
    -        };
    -
    -        let ctx = Secp256k1::signing_only();
    -
    -        let derived_key = self.xkey.derive_priv(&ctx, &deriv_path).unwrap();
    -        derived_key.private_key.sign(psbt, Some(input_index))
    -    }
    -
    -    fn sign_whole_tx(&self) -> bool {
    -        false
    -    }
    -
    -    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
    -        Some(DescriptorSecretKey::XPrv(self.clone()))
    -    }
    -}
    -
    -impl Signer for PrivateKey {
    -    fn sign(
    -        &self,
    -        psbt: &mut psbt::PartiallySignedTransaction,
    -        input_index: Option<usize>,
    -    ) -> Result<(), SignerError> {
    -        let input_index = input_index.unwrap();
    -        if input_index >= psbt.inputs.len() {
    -            return Err(SignerError::InputIndexOutOfRange);
    -        }
    -
    -        let ctx = Secp256k1::signing_only();
    -
    -        let pubkey = self.public_key(&ctx);
    -        if psbt.inputs[input_index].partial_sigs.contains_key(&pubkey) {
    -            return Ok(());
    -        }
    -
    -        // FIXME: use the presence of `witness_utxo` as an indication that we should make a bip143
    -        // sig. Does this make sense? Should we add an extra argument to explicitly swith between
    -        // these? The original idea was to declare sign() as sign<Ctx: ScriptContex>() and use Ctx,
    -        // but that violates the rules for trait-objects, so we can't do it.
    -        let (hash, sighash) = match psbt.inputs[input_index].witness_utxo {
    -            Some(_) => Segwitv0::sighash(psbt, input_index)?,
    -            None => Legacy::sighash(psbt, input_index)?,
    -        };
    -
    -        let signature = ctx.sign(
    -            &Message::from_slice(&hash.into_inner()[..]).unwrap(),
    -            &self.key,
    -        );
    -
    -        let mut final_signature = Vec::with_capacity(75);
    -        final_signature.extend_from_slice(&signature.serialize_der());
    -        final_signature.push(sighash.as_u32() as u8);
    -
    -        psbt.inputs[input_index]
    -            .partial_sigs
    -            .insert(pubkey, final_signature);
    -
    -        Ok(())
    -    }
    -
    -    fn sign_whole_tx(&self) -> bool {
    -        false
    -    }
    -
    -    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
    -        Some(DescriptorSecretKey::PrivKey(self.clone()))
    -    }
    -}
    -
    -/// 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 std::default::Default for SignerOrdering {
    -    fn default() -> Self {
    -        SignerOrdering(100)
    -    }
    -}
    -
    -#[derive(Debug, Clone)]
    -struct SignersContainerKey<Pk: MiniscriptKey> {
    -    id: SignerId<Pk>,
    -    ordering: SignerOrdering,
    -}
    -
    -impl<Pk: MiniscriptKey> From<(SignerId<Pk>, SignerOrdering)> for SignersContainerKey<Pk> {
    -    fn from(tuple: (SignerId<Pk>, SignerOrdering)) -> Self {
    -        SignersContainerKey {
    -            id: tuple.0,
    -            ordering: tuple.1,
    -        }
    -    }
    -}
    -
    -/// Container for multiple signers
    -#[derive(Debug, Default, Clone)]
    -pub struct SignersContainer<Pk: MiniscriptKey>(
    -    BTreeMap<SignersContainerKey<Pk>, Arc<Box<dyn Signer>>>,
    -);
    -
    -impl SignersContainer<DescriptorPublicKey> {
    -    pub fn as_key_map(&self) -> KeyMap {
    -        self.0
    -            .values()
    -            .filter_map(|signer| signer.descriptor_secret_key())
    -            .filter_map(|secret| secret.as_public().ok().map(|public| (public, secret)))
    -            .collect()
    -    }
    -}
    -
    -impl From<KeyMap> for SignersContainer<DescriptorPublicKey> {
    -    fn from(keymap: KeyMap) -> SignersContainer<DescriptorPublicKey> {
    -        let mut container = SignersContainer::new();
    -
    -        for (_, secret) in keymap {
    -            match secret {
    -                DescriptorSecretKey::PrivKey(private_key) => container.add_external(
    -                    SignerId::from(
    -                        private_key
    -                            .public_key(&Secp256k1::signing_only())
    -                            .to_pubkeyhash(),
    -                    ),
    -                    SignerOrdering::default(),
    -                    Arc::new(Box::new(private_key)),
    -                ),
    -                DescriptorSecretKey::XPrv(xprv) => container.add_external(
    -                    SignerId::from(xprv.root_fingerprint()),
    -                    SignerOrdering::default(),
    -                    Arc::new(Box::new(xprv)),
    -                ),
    -            };
    -        }
    -
    -        container
    -    }
    -}
    -
    -impl<Pk: MiniscriptKey> SignersContainer<Pk> {
    -    /// 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 previosuly in the container, if any
    -    pub fn add_external(
    -        &mut self,
    -        id: SignerId<Pk>,
    -        ordering: SignerOrdering,
    -        signer: Arc<Box<dyn Signer>>,
    -    ) -> Option<Arc<Box<dyn Signer>>> {
    -        self.0.insert((id, ordering).into(), signer)
    -    }
    -
    -    /// Removes a signer from the container and returns it
    -    pub fn remove(
    -        &mut self,
    -        id: SignerId<Pk>,
    -        ordering: SignerOrdering,
    -    ) -> Option<Arc<Box<dyn Signer>>> {
    -        self.0.remove(&(id, ordering).into())
    -    }
    -
    -    /// Returns the list of identifiers of all the signers in the container
    -    pub fn ids(&self) -> Vec<&SignerId<Pk>> {
    -        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<Box<dyn Signer>>> {
    -        self.0.values().collect()
    -    }
    -
    -    /// Finds the signer with lowest ordering for a given id in the container.
    -    pub fn find(&self, id: SignerId<Pk>) -> Option<&Arc<Box<dyn Signer>>> {
    -        self.0
    -            .range((
    -                Included(&(id.clone(), SignerOrdering(0)).into()),
    -                Included(&(id, SignerOrdering(usize::MAX)).into()),
    -            ))
    -            .map(|(_, v)| v)
    -            .nth(0)
    -    }
    -}
    -
    -pub(crate) trait ComputeSighash {
    -    fn sighash(
    -        psbt: &psbt::PartiallySignedTransaction,
    -        input_index: usize,
    -    ) -> Result<(SigHash, SigHashType), SignerError>;
    -}
    -
    -impl ComputeSighash for Legacy {
    -    fn sighash(
    -        psbt: &psbt::PartiallySignedTransaction,
    -        input_index: usize,
    -    ) -> Result<(SigHash, SigHashType), SignerError> {
    -        if input_index >= psbt.inputs.len() {
    -            return Err(SignerError::InputIndexOutOfRange);
    -        }
    -
    -        let psbt_input = &psbt.inputs[input_index];
    -        let tx_input = &psbt.global.unsigned_tx.input[input_index];
    -
    -        let sighash = psbt_input.sighash_type.ok_or(SignerError::MissingSighash)?;
    -        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((
    -            psbt.global
    -                .unsigned_tx
    -                .signature_hash(input_index, &script, sighash.as_u32()),
    -            sighash,
    -        ))
    -    }
    -}
    -
    -impl ComputeSighash for Segwitv0 {
    -    fn sighash(
    -        psbt: &psbt::PartiallySignedTransaction,
    -        input_index: usize,
    -    ) -> Result<(SigHash, SigHashType), SignerError> {
    -        if input_index >= psbt.inputs.len() {
    -            return Err(SignerError::InputIndexOutOfRange);
    -        }
    -
    -        let psbt_input = &psbt.inputs[input_index];
    -
    -        let sighash = psbt_input.sighash_type.ok_or(SignerError::MissingSighash)?;
    -
    -        let witness_utxo = psbt_input
    -            .witness_utxo
    -            .as_ref()
    -            .ok_or(SignerError::MissingNonWitnessUtxo)?;
    -        let value = witness_utxo.value;
    -
    -        let script = match &psbt_input.witness_script {
    -            &Some(ref witness_script) => witness_script.clone(),
    -            &None => {
    -                if witness_utxo.script_pubkey.is_v0_p2wpkh() {
    -                    ScriptBuilder::new()
    -                        .push_opcode(opcodes::all::OP_DUP)
    -                        .push_opcode(opcodes::all::OP_HASH160)
    -                        .push_slice(&witness_utxo.script_pubkey[2..])
    -                        .push_opcode(opcodes::all::OP_EQUALVERIFY)
    -                        .push_opcode(opcodes::all::OP_CHECKSIG)
    -                        .into_script()
    -                } else {
    -                    return Err(SignerError::MissingWitnessScript);
    -                }
    -            }
    -        };
    -
    -        Ok((
    -            bip143::SigHashCache::new(&psbt.global.unsigned_tx).signature_hash(
    -                input_index,
    -                &script,
    -                value,
    -                sighash,
    -            ),
    -            sighash,
    -        ))
    -    }
    -}
    -
    -impl<Pk: MiniscriptKey> PartialOrd for SignersContainerKey<Pk> {
    -    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
    -        Some(self.cmp(other))
    -    }
    -}
    -
    -impl<Pk: MiniscriptKey> Ord for SignersContainerKey<Pk> {
    -    fn cmp(&self, other: &Self) -> Ordering {
    -        self.ordering.cmp(&other.ordering)
    -    }
    -}
    -
    -impl<Pk: MiniscriptKey> PartialEq for SignersContainerKey<Pk> {
    -    fn eq(&self, other: &Self) -> bool {
    -        self.ordering == other.ordering
    -    }
    -}
    -
    -impl<Pk: MiniscriptKey> Eq for SignersContainerKey<Pk> {}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/time.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/time.rs.html deleted file mode 100644 index a608dd4158..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/time.rs.html +++ /dev/null @@ -1,175 +0,0 @@ -time.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Cross-platform time
    -//!
    -//! This module provides a function to get the current timestamp that works on all the platforms
    -//! supported by the library.
    -//!
    -//! It can be useful to compare it with the timestamps found in
    -//! [`TransactionDetails`](crate::types::TransactionDetails).
    -
    -use std::time::Duration;
    -
    -#[cfg(target_arch = "wasm32")]
    -use js_sys::Date;
    -#[cfg(not(target_arch = "wasm32"))]
    -use std::time::{Instant as SystemInstant, SystemTime, UNIX_EPOCH};
    -
    -/// Return the current timestamp in seconds
    -#[cfg(not(target_arch = "wasm32"))]
    -pub fn get_timestamp() -> u64 {
    -    SystemTime::now()
    -        .duration_since(UNIX_EPOCH)
    -        .unwrap()
    -        .as_secs()
    -}
    -/// Return the current timestamp in seconds
    -#[cfg(target_arch = "wasm32")]
    -pub fn get_timestamp() -> u64 {
    -    let millis = Date::now();
    -
    -    (millis / 1000.0) as u64
    -}
    -
    -#[cfg(not(target_arch = "wasm32"))]
    -pub(crate) struct Instant(SystemInstant);
    -#[cfg(target_arch = "wasm32")]
    -pub(crate) struct Instant(Duration);
    -
    -impl Instant {
    -    #[cfg(not(target_arch = "wasm32"))]
    -    pub fn new() -> Self {
    -        Instant(SystemInstant::now())
    -    }
    -    #[cfg(target_arch = "wasm32")]
    -    pub fn new() -> Self {
    -        let millis = Date::now();
    -
    -        let secs = millis / 1000.0;
    -        let nanos = (millis % 1000.0) * 1e6;
    -
    -        Instant(Duration::new(secs as u64, nanos as u32))
    -    }
    -
    -    #[cfg(not(target_arch = "wasm32"))]
    -    pub fn elapsed(&self) -> Duration {
    -        self.0.elapsed()
    -    }
    -    #[cfg(target_arch = "wasm32")]
    -    pub fn elapsed(&self) -> Duration {
    -        let now = Instant::new();
    -
    -        now.0.checked_sub(self.0).unwrap_or(Duration::new(0, 0))
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/tx_builder.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/tx_builder.rs.html deleted file mode 100644 index 389d6daf07..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/tx_builder.rs.html +++ /dev/null @@ -1,979 +0,0 @@ -tx_builder.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Transaction builder
    -//!
    -//! ## Example
    -//!
    -//! ```
    -//! # use std::str::FromStr;
    -//! # use bitcoin::*;
    -//! # use bdk::*;
    -//! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -//! // Create a transaction with one output to `to_address` of 50_000 satoshi, with a custom fee rate
    -//! // of 5.0 satoshi/vbyte, only spending non-change outputs and with RBF signaling
    -//! // enabled
    -//! let builder = TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
    -//!     .fee_rate(FeeRate::from_sat_per_vb(5.0))
    -//!     .do_not_spend_change()
    -//!     .enable_rbf();
    -//! ```
    -
    -use std::collections::BTreeMap;
    -use std::default::Default;
    -
    -use bitcoin::{OutPoint, Script, SigHashType, Transaction};
    -
    -use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm};
    -use crate::types::{FeeRate, UTXO};
    -
    -/// A transaction builder
    -///
    -/// This structure contains the configuration that the wallet must follow to build a transaction.
    -///
    -/// For an example see [this module](super::tx_builder)'s documentation;
    -#[derive(Debug, Default)]
    -pub struct TxBuilder<Cs: CoinSelectionAlgorithm> {
    -    pub(crate) recipients: Vec<(Script, u64)>,
    -    pub(crate) send_all: bool,
    -    pub(crate) fee_rate: Option<FeeRate>,
    -    pub(crate) policy_path: Option<BTreeMap<String, Vec<usize>>>,
    -    pub(crate) utxos: Option<Vec<OutPoint>>,
    -    pub(crate) unspendable: Option<Vec<OutPoint>>,
    -    pub(crate) sighash: Option<SigHashType>,
    -    pub(crate) ordering: TxOrdering,
    -    pub(crate) locktime: Option<u32>,
    -    pub(crate) rbf: Option<u32>,
    -    pub(crate) version: Option<Version>,
    -    pub(crate) change_policy: ChangeSpendPolicy,
    -    pub(crate) force_non_witness_utxo: bool,
    -    pub(crate) coin_selection: Cs,
    -}
    -
    -impl TxBuilder<DefaultCoinSelectionAlgorithm> {
    -    /// Create an empty builder
    -    pub fn new() -> Self {
    -        Self::default()
    -    }
    -
    -    /// Create a builder starting from a list of recipients
    -    pub fn with_recipients(recipients: Vec<(Script, u64)>) -> Self {
    -        Self::default().set_recipients(recipients)
    -    }
    -}
    -
    -impl<Cs: CoinSelectionAlgorithm> TxBuilder<Cs> {
    -    /// Replace the recipients already added with a new list
    -    pub fn set_recipients(mut self, recipients: Vec<(Script, u64)>) -> Self {
    -        self.recipients = recipients;
    -        self
    -    }
    -
    -    /// Add a recipient to the internal list
    -    pub fn add_recipient(mut self, script_pubkey: Script, amount: u64) -> Self {
    -        self.recipients.push((script_pubkey, amount));
    -        self
    -    }
    -
    -    /// Send all the selected utxos to a single output
    -    ///
    -    /// Adding more than one recipients with this option enabled will result in an error.
    -    ///
    -    /// The value associated with the only recipient is irrelevant and will be replaced by the wallet.
    -    pub fn send_all(mut self) -> Self {
    -        self.send_all = true;
    -        self
    -    }
    -
    -    /// Set a custom fee rate
    -    pub fn fee_rate(mut self, fee_rate: FeeRate) -> Self {
    -        self.fee_rate = Some(fee_rate);
    -        self
    -    }
    -
    -    /// Set the policy path to use while creating the transaction
    -    ///
    -    /// 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)).
    -    pub fn policy_path(mut self, policy_path: BTreeMap<String, Vec<usize>>) -> Self {
    -        self.policy_path = Some(policy_path);
    -        self
    -    }
    -
    -    /// Replace the internal list of utxos that **must** be spent with a new list
    -    ///
    -    /// 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 utxos(mut self, utxos: Vec<OutPoint>) -> Self {
    -        self.utxos = Some(utxos);
    -        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, utxo: OutPoint) -> Self {
    -        self.utxos.get_or_insert(vec![]).push(utxo);
    -        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::utxos`] and
    -    /// [`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>) -> Self {
    -        self.unspendable = Some(unspendable);
    -        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::utxos`] and
    -    /// [`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) -> Self {
    -        self.unspendable.get_or_insert(vec![]).push(unspendable);
    -        self
    -    }
    -
    -    /// Sign with a specific sig hash
    -    ///
    -    /// **Use this option very carefully**
    -    pub fn sighash(mut self, sighash: SigHashType) -> Self {
    -        self.sighash = Some(sighash);
    -        self
    -    }
    -
    -    /// Choose the ordering for inputs and outputs of the transaction
    -    pub fn ordering(mut self, ordering: TxOrdering) -> Self {
    -        self.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: u32) -> Self {
    -        self.locktime = Some(locktime);
    -        self
    -    }
    -
    -    /// Enable signaling RBF
    -    ///
    -    /// This will use the default nSequence value of `0xFFFFFFFD`.
    -    pub fn enable_rbf(self) -> Self {
    -        self.enable_rbf_with_sequence(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.
    -    pub fn enable_rbf_with_sequence(mut self, nsequence: u32) -> Self {
    -        self.rbf = Some(nsequence);
    -        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: u32) -> Self {
    -        self.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) -> Self {
    -        self.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) -> Self {
    -        self.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) -> Self {
    -        self.change_policy = change_policy;
    -        self
    -    }
    -
    -    /// Fill-in the [`psbt::Input::non_witness_utxo`](bitcoin::util::psbt::Input::non_witness_utxo) field even if the wallet only has SegWit
    -    /// descriptors.
    -    ///
    -    /// This is useful for signers which always require it, like Trezor hardware wallets.
    -    pub fn force_non_witness_utxo(mut self) -> Self {
    -        self.force_non_witness_utxo = true;
    -        self
    -    }
    -
    -    /// Choose the coin selection algorithm
    -    ///
    -    /// Overrides the [`DefaultCoinSelectionAlgorithm`](super::coin_selection::DefaultCoinSelectionAlgorithm).
    -    pub fn coin_selection<P: CoinSelectionAlgorithm>(self, coin_selection: P) -> TxBuilder<P> {
    -        TxBuilder {
    -            recipients: self.recipients,
    -            send_all: self.send_all,
    -            fee_rate: self.fee_rate,
    -            policy_path: self.policy_path,
    -            utxos: self.utxos,
    -            unspendable: self.unspendable,
    -            sighash: self.sighash,
    -            ordering: self.ordering,
    -            locktime: self.locktime,
    -            rbf: self.rbf,
    -            version: self.version,
    -            change_policy: self.change_policy,
    -            force_non_witness_utxo: self.force_non_witness_utxo,
    -            coin_selection,
    -        }
    -    }
    -}
    -
    -/// Ordering of the transaction's inputs and outputs
    -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
    -pub enum TxOrdering {
    -    /// Randomized (default)
    -    Shuffle,
    -    /// Unchanged
    -    Untouched,
    -    /// BIP69 / Lexicographic
    -    BIP69Lexicographic,
    -}
    -
    -impl Default for TxOrdering {
    -    fn default() -> Self {
    -        TxOrdering::Shuffle
    -    }
    -}
    -
    -impl TxOrdering {
    -    pub fn sort_tx(&self, tx: &mut Transaction) {
    -        match self {
    -            TxOrdering::Untouched => {}
    -            TxOrdering::Shuffle => {
    -                use rand::seq::SliceRandom;
    -                #[cfg(test)]
    -                use rand::SeedableRng;
    -
    -                #[cfg(not(test))]
    -                let mut rng = rand::thread_rng();
    -                #[cfg(test)]
    -                let mut rng = rand::rngs::StdRng::seed_from_u64(0);
    -
    -                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) u32);
    -
    -impl Default for Version {
    -    fn default() -> Self {
    -        Version(1)
    -    }
    -}
    -
    -/// Policy regarding the use of change outputs when creating a transaction
    -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
    -pub enum ChangeSpendPolicy {
    -    /// Use both change and non-change outputs (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 Default for ChangeSpendPolicy {
    -    fn default() -> Self {
    -        ChangeSpendPolicy::ChangeAllowed
    -    }
    -}
    -
    -impl ChangeSpendPolicy {
    -    pub(crate) fn filter_utxos<I: Iterator<Item = UTXO>>(&self, iter: I) -> Vec<UTXO> {
    -        match self {
    -            ChangeSpendPolicy::ChangeAllowed => iter.collect(),
    -            ChangeSpendPolicy::OnlyChange => iter.filter(|utxo| utxo.is_internal).collect(),
    -            ChangeSpendPolicy::ChangeForbidden => iter.filter(|utxo| !utxo.is_internal).collect(),
    -        }
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    const ORDERING_TEST_TX: &'static 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 bitcoin::consensus::deserialize;
    -    use bitcoin::hashes::hex::FromHex;
    -
    -    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();
    -
    -        TxOrdering::Shuffle.sort_tx(&mut tx);
    -
    -        assert_eq!(original_tx.input, tx.input);
    -        assert_ne!(original_tx.output, tx.output);
    -    }
    -
    -    #[test]
    -    fn test_output_ordering_bip69() {
    -        use std::str::FromStr;
    -
    -        let original_tx = ordering_test_tx!();
    -        let mut tx = original_tx.clone();
    -
    -        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, 800);
    -        assert_eq!(tx.output[1].script_pubkey, From::from(vec![0xAA]));
    -        assert_eq!(tx.output[2].script_pubkey, From::from(vec![0xAA, 0xEE]));
    -    }
    -
    -    fn get_test_utxos() -> Vec<UTXO> {
    -        vec![
    -            UTXO {
    -                outpoint: OutPoint {
    -                    txid: Default::default(),
    -                    vout: 0,
    -                },
    -                txout: Default::default(),
    -                is_internal: false,
    -            },
    -            UTXO {
    -                outpoint: OutPoint {
    -                    txid: Default::default(),
    -                    vout: 1,
    -                },
    -                txout: Default::default(),
    -                is_internal: true,
    -            },
    -        ]
    -    }
    -
    -    #[test]
    -    fn test_change_spend_policy_default() {
    -        let change_spend_policy = ChangeSpendPolicy::default();
    -        let filtered = change_spend_policy.filter_utxos(get_test_utxos().into_iter());
    -
    -        assert_eq!(filtered.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_change_spend_policy_no_internal() {
    -        let change_spend_policy = ChangeSpendPolicy::ChangeForbidden;
    -        let filtered = change_spend_policy.filter_utxos(get_test_utxos().into_iter());
    -
    -        assert_eq!(filtered.len(), 1);
    -        assert_eq!(filtered[0].is_internal, false);
    -    }
    -
    -    #[test]
    -    fn test_change_spend_policy_only_internal() {
    -        let change_spend_policy = ChangeSpendPolicy::OnlyChange;
    -        let filtered = change_spend_policy.filter_utxos(get_test_utxos().into_iter());
    -
    -        assert_eq!(filtered.len(), 1);
    -        assert_eq!(filtered[0].is_internal, true);
    -    }
    -
    -    #[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/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/utils.rs.html b/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/utils.rs.html deleted file mode 100644 index 7fda4f9243..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/src/bdk/wallet/utils.rs.html +++ /dev/null @@ -1,311 +0,0 @@ -utils.rs.html -- 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use miniscript::{MiniscriptKey, Satisfier};
    -
    -// De-facto standard "dust limit" (even though it should change based on the output type)
    -const DUST_LIMIT_SATOSHI: u64 = 546;
    -
    -/// Trait to check if a value is below the dust limit
    -// we implement this trait to make sure we don't mess up the comparison with off-by-one like a <
    -// instead of a <= etc. The constant value for the dust limit is not public on purpose, to
    -// encourage the usage of this trait.
    -pub trait IsDust {
    -    /// Check whether or not a value is below dust limit
    -    fn is_dust(&self) -> bool;
    -}
    -
    -impl IsDust for u64 {
    -    fn is_dust(&self) -> bool {
    -        *self <= DUST_LIMIT_SATOSHI
    -    }
    -}
    -
    -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,
    -        }
    -    }
    -}
    -
    -impl<Pk: MiniscriptKey> Satisfier<Pk> for After {
    -    fn check_after(&self, n: u32) -> bool {
    -        if let Some(current_height) = self.current_height {
    -            current_height >= n
    -        } 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> Satisfier<Pk> for Older {
    -    fn check_older(&self, n: u32) -> bool {
    -        if let Some(current_height) = self.current_height {
    -            // TODO: test >= / >
    -            current_height as u64 >= self.create_height.unwrap_or(0) as u64 + n as u64
    -        } else {
    -            self.assume_height_reached
    -        }
    -    }
    -}
    -
    -pub struct ChunksIterator<I: Iterator> {
    -    iter: I,
    -    size: usize,
    -}
    -
    -impl<I: Iterator> ChunksIterator<I> {
    -    pub fn new(iter: I, size: usize) -> Self {
    -        ChunksIterator { iter, size }
    -    }
    -}
    -
    -impl<I: Iterator> Iterator for ChunksIterator<I> {
    -    type Item = Vec<<I as std::iter::Iterator>::Item>;
    -
    -    fn next(&mut self) -> Option<Self::Item> {
    -        let mut v = Vec::new();
    -        for _ in 0..self.size {
    -            let e = self.iter.next();
    -
    -            match e {
    -                None => break,
    -                Some(val) => v.push(val),
    -            }
    -        }
    -
    -        if v.is_empty() {
    -            return None;
    -        }
    -
    -        Some(v)
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use crate::types::FeeRate;
    -
    -    #[test]
    -    fn test_fee_from_btc_per_kb() {
    -        let fee = FeeRate::from_btc_per_kvb(1e-5);
    -        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
    -    }
    -
    -    #[test]
    -    fn test_fee_from_sats_vbyte() {
    -        let fee = FeeRate::from_sat_per_vb(1.0);
    -        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
    -    }
    -
    -    #[test]
    -    fn test_fee_default_min_relay_fee() {
    -        let fee = FeeRate::default_min_relay_fee();
    -        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/storage.js b/static/docs-rs/bdk/0.1.0-beta.1/storage.js deleted file mode 100644 index 1b5225126f..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/storage.js +++ /dev/null @@ -1 +0,0 @@ -var resourcesSuffix="";var currentTheme=document.getElementById("themeStyle");var mainTheme=document.getElementById("mainThemeStyle");var savedHref=[];function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(!elem||!elem.classList){return}elem.classList.add(className)}function removeClass(elem,className){if(!elem||!elem.classList){return}elem.classList.remove(className)}function onEach(arr,func,reversed){if(arr&&arr.length>0&&func){var length=arr.length;var i;if(reversed!==true){for(i=0;i=0;--i){if(func(arr[i])===true){return true}}}}return false}function onEachLazy(lazyArray,func,reversed){return onEach(Array.prototype.slice.call(lazyArray),func,reversed)}function hasOwnProperty(obj,property){return Object.prototype.hasOwnProperty.call(obj,property)}function usableLocalStorage(){if(typeof Storage==="undefined"){return false}try{return window.localStorage!==null&&window.localStorage!==undefined}catch(err){return false}}function updateLocalStorage(name,value){if(usableLocalStorage()){localStorage[name]=value}else{}}function getCurrentValue(name){if(usableLocalStorage()&&localStorage[name]!==undefined){return localStorage[name]}return null}function switchTheme(styleElem,mainStyleElem,newTheme,saveTheme){var fullBasicCss="rustdoc"+resourcesSuffix+".css";var fullNewTheme=newTheme+resourcesSuffix+".css";var newHref=mainStyleElem.href.replace(fullBasicCss,fullNewTheme);if(styleElem.href===newHref){return}var found=false;if(savedHref.length===0){onEachLazy(document.getElementsByTagName("link"),function(el){savedHref.push(el.href)})}onEach(savedHref,function(el){if(el===newHref){found=true;return true}});if(found===true){styleElem.href=newHref;if(saveTheme===true){updateLocalStorage("rustdoc-theme",newTheme)}}}function getSystemValue(){var property=getComputedStyle(document.documentElement).getPropertyValue('content');return property.replace(/[\"\']/g,"")}switchTheme(currentTheme,mainTheme,getCurrentValue("rustdoc-theme")||getSystemValue()||"light",false) \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/theme.js b/static/docs-rs/bdk/0.1.0-beta.1/theme.js deleted file mode 100644 index ebd1a87271..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/theme.js +++ /dev/null @@ -1 +0,0 @@ -var themes=document.getElementById("theme-choices");var themePicker=document.getElementById("theme-picker");function showThemeButtonState(){themes.style.display="block";themePicker.style.borderBottomRightRadius="0";themePicker.style.borderBottomLeftRadius="0"}function hideThemeButtonState(){themes.style.display="none";themePicker.style.borderBottomRightRadius="3px";themePicker.style.borderBottomLeftRadius="3px"}function switchThemeButtonState(){if(themes.style.display==="block"){hideThemeButtonState()}else{showThemeButtonState()}};function handleThemeButtonsBlur(e){var active=document.activeElement;var related=e.relatedTarget;if(active.id!=="themePicker"&&(!active.parentNode||active.parentNode.id!=="theme-choices")&&(!related||(related.id!=="themePicker"&&(!related.parentNode||related.parentNode.id!=="theme-choices")))){hideThemeButtonState()}}themePicker.onclick=switchThemeButtonState;themePicker.onblur=handleThemeButtonsBlur;["dark","light"].forEach(function(item){var but=document.createElement('button');but.textContent=item;but.onclick=function(el){switchTheme(currentTheme,mainTheme,item,true)};but.onblur=handleThemeButtonsBlur;themes.appendChild(but)}) \ No newline at end of file diff --git a/static/docs-rs/bdk/0.1.0-beta.1/wheel.svg b/static/docs-rs/bdk/0.1.0-beta.1/wheel.svg deleted file mode 100644 index 01da3b24c7..0000000000 --- a/static/docs-rs/bdk/0.1.0-beta.1/wheel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/static/docs-rs/bdk/index.html b/static/docs-rs/bdk/index.html deleted file mode 100644 index 2a1a8bba18..0000000000 --- a/static/docs-rs/bdk/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - Redirect - - - -

    - You are being re-directed to the latest version.
    - If that doesn't happen click here. -

    - - diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/.lock b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/.lock deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/COPYRIGHT.txt b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/COPYRIGHT.txt deleted file mode 100644 index af77776cca..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/COPYRIGHT.txt +++ /dev/null @@ -1,45 +0,0 @@ -These documentation pages include resources by third parties. This copyright -file applies only to those resources. The following third party resources are -included, and carry their own copyright notices and license terms: - -* Fira Sans (FiraSans-Regular.woff, FiraSans-Medium.woff): - - Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ - with Reserved Font Name Fira Sans. - - Copyright (c) 2014, Telefonica S.A. - - Licensed under the SIL Open Font License, Version 1.1. - See FiraSans-LICENSE.txt. - -* rustdoc.css, main.js, and playpen.js: - - Copyright 2015 The Rust Developers. - Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or - the MIT license (LICENSE-MIT.txt) at your option. - -* normalize.css: - - Copyright (c) Nicolas Gallagher and Jonathan Neal. - Licensed under the MIT license (see LICENSE-MIT.txt). - -* Source Code Pro (SourceCodePro-Regular.woff, SourceCodePro-Semibold.woff): - - Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), - with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark - of Adobe Systems Incorporated in the United States and/or other countries. - - Licensed under the SIL Open Font License, Version 1.1. - See SourceCodePro-LICENSE.txt. - -* Source Serif Pro (SourceSerifPro-Regular.ttf.woff, - SourceSerifPro-Bold.ttf.woff, SourceSerifPro-It.ttf.woff): - - Copyright 2014 Adobe Systems Incorporated (http://www.adobe.com/), with - Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of - Adobe Systems Incorporated in the United States and/or other countries. - - Licensed under the SIL Open Font License, Version 1.1. - See SourceSerifPro-LICENSE.txt. - -This copyright file is intended to be distributed with rustdoc output. diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-LICENSE.txt b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-LICENSE.txt deleted file mode 100644 index d444ea92b6..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-LICENSE.txt +++ /dev/null @@ -1,94 +0,0 @@ -Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. -with Reserved Font Name < Fira >, - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-Medium.woff b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-Medium.woff deleted file mode 100644 index 7d742c5fb7..0000000000 Binary files a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-Medium.woff and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-Regular.woff b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-Regular.woff deleted file mode 100644 index d8e0363f4e..0000000000 Binary files a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/FiraSans-Regular.woff and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/LICENSE-APACHE.txt b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/LICENSE-APACHE.txt deleted file mode 100644 index 16fe87b06e..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/LICENSE-APACHE.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/LICENSE-MIT.txt b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/LICENSE-MIT.txt deleted file mode 100644 index 31aa79387f..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/LICENSE-MIT.txt +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-LICENSE.txt b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-LICENSE.txt deleted file mode 100644 index 07542572e3..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-LICENSE.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. - -This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-Regular.woff b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-Regular.woff deleted file mode 100644 index 5576670903..0000000000 Binary files a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-Regular.woff and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-Semibold.woff b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-Semibold.woff deleted file mode 100644 index ca972a11dc..0000000000 Binary files a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceCodePro-Semibold.woff and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-Bold.ttf.woff b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-Bold.ttf.woff deleted file mode 100644 index ca254318fe..0000000000 Binary files a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-Bold.ttf.woff and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-It.ttf.woff b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-It.ttf.woff deleted file mode 100644 index a287bbe6ed..0000000000 Binary files a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-It.ttf.woff and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-LICENSE.md b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-LICENSE.md deleted file mode 100644 index 22cb755f2f..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-LICENSE.md +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2014-2018 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. - -This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-Regular.ttf.woff b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-Regular.ttf.woff deleted file mode 100644 index a3d55cfdf2..0000000000 Binary files a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/SourceSerifPro-Regular.ttf.woff and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/ayu.css b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/ayu.css deleted file mode 100644 index ae61550be2..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/ayu.css +++ /dev/null @@ -1 +0,0 @@ - body{background-color:#0f1419;color:#c5c5c5;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:white;}h1.fqn{border-bottom-color:#5c6773;}h1.fqn a{color:#fff;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod){border-bottom-color:#5c6773;}h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){border:none;}.in-band{background-color:#0f1419;}.invisible{background:rgba(0,0,0,0);}code{color:#ffb454;}h3>code,h4>code,h5>code{color:#e6e1cf;}pre>code{color:#e6e1cf;}span code{color:#e6e1cf;}.docblock a>code{color:#39AFD7 !important;}.docblock code,.docblock-short code{background-color:#191f26;}pre{color:#e6e1cf;background-color:#191f26;}.sidebar{background-color:#14191f;}.logo-container.rust-logo>img{filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);}*{scrollbar-color:#5c6773 transparent;}.sidebar{scrollbar-color:#5c6773 transparent;}::-webkit-scrollbar-track{background-color:transparent;}::-webkit-scrollbar-thumb{background-color:#5c6773;}.sidebar::-webkit-scrollbar-track{background-color:transparent;}.sidebar::-webkit-scrollbar-thumb{background-color:#5c6773;}.sidebar .current{background-color:transparent;color:#ffb44c;}.source .sidebar{background-color:#0f1419;}.sidebar .location{border-color:#000;background-color:#0f1419;color:#fff;}.sidebar-elems .location{color:#ff7733;}.sidebar-elems .location a{color:#fff;}.sidebar .version{border-bottom-color:#424c57;}.sidebar-title{border-top-color:#5c6773;border-bottom-color:#5c6773;}.block a:hover{background:transparent;color:#ffb44c;}.line-numbers span{color:#5c6773;}.line-numbers .line-highlighted{color:#708090;background-color:rgba(255,236,164,0.06);padding-right:4px;border-right:1px solid #ffb44c;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#5c6773;}.docblock table,.docblock table td,.docblock table th{border-color:#5c6773;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#c5c5c5;}.content .highlighted{color:#000 !important;background-color:#c6afb3;}.content .highlighted a,.content .highlighted span{color:#000 !important;}.content .highlighted{background-color:#c6afb3;}.search-results a{color:#0096cf;}.search-results a span.desc{color:#c5c5c5;}.content .item-info::before{color:#ccc;}.content span.foreigntype,.content a.foreigntype{color:#ef57ff;}.content span.union,.content a.union{color:#98a01c;}.content span.constant,.content a.constant,.content span.static,.content a.static{color:#6380a0;}.content span.primitive,.content a.primitive{color:#32889b;}.content span.traitalias,.content a.traitalias{color:#57d399;}.content span.keyword,.content a.keyword{color:#de5249;}.content span.externcrate,.content span.mod,.content a.mod{color:#acccf9;}.content span.struct,.content a.struct{color:#ffa0a5;}.content span.enum,.content a.enum{color:#99e0c9;}.content span.trait,.content a.trait{color:#39AFD7;}.content span.type,.content a.type{color:#cfbcf5;}.content span.fn,.content a.fn,.content span.method,.content a.method,.content span.tymethod,.content a.tymethod,.content .fnname{color:#fdd687;}.content span.attr,.content a.attr,.content span.derive,.content a.derive,.content span.macro,.content a.macro{color:#a37acc;}pre.rust .comment{color:#788797;}pre.rust .doccomment{color:#a1ac88;}nav:not(.sidebar){border-bottom-color:#424c57;}nav.main .current{border-top-color:#5c6773;border-bottom-color:#5c6773;}nav.main .separator{border:1px solid #5c6773;}a{color:#c5c5c5;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.item-info a,#help a{color:#39AFD7;}.collapse-toggle{color:#999;}#crate-search{color:#c5c5c5;background-color:#141920;box-shadow:0 0 0 1px #424c57,0 0 0 2px transparent;border-color:#424c57;}.search-input{color:#ffffff;background-color:#141920;box-shadow:0 0 0 1px #424c57,0 0 0 2px transparent;transition:box-shadow 150ms ease-in-out;}#crate-search+.search-input:focus{box-shadow:0 0 0 1px #148099,0 0 0 2px transparent;}.search-focus:disabled{color:#929292;}.module-item .stab{color:#000;}.stab.unstable,.stab.deprecated,.stab.portability{color:#c5c5c5;background:#314559 !important;border-style:none !important;border-radius:4px;padding:3px 6px 3px 6px;}.stab.portability>code{color:#e6e1cf;background-color:transparent;}#help>div{background:#14191f;box-shadow:0px 6px 20px 0px black;border:none;border-radius:4px;}#help>div>span{border-bottom-color:#5c6773;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:#788797;}.line-numbers :target{background-color:transparent;}pre.rust .number,pre.rust .string{color:#b8cc52;}pre.rust .kw,pre.rust .kw-2,pre.rust .prelude-ty,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .op,pre.rust .lifetime{color:#ff7733;}pre.rust .macro,pre.rust .macro-nonterminal{color:#a37acc;}pre.rust .question-mark{color:#ff9011;}pre.rust .self{color:#36a3d9;font-style:italic;}pre.rust .attribute{color:#e6e1cf;}pre.rust .attribute .ident,pre.rust .attribute .op{color:#e6e1cf;}.example-wrap>pre.line-number{color:#5c67736e;border:none;}a.test-arrow{font-size:100%;color:#788797;border-radius:4px;background-color:rgba(57,175,215,0.09);}a.test-arrow:hover{background-color:rgba(57,175,215,0.368);color:#c5c5c5;}.toggle-label{color:#999;}:target>code,:target>.in-band{background:rgba(255,236,164,0.06);border-right:3px solid rgba(255,180,76,0.85);}pre.compile_fail{border-left:2px solid rgba(255,0,0,.4);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.4);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.5);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#39AFD7;}.tooltip .tooltiptext{background-color:#314559;color:#c5c5c5;border:1px solid #5c6773;}.tooltip .tooltiptext::after{border-color:transparent #314559 transparent transparent;}.notable-traits-tooltiptext{background-color:#314559;border-color:#5c6773;}#titles>button.selected{background-color:#141920 !important;border-bottom:1px solid #ffb44c !important;border-top:none;}#titles>button:not(.selected){background-color:transparent !important;border:none;}#titles>button:hover{border-bottom:1px solid rgba(242,151,24,0.3);}#titles>button>div.count{color:#888;}.content .highlighted.mod,.content .highlighted.externcrate{}.search-input:focus{}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{}.content .highlighted.trait{}.content span.struct,.content a.struct,.block a.current.struct{}#titles>button:hover,#titles>button.selected{}.content .highlighted.traitalias{}.content span.type,.content a.type,.block a.current.type{}.content span.union,.content a.union,.block a.current.union{}.content .highlighted.foreigntype{}pre.rust .lifetime{}.content .highlighted.primitive{}.content .highlighted.constant,.content .highlighted.static{}.stab.unstable{}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){}.content span.enum,.content a.enum,.block a.current.enum{}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{}.content span.keyword,.content a.keyword,.block a.current.keyword{}pre.rust .comment{}.content .highlighted.enum{}.content .highlighted.struct{}.content .highlighted.keyword{}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{}pre.rust .kw{}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{}pre.rust .doccomment{}.stab.deprecated{}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{}.stab.portability{}.content .highlighted.union{}.content span.primitive,.content a.primitive,.block a.current.primitive{}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{}.content .highlighted.type{}pre.rust .kw-2,pre.rust .prelude-ty{}.content span.trait,.content a.trait,.block a.current.trait{}@media (max-width:700px){.sidebar-menu{background-color:#14191f;border-bottom-color:#5c6773;border-right-color:#5c6773;}.sidebar-elems{background-color:#14191f;border-right-color:#5c6773;}#sidebar-filler{background-color:#14191f;border-bottom-color:#5c6773;}}kbd{color:#c5c5c5;background-color:#314559;border-color:#5c6773;border-bottom-color:#5c6773;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu,.help-button{border-color:#5c6773;background-color:#0f1419;color:#fff;}#theme-picker>img,#settings-menu>img{filter:invert(100);}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus,.help-button:hover,.help-button:focus{border-color:#e0e0e0;}#theme-choices{border-color:#5c6773;background-color:#0f1419;}#theme-choices>button:not(:first-child){border-top-color:#5c6773;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:rgba(110,110,110,0.33);}@media (max-width:700px){#theme-picker{background:#0f1419;}}#all-types{background-color:#14191f;}#all-types:hover{background-color:rgba(70,70,70,0.33);}.search-results td span.alias{color:#c5c5c5;}.search-results td span.grey{color:#999;}#sidebar-toggle{background-color:#14191f;}#sidebar-toggle:hover{background-color:rgba(70,70,70,0.33);}#source-sidebar{background-color:#14191f;}#source-sidebar>.title{color:#fff;border-bottom-color:#5c6773;}div.files>a:hover,div.name:hover{background-color:#14191f;color:#ffb44c;}div.files>.selected{background-color:#14191f;color:#ffb44c;}.setting-line>.title{border-bottom-color:#5c6773;}input:checked+.slider{background-color:#ffb454 !important;} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/all.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/all.html deleted file mode 100644 index 35d47a2b03..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/all.html +++ /dev/null @@ -1,6 +0,0 @@ -List of all items in this crate - -

    [] - - List of all items

    Structs

    Enums

    Traits

    Macros

    Functions

    Typedefs

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/enum.AnyBlockchain.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/enum.AnyBlockchain.html deleted file mode 100644 index 916f07b121..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/enum.AnyBlockchain.html +++ /dev/null @@ -1,52 +0,0 @@ -bdk::blockchain::any::AnyBlockchain - Rust - -

    [][src]Enum bdk::blockchain::any::AnyBlockchain

    pub enum AnyBlockchain {
    -    Electrum(ElectrumBlockchain),
    -    Esplora(EsploraBlockchain),
    -    CompactFilters(CompactFiltersBlockchain),
    -}

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

    -

    It allows switching backend at runtime

    -

    See this module's documentation for a usage example.

    -

    - Variants

    -
    This is supported on crate feature electrum only.

    Electrum client

    -
    This is supported on crate feature esplora only.

    Esplora client

    -
    CompactFilters(CompactFiltersBlockchain)
    This is supported on crate feature compact_filters only.

    Compact filters client

    -

    Trait Implementations

    impl Blockchain for AnyBlockchain[src]

    impl ConfigurableBlockchain for AnyBlockchain[src]

    type Config = AnyBlockchainConfig

    Type that contains the configuration

    -

    impl From<CompactFiltersBlockchain> for AnyBlockchain[src]

    impl From<ElectrumBlockchain> for AnyBlockchain[src]

    impl From<EsploraBlockchain> for AnyBlockchain[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> BlockchainMarker for T where
        T: Blockchain
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/enum.AnyBlockchainConfig.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/enum.AnyBlockchainConfig.html deleted file mode 100644 index a034ec2a32..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/enum.AnyBlockchainConfig.html +++ /dev/null @@ -1,47 +0,0 @@ -bdk::blockchain::any::AnyBlockchainConfig - Rust - -

    [][src]Enum bdk::blockchain::any::AnyBlockchainConfig

    pub enum AnyBlockchainConfig {
    -    Electrum(ElectrumBlockchainConfig),
    -    Esplora(EsploraBlockchainConfig),
    -    CompactFilters(CompactFiltersBlockchainConfig),
    -}

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

    -

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

    -

    - Variants

    -
    This is supported on crate feature electrum only.

    Electrum client

    -
    This is supported on crate feature esplora only.

    Esplora client

    -
    This is supported on crate feature compact_filters only.

    Compact filters client

    -

    Trait Implementations

    impl Debug for AnyBlockchainConfig[src]

    impl<'de> Deserialize<'de> for AnyBlockchainConfig[src]

    impl From<CompactFiltersBlockchainConfig> for AnyBlockchainConfig[src]

    impl From<ElectrumBlockchainConfig> for AnyBlockchainConfig[src]

    impl From<EsploraBlockchainConfig> for AnyBlockchainConfig[src]

    impl Serialize for AnyBlockchainConfig[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> DeserializeOwned for T where
        T: for<'de> Deserialize<'de>, 
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/index.html deleted file mode 100644 index 70a7a733eb..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/index.html +++ /dev/null @@ -1,47 +0,0 @@ -bdk::blockchain::any - Rust - -

    [][src]Module bdk::blockchain::any

    Runtime-checked blockchain types

    -

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

    -

    Example

    -

    In this example both wallet_electrum and wallet_esplora have the same type of -Wallet<AnyBlockchain, MemoryDatabase>. This means that they could both, for instance, be -assigned to a struct member.

    - -
    -let electrum_blockchain = ElectrumBlockchain::from(electrum_client::Client::new("...")?);
    -let wallet_electrum: Wallet<AnyBlockchain, _> = Wallet::new(
    -    "...",
    -    None,
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -    electrum_blockchain.into(),
    -)?;
    -
    -let esplora_blockchain = EsploraBlockchain::new("...", None);
    -let wallet_esplora: Wallet<AnyBlockchain, _> = Wallet::new(
    -    "...",
    -    None,
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -    esplora_blockchain.into(),
    -)?;
    -
    -

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

    - -
    -let config = serde_json::from_str("...")?;
    -let blockchain = AnyBlockchain::from_config(&config)?;
    -let wallet = Wallet::new(
    -    "...",
    -    None,
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -    blockchain,
    -)?;
    -

    Enums

    -
    AnyBlockchain

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

    -
    AnyBlockchainConfig

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

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/sidebar-items.js deleted file mode 100644 index 14144cf693..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/any/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["AnyBlockchain","Type that can contain any of the [`Blockchain`] types defined by the library"],["AnyBlockchainConfig","Type that can contain any of the blockchain configurations defined by the library"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/enum.CompactFiltersError.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/enum.CompactFiltersError.html deleted file mode 100644 index 3fba9f11c4..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/enum.CompactFiltersError.html +++ /dev/null @@ -1,73 +0,0 @@ -bdk::blockchain::compact_filters::CompactFiltersError - Rust - -

    [][src]Enum bdk::blockchain::compact_filters::CompactFiltersError

    pub enum CompactFiltersError {
    -    InvalidResponse,
    -    InvalidHeaders,
    -    InvalidFilterHeader,
    -    InvalidFilter,
    -    MissingBlock,
    -    DataCorruption,
    -    NotConnected,
    -    Timeout,
    -    NoPeers,
    -    DB(Error),
    -    IO(Error),
    -    BIP158(Error),
    -    Time(SystemTimeError),
    -    Global(Box<Error>),
    -}
    This is supported on crate feature compact_filters only.

    An error that can occur during sync with a CompactFiltersBlockchain

    -

    - Variants

    -
    InvalidResponse

    A peer sent an invalid or unexpected response

    -
    InvalidHeaders

    The headers returned are invalid

    -
    InvalidFilterHeader

    The compact filter headers returned are invalid

    -
    InvalidFilter

    The compact filter returned is invalid

    -
    MissingBlock

    The peer is missing a block in the valid chain

    -
    DataCorruption

    The data stored in the block filters storage are corrupted

    -
    NotConnected

    A peer is not connected

    -
    Timeout

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

    -
    NoPeers

    No peers have been specified

    -
    DB(Error)

    Internal database error

    -
    IO(Error)

    Internal I/O error

    -
    BIP158(Error)

    Invalid BIP158 filter

    -

    Internal system time error

    -
    Global(Box<Error>)

    Wrapper for crate::error::Error

    -

    Trait Implementations

    impl Debug for CompactFiltersError[src]

    impl Display for CompactFiltersError[src]

    impl Error for CompactFiltersError[src]

    impl From<CompactFiltersError> for Error[src]

    impl From<Error> for CompactFiltersError[src]

    impl From<Error> for CompactFiltersError[src]

    impl From<Error> for CompactFiltersError[src]

    impl From<Error> for CompactFiltersError[src]

    impl From<SystemTimeError> for CompactFiltersError[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/index.html deleted file mode 100644 index 53f3f770e2..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/index.html +++ /dev/null @@ -1,39 +0,0 @@ -bdk::blockchain::compact_filters - Rust - -

    [][src]Module bdk::blockchain::compact_filters

    This is supported on crate feature compact_filters only.

    Compact Filters

    -

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

    -

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

    -

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

    -

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

    -

    Example

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

    Structs

    -
    BitcoinPeerConfig

    Data to connect to a Bitcoin P2P peer

    -
    CompactFiltersBlockchain

    Structure implementing the required blockchain traits

    -
    CompactFiltersBlockchainConfig

    Configuration for a CompactFiltersBlockchain

    -
    Mempool

    Container for unconfirmed, but valid Bitcoin transactions

    -
    Peer

    A Bitcoin peer

    -

    Enums

    -
    CompactFiltersError

    An error that can occur during sync with a CompactFiltersBlockchain

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/peer/struct.Mempool.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/peer/struct.Mempool.html deleted file mode 100644 index cd04378cbe..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/peer/struct.Mempool.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

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

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/peer/struct.Peer.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/peer/struct.Peer.html deleted file mode 100644 index 11332c3bdb..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/peer/struct.Peer.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

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

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/sidebar-items.js deleted file mode 100644 index 187af79563..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["CompactFiltersError","An error that can occur during sync with a [`CompactFiltersBlockchain`]"]],"struct":[["BitcoinPeerConfig","Data to connect to a Bitcoin P2P peer"],["CompactFiltersBlockchain","Structure implementing the required blockchain traits"],["CompactFiltersBlockchainConfig","Configuration for a [`CompactFiltersBlockchain`]"],["Mempool","Container for unconfirmed, but valid Bitcoin transactions"],["Peer","A Bitcoin peer"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.BitcoinPeerConfig.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.BitcoinPeerConfig.html deleted file mode 100644 index 822c73d161..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.BitcoinPeerConfig.html +++ /dev/null @@ -1,40 +0,0 @@ -bdk::blockchain::compact_filters::BitcoinPeerConfig - Rust - -

    [][src]Struct bdk::blockchain::compact_filters::BitcoinPeerConfig

    pub struct BitcoinPeerConfig {
    -    pub address: String,
    -    pub socks5: Option<String>,
    -    pub socks5_credentials: Option<(String, String)>,
    -}
    This is supported on crate feature compact_filters only.

    Data to connect to a Bitcoin P2P peer

    -

    - Fields

    address: String

    Peer address such as 127.0.0.1:18333

    -
    socks5: Option<String>

    Optional socks5 proxy

    -
    socks5_credentials: Option<(String, String)>

    Optional socks5 proxy credentials

    -

    Trait Implementations

    impl Debug for BitcoinPeerConfig[src]

    impl<'de> Deserialize<'de> for BitcoinPeerConfig[src]

    impl Serialize for BitcoinPeerConfig[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> DeserializeOwned for T where
        T: for<'de> Deserialize<'de>, 
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html deleted file mode 100644 index c99aa78694..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html +++ /dev/null @@ -1,49 +0,0 @@ -bdk::blockchain::compact_filters::CompactFiltersBlockchain - Rust - -

    [][src]Struct bdk::blockchain::compact_filters::CompactFiltersBlockchain

    pub struct CompactFiltersBlockchain { /* fields omitted */ }
    This is supported on crate feature compact_filters only.

    Structure implementing the required blockchain traits

    -

    Example

    -

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

    -

    Implementations

    impl CompactFiltersBlockchain[src]

    pub fn new<P: AsRef<Path>>(
        peers: Vec<Peer>,
        storage_dir: P,
        skip_blocks: Option<usize>
    ) -> Result<Self, CompactFiltersError>
    [src]

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

    -

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

    -

    Trait Implementations

    impl Blockchain for CompactFiltersBlockchain[src]

    impl ConfigurableBlockchain for CompactFiltersBlockchain[src]

    type Config = CompactFiltersBlockchainConfig

    Type that contains the configuration

    -

    impl Debug for CompactFiltersBlockchain[src]

    impl From<CompactFiltersBlockchain> for AnyBlockchain[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> BlockchainMarker for T where
        T: Blockchain
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchainConfig.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchainConfig.html deleted file mode 100644 index 0d8ad732f9..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchainConfig.html +++ /dev/null @@ -1,43 +0,0 @@ -bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig - Rust - -

    [][src]Struct bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig

    pub struct CompactFiltersBlockchainConfig {
    -    pub peers: Vec<BitcoinPeerConfig>,
    -    pub network: Network,
    -    pub storage_dir: String,
    -    pub skip_blocks: Option<usize>,
    -}
    This is supported on crate feature compact_filters only.

    Configuration for a CompactFiltersBlockchain

    -

    - Fields

    peers: Vec<BitcoinPeerConfig>

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

    -
    network: Network

    Network used

    -
    storage_dir: String

    Storage dir to save partially downloaded headers and full blocks

    -
    skip_blocks: Option<usize>

    Optionally skip initial skip_blocks blocks (default: 0)

    -

    Trait Implementations

    impl Debug for CompactFiltersBlockchainConfig[src]

    impl<'de> Deserialize<'de> for CompactFiltersBlockchainConfig[src]

    impl From<CompactFiltersBlockchainConfig> for AnyBlockchainConfig[src]

    impl Serialize for CompactFiltersBlockchainConfig[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> DeserializeOwned for T where
        T: for<'de> Deserialize<'de>, 
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.Mempool.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.Mempool.html deleted file mode 100644 index e03a70996f..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.Mempool.html +++ /dev/null @@ -1,39 +0,0 @@ -bdk::blockchain::compact_filters::Mempool - Rust - -

    [][src]Struct bdk::blockchain::compact_filters::Mempool

    pub struct Mempool { /* fields omitted */ }
    This is supported on crate feature compact_filters only.

    Container for unconfirmed, but valid Bitcoin transactions

    -

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

    -

    Implementations

    impl Mempool[src]

    pub fn add_tx(&self, tx: Transaction)[src]

    Add a transaction to the mempool

    -

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

    -

    pub fn get_tx(&self, inventory: &Inventory) -> Option<Transaction>[src]

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

    -

    pub fn has_tx(&self, txid: &Txid) -> bool[src]

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

    -

    pub fn iter_txs(&self) -> Vec<Transaction>[src]

    Return the list of transactions contained in the mempool

    -

    Trait Implementations

    impl Debug for Mempool[src]

    impl Default for Mempool[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.Peer.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.Peer.html deleted file mode 100644 index 5c3eb0c9a9..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/compact_filters/struct.Peer.html +++ /dev/null @@ -1,43 +0,0 @@ -bdk::blockchain::compact_filters::Peer - Rust - -

    [][src]Struct bdk::blockchain::compact_filters::Peer

    pub struct Peer { /* fields omitted */ }
    This is supported on crate feature compact_filters only.

    A Bitcoin peer

    -

    Implementations

    impl Peer[src]

    pub fn connect<A: ToSocketAddrs>(
        address: A,
        mempool: Arc<Mempool>,
        network: Network
    ) -> Result<Self, CompactFiltersError>
    [src]

    Connect to a peer over a plaintext TCP connection

    -

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

    -

    pub fn connect_proxy<T: ToTargetAddr, P: ToSocketAddrs>(
        target: T,
        proxy: P,
        credentials: Option<(&str, &str)>,
        mempool: Arc<Mempool>,
        network: Network
    ) -> Result<Self, CompactFiltersError>
    [src]

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

    -

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

    -

    pub fn get_version(&self) -> &VersionMessage[src]

    Return the [VersionMessage] sent by the peer

    -

    pub fn get_network(&self) -> Network[src]

    Return the Bitcoin [Network] in use

    -

    pub fn get_mempool(&self) -> Arc<Mempool>[src]

    Return the mempool used by this peer

    -

    pub fn is_connected(&self) -> bool[src]

    Return whether or not the peer is still connected

    -

    pub fn send(&self, payload: NetworkMessage) -> Result<(), CompactFiltersError>[src]

    Send a raw Bitcoin message to the peer

    -

    pub fn recv(
        &self,
        wait_for: &'static str,
        timeout: Option<Duration>
    ) -> Result<Option<NetworkMessage>, CompactFiltersError>
    [src]

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

    -

    Trait Implementations

    impl Debug for Peer[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/index.html deleted file mode 100644 index 10b5f8a1cd..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/index.html +++ /dev/null @@ -1,15 +0,0 @@ -bdk::blockchain::electrum - Rust - -

    [][src]Module bdk::blockchain::electrum

    This is supported on crate feature electrum only.

    Electrum

    -

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

    -

    Example

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

    Structs

    -
    ElectrumBlockchain

    Wrapper over an Electrum Client that implements the required blockchain traits

    -
    ElectrumBlockchainConfig

    Configuration for an ElectrumBlockchain

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/sidebar-items.js deleted file mode 100644 index 1bd5458912..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["ElectrumBlockchain","Wrapper over an Electrum Client that implements the required blockchain traits"],["ElectrumBlockchainConfig","Configuration for an [`ElectrumBlockchain`]"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/struct.ElectrumBlockchain.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/struct.ElectrumBlockchain.html deleted file mode 100644 index 1d0542e6fe..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/struct.ElectrumBlockchain.html +++ /dev/null @@ -1,42 +0,0 @@ -bdk::blockchain::electrum::ElectrumBlockchain - Rust - -

    [][src]Struct bdk::blockchain::electrum::ElectrumBlockchain

    pub struct ElectrumBlockchain(_);
    This is supported on crate feature electrum only.

    Wrapper over an Electrum Client that implements the required blockchain traits

    -

    Example

    -

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

    -

    Trait Implementations

    impl Blockchain for ElectrumBlockchain[src]

    impl ConfigurableBlockchain for ElectrumBlockchain[src]

    type Config = ElectrumBlockchainConfig

    Type that contains the configuration

    -

    impl From<Client> for ElectrumBlockchain[src]

    impl From<ElectrumBlockchain> for AnyBlockchain[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> BlockchainMarker for T where
        T: Blockchain
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/struct.ElectrumBlockchainConfig.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/struct.ElectrumBlockchainConfig.html deleted file mode 100644 index f15a951de2..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/electrum/struct.ElectrumBlockchainConfig.html +++ /dev/null @@ -1,44 +0,0 @@ -bdk::blockchain::electrum::ElectrumBlockchainConfig - Rust - -

    [][src]Struct bdk::blockchain::electrum::ElectrumBlockchainConfig

    pub struct ElectrumBlockchainConfig {
    -    pub url: String,
    -    pub socks5: Option<String>,
    -    pub retry: u8,
    -    pub timeout: u8,
    -}
    This is supported on crate feature electrum only.

    Configuration for an ElectrumBlockchain

    -

    - Fields

    url: String

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

    -

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

    -
    socks5: Option<String>

    URL of the socks5 proxy server or a Tor service

    -
    retry: u8

    Request retry count

    -
    timeout: u8

    Request timeout (seconds)

    -

    Trait Implementations

    impl Debug for ElectrumBlockchainConfig[src]

    impl<'de> Deserialize<'de> for ElectrumBlockchainConfig[src]

    impl From<ElectrumBlockchainConfig> for AnyBlockchainConfig[src]

    impl Serialize for ElectrumBlockchainConfig[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> DeserializeOwned for T where
        T: for<'de> Deserialize<'de>, 
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/enum.Capability.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/enum.Capability.html deleted file mode 100644 index 613d781903..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/enum.Capability.html +++ /dev/null @@ -1,51 +0,0 @@ -bdk::blockchain::Capability - Rust - -

    [][src]Enum bdk::blockchain::Capability

    pub enum Capability {
    -    FullHistory,
    -    GetAnyTx,
    -    AccurateFees,
    -}

    Capabilities that can be supported by a Blockchain backend

    -

    - Variants

    -
    FullHistory

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

    -
    GetAnyTx

    Can fetch any historical transaction given its txid

    -
    AccurateFees

    Can compute accurate fees for the transactions found during sync

    -

    Trait Implementations

    impl Clone for Capability[src]

    impl Copy for Capability[src]

    impl Debug for Capability[src]

    impl Eq for Capability[src]

    impl Hash for Capability[src]

    impl PartialEq<Capability> for Capability[src]

    impl StructuralEq for Capability[src]

    impl StructuralPartialEq for Capability[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/enum.EsploraError.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/enum.EsploraError.html deleted file mode 100644 index 3a45d9599c..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/enum.EsploraError.html +++ /dev/null @@ -1,58 +0,0 @@ -bdk::blockchain::esplora::EsploraError - Rust - -

    [][src]Enum bdk::blockchain::esplora::EsploraError

    pub enum EsploraError {
    -    Reqwest(Error),
    -    Parsing(ParseIntError),
    -    BitcoinEncoding(Error),
    -    Hex(Error),
    -    TransactionNotFound(Txid),
    -    HeaderHeightNotFound(u32),
    -    HeaderHashNotFound(BlockHash),
    -}
    This is supported on crate feature esplora only.

    Errors that can happen during a sync with EsploraBlockchain

    -

    - Variants

    -
    Reqwest(Error)

    Error with the HTTP call

    -
    Parsing(ParseIntError)

    Invalid number returned

    -
    BitcoinEncoding(Error)

    Invalid Bitcoin data returned

    -
    Hex(Error)

    Invalid Hex data returned

    -
    TransactionNotFound(Txid)

    Transaction not found

    -
    HeaderHeightNotFound(u32)

    Header height not found

    -
    HeaderHashNotFound(BlockHash)

    Header hash not found

    -

    Trait Implementations

    impl Debug for EsploraError[src]

    impl Display for EsploraError[src]

    impl Error for EsploraError[src]

    impl From<Error> for EsploraError[src]

    impl From<Error> for EsploraError[src]

    impl From<Error> for EsploraError[src]

    impl From<EsploraError> for Error[src]

    impl From<ParseIntError> for EsploraError[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/index.html deleted file mode 100644 index d6ed3b9df2..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/index.html +++ /dev/null @@ -1,15 +0,0 @@ -bdk::blockchain::esplora - Rust - -

    [][src]Module bdk::blockchain::esplora

    This is supported on crate feature esplora only.

    Esplora

    -

    This module defines a Blockchain struct that can query an Esplora backend -populate the wallet's database by

    -

    Example

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

    Structs

    -
    EsploraBlockchain

    Structure that implements the logic to sync with Esplora

    -
    EsploraBlockchainConfig

    Configuration for an EsploraBlockchain

    -

    Enums

    -
    EsploraError

    Errors that can happen during a sync with EsploraBlockchain

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/sidebar-items.js deleted file mode 100644 index d4d17db97b..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["EsploraError","Errors that can happen during a sync with [`EsploraBlockchain`]"]],"struct":[["EsploraBlockchain","Structure that implements the logic to sync with Esplora"],["EsploraBlockchainConfig","Configuration for an [`EsploraBlockchain`]"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/struct.EsploraBlockchain.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/struct.EsploraBlockchain.html deleted file mode 100644 index b645d65ca6..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/struct.EsploraBlockchain.html +++ /dev/null @@ -1,43 +0,0 @@ -bdk::blockchain::esplora::EsploraBlockchain - Rust - -

    [][src]Struct bdk::blockchain::esplora::EsploraBlockchain

    pub struct EsploraBlockchain(_);
    This is supported on crate feature esplora only.

    Structure that implements the logic to sync with Esplora

    -

    Example

    -

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

    -

    Implementations

    impl EsploraBlockchain[src]

    pub fn new(base_url: &str, concurrency: Option<u8>) -> Self[src]

    Create a new instance of the client from a base URL

    -

    Trait Implementations

    impl Blockchain for EsploraBlockchain[src]

    impl ConfigurableBlockchain for EsploraBlockchain[src]

    type Config = EsploraBlockchainConfig

    Type that contains the configuration

    -

    impl Debug for EsploraBlockchain[src]

    impl From<EsploraBlockchain> for AnyBlockchain[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> BlockchainMarker for T where
        T: Blockchain
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/struct.EsploraBlockchainConfig.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/struct.EsploraBlockchainConfig.html deleted file mode 100644 index 3f00c32c65..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/esplora/struct.EsploraBlockchainConfig.html +++ /dev/null @@ -1,40 +0,0 @@ -bdk::blockchain::esplora::EsploraBlockchainConfig - Rust - -

    [][src]Struct bdk::blockchain::esplora::EsploraBlockchainConfig

    pub struct EsploraBlockchainConfig {
    -    pub base_url: String,
    -    pub concurrency: Option<u8>,
    -}
    This is supported on crate feature esplora only.

    Configuration for an EsploraBlockchain

    -

    - Fields

    base_url: String

    Base URL of the esplora service

    -

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

    -
    concurrency: Option<u8>

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

    -

    Trait Implementations

    impl Debug for EsploraBlockchainConfig[src]

    impl<'de> Deserialize<'de> for EsploraBlockchainConfig[src]

    impl From<EsploraBlockchainConfig> for AnyBlockchainConfig[src]

    impl Serialize for EsploraBlockchainConfig[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> DeserializeOwned for T where
        T: for<'de> Deserialize<'de>, 
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.log_progress.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.log_progress.html deleted file mode 100644 index 8f223b1af9..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.log_progress.html +++ /dev/null @@ -1,5 +0,0 @@ -bdk::blockchain::log_progress - Rust - -

    [][src]Function bdk::blockchain::log_progress

    pub fn log_progress() -> LogProgress

    Create a nwe instance of LogProgress

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.noop_progress.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.noop_progress.html deleted file mode 100644 index 07602022d5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.noop_progress.html +++ /dev/null @@ -1,5 +0,0 @@ -bdk::blockchain::noop_progress - Rust - -

    [][src]Function bdk::blockchain::noop_progress

    pub fn noop_progress() -> NoopProgress

    Create a new instance of NoopProgress

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.progress.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.progress.html deleted file mode 100644 index f07065fd91..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/fn.progress.html +++ /dev/null @@ -1,5 +0,0 @@ -bdk::blockchain::progress - Rust - -

    [][src]Function bdk::blockchain::progress

    pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>)

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

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/index.html deleted file mode 100644 index 15f7341c86..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/index.html +++ /dev/null @@ -1,33 +0,0 @@ -bdk::blockchain - Rust - -

    [][src]Module bdk::blockchain

    Blockchain backends

    -

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

    -

    Re-exports

    -
    pub use any::AnyBlockchain;
    pub use any::AnyBlockchainConfig;
    pub use self::electrum::ElectrumBlockchain;
    pub use self::electrum::ElectrumBlockchainConfig;
    pub use self::esplora::EsploraBlockchain;
    pub use self::compact_filters::CompactFiltersBlockchain;

    Modules

    -
    any

    Runtime-checked blockchain types

    -
    compact_filterscompact_filters

    Compact Filters

    -
    electrumelectrum

    Electrum

    -
    esploraesplora

    Esplora

    -

    Structs

    -
    LogProgress

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

    -
    NoopProgress

    Type that implements Progress and drops every update received

    -
    OfflineBlockchain

    Type that only implements BlockchainMarker and is always "offline"

    -

    Enums

    -
    Capability

    Capabilities that can be supported by a Blockchain backend

    -

    Traits

    -
    Blockchain

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

    -
    BlockchainMarker

    Marker trait for a blockchain backend

    -
    ConfigurableBlockchain

    Trait for Blockchain types that can be created given a configuration

    -
    Progress

    Trait for types that can receive and process progress updates during Blockchain::sync and -Blockchain::setup

    -

    Functions

    -
    log_progress

    Create a nwe instance of LogProgress

    -
    noop_progress

    Create a new instance of NoopProgress

    -
    progress

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

    -

    Type Definitions

    -
    ProgressData

    Data sent with a progress update over a channel

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/sidebar-items.js deleted file mode 100644 index 7e42516826..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Capability","Capabilities that can be supported by a [`Blockchain`] backend"]],"fn":[["log_progress","Create a nwe instance of [`LogProgress`]"],["noop_progress","Create a new instance of [`NoopProgress`]"],["progress","Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]"]],"mod":[["any","Runtime-checked blockchain types"],["compact_filters","Compact Filters"],["electrum","Electrum"],["esplora","Esplora"]],"struct":[["LogProgress","Type that implements [`Progress`] and logs at level `INFO` every update received"],["NoopProgress","Type that implements [`Progress`] and drops every update received"],["OfflineBlockchain","Type that only implements [`BlockchainMarker`] and is always \"offline\""]],"trait":[["Blockchain","Trait that defines the actions that must be supported by a blockchain backend"],["BlockchainMarker","Marker trait for a blockchain backend"],["ConfigurableBlockchain","Trait for [`Blockchain`] types that can be created given a configuration"],["Progress","Trait for types that can receive and process progress updates during [`Blockchain::sync`] and [`Blockchain::setup`]"]],"type":[["ProgressData","Data sent with a progress update over a [`channel`]"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.LogProgress.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.LogProgress.html deleted file mode 100644 index 37fecdf533..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.LogProgress.html +++ /dev/null @@ -1,36 +0,0 @@ -bdk::blockchain::LogProgress - Rust - -

    [][src]Struct bdk::blockchain::LogProgress

    pub struct LogProgress;

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

    -

    Trait Implementations

    impl Clone for LogProgress[src]

    impl Progress for LogProgress[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.NoopProgress.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.NoopProgress.html deleted file mode 100644 index 32da05a48d..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.NoopProgress.html +++ /dev/null @@ -1,36 +0,0 @@ -bdk::blockchain::NoopProgress - Rust - -

    [][src]Struct bdk::blockchain::NoopProgress

    pub struct NoopProgress;

    Type that implements Progress and drops every update received

    -

    Trait Implementations

    impl Clone for NoopProgress[src]

    impl Progress for NoopProgress[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.OfflineBlockchain.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.OfflineBlockchain.html deleted file mode 100644 index a828794792..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/struct.OfflineBlockchain.html +++ /dev/null @@ -1,29 +0,0 @@ -bdk::blockchain::OfflineBlockchain - Rust - -

    [][src]Struct bdk::blockchain::OfflineBlockchain

    pub struct OfflineBlockchain;

    Type that only implements BlockchainMarker and is always "offline"

    -

    Trait Implementations

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.Blockchain.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.Blockchain.html deleted file mode 100644 index ccb3c3548b..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.Blockchain.html +++ /dev/null @@ -1,36 +0,0 @@ -bdk::blockchain::Blockchain - Rust - -

    [][src]Trait bdk::blockchain::Blockchain

    pub trait Blockchain: BlockchainMarker {
    -    pub fn get_capabilities(&self) -> HashSet<Capability>;
    -
    pub fn setup<D: BatchDatabase, P: 'static + Progress>(
            &self,
            stop_gap: Option<usize>,
            database: &mut D,
            progress_update: P
        ) -> Result<(), Error>; -
    pub fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>; -
    pub fn broadcast(&self, tx: &Transaction) -> Result<(), Error>; -
    pub fn get_height(&self) -> Result<u32, Error>; -
    pub fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>; - - pub fn sync<D: BatchDatabase, P: 'static + Progress>(
            &self,
            stop_gap: Option<usize>,
            database: &mut D,
            progress_update: P
        ) -> Result<(), Error> { ... } -}

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

    -

    Required methods

    pub fn get_capabilities(&self) -> HashSet<Capability>[src]

    Return the set of Capability supported by this backend

    -

    pub fn setup<D: BatchDatabase, P: 'static + Progress>(
        &self,
        stop_gap: Option<usize>,
        database: &mut D,
        progress_update: P
    ) -> Result<(), Error>
    [src]

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

    -

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

    -

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

    -

    For types that do not have that distinction, only this method can be implemented, since -Blockchain::sync defaults to calling this internally if not overridden.

    -

    pub fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>[src]

    Fetch a transaction from the blockchain given its txid

    -

    pub fn broadcast(&self, tx: &Transaction) -> Result<(), Error>[src]

    Broadcast a transaction

    -

    pub fn get_height(&self) -> Result<u32, Error>[src]

    Return the current height

    -

    pub fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>[src]

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

    -
    Loading content...

    Provided methods

    pub fn sync<D: BatchDatabase, P: 'static + Progress>(
        &self,
        stop_gap: Option<usize>,
        database: &mut D,
        progress_update: P
    ) -> Result<(), Error>
    [src]

    Populate the internal database with transactions and UTXOs

    -

    If not overridden, it defaults to calling Blockchain::setup internally.

    -

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

    -

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

    -

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

    -
    Loading content...

    Implementations on Foreign Types

    impl<T: Blockchain> Blockchain for Arc<T>[src]

    Loading content...

    Implementors

    impl Blockchain for AnyBlockchain[src]

    impl Blockchain for CompactFiltersBlockchain[src]

    This is supported on crate feature compact_filters only.

    impl Blockchain for ElectrumBlockchain[src]

    This is supported on crate feature electrum only.

    impl Blockchain for EsploraBlockchain[src]

    This is supported on crate feature esplora only.
    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.BlockchainMarker.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.BlockchainMarker.html deleted file mode 100644 index 6b7b52152c..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.BlockchainMarker.html +++ /dev/null @@ -1,14 +0,0 @@ -bdk::blockchain::BlockchainMarker - Rust - -

    [][src]Trait bdk::blockchain::BlockchainMarker

    pub trait BlockchainMarker { }

    Marker trait for a blockchain backend

    -

    This is a marker trait for blockchain types. It is automatically implemented for types that -implement Blockchain, so as a user of the library you won't have to implement this -manually.

    -

    Users of the library will probably never have to implement this trait manually, but they -could still need to import it to define types and structs with generics; -Implementing only the marker trait is pointless, since OfflineBlockchain -already does that, and whenever Blockchain is implemented, the marker trait is also -automatically implemented by the library.

    -

    Implementors

    impl BlockchainMarker for OfflineBlockchain[src]

    impl<T: Blockchain> BlockchainMarker for T[src]

    The BlockchainMarker marker trait is automatically implemented for Blockchain types

    -
    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.ConfigurableBlockchain.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.ConfigurableBlockchain.html deleted file mode 100644 index 131ce0ecec..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.ConfigurableBlockchain.html +++ /dev/null @@ -1,10 +0,0 @@ -bdk::blockchain::ConfigurableBlockchain - Rust - -

    [][src]Trait bdk::blockchain::ConfigurableBlockchain

    pub trait ConfigurableBlockchain: Blockchain + Sized {
    -    type Config: Debug;
    -    pub fn from_config(config: &Self::Config) -> Result<Self, Error>;
    -}

    Trait for Blockchain types that can be created given a configuration

    -

    Associated Types

    type Config: Debug[src]

    Type that contains the configuration

    -
    Loading content...

    Required methods

    pub fn from_config(config: &Self::Config) -> Result<Self, Error>[src]

    Create a new instance given a configuration

    -
    Loading content...

    Implementors

    impl ConfigurableBlockchain for AnyBlockchain[src]

    type Config = AnyBlockchainConfig

    impl ConfigurableBlockchain for CompactFiltersBlockchain[src]

    This is supported on crate feature compact_filters only.

    impl ConfigurableBlockchain for ElectrumBlockchain[src]

    This is supported on crate feature electrum only.

    type Config = ElectrumBlockchainConfig

    impl ConfigurableBlockchain for EsploraBlockchain[src]

    This is supported on crate feature esplora only.

    type Config = EsploraBlockchainConfig

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.Progress.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.Progress.html deleted file mode 100644 index f2d54223cd..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/trait.Progress.html +++ /dev/null @@ -1,11 +0,0 @@ -bdk::blockchain::Progress - Rust - -

    [][src]Trait bdk::blockchain::Progress

    pub trait Progress: Send {
    -    pub fn update(
            &self,
            progress: f32,
            message: Option<String>
        ) -> Result<(), Error>; -}

    Trait for types that can receive and process progress updates during Blockchain::sync and -Blockchain::setup

    -

    Required methods

    pub fn update(
        &self,
        progress: f32,
        message: Option<String>
    ) -> Result<(), Error>
    [src]

    Send a new progress update

    -

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

    -
    Loading content...

    Implementations on Foreign Types

    impl Progress for Sender<ProgressData>[src]

    Loading content...

    Implementors

    impl Progress for LogProgress[src]

    impl Progress for NoopProgress[src]

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/type.ProgressData.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/type.ProgressData.html deleted file mode 100644 index 43b5347cb5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/blockchain/type.ProgressData.html +++ /dev/null @@ -1,5 +0,0 @@ -bdk::blockchain::ProgressData - Rust - -

    [][src]Type Definition bdk::blockchain::ProgressData

    type ProgressData = (f32, Option<String>);

    Data sent with a progress update over a channel

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyBatch.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyBatch.html deleted file mode 100644 index 2780dfa143..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyBatch.html +++ /dev/null @@ -1,50 +0,0 @@ -bdk::database::any::AnyBatch - Rust - -

    [][src]Enum bdk::database::any::AnyBatch

    pub enum AnyBatch {
    -    Memory(<MemoryDatabase as BatchDatabase>::Batch),
    -    Sled(<Tree as BatchDatabase>::Batch),
    -}

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

    -

    - Variants

    -

    In-memory ephemeral database

    -
    Sled(<Tree as BatchDatabase>::Batch)
    This is supported on crate feature key-value-db only.

    Simple key-value embedded database based on [sled]

    -

    Trait Implementations

    impl BatchOperations for AnyBatch[src]

    impl From<<MemoryDatabase as BatchDatabase>::Batch> for AnyBatch[src]

    impl From<<Tree as BatchDatabase>::Batch> for AnyBatch[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyDatabase.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyDatabase.html deleted file mode 100644 index ba702ed155..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyDatabase.html +++ /dev/null @@ -1,70 +0,0 @@ -bdk::database::any::AnyDatabase - Rust - -

    [][src]Enum bdk::database::any::AnyDatabase

    pub enum AnyDatabase {
    -    Memory(MemoryDatabase),
    -    Sled(Tree),
    -}

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

    -

    It allows switching database type at runtime.

    -

    See this module's documentation for a usage example.

    -

    - Variants

    -

    In-memory ephemeral database

    -
    Sled(Tree)
    This is supported on crate feature key-value-db only.

    Simple key-value embedded database based on [sled]

    -

    Trait Implementations

    impl BatchDatabase for AnyDatabase[src]

    type Batch = AnyBatch

    Container for the operations

    -

    impl BatchOperations for AnyDatabase[src]

    impl ConfigurableDatabase for AnyDatabase[src]

    type Config = AnyDatabaseConfig

    Type that contains the configuration

    -

    impl Database for AnyDatabase[src]

    impl Debug for AnyDatabase[src]

    impl From<MemoryDatabase> for AnyDatabase[src]

    impl From<Tree> for AnyDatabase[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyDatabaseConfig.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyDatabaseConfig.html deleted file mode 100644 index c880a327c7..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/enum.AnyDatabaseConfig.html +++ /dev/null @@ -1,44 +0,0 @@ -bdk::database::any::AnyDatabaseConfig - Rust - -

    [][src]Enum bdk::database::any::AnyDatabaseConfig

    pub enum AnyDatabaseConfig {
    -    Memory(()),
    -    Sled(SledDbConfiguration),
    -}

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

    -

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

    -

    - Variants

    -
    Memory(())

    Memory database has no config

    -
    This is supported on crate feature key-value-db only.

    Simple key-value embedded database based on [sled]

    -

    Trait Implementations

    impl Debug for AnyDatabaseConfig[src]

    impl<'de> Deserialize<'de> for AnyDatabaseConfig[src]

    impl From<()> for AnyDatabaseConfig[src]

    impl From<SledDbConfiguration> for AnyDatabaseConfig[src]

    impl Serialize for AnyDatabaseConfig[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> DeserializeOwned for T where
        T: for<'de> Deserialize<'de>, 
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/index.html deleted file mode 100644 index abe18b01fd..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/index.html +++ /dev/null @@ -1,31 +0,0 @@ -bdk::database::any - Rust - -

    [][src]Module bdk::database::any

    Runtime-checked database types

    -

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

    -

    Example

    -

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

    - -
    -let memory = MemoryDatabase::default().into();
    -let wallet_memory: OfflineWallet<AnyDatabase> =
    -    Wallet::new_offline("...", None, Network::Testnet, memory)?;
    -
    -let sled = sled::open("my-database")?.open_tree("default_tree")?.into();
    -let wallet_sled: OfflineWallet<AnyDatabase> =
    -    Wallet::new_offline("...", None, Network::Testnet, sled)?;
    -

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

    - -
    -let config = serde_json::from_str("...")?;
    -let database = AnyDatabase::from_config(&config)?;
    -let wallet: OfflineWallet<_> = Wallet::new_offline("...", None, Network::Testnet, database)?;
    -

    Structs

    -
    SledDbConfiguration

    Configuration type for a [sled::Tree] database

    -

    Enums

    -
    AnyBatch

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

    -
    AnyDatabase

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

    -
    AnyDatabaseConfig

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

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/sidebar-items.js deleted file mode 100644 index c0fb4445df..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["AnyBatch","Type that contains any of the [`BatchDatabase::Batch`] types defined by the library"],["AnyDatabase","Type that can contain any of the [`Database`] types defined by the library"],["AnyDatabaseConfig","Type that can contain any of the database configurations defined by the library"]],"struct":[["SledDbConfiguration","Configuration type for a [`sled::Tree`] database"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/struct.SledDbConfiguration.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/struct.SledDbConfiguration.html deleted file mode 100644 index 634abca3dd..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/any/struct.SledDbConfiguration.html +++ /dev/null @@ -1,39 +0,0 @@ -bdk::database::any::SledDbConfiguration - Rust - -

    [][src]Struct bdk::database::any::SledDbConfiguration

    pub struct SledDbConfiguration {
    -    pub path: String,
    -    pub tree_name: String,
    -}

    Configuration type for a [sled::Tree] database

    -

    - Fields

    path: String

    Main directory of the db

    -
    tree_name: String

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

    -

    Trait Implementations

    impl Debug for SledDbConfiguration[src]

    impl<'de> Deserialize<'de> for SledDbConfiguration[src]

    impl From<SledDbConfiguration> for AnyDatabaseConfig[src]

    impl Serialize for SledDbConfiguration[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> DeserializeOwned for T where
        T: for<'de> Deserialize<'de>, 
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/index.html deleted file mode 100644 index fb5d1a74e7..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/index.html +++ /dev/null @@ -1,22 +0,0 @@ -bdk::database - Rust - -

    [][src]Module bdk::database

    Database types

    -

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

    -

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

    -

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

    -

    Re-exports

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

    Modules

    -
    any

    Runtime-checked database types

    -
    memory

    In-memory ephemeral database

    -

    Traits

    -
    BatchDatabase

    Trait for a database that supports batch operations

    -
    BatchOperations

    Trait for operations that can be batched

    -
    ConfigurableDatabase

    Trait for Database types that can be created given a configuration

    -
    Database

    Trait for reading data from a database

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/index.html deleted file mode 100644 index ca05a688e0..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/index.html +++ /dev/null @@ -1,9 +0,0 @@ -bdk::database::memory - Rust - -

    [][src]Module bdk::database::memory

    In-memory ephemeral database

    -

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

    -

    Structs

    -
    MemoryDatabase

    In-memory ephemeral database

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/sidebar-items.js deleted file mode 100644 index 665f6718d0..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["MemoryDatabase","In-memory ephemeral database"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/struct.MemoryDatabase.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/struct.MemoryDatabase.html deleted file mode 100644 index a50d11bfaf..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/memory/struct.MemoryDatabase.html +++ /dev/null @@ -1,68 +0,0 @@ -bdk::database::memory::MemoryDatabase - Rust - -

    [][src]Struct bdk::database::memory::MemoryDatabase

    pub struct MemoryDatabase { /* fields omitted */ }

    In-memory ephemeral database

    -

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

    -

    Once it's dropped its content will be lost.

    -

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

    -

    Implementations

    impl MemoryDatabase[src]

    pub fn new() -> Self[src]

    Create a new empty database

    -

    Trait Implementations

    impl BatchDatabase for MemoryDatabase[src]

    type Batch = Self

    Container for the operations

    -

    impl BatchOperations for MemoryDatabase[src]

    impl ConfigurableDatabase for MemoryDatabase[src]

    type Config = ()

    Type that contains the configuration

    -

    impl Database for MemoryDatabase[src]

    impl Debug for MemoryDatabase[src]

    impl Default for MemoryDatabase[src]

    impl From<<MemoryDatabase as BatchDatabase>::Batch> for AnyBatch[src]

    impl From<MemoryDatabase> for AnyDatabase[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/sidebar-items.js deleted file mode 100644 index 8349d566b5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"mod":[["any","Runtime-checked database types"],["memory","In-memory ephemeral database"]],"trait":[["BatchDatabase","Trait for a database that supports batch operations"],["BatchOperations","Trait for operations that can be batched"],["ConfigurableDatabase","Trait for [`Database`] types that can be created given a configuration"],["Database","Trait for reading data from a database"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.BatchDatabase.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.BatchDatabase.html deleted file mode 100644 index 4edc4e5295..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.BatchDatabase.html +++ /dev/null @@ -1,13 +0,0 @@ -bdk::database::BatchDatabase - Rust - -

    [][src]Trait bdk::database::BatchDatabase

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

    Trait for a database that supports batch operations

    -

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

    -

    Associated Types

    type Batch: BatchOperations[src]

    Container for the operations

    -
    Loading content...

    Required methods

    pub fn begin_batch(&self) -> Self::Batch[src]

    Create a new batch container

    -

    pub fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>[src]

    Consume and apply a batch of operations

    -
    Loading content...

    Implementations on Foreign Types

    impl BatchDatabase for Tree[src]

    type Batch = Batch

    Loading content...

    Implementors

    impl BatchDatabase for AnyDatabase[src]

    type Batch = AnyBatch

    impl BatchDatabase for MemoryDatabase[src]

    type Batch = Self

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.BatchOperations.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.BatchOperations.html deleted file mode 100644 index 43cec5ac1a..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.BatchOperations.html +++ /dev/null @@ -1,31 +0,0 @@ -bdk::database::BatchOperations - Rust - -

    [][src]Trait bdk::database::BatchOperations

    pub trait BatchOperations {
    -    pub fn set_script_pubkey(
            &mut self,
            script: &Script,
            keychain: KeychainKind,
            child: u32
        ) -> Result<(), Error>; -
    pub fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>; -
    pub fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>; -
    pub fn set_tx(
            &mut self,
            transaction: &TransactionDetails
        ) -> Result<(), Error>; -
    pub fn set_last_index(
            &mut self,
            keychain: KeychainKind,
            value: u32
        ) -> Result<(), Error>; -
    pub fn del_script_pubkey_from_path(
            &mut self,
            keychain: KeychainKind,
            child: u32
        ) -> Result<Option<Script>, Error>; -
    pub fn del_path_from_script_pubkey(
            &mut self,
            script: &Script
        ) -> Result<Option<(KeychainKind, u32)>, Error>; -
    pub fn del_utxo(
            &mut self,
            outpoint: &OutPoint
        ) -> Result<Option<UTXO>, Error>; -
    pub fn del_raw_tx(
            &mut self,
            txid: &Txid
        ) -> Result<Option<Transaction>, Error>; -
    pub fn del_tx(
            &mut self,
            txid: &Txid,
            include_raw: bool
        ) -> Result<Option<TransactionDetails>, Error>; -
    pub fn del_last_index(
            &mut self,
            keychain: KeychainKind
        ) -> Result<Option<u32>, Error>; -}

    Trait for operations that can be batched

    -

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

    -

    Required methods

    pub fn set_script_pubkey(
        &mut self,
        script: &Script,
        keychain: KeychainKind,
        child: u32
    ) -> Result<(), Error>
    [src]

    Store a script_pubkey along with its keychain and child number.

    -

    pub fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>[src]

    Store a UTXO

    -

    pub fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>[src]

    Store a raw transaction

    -

    pub fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>[src]

    Store the metadata of a transaction

    -

    pub fn set_last_index(
        &mut self,
        keychain: KeychainKind,
        value: u32
    ) -> Result<(), Error>
    [src]

    Store the last derivation index for a given keychain.

    -

    pub fn del_script_pubkey_from_path(
        &mut self,
        keychain: KeychainKind,
        child: u32
    ) -> Result<Option<Script>, Error>
    [src]

    Delete a script_pubkey given the keychain and its child number.

    -

    pub fn del_path_from_script_pubkey(
        &mut self,
        script: &Script
    ) -> Result<Option<(KeychainKind, u32)>, Error>
    [src]

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

    -

    pub fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>[src]

    Delete a UTXO given its [OutPoint]

    -

    pub fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>[src]

    Delete a raw transaction given its [Txid]

    -

    pub fn del_tx(
        &mut self,
        txid: &Txid,
        include_raw: bool
    ) -> Result<Option<TransactionDetails>, Error>
    [src]

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

    -

    pub fn del_last_index(
        &mut self,
        keychain: KeychainKind
    ) -> Result<Option<u32>, Error>
    [src]

    Delete the last derivation index for a keychain.

    -
    Loading content...

    Implementations on Foreign Types

    impl BatchOperations for Tree[src]

    impl BatchOperations for Batch[src]

    Loading content...

    Implementors

    impl BatchOperations for AnyBatch[src]

    impl BatchOperations for AnyDatabase[src]

    impl BatchOperations for MemoryDatabase[src]

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.ConfigurableDatabase.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.ConfigurableDatabase.html deleted file mode 100644 index 463d548462..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.ConfigurableDatabase.html +++ /dev/null @@ -1,10 +0,0 @@ -bdk::database::ConfigurableDatabase - Rust - -

    [][src]Trait bdk::database::ConfigurableDatabase

    pub trait ConfigurableDatabase: Database + Sized {
    -    type Config: Debug;
    -    pub fn from_config(config: &Self::Config) -> Result<Self, Error>;
    -}

    Trait for Database types that can be created given a configuration

    -

    Associated Types

    type Config: Debug[src]

    Type that contains the configuration

    -
    Loading content...

    Required methods

    pub fn from_config(config: &Self::Config) -> Result<Self, Error>[src]

    Create a new instance given a configuration

    -
    Loading content...

    Implementations on Foreign Types

    impl ConfigurableDatabase for Tree[src]

    type Config = SledDbConfiguration

    Loading content...

    Implementors

    impl ConfigurableDatabase for AnyDatabase[src]

    type Config = AnyDatabaseConfig

    impl ConfigurableDatabase for MemoryDatabase[src]

    type Config = ()

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.Database.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.Database.html deleted file mode 100644 index c776d70675..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/database/trait.Database.html +++ /dev/null @@ -1,35 +0,0 @@ -bdk::database::Database - Rust - -

    [][src]Trait bdk::database::Database

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

    Trait for reading data from a database

    -

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

    -

    Required methods

    pub fn check_descriptor_checksum<B: AsRef<[u8]>>(
        &mut self,
        keychain: KeychainKind,
        bytes: B
    ) -> Result<(), Error>
    [src]

    Read and checks the descriptor checksum for a given keychain.

    -

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

    -

    pub fn iter_script_pubkeys(
        &self,
        keychain: Option<KeychainKind>
    ) -> Result<Vec<Script>, Error>
    [src]

    Return the list of script_pubkeys

    -

    pub fn iter_utxos(&self) -> Result<Vec<UTXO>, Error>[src]

    Return the list of UTXOs

    -

    pub fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>[src]

    Return the list of raw transactions

    -

    pub fn iter_txs(
        &self,
        include_raw: bool
    ) -> Result<Vec<TransactionDetails>, Error>
    [src]

    Return the list of transactions metadata

    -

    pub fn get_script_pubkey_from_path(
        &self,
        keychain: KeychainKind,
        child: u32
    ) -> Result<Option<Script>, Error>
    [src]

    Fetch a script_pubkey given the child number of a keychain.

    -

    pub fn get_path_from_script_pubkey(
        &self,
        script: &Script
    ) -> Result<Option<(KeychainKind, u32)>, Error>
    [src]

    Fetch the keychain and child number of a given script_pubkey

    -

    pub fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>[src]

    Fetch a UTXO given its [OutPoint]

    -

    pub fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>[src]

    Fetch a raw transaction given its [Txid]

    -

    pub fn get_tx(
        &self,
        txid: &Txid,
        include_raw: bool
    ) -> Result<Option<TransactionDetails>, Error>
    [src]

    Fetch the transaction metadata and optionally also the raw transaction

    -

    pub fn get_last_index(
        &self,
        keychain: KeychainKind
    ) -> Result<Option<u32>, Error>
    [src]

    Return the last defivation index for a keychain.

    -

    pub fn increment_last_index(
        &mut self,
        keychain: KeychainKind
    ) -> Result<u32, Error>
    [src]

    Increment the last derivation index for a keychain and return it

    -

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

    -
    Loading content...

    Implementations on Foreign Types

    impl Database for Tree[src]

    Loading content...

    Implementors

    impl Database for AnyDatabase[src]

    impl Database for MemoryDatabase[src]

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/fn.get_checksum.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/fn.get_checksum.html deleted file mode 100644 index 6b9e25e90a..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/fn.get_checksum.html +++ /dev/null @@ -1,5 +0,0 @@ -bdk::descriptor::checksum::get_checksum - Rust - -

    [][src]Function bdk::descriptor::checksum::get_checksum

    pub fn get_checksum(desc: &str) -> Result<String, Error>

    Compute the checksum of a descriptor

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/index.html deleted file mode 100644 index 0c7f9bb96d..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/index.html +++ /dev/null @@ -1,9 +0,0 @@ -bdk::descriptor::checksum - Rust - -

    [][src]Module bdk::descriptor::checksum

    Descriptor checksum

    -

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

    -

    Functions

    -
    get_checksum

    Compute the checksum of a descriptor

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/sidebar-items.js deleted file mode 100644 index e1add094a5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/checksum/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"fn":[["get_checksum","Compute the checksum of a descriptor"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Descriptor.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Descriptor.html deleted file mode 100644 index 42300b0891..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Descriptor.html +++ /dev/null @@ -1,156 +0,0 @@ -bdk::descriptor::Descriptor - Rust - -

    []Enum bdk::descriptor::Descriptor

    pub enum Descriptor<Pk> where
        Pk: MiniscriptKey
    { - Bare(Miniscript<Pk, Bare>), - Pk(Pk), - Pkh(Pk), - Wpkh(Pk), - ShWpkh(Pk), - Sh(Miniscript<Pk, Legacy>), - Wsh(Miniscript<Pk, Segwitv0>), - ShWsh(Miniscript<Pk, Segwitv0>), - ShSortedMulti(SortedMultiVec<Pk, Legacy>), - WshSortedMulti(SortedMultiVec<Pk, Segwitv0>), - ShWshSortedMulti(SortedMultiVec<Pk, Segwitv0>), -}

    Script descriptor

    -

    - Variants

    -
    Bare(Miniscript<Pk, Bare>)

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

    -
    Pk(Pk)

    Pay-to-Pubkey

    -
    Pkh(Pk)

    Pay-to-PubKey-Hash

    -
    Wpkh(Pk)

    Pay-to-Witness-PubKey-Hash

    -
    ShWpkh(Pk)

    Pay-to-Witness-PubKey-Hash inside P2SH

    -

    Pay-to-ScriptHash with Legacy context

    -

    Pay-to-Witness-ScriptHash with Segwitv0 context

    -
    ShWsh(Miniscript<Pk, Segwitv0>)

    P2SH-P2WSH with Segwitv0 context

    -
    ShSortedMulti(SortedMultiVec<Pk, Legacy>)

    Sortedmulti under P2SH

    -
    WshSortedMulti(SortedMultiVec<Pk, Segwitv0>)

    Sortedmulti under P2WSH

    -
    ShWshSortedMulti(SortedMultiVec<Pk, Segwitv0>)

    Sortedmulti under P2SH-P2WSH

    -

    Implementations

    impl<Pk> Descriptor<Pk> where
        Pk: MiniscriptKey

    pub fn translate_pk<Fpk, Fpkh, Q, E>(
        &self,
        translatefpk: Fpk,
        translatefpkh: Fpkh
    ) -> Result<Descriptor<Q>, E> where
        Fpk: FnMut(&Pk) -> Result<Q, E>,
        Fpkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, E>,
        Q: MiniscriptKey

    Convert a descriptor using abstract keys to one using specific keys -This will panic if translatefpk returns an uncompressed key when -converting to a Segwit descriptor. To prevent this panic, ensure -translatefpk returns an error in this case instead.

    -

    pub fn sanity_check(&self) -> Result<(), Error>

    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 signauture on all spend paths -And whether the script is malleable. -In general, all the guarantees of miniscript hold only for safe scripts. -All the analysis guarantees of miniscript only hold safe scripts. -The signer may not be able to find satisfactions even if one exists

    -

    impl<Pk> Descriptor<Pk> where
        Pk: MiniscriptKey

    pub fn address<ToPkCtx>(
        &self,
        network: Network,
        to_pk_ctx: ToPkCtx
    ) -> Option<Address> where
        Pk: ToPublicKey<ToPkCtx>,
        ToPkCtx: Copy

    Computes the Bitcoin address of the descriptor, if one exists -to_pk_ctx denotes the ToPkCtx required for deriving bitcoin::PublicKey -from MiniscriptKey using ToPublicKey. -If MiniscriptKey is already is [bitcoin::PublicKey], then the context -would be [NullCtx] and [descriptor.DescriptorPublicKeyCtx] if MiniscriptKey is [descriptor.DescriptorPublicKey]

    -

    In general, this is defined by generic for the trait [trait.ToPublicKey]

    -

    pub fn script_pubkey<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> Script where
        Pk: ToPublicKey<ToPkCtx>,
        ToPkCtx: Copy

    Computes the scriptpubkey of the descriptor -to_pk_ctx denotes the ToPkCtx required for deriving bitcoin::PublicKey -from MiniscriptKey using ToPublicKey. -If MiniscriptKey is already is [bitcoin::PublicKey], then the context -would be [NullCtx] and [descriptor.DescriptorPublicKeyCtx] if MiniscriptKey is [descriptor.DescriptorPublicKey]

    -

    In general, this is defined by generic for the trait ToPublicKey

    -

    pub fn unsigned_script_sig<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> Script where
        Pk: ToPublicKey<ToPkCtx>,
        ToPkCtx: Copy

    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). -to_pk_ctx denotes the ToPkCtx required for deriving bitcoin::PublicKey -from MiniscriptKey using ToPublicKey. -If MiniscriptKey is already is [bitcoin::PublicKey], then the context -would be [NullCtx] and [descriptor.DescriptorPublicKeyCtx] if MiniscriptKey is [descriptor.DescriptorPublicKey]

    -

    In general, this is defined by generic for the trait ToPublicKey

    -

    pub fn witness_script<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> Script where
        Pk: ToPublicKey<ToPkCtx>,
        ToPkCtx: Copy

    Computes the "witness script" of the descriptor, i.e. 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. -to_pk_ctx denotes the ToPkCtx required for deriving bitcoin::PublicKey -from MiniscriptKey using ToPublicKey. -If MiniscriptKey is already is [bitcoin::PublicKey], then the context -would be [NullCtx] and [descriptor.DescriptorPublicKeyCtx] if MiniscriptKey is [descriptor.DescriptorPublicKey]

    -

    In general, this is defined by generic for the trait ToPublicKey

    -

    pub fn get_satisfication<ToPkCtx, S>(
        &self,
        satisfier: S,
        to_pk_ctx: ToPkCtx
    ) -> Result<(Vec<Vec<u8, Global>, Global>, Script), Error> where
        Pk: ToPublicKey<ToPkCtx>,
        S: Satisfier<ToPkCtx, Pk>,
        ToPkCtx: Copy

    Returns satisfying witness and scriptSig to spend an -output controlled by the given descriptor if it possible to -construct one using the satisfier S. -to_pk_ctx denotes the ToPkCtx required for deriving bitcoin::PublicKey -from MiniscriptKey using ToPublicKey. -If MiniscriptKey is already is [bitcoin::PublicKey], then the context -would be [NullCtx] and [descriptor.DescriptorPublicKeyCtx] if MiniscriptKey is [descriptor.DescriptorPublicKey]

    -

    In general, this is defined by generic for the trait ToPublicKey

    -

    pub fn satisfy<ToPkCtx, S>(
        &self,
        txin: &mut TxIn,
        satisfier: S,
        to_pk_ctx: ToPkCtx
    ) -> Result<(), Error> where
        Pk: ToPublicKey<ToPkCtx>,
        S: Satisfier<ToPkCtx, Pk>,
        ToPkCtx: Copy

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

    -

    pub fn max_satisfaction_weight<ToPkCtx>(
        &self,
        to_pk_ctx: ToPkCtx
    ) -> Option<usize> where
        Pk: ToPublicKey<ToPkCtx>,
        ToPkCtx: Copy

    Computes an upper bound on the weight of a satisfying witness to the -transaction. Assumes all signatures are 73 bytes, including push opcode -and sighash suffix. Includes the weight of the VarInts encoding the -scriptSig and witness stack length.

    -

    pub fn script_code<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> Script where
        Pk: ToPublicKey<ToPkCtx>,
        ToPkCtx: Copy

    Get 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. -to_pk_ctx denotes the ToPkCtx required for deriving bitcoin::PublicKey -from MiniscriptKey using ToPublicKey. -If MiniscriptKey is already is [bitcoin::PublicKey], then the context -would be [NullCtx] and [descriptor.DescriptorPublicKeyCtx] if MiniscriptKey is [descriptor.DescriptorPublicKey]

    -

    In general, this is defined by generic for the trait ToPublicKey

    -

    impl Descriptor<DescriptorPublicKey>

    pub fn derive(
        &self,
        child_number: ChildNumber
    ) -> Descriptor<DescriptorPublicKey>

    Derives all wildcard keys in the descriptor using the supplied child_number

    -

    pub fn parse_descriptor(
        s: &str
    ) -> Result<(Descriptor<DescriptorPublicKey>, HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>), Error>

    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.

    -

    pub fn to_string_with_secret(
        &self,
        key_map: &HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>
    ) -> String

    Serialize a descriptor to string with its secret keys

    -

    Trait Implementations

    impl<Pk> Clone for Descriptor<Pk> where
        Pk: MiniscriptKey + Clone

    impl<Pk> Debug for Descriptor<Pk> where
        Pk: MiniscriptKey

    impl<Pk> Display for Descriptor<Pk> where
        Pk: MiniscriptKey

    impl<Pk> Eq for Descriptor<Pk> where
        Pk: MiniscriptKey + Eq

    impl ExtractPolicy for Descriptor<DescriptorPublicKey>[src]

    impl<Pk> FromStr for Descriptor<Pk> where
        Pk: MiniscriptKey,
        <Pk as FromStr>::Err: ToString,
        <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

    type Err = Error

    The associated error which can be returned from parsing.

    -

    impl<Pk> FromTree for Descriptor<Pk> where
        Pk: MiniscriptKey,
        <Pk as FromStr>::Err: ToString,
        <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

    pub fn from_tree(top: &Tree<'_>) -> Result<Descriptor<Pk>, Error>

    Parse an expression tree into a descriptor

    -

    impl<Pk> Liftable<Pk> for Descriptor<Pk> where
        Pk: MiniscriptKey

    impl<Pk> Ord for Descriptor<Pk> where
        Pk: MiniscriptKey + Ord

    impl<Pk> PartialEq<Descriptor<Pk>> for Descriptor<Pk> where
        Pk: MiniscriptKey + PartialEq<Pk>, 

    impl<Pk> PartialOrd<Descriptor<Pk>> for Descriptor<Pk> where
        Pk: MiniscriptKey + PartialOrd<Pk>, 

    impl<Pk> StructuralEq for Descriptor<Pk> where
        Pk: MiniscriptKey

    impl<Pk> StructuralPartialEq for Descriptor<Pk> where
        Pk: MiniscriptKey

    Auto Trait Implementations

    impl<Pk> RefUnwindSafe for Descriptor<Pk> where
        Pk: RefUnwindSafe,
        <Pk as MiniscriptKey>::Hash: RefUnwindSafe
    [src]

    impl<Pk> Send for Descriptor<Pk> where
        Pk: Send + Sync,
        <Pk as MiniscriptKey>::Hash: Send + Sync
    [src]

    impl<Pk> Sync for Descriptor<Pk> where
        Pk: Send + Sync,
        <Pk as MiniscriptKey>::Hash: Send + Sync
    [src]

    impl<Pk> Unpin for Descriptor<Pk> where
        Pk: Unpin,
        <Pk as MiniscriptKey>::Hash: Unpin
    [src]

    impl<Pk> UnwindSafe for Descriptor<Pk> where
        Pk: RefUnwindSafe + UnwindSafe,
        <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe
    [src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Legacy.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Legacy.html deleted file mode 100644 index ffb2ec62ab..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Legacy.html +++ /dev/null @@ -1,103 +0,0 @@ -bdk::descriptor::Legacy - Rust - -

    []Enum bdk::descriptor::Legacy

    pub enum Legacy {}

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

    -

    Trait Implementations

    impl Clone for Legacy

    impl Debug for Legacy

    impl Eq for Legacy

    impl Ord for Legacy

    impl PartialEq<Legacy> for Legacy

    impl PartialOrd<Legacy> for Legacy

    impl ScriptContext for Legacy

    impl StructuralEq for Legacy

    impl StructuralPartialEq for Legacy

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<Ctx> ExtScriptContext for Ctx where
        Ctx: 'static + ScriptContext
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Segwitv0.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Segwitv0.html deleted file mode 100644 index 8d6af85ba0..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Segwitv0.html +++ /dev/null @@ -1,100 +0,0 @@ -bdk::descriptor::Segwitv0 - Rust - -

    []Enum bdk::descriptor::Segwitv0

    pub enum Segwitv0 {}

    Segwitv0 ScriptContext

    -

    Trait Implementations

    impl Clone for Segwitv0

    impl Debug for Segwitv0

    impl Eq for Segwitv0

    impl Ord for Segwitv0

    impl PartialEq<Segwitv0> for Segwitv0

    impl PartialOrd<Segwitv0> for Segwitv0

    impl ScriptContext for Segwitv0

    impl StructuralEq for Segwitv0

    impl StructuralPartialEq for Segwitv0

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<Ctx> ExtScriptContext for Ctx where
        Ctx: 'static + ScriptContext
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Terminal.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Terminal.html deleted file mode 100644 index 1cf838dcc4..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/enum.Terminal.html +++ /dev/null @@ -1,124 +0,0 @@ -bdk::descriptor::Terminal - Rust - -

    []Enum bdk::descriptor::Terminal

    pub enum Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
    { - True, - False, - PkK(Pk), - PkH(<Pk as MiniscriptKey>::Hash), - After(u32), - Older(u32), - Sha256(Hash), - Hash256(Hash), - Ripemd160(Hash), - Hash160(Hash), - Alt(Arc<Miniscript<Pk, Ctx>>), - Swap(Arc<Miniscript<Pk, Ctx>>), - Check(Arc<Miniscript<Pk, Ctx>>), - DupIf(Arc<Miniscript<Pk, Ctx>>), - Verify(Arc<Miniscript<Pk, Ctx>>), - NonZero(Arc<Miniscript<Pk, Ctx>>), - ZeroNotEqual(Arc<Miniscript<Pk, Ctx>>), - AndV(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - AndB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - AndOr(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - OrB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - OrD(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - OrC(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - OrI(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>), - Thresh(usizeVec<Arc<Miniscript<Pk, Ctx>>, Global>), - Multi(usizeVec<Pk, Global>), -}

    All AST elements

    -

    - Variants

    -
    True

    1

    -
    False

    0

    -
    PkK(Pk)

    <key>

    -
    PkH(<Pk as MiniscriptKey>::Hash)

    DUP HASH160 <keyhash> EQUALVERIFY

    -
    After(u32)

    n CHECKLOCKTIMEVERIFY

    -
    Older(u32)

    n CHECKSEQUENCEVERIFY

    -
    Sha256(Hash)

    SIZE 32 EQUALVERIFY SHA256 <hash> EQUAL

    -
    Hash256(Hash)

    SIZE 32 EQUALVERIFY HASH256 <hash> EQUAL

    -
    Ripemd160(Hash)

    SIZE 32 EQUALVERIFY RIPEMD160 <hash> EQUAL

    -
    Hash160(Hash)

    SIZE 32 EQUALVERIFY HASH160 <hash> EQUAL

    -
    Alt(Arc<Miniscript<Pk, Ctx>>)

    TOALTSTACK [E] FROMALTSTACK

    -
    Swap(Arc<Miniscript<Pk, Ctx>>)

    SWAP [E1]

    -
    Check(Arc<Miniscript<Pk, Ctx>>)

    [Kt]/[Ke] CHECKSIG

    -
    DupIf(Arc<Miniscript<Pk, Ctx>>)

    DUP IF [V] ENDIF

    -
    Verify(Arc<Miniscript<Pk, Ctx>>)

    [T] VERIFY

    -
    NonZero(Arc<Miniscript<Pk, Ctx>>)

    SIZE 0NOTEQUAL IF Fn ENDIF

    -
    ZeroNotEqual(Arc<Miniscript<Pk, Ctx>>)

    [X] 0NOTEQUAL

    -
    AndV(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

    [V] [T]/[V]/[F]/[Kt]

    -
    AndB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

    [E] [W] BOOLAND

    -
    AndOr(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

    [various] NOTIF [various] ELSE [various] ENDIF

    -
    OrB(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

    [E] [W] BOOLOR

    -
    OrD(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

    [E] IFDUP NOTIF [T]/[E] ENDIF

    -
    OrC(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

    [E] NOTIF [V] ENDIF

    -
    OrI(Arc<Miniscript<Pk, Ctx>>, Arc<Miniscript<Pk, Ctx>>)

    IF [various] ELSE [various] ENDIF

    -
    Thresh(usizeVec<Arc<Miniscript<Pk, Ctx>>, Global>)

    [E] ([W] ADD)* k EQUAL

    -
    Multi(usizeVec<Pk, Global>)

    k ()* n CHECKMULTISIG

    -

    Implementations

    impl<Pk, Ctx> Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn translate_pk<FPk, FPkh, Q, Error>(
        &self,
        translatefpk: &mut FPk,
        translatefpkh: &mut FPkh
    ) -> Result<Terminal<Q, Ctx>, Error> where
        FPk: FnMut(&Pk) -> Result<Q, Error>,
        FPkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, Error>,
        Q: MiniscriptKey

    Convert an AST element with one public key type to one of another -public key type .This will panic while converting to -Segwit Miniscript using uncompressed public keys

    -

    impl<Pk, Ctx> Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn encode<ToPkCtx>(&self, builder: Builder, to_pk_ctx: ToPkCtx) -> Builder where
        Pk: ToPublicKey<ToPkCtx>,
        ToPkCtx: Copy

    Encode the element as a fragment of Bitcoin Script. The inverse -function, from Script to an AST element, is implemented in the -parse module.

    -

    pub fn script_size<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> usize where
        Pk: ToPublicKey<ToPkCtx>,
        ToPkCtx: Copy

    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.

    -

    Trait Implementations

    impl<Pk, Ctx> Clone for Terminal<Pk, Ctx> where
        Ctx: ScriptContext + Clone,
        Pk: MiniscriptKey + Clone,
        <Pk as MiniscriptKey>::Hash: Clone

    impl<Pk, Ctx> Debug for Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> Display for Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> Eq for Terminal<Pk, Ctx> where
        Ctx: ScriptContext + Eq,
        Pk: MiniscriptKey + Eq,
        <Pk as MiniscriptKey>::Hash: Eq

    impl<Pk, Ctx> FromTree for Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey,
        <Pk as FromStr>::Err: ToString,
        <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

    impl<Pk, Ctx> Hash for Terminal<Pk, Ctx> where
        Ctx: ScriptContext + Hash,
        Pk: MiniscriptKey + Hash,
        <Pk as MiniscriptKey>::Hash: Hash

    impl<Pk, Ctx> Liftable<Pk> for Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> Ord for Terminal<Pk, Ctx> where
        Ctx: ScriptContext + Ord,
        Pk: MiniscriptKey + Ord,
        <Pk as MiniscriptKey>::Hash: Ord

    impl<Pk, Ctx> PartialEq<Terminal<Pk, Ctx>> for Terminal<Pk, Ctx> where
        Ctx: ScriptContext + PartialEq<Ctx>,
        Pk: MiniscriptKey + PartialEq<Pk>,
        <Pk as MiniscriptKey>::Hash: PartialEq<<Pk as MiniscriptKey>::Hash>, 

    impl<Pk, Ctx> PartialOrd<Terminal<Pk, Ctx>> for Terminal<Pk, Ctx> where
        Ctx: ScriptContext + PartialOrd<Ctx>,
        Pk: MiniscriptKey + PartialOrd<Pk>,
        <Pk as MiniscriptKey>::Hash: PartialOrd<<Pk as MiniscriptKey>::Hash>, 

    impl<Pk, Ctx> StructuralEq for Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> StructuralPartialEq for Terminal<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    Auto Trait Implementations

    impl<Pk, Ctx> RefUnwindSafe for Terminal<Pk, Ctx> where
        Ctx: RefUnwindSafe,
        Pk: RefUnwindSafe,
        <Pk as MiniscriptKey>::Hash: RefUnwindSafe
    [src]

    impl<Pk, Ctx> Send for Terminal<Pk, Ctx> where
        Ctx: Send + Sync,
        Pk: Send + Sync,
        <Pk as MiniscriptKey>::Hash: Send + Sync
    [src]

    impl<Pk, Ctx> Sync for Terminal<Pk, Ctx> where
        Ctx: Send + Sync,
        Pk: Send + Sync,
        <Pk as MiniscriptKey>::Hash: Send + Sync
    [src]

    impl<Pk, Ctx> Unpin for Terminal<Pk, Ctx> where
        Pk: Unpin,
        <Pk as MiniscriptKey>::Hash: Unpin
    [src]

    impl<Pk, Ctx> UnwindSafe for Terminal<Pk, Ctx> where
        Ctx: RefUnwindSafe,
        Pk: RefUnwindSafe + UnwindSafe,
        <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe
    [src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/enum.Error.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/enum.Error.html deleted file mode 100644 index f85b978722..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/enum.Error.html +++ /dev/null @@ -1,65 +0,0 @@ -bdk::descriptor::error::Error - Rust - -

    [][src]Enum bdk::descriptor::error::Error

    pub enum Error {
    -    InvalidHDKeyPath,
    -    Key(KeyError),
    -    Policy(PolicyError),
    -    InvalidDescriptorCharacter(char),
    -    BIP32(Error),
    -    Base58(Error),
    -    PK(Error),
    -    Miniscript(Error),
    -    Hex(Error),
    -}

    Errors related to the parsing and usage of descriptors

    -

    - Variants

    -
    InvalidHDKeyPath

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

    -

    Error thrown while working with keys

    -
    Policy(PolicyError)

    Error while extracting and manipulating policies

    -
    InvalidDescriptorCharacter(char)

    Invalid character 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(Error)

    Hex decoding error

    -

    Trait Implementations

    impl Debug for Error[src]

    impl Display for Error[src]

    impl Error for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<KeyError> for Error[src]

    impl From<PolicyError> for Error[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/index.html deleted file mode 100644 index 7f40f8e520..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/index.html +++ /dev/null @@ -1,7 +0,0 @@ -bdk::descriptor::error - Rust - -

    [][src]Module bdk::descriptor::error

    Descriptor errors

    -

    Enums

    -
    Error

    Errors related to the parsing and usage of descriptors

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/sidebar-items.js deleted file mode 100644 index 1ad99d4faf..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/error/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Error","Errors related to the parsing and usage of descriptors"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/index.html deleted file mode 100644 index ccb74e27c0..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/index.html +++ /dev/null @@ -1,39 +0,0 @@ -bdk::descriptor - Rust - -

    [][src]Module bdk::descriptor

    Descriptors

    -

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

    -

    Re-exports

    -
    pub use self::checksum::get_checksum;
    pub use self::policy::Policy;

    Modules

    -
    checksum

    Descriptor checksum

    -
    error

    Descriptor errors

    -
    policy

    Descriptor policy

    -
    template

    Descriptor templates

    -

    Structs

    -
    Miniscript

    Top-level script AST type

    -

    Enums

    -
    Descriptor

    Script descriptor

    -
    Legacy

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

    -
    Segwitv0

    Segwitv0 ScriptContext

    -
    Terminal

    All AST elements

    -

    Traits

    -
    ExtractPolicy

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

    -
    MiniscriptKey

    Public key trait which can be converted to Hash type

    -
    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

    -
    ToPublicKey

    Trait describing public key types which can be converted to bitcoin pubkeys -The trait relies on Copy trait because in all practical usecases ToPkCtx -should contain references to objects which should be cheap to Copy.

    -
    ToWalletDescriptor

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

    -

    Type Definitions

    -
    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

    -
    KeyMap

    Alias type for a map of public key to secret key

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.PolicyError.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.PolicyError.html deleted file mode 100644 index c514b71eff..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.PolicyError.html +++ /dev/null @@ -1,55 +0,0 @@ -bdk::descriptor::policy::PolicyError - Rust - -

    [][src]Enum bdk::descriptor::policy::PolicyError

    pub enum PolicyError {
    -    NotEnoughItemsSelected(String),
    -    TooManyItemsSelected(String),
    -    IndexOutOfRange(usize),
    -    AddOnLeaf,
    -    AddOnPartialComplete,
    -    MixedTimelockUnits,
    -    IncompatibleConditions,
    -}

    Errors that can happen while extracting and manipulating policies

    -

    - Variants

    -
    NotEnoughItemsSelected(String)

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

    -
    TooManyItemsSelected(String)

    Too many items are selected to satisfy a SatisfiableItem::Thresh

    -
    IndexOutOfRange(usize)

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

    -
    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

    impl Debug for PolicyError[src]

    impl Display for PolicyError[src]

    impl Error for PolicyError[src]

    impl From<PolicyError> for Error[src]

    impl From<PolicyError> for Error[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.Satisfaction.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.Satisfaction.html deleted file mode 100644 index 5c56c8e9b8..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.Satisfaction.html +++ /dev/null @@ -1,75 +0,0 @@ -bdk::descriptor::policy::Satisfaction - Rust - -

    [][src]Enum bdk::descriptor::policy::Satisfaction

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

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

    -

    - Variants

    -
    Partial

    Only a partial satisfaction of some kind of threshold policy

    -

    Fields of Partial

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

    Extra conditions that also need to be satisfied

    -
    PartialComplete

    Can reach the threshold of some kind of threshold policy

    -

    Fields of PartialComplete

    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

    -
    Complete

    Can satisfy the policy item

    -

    Fields of Complete

    condition: Condition

    Extra conditions that also need to be satisfied

    -
    None

    Cannot satisfy or contribute to the policy item

    -

    Implementations

    impl Satisfaction[src]

    pub fn is_leaf(&self) -> bool[src]

    Returns whether the Satisfaction is a leaf item

    -

    Trait Implementations

    impl Clone for Satisfaction[src]

    impl Debug for Satisfaction[src]

    impl From<bool> for Satisfaction[src]

    impl Serialize for Satisfaction[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.SatisfiableItem.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.SatisfiableItem.html deleted file mode 100644 index e5fa6b2346..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/enum.SatisfiableItem.html +++ /dev/null @@ -1,91 +0,0 @@ -bdk::descriptor::policy::SatisfiableItem - Rust - -

    [][src]Enum bdk::descriptor::policy::SatisfiableItem

    pub enum SatisfiableItem {
    -    Signature(PKOrF),
    -    SignatureKey(PKOrF),
    -    SHA256Preimage {
    -        hash: Hash,
    -    },
    -    HASH256Preimage {
    -        hash: Hash,
    -    },
    -    RIPEMD160Preimage {
    -        hash: Hash,
    -    },
    -    HASH160Preimage {
    -        hash: Hash,
    -    },
    -    AbsoluteTimelock {
    -        value: u32,
    -    },
    -    RelativeTimelock {
    -        value: u32,
    -    },
    -    Multisig {
    -        keys: Vec<PKOrF>,
    -        threshold: usize,
    -    },
    -    Thresh {
    -        items: Vec<Policy>,
    -        threshold: usize,
    -    },
    -}

    An item that needs to be satisfied

    -

    - Variants

    -
    Signature(PKOrF)

    Signature for a raw public key

    -
    SignatureKey(PKOrF)

    Signature for an extended key fingerprint

    -
    SHA256Preimage

    SHA256 preimage hash

    -

    Fields of SHA256Preimage

    hash: Hash

    The digest value

    -
    HASH256Preimage

    Double SHA256 preimage hash

    -

    Fields of HASH256Preimage

    hash: Hash

    The digest value

    -
    RIPEMD160Preimage

    RIPEMD160 preimage hash

    -

    Fields of RIPEMD160Preimage

    hash: Hash

    The digest value

    -
    HASH160Preimage

    SHA256 then RIPEMD160 preimage hash

    -

    Fields of HASH160Preimage

    hash: Hash

    The digest value

    -
    AbsoluteTimelock

    Absolute timeclock timestamp

    -

    Fields of AbsoluteTimelock

    value: u32

    The timestamp value

    -
    RelativeTimelock

    Relative timelock locktime

    -

    Fields of RelativeTimelock

    value: u32

    The locktime value

    -
    Multisig

    Multi-signature public keys with threshold count

    -

    Fields of Multisig

    keys: Vec<PKOrF>

    The raw public key or extended key fingerprint

    -
    threshold: usize

    The required threshold count

    -
    Thresh

    Threshold items with threshold count

    -

    Fields of Thresh

    items: Vec<Policy>

    The policy items

    -
    threshold: usize

    The required threshold count

    -

    Implementations

    impl SatisfiableItem[src]

    pub fn is_leaf(&self) -> bool[src]

    Returns whether the SatisfiableItem is a leaf item

    -

    pub fn id(&self) -> String[src]

    Returns a unique id for the SatisfiableItem

    -

    Trait Implementations

    impl Clone for SatisfiableItem[src]

    impl Debug for SatisfiableItem[src]

    impl From<SatisfiableItem> for Policy[src]

    impl Serialize for SatisfiableItem[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/index.html deleted file mode 100644 index b63abf9c5b..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/index.html +++ /dev/null @@ -1,30 +0,0 @@ -bdk::descriptor::policy - Rust - -

    [][src]Module bdk::descriptor::policy

    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

    -
    -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(desc)?;
    -println!("{:?}", extended_desc);
    -
    -let signers = Arc::new(key_map.into());
    -let policy = extended_desc.extract_policy(&signers, &secp)?;
    -println!("policy: {}", serde_json::to_string(&policy)?);
    -

    Structs

    -
    Condition

    An extra condition that must be satisfied but that is out of control of the user

    -
    PKOrF

    Raw public key or extended key fingerprint

    -
    Policy

    Descriptor spending policy

    -

    Enums

    -
    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

    -

    Type Definitions

    -
    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/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/sidebar-items.js deleted file mode 100644 index 4a150396ce..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["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"],["PKOrF","Raw public key or extended key fingerprint"],["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/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.Condition.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.Condition.html deleted file mode 100644 index 494ddc412f..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.Condition.html +++ /dev/null @@ -1,62 +0,0 @@ -bdk::descriptor::policy::Condition - Rust - -

    [][src]Struct bdk::descriptor::policy::Condition

    pub struct Condition {
    -    pub csv: Option<u32>,
    -    pub timelock: Option<u32>,
    -}

    An extra condition that must be satisfied but that is out of control of the user

    -

    - Fields

    csv: Option<u32>

    Optional CheckSequenceVerify condition

    -
    timelock: Option<u32>

    Optional timelock condition

    -

    Implementations

    impl Condition[src]

    pub fn is_null(&self) -> bool[src]

    Returns true if there are no extra conditions to verify

    -

    Trait Implementations

    impl Clone for Condition[src]

    impl Copy for Condition[src]

    impl Debug for Condition[src]

    impl Default for Condition[src]

    impl Eq for Condition[src]

    impl Hash for Condition[src]

    impl Ord for Condition[src]

    impl PartialEq<Condition> for Condition[src]

    impl PartialOrd<Condition> for Condition[src]

    impl Serialize for Condition[src]

    impl StructuralEq for Condition[src]

    impl StructuralPartialEq for Condition[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.PKOrF.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.PKOrF.html deleted file mode 100644 index 2033adda15..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.PKOrF.html +++ /dev/null @@ -1,38 +0,0 @@ -bdk::descriptor::policy::PKOrF - Rust - -

    [][src]Struct bdk::descriptor::policy::PKOrF

    pub struct PKOrF { /* fields omitted */ }

    Raw public key or extended key fingerprint

    -

    Trait Implementations

    impl Clone for PKOrF[src]

    impl Debug for PKOrF[src]

    impl Default for PKOrF[src]

    impl Serialize for PKOrF[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.Policy.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.Policy.html deleted file mode 100644 index edb84dab4d..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/struct.Policy.html +++ /dev/null @@ -1,55 +0,0 @@ -bdk::descriptor::policy::Policy - Rust - -

    [][src]Struct bdk::descriptor::policy::Policy

    pub struct Policy {
    -    pub id: String,
    -    pub item: SatisfiableItem,
    -    pub satisfaction: Satisfaction,
    -    pub contribution: Satisfaction,
    -}

    Descriptor spending policy

    -

    - Fields

    id: String

    Identifier for this policy node

    -
    item: SatisfiableItem

    Type of this policy node

    -
    satisfaction: Satisfaction

    How a much given PSBT already satisfies this polcy node (currently unused)

    -
    contribution: Satisfaction

    How the wallet's descriptor can satisfy this policy node

    -

    Implementations

    impl Policy[src]

    pub fn requires_path(&self) -> bool[src]

    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 get_condition(
        &self,
        path: &BTreeMap<String, Vec<usize>>
    ) -> Result<Condition, PolicyError>
    [src]

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

    -

    Trait Implementations

    impl Clone for Policy[src]

    impl Debug for Policy[src]

    impl From<SatisfiableItem> for Policy[src]

    impl Serialize for Policy[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/type.ConditionMap.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/type.ConditionMap.html deleted file mode 100644 index 04cdc96053..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/type.ConditionMap.html +++ /dev/null @@ -1,5 +0,0 @@ -bdk::descriptor::policy::ConditionMap - Rust - -

    [][src]Type Definition bdk::descriptor::policy::ConditionMap

    type ConditionMap = BTreeMap<usize, HashSet<Condition>>;

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

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/type.FoldedConditionMap.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/type.FoldedConditionMap.html deleted file mode 100644 index d677ccbae2..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/policy/type.FoldedConditionMap.html +++ /dev/null @@ -1,5 +0,0 @@ -bdk::descriptor::policy::FoldedConditionMap - Rust - -

    [][src]Type Definition bdk::descriptor::policy::FoldedConditionMap

    type FoldedConditionMap = BTreeMap<Vec<usize>, HashSet<Condition>>;

    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/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/sidebar-items.js deleted file mode 100644 index 91b23d7fe1..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Descriptor","Script descriptor"],["Legacy","Legacy ScriptContext To be used as P2SH scripts For creation of Bare scriptpubkeys, construct the Miniscript under `Bare` ScriptContext"],["Segwitv0","Segwitv0 ScriptContext"],["Terminal","All AST elements"]],"mod":[["checksum","Descriptor checksum"],["error","Descriptor errors"],["policy","Descriptor policy"],["template","Descriptor templates"]],"struct":[["Miniscript","Top-level script AST type"]],"trait":[["ExtractPolicy","Trait implemented on [`Descriptor`]s to add a method to extract the spending [`policy`]"],["MiniscriptKey","Public key trait which can be converted to Hash type"],["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"],["ToPublicKey","Trait describing public key types which can be converted to bitcoin pubkeys The trait relies on Copy trait because in all practical usecases `ToPkCtx` should contain references to objects which should be cheap to `Copy`."],["ToWalletDescriptor","Trait for types which can be converted into an [`ExtendedDescriptor`] and a [`KeyMap`] usable by a wallet in a specific [`Network`]"]],"type":[["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`"],["KeyMap","Alias type for a map of public key to secret key"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/struct.Miniscript.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/struct.Miniscript.html deleted file mode 100644 index 1c5121d486..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/struct.Miniscript.html +++ /dev/null @@ -1,206 +0,0 @@ -bdk::descriptor::Miniscript - Rust - -

    []Struct bdk::descriptor::Miniscript

    pub struct Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
    { - pub node: Terminal<Pk, Ctx>, - pub ty: Type, - pub ext: ExtData, - // some fields omitted -}

    Top-level script AST type

    -

    - Fields

    node: Terminal<Pk, Ctx>

    A node in the Abstract Syntax Tree(

    -
    ty: Type

    The correctness and malleability type information for the AST node

    -
    ext: ExtData

    Additional information helpful for extra analysis.

    -

    Implementations

    impl<Pk, Ctx> Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn requires_sig(&self) -> bool

    Whether all spend paths of miniscript require a signature

    -

    pub fn is_non_malleable(&self) -> bool

    Whether the miniscript is malleable

    -

    pub fn within_resource_limits(&self) -> bool

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

    -

    pub fn has_mixed_timelocks(&self) -> bool

    Whether the miniscript contains a combination of timelocks

    -

    pub fn has_repeated_keys(&self) -> bool

    Whether the miniscript has repeated Pk or Pkh

    -

    pub fn sanity_check(&self) -> Result<(), AnalysisError>

    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

    -

    impl<Pk, Ctx> Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    Iterator-related extensions for Miniscript

    -

    pub fn iter(&self) -> Iter<'_, Pk, Ctx>

    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.

    -

    pub fn iter_pk(&self) -> PkIter<'_, Pk, Ctx>

    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.

    -

    pub fn iter_pkh(&self) -> PkhIter<'_, Pk, Ctx>

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

    -

    pub fn iter_pk_pkh(&self) -> PkPkhIter<'_, Pk, Ctx>

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

    -

    pub fn branches(&self) -> Vec<&Miniscript<Pk, Ctx>, Global>

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

    -

    pub fn get_nth_child(&self, n: usize) -> Option<&Miniscript<Pk, Ctx>>

    Returns child node with given index, if any

    -

    pub fn get_leaf_pk(&self) -> Vec<Pk, Global>

    Returns Vec with cloned version of all public keys from the current miniscript item, -if any. Otherwise returns an empty Vec.

    -

    NB: The function analyzes only single miniscript item and not any of its descendants in AST. -To obtain a list of all public keys within AST use [fn.iter_pk()] function, for example -miniscript.iter_pubkeys().collect().

    -

    pub fn get_leaf_pkh(&self) -> Vec<<Pk as MiniscriptKey>::Hash, Global>

    Returns Vec with hashes of all public keys from the current miniscript item, if any. -Otherwise returns an empty Vec.

    -

    For each public key the function computes hash; for each hash of the public key the function -returns its cloned copy.

    -

    NB: The function analyzes only single miniscript item and not any of its descendants in AST. -To obtain a list of all public key hashes within AST use [fn.iter_pkh()] function, -for example miniscript.iter_pubkey_hashes().collect().

    -

    pub fn get_leaf_pk_pkh(&self) -> Vec<PkPkh<Pk>, Global>

    Returns Vec of [PkPkh] entries, representing either public keys or public key -hashes, depending on the data from the current miniscript item. If there is no public -keys or hashes, the function returns an empty Vec.

    -

    NB: The function analyzes only single miniscript item and not any of its descendants in AST. -To obtain a list of all public keys or hashes within AST use [fn.iter_pk_pkh()] -function, for example miniscript.iter_pubkeys_and_hashes().collect().

    -

    pub fn get_nth_pk(&self, n: usize) -> Option<Pk>

    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.

    -

    pub fn get_nth_pkh(&self, n: usize) -> Option<<Pk as MiniscriptKey>::Hash>

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

    -

    For each public key the function computes hash; for each hash of the public key the function -returns it cloned copy.

    -

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

    -

    pub fn get_nth_pk_pkh(&self, n: usize) -> Option<PkPkh<Pk>>

    Returns Option::Some with hash of n'th public key or hash 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.

    -

    impl<Pk, Ctx> Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn from_ast(t: Terminal<Pk, Ctx>) -> Result<Miniscript<Pk, Ctx>, Error>

    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.

    -

    impl<Pk, Ctx> Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn into_inner(self) -> Terminal<Pk, Ctx>

    Extracts the AstElem representing the root of the miniscript

    -

    pub fn as_inner(&self) -> &Terminal<Pk, Ctx>

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

    -

    impl<Ctx> Miniscript<PublicKey, Ctx> where
        Ctx: ScriptContext

    pub fn parse_insane(
        script: &Script
    ) -> Result<Miniscript<PublicKey, Ctx>, Error>

    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.

    -

    pub fn parse(script: &Script) -> Result<Miniscript<PublicKey, Ctx>, Error>

    Attempt to parse a Script into Miniscript representation. -This function will fail parsing for scripts that do not clear -the [fn.analyzable.sanity_check] checks. Use [fn.parse_insane] to -parse such scripts.

    -

    impl<Pk, Ctx> Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn encode<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> Script where
        Pk: ToPublicKey<ToPkCtx>,
        ToPkCtx: Copy

    Encode as a Bitcoin script

    -

    pub fn script_size<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> usize where
        Pk: ToPublicKey<ToPkCtx>,
        ToPkCtx: Copy

    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.

    -

    impl<Pk, Ctx> Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn max_satisfaction_witness_elements(&self) -> Option<usize>

    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 return None on malformed Miniscript objects which do -not correspond to semantically sane Scripts. (Such scripts should be -rejected at parse time. Any exceptions are bugs.)

    -

    pub fn max_satisfaction_size(&self) -> Option<usize>

    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.

    -

    impl<Pk, Ctx> Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn translate_pk<FPk, FPkh, Q, FuncError>(
        &self,
        translatefpk: &mut FPk,
        translatefpkh: &mut FPkh
    ) -> Result<Miniscript<Q, Ctx>, FuncError> where
        FPk: FnMut(&Pk) -> Result<Q, FuncError>,
        FPkh: FnMut(&<Pk as MiniscriptKey>::Hash) -> Result<<Q as MiniscriptKey>::Hash, FuncError>,
        Q: MiniscriptKey

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

    -

    pub fn from_str_insane(s: &str) -> Result<Miniscript<Pk, Ctx>, Error> where
        <Pk as FromStr>::Err: ToString,
        <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

    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.

    -

    impl<Pk, Ctx> Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn satisfy<ToPkCtx, S>(
        &self,
        satisfier: S,
        to_pk_ctx: ToPkCtx
    ) -> Result<Vec<Vec<u8, Global>, Global>, Error> where
        Pk: ToPublicKey<ToPkCtx>,
        S: Satisfier<ToPkCtx, Pk>,
        ToPkCtx: Copy

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

    -

    pub fn satisfy_malleable<ToPkCtx, S>(
        &self,
        satisfier: S,
        to_pk_ctx: ToPkCtx
    ) -> Result<Vec<Vec<u8, Global>, Global>, Error> where
        Pk: ToPublicKey<ToPkCtx>,
        S: Satisfier<ToPkCtx, Pk>,
        ToPkCtx: Copy

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

    -

    impl<Pk, Ctx> Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn lift_check(&self) -> Result<(), LiftError>

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

    -
      -
    1. Timelock combination
    2. -
    3. Contains a spend that exceeds resource limits
    4. -
    -

    Trait Implementations

    impl<Pk, Ctx> Clone for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext + Clone,
        Pk: MiniscriptKey + Clone

    impl<Pk, Ctx> Debug for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> Display for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> Eq for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

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

    -

    impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx>[src]

    impl<Pk, Ctx> FromStr for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey,
        <Pk as FromStr>::Err: ToString,
        <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

    type Err = Error

    The associated error which can be returned from parsing.

    -

    pub fn from_str(s: &str) -> Result<Miniscript<Pk, Ctx>, Error>

    Parse a Miniscript from string and perform sanity checks -See [fn.from_str_insane] to parse scripts from string that -do not clear the [fn.analyzable.sanity_check] checks.

    -

    impl<Pk, Ctx> FromTree for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey,
        <Pk as FromStr>::Err: ToString,
        <<Pk as MiniscriptKey>::Hash as FromStr>::Err: ToString

    pub fn from_tree(top: &Tree<'_>) -> Result<Miniscript<Pk, Ctx>, Error>

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

    -

    impl<Pk, Ctx> Hash for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext + Hash,
        Pk: MiniscriptKey + Hash

    impl<Pk, Ctx> Liftable<Pk> for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> Ord for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

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

    -

    impl<Pk, Ctx> PartialEq<Miniscript<Pk, Ctx>> for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

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

    -

    impl<Pk, Ctx> PartialOrd<Miniscript<Pk, Ctx>> for Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

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

    -

    Auto Trait Implementations

    impl<Pk, Ctx> RefUnwindSafe for Miniscript<Pk, Ctx> where
        Ctx: RefUnwindSafe,
        Pk: RefUnwindSafe,
        <Pk as MiniscriptKey>::Hash: RefUnwindSafe
    [src]

    impl<Pk, Ctx> Send for Miniscript<Pk, Ctx> where
        Ctx: Send + Sync,
        Pk: Send + Sync,
        <Pk as MiniscriptKey>::Hash: Send + Sync
    [src]

    impl<Pk, Ctx> Sync for Miniscript<Pk, Ctx> where
        Ctx: Send + Sync,
        Pk: Send + Sync,
        <Pk as MiniscriptKey>::Hash: Send + Sync
    [src]

    impl<Pk, Ctx> Unpin for Miniscript<Pk, Ctx> where
        Ctx: Unpin,
        Pk: Unpin,
        <Pk as MiniscriptKey>::Hash: Unpin
    [src]

    impl<Pk, Ctx> UnwindSafe for Miniscript<Pk, Ctx> where
        Ctx: RefUnwindSafe + UnwindSafe,
        Pk: RefUnwindSafe + UnwindSafe,
        <Pk as MiniscriptKey>::Hash: RefUnwindSafe + UnwindSafe
    [src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/index.html deleted file mode 100644 index a701f40721..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/index.html +++ /dev/null @@ -1,21 +0,0 @@ -bdk::descriptor::template - Rust - -

    [][src]Module bdk::descriptor::template

    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

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

    -
    BIP44Public

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

    -
    BIP49

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

    -
    BIP49Public

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

    -
    BIP84

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

    -
    BIP84Public

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

    -
    P2PKH

    P2PKH template. Expands to a descriptor pkh(key)

    -
    P2WPKH

    P2WPKH template. Expands to a descriptor wpkh(key)

    -
    P2WPKH_P2SH

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

    -

    Traits

    -
    DescriptorTemplate

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

    -

    Type Definitions

    -
    DescriptorTemplateOut

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

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/sidebar-items.js deleted file mode 100644 index 1e10991c5b..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["BIP44","BIP44 template. Expands to `pkh(key/44'/0'/0'/{0,1}/*)`"],["BIP44Public","BIP44 public template. Expands to `pkh(key/{0,1}/*)`"],["BIP49","BIP49 template. Expands to `sh(wpkh(key/49'/0'/0'/{0,1}/*))`"],["BIP49Public","BIP49 public template. Expands to `sh(wpkh(key/{0,1}/*))`"],["BIP84","BIP84 template. Expands to `wpkh(key/84'/0'/0'/{0,1}/*)`"],["BIP84Public","BIP84 public template. Expands to `wpkh(key/{0,1}/*)`"],["P2PKH","P2PKH template. Expands to a descriptor `pkh(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/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP44.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP44.html deleted file mode 100644 index e1665c341e..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP44.html +++ /dev/null @@ -1,47 +0,0 @@ -bdk::descriptor::template::BIP44 - Rust - -

    [][src]Struct bdk::descriptor::template::BIP44

    pub struct BIP44<K: DerivableKey<Legacy>>(pub K, pub KeychainKind);

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

    -

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

    -

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

    -

    Example

    -
    -use bdk::template::BIP44;
    -
    -let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -let wallet: OfflineWallet<_> = Wallet::new_offline(
    -    BIP44(key.clone(), KeychainKind::External),
    -    Some(BIP44(key, KeychainKind::Internal)),
    -    Network::Testnet,
    -    MemoryDatabase::default()
    -)?;
    -
    -assert_eq!(wallet.get_new_address()?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
    -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)");
    -

    Trait Implementations

    impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44<K>[src]

    Auto Trait Implementations

    impl<K> RefUnwindSafe for BIP44<K> where
        K: RefUnwindSafe
    [src]

    impl<K> Send for BIP44<K> where
        K: Send
    [src]

    impl<K> Sync for BIP44<K> where
        K: Sync
    [src]

    impl<K> Unpin for BIP44<K> where
        K: Unpin
    [src]

    impl<K> UnwindSafe for BIP44<K> where
        K: UnwindSafe
    [src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToWalletDescriptor for T where
        T: DescriptorTemplate
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP44Public.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP44Public.html deleted file mode 100644 index 6eb406b0a5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP44Public.html +++ /dev/null @@ -1,50 +0,0 @@ -bdk::descriptor::template::BIP44Public - Rust - -

    [][src]Struct bdk::descriptor::template::BIP44Public

    pub struct BIP44Public<K: DerivableKey<Legacy>>(pub K, pub Fingerprint, pub KeychainKind);

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

    -

    This assumes that the key used has already been derived with m/44'/0'/0'.

    -

    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::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
    -let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
    -let wallet: OfflineWallet<_> = Wallet::new_offline(
    -    BIP44Public(key.clone(), fingerprint, KeychainKind::External),
    -    Some(BIP44Public(key, fingerprint, KeychainKind::Internal)),
    -    Network::Testnet,
    -    MemoryDatabase::default()
    -)?;
    -
    -assert_eq!(wallet.get_new_address()?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
    -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)");
    -

    Trait Implementations

    impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44Public<K>[src]

    Auto Trait Implementations

    impl<K> RefUnwindSafe for BIP44Public<K> where
        K: RefUnwindSafe
    [src]

    impl<K> Send for BIP44Public<K> where
        K: Send
    [src]

    impl<K> Sync for BIP44Public<K> where
        K: Sync
    [src]

    impl<K> Unpin for BIP44Public<K> where
        K: Unpin
    [src]

    impl<K> UnwindSafe for BIP44Public<K> where
        K: UnwindSafe
    [src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToWalletDescriptor for T where
        T: DescriptorTemplate
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP49.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP49.html deleted file mode 100644 index 2efbae9d75..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP49.html +++ /dev/null @@ -1,47 +0,0 @@ -bdk::descriptor::template::BIP49 - Rust - -

    [][src]Struct bdk::descriptor::template::BIP49

    pub struct BIP49<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);

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

    -

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

    -

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

    -

    Example

    -
    -use bdk::template::BIP49;
    -
    -let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -let wallet: OfflineWallet<_> = Wallet::new_offline(
    -    BIP49(key.clone(), KeychainKind::External),
    -    Some(BIP49(key, KeychainKind::Internal)),
    -    Network::Testnet,
    -    MemoryDatabase::default()
    -)?;
    -
    -assert_eq!(wallet.get_new_address()?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
    -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))");
    -

    Trait Implementations

    impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49<K>[src]

    Auto Trait Implementations

    impl<K> RefUnwindSafe for BIP49<K> where
        K: RefUnwindSafe
    [src]

    impl<K> Send for BIP49<K> where
        K: Send
    [src]

    impl<K> Sync for BIP49<K> where
        K: Sync
    [src]

    impl<K> Unpin for BIP49<K> where
        K: Unpin
    [src]

    impl<K> UnwindSafe for BIP49<K> where
        K: UnwindSafe
    [src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToWalletDescriptor for T where
        T: DescriptorTemplate
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP49Public.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP49Public.html deleted file mode 100644 index 7fff60cfd4..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP49Public.html +++ /dev/null @@ -1,50 +0,0 @@ -bdk::descriptor::template::BIP49Public - Rust - -

    [][src]Struct bdk::descriptor::template::BIP49Public

    pub struct BIP49Public<K: DerivableKey<Segwitv0>>(pub K, pub Fingerprint, pub KeychainKind);

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

    -

    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::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
    -let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
    -let wallet: OfflineWallet<_> = Wallet::new_offline(
    -    BIP49Public(key.clone(), fingerprint, KeychainKind::External),
    -    Some(BIP49Public(key, fingerprint, KeychainKind::Internal)),
    -    Network::Testnet,
    -    MemoryDatabase::default()
    -)?;
    -
    -assert_eq!(wallet.get_new_address()?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
    -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))");
    -

    Trait Implementations

    impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49Public<K>[src]

    Auto Trait Implementations

    impl<K> RefUnwindSafe for BIP49Public<K> where
        K: RefUnwindSafe
    [src]

    impl<K> Send for BIP49Public<K> where
        K: Send
    [src]

    impl<K> Sync for BIP49Public<K> where
        K: Sync
    [src]

    impl<K> Unpin for BIP49Public<K> where
        K: Unpin
    [src]

    impl<K> UnwindSafe for BIP49Public<K> where
        K: UnwindSafe
    [src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToWalletDescriptor for T where
        T: DescriptorTemplate
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP84.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP84.html deleted file mode 100644 index 934b4dc733..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP84.html +++ /dev/null @@ -1,47 +0,0 @@ -bdk::descriptor::template::BIP84 - Rust - -

    [][src]Struct bdk::descriptor::template::BIP84

    pub struct BIP84<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);

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

    -

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

    -

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

    -

    Example

    -
    -use bdk::template::BIP84;
    -
    -let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -let wallet: OfflineWallet<_> = Wallet::new_offline(
    -    BIP84(key.clone(), KeychainKind::External),
    -    Some(BIP84(key, KeychainKind::Internal)),
    -    Network::Testnet,
    -    MemoryDatabase::default()
    -)?;
    -
    -assert_eq!(wallet.get_new_address()?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
    -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)");
    -

    Trait Implementations

    impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP84<K>[src]

    Auto Trait Implementations

    impl<K> RefUnwindSafe for BIP84<K> where
        K: RefUnwindSafe
    [src]

    impl<K> Send for BIP84<K> where
        K: Send
    [src]

    impl<K> Sync for BIP84<K> where
        K: Sync
    [src]

    impl<K> Unpin for BIP84<K> where
        K: Unpin
    [src]

    impl<K> UnwindSafe for BIP84<K> where
        K: UnwindSafe
    [src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToWalletDescriptor for T where
        T: DescriptorTemplate
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP84Public.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP84Public.html deleted file mode 100644 index 632706f146..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.BIP84Public.html +++ /dev/null @@ -1,50 +0,0 @@ -bdk::descriptor::template::BIP84Public - Rust - -

    [][src]Struct bdk::descriptor::template::BIP84Public

    pub struct BIP84Public<K: DerivableKey<Segwitv0>>(pub K, pub Fingerprint, pub KeychainKind);

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

    -

    This assumes that the key used has already been derived with m/84'/0'/0'.

    -

    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::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
    -let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
    -let wallet: OfflineWallet<_> = Wallet::new_offline(
    -    BIP84Public(key.clone(), fingerprint, KeychainKind::External),
    -    Some(BIP84Public(key, fingerprint, KeychainKind::Internal)),
    -    Network::Testnet,
    -    MemoryDatabase::default()
    -)?;
    -
    -assert_eq!(wallet.get_new_address()?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
    -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)");
    -

    Trait Implementations

    impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP84Public<K>[src]

    Auto Trait Implementations

    impl<K> RefUnwindSafe for BIP84Public<K> where
        K: RefUnwindSafe
    [src]

    impl<K> Send for BIP84Public<K> where
        K: Send
    [src]

    impl<K> Sync for BIP84Public<K> where
        K: Sync
    [src]

    impl<K> Unpin for BIP84Public<K> where
        K: Unpin
    [src]

    impl<K> UnwindSafe for BIP84Public<K> where
        K: UnwindSafe
    [src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToWalletDescriptor for T where
        T: DescriptorTemplate
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2PKH.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2PKH.html deleted file mode 100644 index 0678bdd7e4..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2PKH.html +++ /dev/null @@ -1,48 +0,0 @@ -bdk::descriptor::template::P2PKH - Rust - -

    [][src]Struct bdk::descriptor::template::P2PKH

    pub struct P2PKH<K: ToDescriptorKey<Legacy>>(pub K);

    P2PKH template. Expands to a descriptor pkh(key)

    -

    Example

    -
    -use bdk::template::P2PKH;
    -
    -let key =
    -    bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
    -let wallet: OfflineWallet<_> = Wallet::new_offline(
    -    P2PKH(key),
    -    None,
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -)?;
    -
    -assert_eq!(
    -    wallet.get_new_address()?.to_string(),
    -    "mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"
    -);
    -

    Trait Implementations

    impl<K: ToDescriptorKey<Legacy>> DescriptorTemplate for P2PKH<K>[src]

    Auto Trait Implementations

    impl<K> RefUnwindSafe for P2PKH<K> where
        K: RefUnwindSafe
    [src]

    impl<K> Send for P2PKH<K> where
        K: Send
    [src]

    impl<K> Sync for P2PKH<K> where
        K: Sync
    [src]

    impl<K> Unpin for P2PKH<K> where
        K: Unpin
    [src]

    impl<K> UnwindSafe for P2PKH<K> where
        K: UnwindSafe
    [src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToWalletDescriptor for T where
        T: DescriptorTemplate
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2WPKH.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2WPKH.html deleted file mode 100644 index 4766fc25f8..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2WPKH.html +++ /dev/null @@ -1,48 +0,0 @@ -bdk::descriptor::template::P2WPKH - Rust - -

    [][src]Struct bdk::descriptor::template::P2WPKH

    pub struct P2WPKH<K: ToDescriptorKey<Segwitv0>>(pub K);

    P2WPKH template. Expands to a descriptor wpkh(key)

    -

    Example

    -
    -use bdk::template::P2WPKH;
    -
    -let key =
    -    bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
    -let wallet: OfflineWallet<_> = Wallet::new_offline(
    -    P2WPKH(key),
    -    None,
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -)?;
    -
    -assert_eq!(
    -    wallet.get_new_address()?.to_string(),
    -    "tb1q4525hmgw265tl3drrl8jjta7ayffu6jf68ltjd"
    -);
    -

    Trait Implementations

    impl<K: ToDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH<K>[src]

    Auto Trait Implementations

    impl<K> RefUnwindSafe for P2WPKH<K> where
        K: RefUnwindSafe
    [src]

    impl<K> Send for P2WPKH<K> where
        K: Send
    [src]

    impl<K> Sync for P2WPKH<K> where
        K: Sync
    [src]

    impl<K> Unpin for P2WPKH<K> where
        K: Unpin
    [src]

    impl<K> UnwindSafe for P2WPKH<K> where
        K: UnwindSafe
    [src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToWalletDescriptor for T where
        T: DescriptorTemplate
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2WPKH_P2SH.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2WPKH_P2SH.html deleted file mode 100644 index 74f62aeac6..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/struct.P2WPKH_P2SH.html +++ /dev/null @@ -1,48 +0,0 @@ -bdk::descriptor::template::P2WPKH_P2SH - Rust - -

    [][src]Struct bdk::descriptor::template::P2WPKH_P2SH

    pub struct P2WPKH_P2SH<K: ToDescriptorKey<Segwitv0>>(pub K);

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

    -

    Example

    -
    -use bdk::template::P2WPKH_P2SH;
    -
    -let key =
    -    bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
    -let wallet: OfflineWallet<_> = Wallet::new_offline(
    -    P2WPKH_P2SH(key),
    -    None,
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -)?;
    -
    -assert_eq!(
    -    wallet.get_new_address()?.to_string(),
    -    "2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"
    -);
    -

    Trait Implementations

    impl<K: ToDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH_P2SH<K>[src]

    Auto Trait Implementations

    impl<K> RefUnwindSafe for P2WPKH_P2SH<K> where
        K: RefUnwindSafe
    [src]

    impl<K> Send for P2WPKH_P2SH<K> where
        K: Send
    [src]

    impl<K> Sync for P2WPKH_P2SH<K> where
        K: Sync
    [src]

    impl<K> Unpin for P2WPKH_P2SH<K> where
        K: Unpin
    [src]

    impl<K> UnwindSafe for P2WPKH_P2SH<K> where
        K: UnwindSafe
    [src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToWalletDescriptor for T where
        T: DescriptorTemplate
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/trait.DescriptorTemplate.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/trait.DescriptorTemplate.html deleted file mode 100644 index 8f3a721057..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/trait.DescriptorTemplate.html +++ /dev/null @@ -1,23 +0,0 @@ -bdk::descriptor::template::DescriptorTemplate - Rust - -

    [][src]Trait bdk::descriptor::template::DescriptorTemplate

    pub trait DescriptorTemplate {
    -    pub fn build(self) -> Result<DescriptorTemplateOut, KeyError>;
    -}

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

    -

    Since ToWalletDescriptor is implemented for any DescriptorTemplate, they can also be -passed directly to the Wallet constructor.

    -

    Example

    -
    -use bdk::keys::{KeyError, ToDescriptorKey};
    -use bdk::miniscript::Legacy;
    -use bdk::template::{DescriptorTemplate, DescriptorTemplateOut};
    -
    -struct MyP2PKH<K: ToDescriptorKey<Legacy>>(K);
    -
    -impl<K: ToDescriptorKey<Legacy>> DescriptorTemplate for MyP2PKH<K> {
    -    fn build(self) -> Result<DescriptorTemplateOut, KeyError> {
    -        Ok(bdk::descriptor!(pkh(self.0))?)
    -    }
    -}
    -

    Required methods

    pub fn build(self) -> Result<DescriptorTemplateOut, KeyError>[src]

    Build the complete descriptor

    -
    Loading content...

    Implementors

    impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44<K>[src]

    impl<K: DerivableKey<Legacy>> DescriptorTemplate for BIP44Public<K>[src]

    impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49<K>[src]

    impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP49Public<K>[src]

    impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP84<K>[src]

    impl<K: DerivableKey<Segwitv0>> DescriptorTemplate for BIP84Public<K>[src]

    impl<K: ToDescriptorKey<Legacy>> DescriptorTemplate for P2PKH<K>[src]

    impl<K: ToDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH<K>[src]

    impl<K: ToDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH_P2SH<K>[src]

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/type.DescriptorTemplateOut.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/type.DescriptorTemplateOut.html deleted file mode 100644 index 2dc811d4f4..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/template/type.DescriptorTemplateOut.html +++ /dev/null @@ -1,6 +0,0 @@ -bdk::descriptor::template::DescriptorTemplateOut - Rust - -

    [][src]Type Definition bdk::descriptor::template::DescriptorTemplateOut

    type DescriptorTemplateOut = (ExtendedDescriptor, KeyMap, ValidNetworks);

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

    -

    Trait Implementations

    impl ToWalletDescriptor for DescriptorTemplateOut[src]

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ExtractPolicy.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ExtractPolicy.html deleted file mode 100644 index 1012bebadf..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ExtractPolicy.html +++ /dev/null @@ -1,8 +0,0 @@ -bdk::descriptor::ExtractPolicy - Rust - -

    [][src]Trait bdk::descriptor::ExtractPolicy

    pub trait ExtractPolicy {
    -    pub fn extract_policy(
            &self,
            signers: &SignersContainer,
            secp: &Secp256k1<All>
        ) -> Result<Option<Policy>, Error>; -}

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

    -

    Required methods

    pub fn extract_policy(
        &self,
        signers: &SignersContainer,
        secp: &Secp256k1<All>
    ) -> Result<Option<Policy>, Error>
    [src]

    Extract the spending policy

    -
    Loading content...

    Implementors

    impl ExtractPolicy for Descriptor<DescriptorPublicKey>[src]

    impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx>[src]

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.MiniscriptKey.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.MiniscriptKey.html deleted file mode 100644 index 45e2f12a24..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.MiniscriptKey.html +++ /dev/null @@ -1,16 +0,0 @@ -bdk::descriptor::MiniscriptKey - Rust - -

    []Trait bdk::descriptor::MiniscriptKey

    pub trait MiniscriptKey: Clone + Eq + Ord + Debug + Display + Hash + FromStr {
    -    type Hash: Clone + Eq + Ord + Debug + Display + Hash + FromStr;
    -    pub fn to_pubkeyhash(&self) -> Self::Hash;
    -
    -    pub fn is_uncompressed(&self) -> bool { ... }
    -}

    Public key trait which can be converted to Hash type

    -

    Associated Types

    type Hash: Clone + Eq + Ord + Debug + Display + Hash + FromStr

    The associated Hash type with the publicKey

    -
    Loading content...

    Required methods

    pub fn to_pubkeyhash(&self) -> Self::Hash

    Converts an object to PublicHash

    -
    Loading content...

    Provided methods

    pub fn is_uncompressed(&self) -> bool

    Check if the publicKey is uncompressed. The default -implementation returns false

    -
    Loading content...

    Implementations on Foreign Types

    impl MiniscriptKey for String

    type Hash = String

    impl MiniscriptKey for DummyKey

    type Hash = DummyKeyHash

    impl MiniscriptKey for PublicKey

    pub fn is_uncompressed(&self) -> bool

    is_uncompressed returns true only for -bitcoin::Publickey type if the underlying key is uncompressed.

    -

    type Hash = Hash

    Loading content...

    Implementors

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ScriptContext.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ScriptContext.html deleted file mode 100644 index c2bd80c5da..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ScriptContext.html +++ /dev/null @@ -1,78 +0,0 @@ -bdk::descriptor::ScriptContext - Rust - -

    []Trait bdk::descriptor::ScriptContext

    pub trait ScriptContext: Sealed + Clone + PartialEq<Self> + Eq + Ord + PartialOrd<Self> + Debug {
    -    pub fn check_terminal_non_malleable<Pk, Ctx>(
            _frag: &Terminal<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    ; -
    pub fn max_satisfaction_size<Pk, Ctx>(
            ms: &Miniscript<Pk, Ctx>
        ) -> Option<usize>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    ; - - pub fn check_witness<Pk, Ctx>(
            _witness: &[Vec<u8, Global>]
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn check_global_consensus_validity<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn check_global_policy_validity<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn check_local_consensus_validity<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn check_local_policy_validity<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn check_global_validity<Pk, Ctx>(
            ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn check_local_validity<Pk, Ctx>(
            ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn top_level_type_check<Pk, Ctx>(
            ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), Error>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn other_top_level_checks<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), Error>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn top_level_checks<Pk, Ctx>(
            ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), Error>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -}

    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 methods

    pub fn check_terminal_non_malleable<Pk, Ctx>(
        _frag: &Terminal<Pk, Ctx>
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    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.

    -

    pub fn max_satisfaction_size<Pk, Ctx>(ms: &Miniscript<Pk, Ctx>) -> Option<usize> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

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

    -
    Loading content...

    Provided methods

    pub fn check_witness<Pk, Ctx>(
        _witness: &[Vec<u8, Global>]
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    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.

    -

    pub fn check_global_consensus_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    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.

    -

    pub fn check_global_policy_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    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.

    -

    pub fn check_local_consensus_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    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.

    -

    pub fn check_local_policy_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    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

    -

    pub fn check_global_validity<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

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

    -

    pub fn check_local_validity<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

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

    -

    pub fn top_level_type_check<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), Error> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    Check whether the top-level is type B

    -

    pub fn other_top_level_checks<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), Error> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    Other top level checks that are context specific

    -

    pub fn top_level_checks<Pk, Ctx>(ms: &Miniscript<Pk, Ctx>) -> Result<(), Error> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    Check top level consensus rules.

    -
    Loading content...

    Implementations on Foreign Types

    impl ScriptContext for Bare

    Loading content...

    Implementors

    impl ScriptContext for Legacy

    impl ScriptContext for Segwitv0

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ToPublicKey.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ToPublicKey.html deleted file mode 100644 index 1c2cfde4f4..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ToPublicKey.html +++ /dev/null @@ -1,25 +0,0 @@ -bdk::descriptor::ToPublicKey - Rust - -

    []Trait bdk::descriptor::ToPublicKey

    pub trait ToPublicKey<ToPkCtx>: MiniscriptKey where
        ToPkCtx: Copy
    { - pub fn to_public_key(&self, to_pk_ctx: ToPkCtx) -> PublicKey; -
    pub fn hash_to_hash160(hash: &Self::Hash, to_pk_ctx: ToPkCtx) -> Hash; - - pub fn serialized_len(&self, to_pk_ctx: ToPkCtx) -> usize { ... } -}

    Trait describing public key types which can be converted to bitcoin pubkeys -The trait relies on Copy trait because in all practical usecases ToPkCtx -should contain references to objects which should be cheap to Copy.

    -

    Required methods

    pub fn to_public_key(&self, to_pk_ctx: ToPkCtx) -> PublicKey

    Converts an object to a public key -C represents additional context information that maybe -required for deriving a bitcoin::PublicKey from MiniscriptKey -You may require secp context for crypto operations -or additional information for substituting the wildcard in -extended pubkeys

    -

    pub fn hash_to_hash160(hash: &Self::Hash, to_pk_ctx: ToPkCtx) -> Hash

    Converts a hashed version of the public key to a hash160 hash.

    -

    This method must be consistent with to_public_key, in the sense -that calling MiniscriptKey::to_pubkeyhash followed by this function -should give the same result as calling to_public_key and hashing -the result directly.

    -
    Loading content...

    Provided methods

    pub fn serialized_len(&self, to_pk_ctx: ToPkCtx) -> usize

    Computes the size of a public key when serialized in a script, -including the length bytes

    -
    Loading content...

    Implementations on Foreign Types

    impl ToPublicKey<NullCtx> for DummyKey

    impl ToPublicKey<NullCtx> for PublicKey

    Loading content...

    Implementors

    impl<'secp, C> ToPublicKey<DescriptorPublicKeyCtx<'secp, C>> for DescriptorPublicKey where
        C: Verification, 

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ToWalletDescriptor.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ToWalletDescriptor.html deleted file mode 100644 index e748fbf297..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/trait.ToWalletDescriptor.html +++ /dev/null @@ -1,10 +0,0 @@ -bdk::descriptor::ToWalletDescriptor - Rust - -

    [][src]Trait bdk::descriptor::ToWalletDescriptor

    pub trait ToWalletDescriptor {
    -    pub fn to_wallet_descriptor(
            self,
            network: Network
        ) -> Result<(ExtendedDescriptor, KeyMap), KeyError>; -}

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

    -

    Required methods

    pub fn to_wallet_descriptor(
        self,
        network: Network
    ) -> Result<(ExtendedDescriptor, KeyMap), KeyError>
    [src]

    Convert to wallet descriptor

    -
    Loading content...

    Implementations on Foreign Types

    impl<'_> ToWalletDescriptor for &'_ str[src]

    impl<'_> ToWalletDescriptor for &'_ String[src]

    impl ToWalletDescriptor for (ExtendedDescriptor, KeyMap)[src]

    Loading content...

    Implementors

    impl ToWalletDescriptor for DescriptorTemplateOut[src]

    impl ToWalletDescriptor for ExtendedDescriptor[src]

    impl<T: DescriptorTemplate> ToWalletDescriptor for T[src]

    Turns a DescriptorTemplate into a valid wallet descriptor by calling its -build method

    -
    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.ExtendedDescriptor.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.ExtendedDescriptor.html deleted file mode 100644 index 846b405272..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.ExtendedDescriptor.html +++ /dev/null @@ -1,6 +0,0 @@ -bdk::descriptor::ExtendedDescriptor - Rust - -

    [][src]Type Definition bdk::descriptor::ExtendedDescriptor

    type ExtendedDescriptor = Descriptor<DescriptorPublicKey>;

    Alias for a Descriptor that can contain extended keys using DescriptorPublicKey

    -

    Trait Implementations

    impl ToWalletDescriptor for ExtendedDescriptor[src]

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.HDKeyPaths.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.HDKeyPaths.html deleted file mode 100644 index 25850ae841..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.HDKeyPaths.html +++ /dev/null @@ -1,6 +0,0 @@ -bdk::descriptor::HDKeyPaths - Rust - -

    [][src]Type Definition bdk::descriptor::HDKeyPaths

    type HDKeyPaths = BTreeMap<PublicKey, KeySource>;

    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/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.KeyMap.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.KeyMap.html deleted file mode 100644 index bfe0522027..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/descriptor/type.KeyMap.html +++ /dev/null @@ -1,9 +0,0 @@ -bdk::descriptor::KeyMap - Rust - -

    []Type Definition bdk::descriptor::KeyMap

    type KeyMap = HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>;

    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/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.Error.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.Error.html deleted file mode 100644 index a6f2f695e6..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.Error.html +++ /dev/null @@ -1,148 +0,0 @@ -bdk::Error - Rust - -

    [][src]Enum bdk::Error

    pub enum Error {
    -    InvalidU32Bytes(Vec<u8>),
    -    Generic(String),
    -    ScriptDoesntHaveAddressForm,
    -    SingleRecipientMultipleOutputs,
    -    SingleRecipientNoInputs,
    -    NoRecipients,
    -    NoUtxosSelected,
    -    OutputBelowDustLimit(usize),
    -    InsufficientFunds,
    -    BnBTotalTriesExceeded,
    -    BnBNoExactMatch,
    -    UnknownUTXO,
    -    TransactionNotFound,
    -    TransactionConfirmed,
    -    IrreplaceableTransaction,
    -    FeeRateTooLow {
    -        required: FeeRate,
    -    },
    -    FeeTooLow {
    -        required: u64,
    -    },
    -    MissingKeyOrigin(String),
    -    Key(KeyError),
    -    ChecksumMismatch,
    -    SpendingPolicyRequired(KeychainKind),
    -    InvalidPolicyPathError(PolicyError),
    -    Signer(SignerError),
    -    OfflineClient,
    -    InvalidProgressValue(f32),
    -    ProgressUpdateError,
    -    InvalidOutpoint(OutPoint),
    -    Descriptor(Error),
    -    AddressValidator(AddressValidatorError),
    -    Encode(Error),
    -    Miniscript(Error),
    -    BIP32(Error),
    -    Secp256k1(Error),
    -    JSON(Error),
    -    Hex(Error),
    -    PSBT(Error),
    -    Electrum(Error),
    -    Esplora(EsploraError),
    -    CompactFilters(CompactFiltersError),
    -    Sled(Error),
    -}

    Errors that can be thrown by the Wallet

    -

    - Variants

    -
    InvalidU32Bytes(Vec<u8>)

    Wrong number of bytes found when trying to convert to u32

    -
    Generic(String)

    Generic error

    -
    ScriptDoesntHaveAddressForm

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

    -
    SingleRecipientMultipleOutputs

    Found multiple outputs when single_recipient option has been specified

    -
    SingleRecipientNoInputs

    single_recipient option is selected but neither drain_wallet nor manually_selected_only are

    -
    NoRecipients

    Cannot build a tx without recipients

    -
    NoUtxosSelected

    manually_selected_only option is selected but no utxo has been passed

    -
    OutputBelowDustLimit(usize)

    Output created is under the dust limit, 546 satoshis

    -
    InsufficientFunds

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

    -
    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

    -
    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

    -
    UnknownUTXO

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

    -
    TransactionNotFound

    Thrown when a tx is not found in the internal database

    -
    TransactionConfirmed

    Happens when trying to bump a transaction that is already confirmed

    -
    IrreplaceableTransaction

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

    -
    FeeRateTooLow

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

    -

    Fields of FeeRateTooLow

    required: FeeRate

    Required fee rate (satoshi/vbyte)

    -
    FeeTooLow

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

    -

    Fields of FeeTooLow

    required: u64

    Required fee absolute value (satoshi)

    -
    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

    -

    Error while working with keys

    -
    ChecksumMismatch

    Descriptor checksum mismatch

    -
    SpendingPolicyRequired(KeychainKind)

    Spending policy is not compatible with this KeychainKind

    -
    InvalidPolicyPathError(PolicyError)

    Error while extracting and manipulating policies

    -
    Signer(SignerError)

    Signing error

    -
    OfflineClient

    Thrown when trying to call a method that requires a network connection, Wallet::sync and Wallet::broadcast -This error is thrown when creating the Client for the first time, while recovery attempts are tried -during the sync

    -
    InvalidProgressValue(f32)

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

    -
    ProgressUpdateError

    Progress update error (maybe the channel has been closed)

    -
    InvalidOutpoint(OutPoint)

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

    -
    Descriptor(Error)

    Error related to the parsing and usage of descriptors

    -
    AddressValidator(AddressValidatorError)

    Error that can be returned to fail the validation of an address

    -
    Encode(Error)

    Encoding error

    -
    Miniscript(Error)

    Miniscript error

    -
    BIP32(Error)

    BIP32 error

    -
    Secp256k1(Error)

    An ECDSA error

    -
    JSON(Error)

    Error serializing or deserializing JSON data

    -
    Hex(Error)

    Hex decoding error

    -
    PSBT(Error)

    Partially signed bitcoin transaction error

    -
    Electrum(Error)

    Electrum client error

    -
    Esplora(EsploraError)

    Esplora client error

    -
    CompactFilters(CompactFiltersError)

    Compact filters client error)

    -
    Sled(Error)

    Sled database error

    -

    Trait Implementations

    impl Debug for Error[src]

    impl Display for Error[src]

    impl Error for Error[src]

    impl From<AddressValidatorError> for Error[src]

    impl From<CompactFiltersError> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for CompactFiltersError[src]

    This is supported on crate feature compact_filters only.

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<Error> for Error[src]

    impl From<EsploraError> for Error[src]

    impl From<KeyError> for Error[src]

    impl From<PolicyError> for Error[src]

    impl From<SignerError> for Error[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.KeychainKind.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.KeychainKind.html deleted file mode 100644 index 491efbac18..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.KeychainKind.html +++ /dev/null @@ -1,59 +0,0 @@ -bdk::KeychainKind - Rust - -

    [][src]Enum bdk::KeychainKind

    pub enum KeychainKind {
    -    External,
    -    Internal,
    -}

    Types of keychains

    -

    - Variants

    -
    External

    External

    -
    Internal

    Internal, usually used for change outputs

    -

    Implementations

    impl KeychainKind[src]

    pub fn as_byte(&self) -> u8[src]

    Return KeychainKind as a byte

    -

    Trait Implementations

    impl AsRef<[u8]> for KeychainKind[src]

    impl Clone for KeychainKind[src]

    impl Copy for KeychainKind[src]

    impl Debug for KeychainKind[src]

    impl<'de> Deserialize<'de> for KeychainKind[src]

    impl Eq for KeychainKind[src]

    impl Hash for KeychainKind[src]

    impl PartialEq<KeychainKind> for KeychainKind[src]

    impl Serialize for KeychainKind[src]

    impl StructuralEq for KeychainKind[src]

    impl StructuralPartialEq for KeychainKind[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Base32Len for T where
        T: AsRef<[u8]>, 

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<'f, T> CheckBase32<Vec<u5, Global>> for T where
        T: AsRef<[u8]>, 

    type Err = Error

    Error type if conversion fails

    -

    impl<T> DeserializeOwned for T where
        T: for<'de> Deserialize<'de>, 
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToBase32 for T where
        T: AsRef<[u8]>, 

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.ScriptType.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.ScriptType.html deleted file mode 100644 index fac96f212c..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/enum.ScriptType.html +++ /dev/null @@ -1,58 +0,0 @@ -bdk::ScriptType - Rust - -

    [][src]Enum bdk::ScriptType

    pub enum ScriptType {
    -    External,
    -    Internal,
    -}

    Types of script

    -

    - Variants

    -
    External

    External

    -
    Internal

    Internal, usually used for change outputs

    -

    Implementations

    impl ScriptType[src]

    pub fn as_byte(&self) -> u8[src]

    Trait Implementations

    impl AsRef<[u8]> for ScriptType[src]

    impl Clone for ScriptType[src]

    impl Copy for ScriptType[src]

    impl Debug for ScriptType[src]

    impl<'de> Deserialize<'de> for ScriptType[src]

    impl Eq for ScriptType[src]

    impl Hash for ScriptType[src]

    impl PartialEq<ScriptType> for ScriptType[src]

    impl Serialize for ScriptType[src]

    impl StructuralEq for ScriptType[src]

    impl StructuralPartialEq for ScriptType[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Base32Len for T where
        T: AsRef<[u8]>, 

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<'f, T> CheckBase32<Vec<u5, Global>> for T where
        T: AsRef<[u8]>, 

    type Err = Error

    Error type if conversion fails

    -

    impl<T> DeserializeOwned for T where
        T: for<'de> Deserialize<'de>, 
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToBase32 for T where
        T: AsRef<[u8]>, 

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/error/enum.Error.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/error/enum.Error.html deleted file mode 100644 index 113a951037..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/error/enum.Error.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

    Redirecting to ../../bdk/enum.Error.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/index.html deleted file mode 100644 index 8323289c69..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/index.html +++ /dev/null @@ -1,167 +0,0 @@ -bdk - Rust - -

    [][src]Crate bdk

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

    -

    About

    -

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

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

    A Tour of BDK

    -

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

    -

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

    -
    bdk = "0.2.0"
    -
    -

    Sync the balance of a descriptor

    Example

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

    Generate a few addresses

    Example

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

    Create a transaction

    Example

    -
    ⓘThis example is not tested
    -use base64::decode;
    -use bdk::{FeeRate, TxBuilder, Wallet};
    -use bdk::database::MemoryDatabase;
    -use bdk::blockchain::{noop_progress, ElectrumBlockchain};
    -
    -use bdk::electrum_client::Client;
    -
    -use bitcoin::consensus::serialize;
    -
    -fn main() -> Result<(), bdk::Error> {
    -    let client = Client::new("ssl://electrum.blockstream.info:60002")?;
    -    let wallet = Wallet::new(
    -        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
    -        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
    -        bitcoin::Network::Testnet,
    -        MemoryDatabase::default(),
    -        ElectrumBlockchain::from(client)
    -    )?;
    -
    -    wallet.sync(noop_progress(), None)?;
    -
    -    let send_to = wallet.get_new_address()?;
    -    let (psbt, details) = wallet.create_tx(
    -        TxBuilder::with_recipients(vec![(send_to.script_pubkey(), 50_000)])
    -            .enable_rbf()
    -            .do_not_spend_change()
    -            .fee_rate(FeeRate::from_sat_per_vb(5.0))
    -    )?;
    -
    -    println!("Transaction details: {:#?}", details);
    -    println!("Unsigned PSBT: {}", base64::encode(&serialize(&psbt)));
    -
    -    Ok(())
    -}
    -

    Sign a transaction

    Example

    -
    ⓘThis example is not tested
    -use base64::decode;
    -use bdk::{Wallet, OfflineWallet};
    -use bdk::database::MemoryDatabase;
    -
    -use bitcoin::consensus::deserialize;
    -
    -fn main() -> Result<(), bdk::Error> {
    -    let wallet: OfflineWallet<_> = Wallet::new_offline(
    -        "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
    -        Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
    -        bitcoin::Network::Testnet,
    -        MemoryDatabase::default(),
    -    )?;
    -
    -    let psbt = "...";
    -    let psbt = deserialize(&base64::decode(psbt).unwrap())?;
    -
    -    let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
    -
    -    Ok(())
    -}
    -

    Feature flags

    -

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

    -

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

    -
      -
    • all-keys: all features for working with bitcoin keys
    • -
    • async-interface: async functions in bdk traits
    • -
    • cli-utils: utilities for creating a command line interface wallet
    • -
    • keys-bip39: BIP-39 mnemonic codes for generating deterministic keys
    • -
    -

    Internal features

    -

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

    -
      -
    • compact_filters: compact_filters client protocol for interacting with the bitcoin P2P network
    • -
    • electrum: electrum client protocol for interacting with electrum servers
    • -
    • esplora: esplora client protocol for interacting with blockstream electrs servers
    • -
    • key-value-db: key value database based on sled for caching blockchain data
    • -
    -

    Re-exports

    -
    pub extern crate bitcoin;
    pub extern crate miniscript;
    pub extern crate electrum_client;
    pub extern crate reqwest;
    pub extern crate sled;
    pub use descriptor::template;
    pub use descriptor::HDKeyPaths;
    pub use wallet::address_validator;
    pub use wallet::signer;
    pub use wallet::tx_builder::TxBuilder;
    pub use wallet::OfflineWallet;
    pub use wallet::Wallet;

    Modules

    -
    blockchain

    Blockchain backends

    -
    database

    Database types

    -
    descriptor

    Descriptors

    -
    keys

    Key formats

    -
    wallet

    Wallet

    -

    Macros

    -
    descriptor

    Macro to write full descriptors with code

    -
    fragment

    Macro to write descriptor fragments with code

    -

    Structs

    -
    FeeRate

    Fee rate

    -
    TransactionDetails

    A wallet transaction

    -
    UTXO

    A wallet unspent output

    -

    Enums

    -
    Error

    Errors that can be thrown by the Wallet

    -
    KeychainKind

    Types of keychains

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/index.html deleted file mode 100644 index 7beb4dcbbd..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/index.html +++ /dev/null @@ -1,7 +0,0 @@ -bdk::keys::bip39 - Rust - -

    [][src]Module bdk::keys::bip39

    This is supported on crate feature keys-bip39 only.

    BIP-0039

    -

    Type Definitions

    -
    MnemonicWithPassphrase

    Type for a BIP39 mnemonic with an optional passphrase

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/sidebar-items.js deleted file mode 100644 index e3212ff208..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"type":[["MnemonicWithPassphrase","Type for a BIP39 mnemonic with an optional passphrase"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/type.MnemonicWithPassphrase.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/type.MnemonicWithPassphrase.html deleted file mode 100644 index 64af95a2d4..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/bip39/type.MnemonicWithPassphrase.html +++ /dev/null @@ -1,6 +0,0 @@ -bdk::keys::bip39::MnemonicWithPassphrase - Rust - -

    [][src]Type Definition bdk::keys::bip39::MnemonicWithPassphrase

    type MnemonicWithPassphrase = (Mnemonic, Option<String>);
    This is supported on crate feature keys-bip39 only.

    Type for a BIP39 mnemonic with an optional passphrase

    -

    Trait Implementations

    impl<Ctx: ScriptContext> DerivableKey<Ctx> for MnemonicWithPassphrase[src]

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorKey.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorKey.html deleted file mode 100644 index 8e38293842..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorKey.html +++ /dev/null @@ -1,37 +0,0 @@ -bdk::keys::DescriptorKey - Rust - -

    [][src]Enum bdk::keys::DescriptorKey

    pub enum DescriptorKey<Ctx: ScriptContext> {
    -    // some variants omitted
    -}

    Container for public or secret keys

    -

    Implementations

    impl<Ctx: ScriptContext> DescriptorKey<Ctx>[src]

    pub fn from_public(public: DescriptorPublicKey, networks: ValidNetworks) -> Self[src]

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

    -

    pub fn from_secret(secret: DescriptorSecretKey, networks: ValidNetworks) -> Self[src]

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

    -

    pub fn override_valid_networks(self, networks: ValidNetworks) -> Self[src]

    Override the computed set of valid networks

    -

    Trait Implementations

    impl<Ctx: Debug + ScriptContext> Debug for DescriptorKey<Ctx>[src]

    impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorKey<Ctx>[src]

    The "identity" conversion is used internally by some bdk::fragments

    -

    Auto Trait Implementations

    impl<Ctx> RefUnwindSafe for DescriptorKey<Ctx> where
        Ctx: RefUnwindSafe
    [src]

    impl<Ctx> Send for DescriptorKey<Ctx> where
        Ctx: Send
    [src]

    impl<Ctx> Sync for DescriptorKey<Ctx> where
        Ctx: Sync
    [src]

    impl<Ctx> Unpin for DescriptorKey<Ctx> where
        Ctx: Unpin
    [src]

    impl<Ctx> UnwindSafe for DescriptorKey<Ctx> where
        Ctx: UnwindSafe
    [src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorPublicKey.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorPublicKey.html deleted file mode 100644 index 38c6c9e90c..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorPublicKey.html +++ /dev/null @@ -1,81 +0,0 @@ -bdk::keys::DescriptorPublicKey - Rust - -

    []Enum bdk::keys::DescriptorPublicKey

    pub enum DescriptorPublicKey {
    -    SinglePub(DescriptorSinglePub),
    -    XPub(DescriptorXKey<ExtendedPubKey>),
    -}

    The MiniscriptKey corresponding to Descriptors. This can -either be Single public key or a Xpub

    -

    - Variants

    -

    Single Public Key

    -
    XPub(DescriptorXKey<ExtendedPubKey>)

    Xpub

    -

    Implementations

    impl DescriptorPublicKey

    pub fn derive(self, child_number: ChildNumber) -> DescriptorPublicKey

    Derives the specified child key if self is a wildcard xpub. Otherwise returns self.

    -

    Panics if given a hardened child number

    -

    Trait Implementations

    impl Clone for DescriptorPublicKey

    impl Debug for DescriptorPublicKey

    impl Display for DescriptorPublicKey

    impl Eq for DescriptorPublicKey

    impl FromStr for DescriptorPublicKey

    type Err = DescriptorKeyParseError

    The associated error which can be returned from parsing.

    -

    impl Hash for DescriptorPublicKey

    impl MiniscriptKey for DescriptorPublicKey

    type Hash = DescriptorPublicKey

    The associated Hash type with the publicKey

    -

    impl Ord for DescriptorPublicKey

    impl PartialEq<DescriptorPublicKey> for DescriptorPublicKey

    impl PartialOrd<DescriptorPublicKey> for DescriptorPublicKey

    impl StructuralEq for DescriptorPublicKey

    impl StructuralPartialEq for DescriptorPublicKey

    impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorPublicKey[src]

    impl<'secp, C> ToPublicKey<DescriptorPublicKeyCtx<'secp, C>> for DescriptorPublicKey where
        C: Verification, 

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorSecretKey.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorSecretKey.html deleted file mode 100644 index 77ee6bed66..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.DescriptorSecretKey.html +++ /dev/null @@ -1,48 +0,0 @@ -bdk::keys::DescriptorSecretKey - Rust - -

    []Enum bdk::keys::DescriptorSecretKey

    pub enum DescriptorSecretKey {
    -    SinglePriv(DescriptorSinglePriv),
    -    XPrv(DescriptorXKey<ExtendedPrivKey>),
    -}

    A Secret Key that can be either a single key or an Xprv

    -

    - Variants

    -

    Single Secret Key

    -
    XPrv(DescriptorXKey<ExtendedPrivKey>)

    Xprv

    -

    Implementations

    impl DescriptorSecretKey

    pub fn as_public<C>(
        &self,
        secp: &Secp256k1<C>
    ) -> Result<DescriptorPublicKey, DescriptorKeyParseError> where
        C: Signing, 

    Return the public version of this key, by applying either -DescriptorSinglePriv::as_public or [DescriptorXKey<bip32::ExtendedPrivKey>::as_public] -depending on the type of key.

    -

    If the key is an "XPrv", the hardened derivation steps will be applied before converting it -to a public key. See the documentation of [DescriptorXKey<bip32::ExtendedPrivKey>::as_public] -for more details.

    -

    Trait Implementations

    impl Debug for DescriptorSecretKey

    impl Display for DescriptorSecretKey

    impl FromStr for DescriptorSecretKey

    type Err = DescriptorKeyParseError

    The associated error which can be returned from parsing.

    -

    impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorSecretKey[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.KeyError.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.KeyError.html deleted file mode 100644 index ef3178668e..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.KeyError.html +++ /dev/null @@ -1,55 +0,0 @@ -bdk::keys::KeyError - Rust - -

    [][src]Enum bdk::keys::KeyError

    pub enum KeyError {
    -    InvalidScriptContext,
    -    InvalidNetwork,
    -    InvalidChecksum,
    -    Message(String),
    -    BIP32(Error),
    -    Miniscript(Error),
    -}

    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

    impl Debug for KeyError[src]

    impl Display for KeyError[src]

    impl Error for KeyError[src]

    impl From<Error> for KeyError[src]

    impl From<Error> for KeyError[src]

    impl From<KeyError> for Error[src]

    impl From<KeyError> for Error[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.ScriptContextEnum.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.ScriptContextEnum.html deleted file mode 100644 index 9e93778129..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/enum.ScriptContextEnum.html +++ /dev/null @@ -1,49 +0,0 @@ -bdk::keys::ScriptContextEnum - Rust - -

    [][src]Enum bdk::keys::ScriptContextEnum

    pub enum ScriptContextEnum {
    -    Legacy,
    -    Segwitv0,
    -}

    Enum representation of the known valid ScriptContexts

    -

    - Variants

    -
    Legacy

    Legacy scripts

    -
    Segwitv0

    Segwitv0 scripts

    -

    Implementations

    impl ScriptContextEnum[src]

    pub fn is_legacy(&self) -> bool[src]

    Returns whether the script context is ScriptContextEnum::Legacy

    -

    pub fn is_segwit_v0(&self) -> bool[src]

    Returns whether the script context is ScriptContextEnum::Segwitv0

    -

    Trait Implementations

    impl Clone for ScriptContextEnum[src]

    impl Copy for ScriptContextEnum[src]

    impl Debug for ScriptContextEnum[src]

    impl Eq for ScriptContextEnum[src]

    impl PartialEq<ScriptContextEnum> for ScriptContextEnum[src]

    impl StructuralEq for ScriptContextEnum[src]

    impl StructuralPartialEq for ScriptContextEnum[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.any_network.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.any_network.html deleted file mode 100644 index 76ff654177..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.any_network.html +++ /dev/null @@ -1,5 +0,0 @@ -bdk::keys::any_network - Rust - -

    [][src]Function bdk::keys::any_network

    pub fn any_network() -> ValidNetworks

    Create a set containing mainnet, testnet and regtest

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.mainnet_network.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.mainnet_network.html deleted file mode 100644 index d0807b41c8..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.mainnet_network.html +++ /dev/null @@ -1,5 +0,0 @@ -bdk::keys::mainnet_network - Rust - -

    [][src]Function bdk::keys::mainnet_network

    pub fn mainnet_network() -> ValidNetworks

    Create a set only containing mainnet

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.merge_networks.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.merge_networks.html deleted file mode 100644 index 86a3528a58..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.merge_networks.html +++ /dev/null @@ -1,5 +0,0 @@ -bdk::keys::merge_networks - Rust - -

    [][src]Function bdk::keys::merge_networks

    pub fn merge_networks(a: &ValidNetworks, b: &ValidNetworks) -> ValidNetworks

    Compute the intersection of two sets

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.test_networks.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.test_networks.html deleted file mode 100644 index 4071c41fd5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/fn.test_networks.html +++ /dev/null @@ -1,5 +0,0 @@ -bdk::keys::test_networks - Rust - -

    [][src]Function bdk::keys::test_networks

    pub fn test_networks() -> ValidNetworks

    Create a set containing testnet and regtest

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/index.html deleted file mode 100644 index 7442d78e48..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/index.html +++ /dev/null @@ -1,37 +0,0 @@ -bdk::keys - Rust - -

    [][src]Module bdk::keys

    Key formats

    -

    Modules

    -
    bip39keys-bip39

    BIP-0039

    -

    Structs

    -
    DescriptorSinglePriv

    A Single Descriptor Secret Key with optional origin information

    -
    DescriptorSinglePub

    A Single Descriptor Key with optional origin information

    -
    GeneratedKey

    Output of a GeneratableKey key generation

    -
    PrivateKeyGenerateOptions

    Options for generating a [PrivateKey]

    -
    SortedMultiVec

    Contents of a "sortedmulti" descriptor

    -

    Enums

    -
    DescriptorKey

    Container for public or secret keys

    -
    DescriptorPublicKey

    The MiniscriptKey corresponding to Descriptors. This can -either be Single public key or a Xpub

    -
    DescriptorSecretKey

    A Secret Key that can be either a single key or an Xprv

    -
    KeyError

    Errors thrown while working with keys

    -
    ScriptContextEnum

    Enum representation of the known valid ScriptContexts

    -

    Traits

    -
    DerivableKey

    Trait for keys that can be derived.

    -
    ExtScriptContext

    Trait that adds extra useful methods to ScriptContexts

    -
    GeneratableDefaultOptions

    Trait that allows generating a key with the default options

    -
    GeneratableKey

    Trait for keys that can be generated

    -
    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

    -
    ToDescriptorKey

    Trait for objects that can be turned into a public or secret DescriptorKey

    -

    Functions

    -
    any_network

    Create a set containing mainnet, testnet 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

    -

    Type Definitions

    -
    ValidNetworks

    Set of valid networks for a key

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/sidebar-items.js deleted file mode 100644 index 9ba16e1f5e..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["DescriptorKey","Container for public or secret keys"],["DescriptorPublicKey","The MiniscriptKey corresponding to Descriptors. This can either be Single public key or a Xpub"],["DescriptorSecretKey","A Secret Key that can be either a single key or an Xprv"],["KeyError","Errors thrown while working with `keys`"],["ScriptContextEnum","Enum representation of the known valid [`ScriptContext`]s"]],"fn":[["any_network","Create a set containing mainnet, testnet and regtest"],["mainnet_network","Create a set only containing mainnet"],["merge_networks","Compute the intersection of two sets"],["test_networks","Create a set containing testnet and regtest"]],"mod":[["bip39","BIP-0039"]],"struct":[["DescriptorSinglePriv","A Single Descriptor Secret Key with optional origin information"],["DescriptorSinglePub","A Single Descriptor Key with optional origin information"],["GeneratedKey","Output of a [`GeneratableKey`] key generation"],["PrivateKeyGenerateOptions","Options for generating a [`PrivateKey`]"],["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"],["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"],["ToDescriptorKey","Trait for objects that can be turned into a public or secret [`DescriptorKey`]"]],"type":[["ValidNetworks","Set of valid networks for a key"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.DescriptorSinglePriv.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.DescriptorSinglePriv.html deleted file mode 100644 index 13fd899c3a..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.DescriptorSinglePriv.html +++ /dev/null @@ -1,36 +0,0 @@ -bdk::keys::DescriptorSinglePriv - Rust - -

    []Struct bdk::keys::DescriptorSinglePriv

    pub struct DescriptorSinglePriv {
    -    pub origin: Option<(Fingerprint, DerivationPath)>,
    -    pub key: PrivateKey,
    -}

    A Single Descriptor Secret Key with optional origin information

    -

    - Fields

    origin: Option<(Fingerprint, DerivationPath)>

    Origin information

    -
    key: PrivateKey

    The key

    -

    Trait Implementations

    impl Debug for DescriptorSinglePriv

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.DescriptorSinglePub.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.DescriptorSinglePub.html deleted file mode 100644 index 6a9b79d215..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.DescriptorSinglePub.html +++ /dev/null @@ -1,59 +0,0 @@ -bdk::keys::DescriptorSinglePub - Rust - -

    []Struct bdk::keys::DescriptorSinglePub

    pub struct DescriptorSinglePub {
    -    pub origin: Option<(Fingerprint, DerivationPath)>,
    -    pub key: PublicKey,
    -}

    A Single Descriptor Key with optional origin information

    -

    - Fields

    origin: Option<(Fingerprint, DerivationPath)>

    Origin information

    -
    key: PublicKey

    The key

    -

    Trait Implementations

    impl Clone for DescriptorSinglePub

    impl Debug for DescriptorSinglePub

    impl Eq for DescriptorSinglePub

    impl Hash for DescriptorSinglePub

    impl Ord for DescriptorSinglePub

    impl PartialEq<DescriptorSinglePub> for DescriptorSinglePub

    impl PartialOrd<DescriptorSinglePub> for DescriptorSinglePub

    impl StructuralEq for DescriptorSinglePub

    impl StructuralPartialEq for DescriptorSinglePub

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.GeneratedKey.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.GeneratedKey.html deleted file mode 100644 index d92eab815c..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.GeneratedKey.html +++ /dev/null @@ -1,34 +0,0 @@ -bdk::keys::GeneratedKey - Rust - -

    [][src]Struct bdk::keys::GeneratedKey

    pub struct GeneratedKey<K, Ctx: ScriptContext> { /* fields omitted */ }

    Output of a GeneratableKey key generation

    -

    Implementations

    impl<K, Ctx: ScriptContext> GeneratedKey<K, Ctx>[src]

    pub fn into_key(self) -> K[src]

    Consumes self and returns the key

    -

    Trait Implementations

    impl<K, Ctx: ScriptContext> Deref for GeneratedKey<K, Ctx>[src]

    type Target = K

    The resulting type after dereferencing.

    -

    impl<Ctx, K> DerivableKey<Ctx> for GeneratedKey<K, Ctx> where
        Ctx: ScriptContext,
        K: DerivableKey<Ctx>, 
    [src]

    impl<Ctx, K> ToDescriptorKey<Ctx> for GeneratedKey<K, Ctx> where
        Ctx: ScriptContext,
        K: ToDescriptorKey<Ctx>, 
    [src]

    Auto Trait Implementations

    impl<K, Ctx> RefUnwindSafe for GeneratedKey<K, Ctx> where
        Ctx: RefUnwindSafe,
        K: RefUnwindSafe
    [src]

    impl<K, Ctx> Send for GeneratedKey<K, Ctx> where
        Ctx: Send,
        K: Send
    [src]

    impl<K, Ctx> Sync for GeneratedKey<K, Ctx> where
        Ctx: Sync,
        K: Sync
    [src]

    impl<K, Ctx> Unpin for GeneratedKey<K, Ctx> where
        Ctx: Unpin,
        K: Unpin
    [src]

    impl<K, Ctx> UnwindSafe for GeneratedKey<K, Ctx> where
        Ctx: UnwindSafe,
        K: UnwindSafe
    [src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.PrivateKeyGenerateOptions.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.PrivateKeyGenerateOptions.html deleted file mode 100644 index af5794738a..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.PrivateKeyGenerateOptions.html +++ /dev/null @@ -1,42 +0,0 @@ -bdk::keys::PrivateKeyGenerateOptions - Rust - -

    [][src]Struct bdk::keys::PrivateKeyGenerateOptions

    pub struct PrivateKeyGenerateOptions {
    -    pub compressed: bool,
    -}

    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

    impl Clone for PrivateKeyGenerateOptions[src]

    impl Copy for PrivateKeyGenerateOptions[src]

    impl Debug for PrivateKeyGenerateOptions[src]

    impl Default for PrivateKeyGenerateOptions[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.SortedMultiVec.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.SortedMultiVec.html deleted file mode 100644 index 82ea82db66..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/struct.SortedMultiVec.html +++ /dev/null @@ -1,96 +0,0 @@ -bdk::keys::SortedMultiVec - Rust - -

    []Struct bdk::keys::SortedMultiVec

    pub struct SortedMultiVec<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey
    { - pub k: usize, - pub pks: Vec<Pk, Global>, - // some fields omitted -}

    Contents of a "sortedmulti" descriptor

    -

    - Fields

    k: usize

    signatures required

    -
    pks: Vec<Pk, Global>

    public keys inside sorted Multi

    -

    Implementations

    impl<Pk, Ctx> SortedMultiVec<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn new(
        k: usize,
        pks: Vec<Pk, Global>
    ) -> Result<SortedMultiVec<Pk, Ctx>, Error>

    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.

    -

    impl<Pk, Ctx> SortedMultiVec<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn translate_pk<FPk, Q, FuncError>(
        &self,
        translatefpk: &mut FPk
    ) -> Result<SortedMultiVec<Q, Ctx>, FuncError> where
        FPk: FnMut(&Pk) -> Result<Q, FuncError>,
        Q: MiniscriptKey

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

    -

    impl<Pk, Ctx> SortedMultiVec<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    pub fn sorted_node<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> Terminal<Pk, Ctx> where
        Pk: ToPublicKey<ToPkCtx>,
        ToPkCtx: Copy

    Create Terminal::Multi containing sorted pubkeys

    -

    pub fn encode<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> Script where
        Pk: ToPublicKey<ToPkCtx>,
        ToPkCtx: Copy

    Encode as a Bitcoin script

    -

    pub fn satisfy<ToPkCtx, S>(
        &self,
        satisfier: S,
        to_pk_ctx: ToPkCtx
    ) -> Result<Vec<Vec<u8, Global>, Global>, Error> where
        Pk: ToPublicKey<ToPkCtx>,
        S: Satisfier<ToPkCtx, Pk>,
        ToPkCtx: Copy

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

    -

    pub fn script_size<ToPkCtx>(&self, to_pk_ctx: ToPkCtx) -> usize where
        Pk: ToPublicKey<ToPkCtx>,
        ToPkCtx: Copy

    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.

    -

    pub fn max_satisfaction_witness_elements(&self) -> usize

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

    -

    pub fn max_satisfaction_size(&self, usize) -> usize

    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.

    -

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

    -

    Trait Implementations

    impl<Pk, Ctx> Clone for SortedMultiVec<Pk, Ctx> where
        Ctx: ScriptContext + Clone,
        Pk: MiniscriptKey + Clone

    impl<Pk, Ctx> Debug for SortedMultiVec<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> Display for SortedMultiVec<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> Eq for SortedMultiVec<Pk, Ctx> where
        Ctx: ScriptContext + Eq,
        Pk: MiniscriptKey + Eq

    impl<Pk, Ctx> Liftable<Pk> for SortedMultiVec<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> Ord for SortedMultiVec<Pk, Ctx> where
        Ctx: ScriptContext + Ord,
        Pk: MiniscriptKey + Ord

    impl<Pk, Ctx> PartialEq<SortedMultiVec<Pk, Ctx>> for SortedMultiVec<Pk, Ctx> where
        Ctx: ScriptContext + PartialEq<Ctx>,
        Pk: MiniscriptKey + PartialEq<Pk>, 

    impl<Pk, Ctx> PartialOrd<SortedMultiVec<Pk, Ctx>> for SortedMultiVec<Pk, Ctx> where
        Ctx: ScriptContext + PartialOrd<Ctx>,
        Pk: MiniscriptKey + PartialOrd<Pk>, 

    impl<Pk, Ctx> StructuralEq for SortedMultiVec<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    impl<Pk, Ctx> StructuralPartialEq for SortedMultiVec<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    Auto Trait Implementations

    impl<Pk, Ctx> RefUnwindSafe for SortedMultiVec<Pk, Ctx> where
        Ctx: RefUnwindSafe,
        Pk: RefUnwindSafe
    [src]

    impl<Pk, Ctx> Send for SortedMultiVec<Pk, Ctx> where
        Ctx: Send,
        Pk: Send
    [src]

    impl<Pk, Ctx> Sync for SortedMultiVec<Pk, Ctx> where
        Ctx: Sync,
        Pk: Sync
    [src]

    impl<Pk, Ctx> Unpin for SortedMultiVec<Pk, Ctx> where
        Ctx: Unpin,
        Pk: Unpin
    [src]

    impl<Pk, Ctx> UnwindSafe for SortedMultiVec<Pk, Ctx> where
        Ctx: UnwindSafe,
        Pk: UnwindSafe
    [src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.DerivableKey.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.DerivableKey.html deleted file mode 100644 index e5228642f7..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.DerivableKey.html +++ /dev/null @@ -1,15 +0,0 @@ -bdk::keys::DerivableKey - Rust - -

    [][src]Trait bdk::keys::DerivableKey

    pub trait DerivableKey<Ctx: ScriptContext> {
    -    pub fn add_metadata(
            self,
            origin: Option<KeySource>,
            derivation_path: DerivationPath
        ) -> Result<DescriptorKey<Ctx>, KeyError>; -}

    Trait for keys that can be derived.

    -

    When extra metadata are provided, a DerivableKey can be transofrmed into a -DescriptorKey: the trait ToDescriptorKey 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 implemented this trait instead of ToDescriptorKey. The same -rules regarding script context and valid networks apply.

    -

    Required methods

    pub fn add_metadata(
        self,
        origin: Option<KeySource>,
        derivation_path: DerivationPath
    ) -> Result<DescriptorKey<Ctx>, KeyError>
    [src]

    Add a extra metadata, consume self and turn it into a DescriptorKey

    -
    Loading content...

    Implementations on Foreign Types

    impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed[src]

    This is supported on crate feature keys-bip39 only.

    impl<Ctx: ScriptContext> DerivableKey<Ctx> for Mnemonic[src]

    This is supported on crate feature keys-bip39 only.

    impl<Ctx: ScriptContext> DerivableKey<Ctx> for ExtendedPubKey[src]

    impl<Ctx: ScriptContext> DerivableKey<Ctx> for ExtendedPrivKey[src]

    Loading content...

    Implementors

    impl<Ctx, K> DerivableKey<Ctx> for GeneratedKey<K, Ctx> where
        Ctx: ScriptContext,
        K: DerivableKey<Ctx>, 
    [src]

    impl<Ctx: ScriptContext> DerivableKey<Ctx> for MnemonicWithPassphrase[src]

    This is supported on crate feature keys-bip39 only.
    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ExtScriptContext.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ExtScriptContext.html deleted file mode 100644 index f22a12511a..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ExtScriptContext.html +++ /dev/null @@ -1,13 +0,0 @@ -bdk::keys::ExtScriptContext - Rust - -

    [][src]Trait bdk::keys::ExtScriptContext

    pub trait ExtScriptContext: ScriptContext {
    -    pub fn as_enum() -> ScriptContextEnum;
    -
    -    pub fn is_legacy() -> bool { ... }
    -
    pub fn is_segwit_v0() -> bool { ... } -}

    Trait that adds extra useful methods to ScriptContexts

    -

    Required methods

    Loading content...

    Provided methods

    pub fn is_legacy() -> bool[src]

    Returns whether the script context is Legacy

    -

    pub fn is_segwit_v0() -> bool[src]

    Returns whether the script context is Segwitv0

    -
    Loading content...

    Implementors

    impl<Ctx: ScriptContext + 'static> ExtScriptContext for Ctx[src]

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.GeneratableDefaultOptions.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.GeneratableDefaultOptions.html deleted file mode 100644 index 17759d7720..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.GeneratableDefaultOptions.html +++ /dev/null @@ -1,13 +0,0 @@ -bdk::keys::GeneratableDefaultOptions - Rust - -

    [][src]Trait bdk::keys::GeneratableDefaultOptions

    pub trait GeneratableDefaultOptions<Ctx>: GeneratableKey<Ctx> where
        Ctx: ScriptContext,
        Self::Options: Default
    { - pub fn generate_with_entropy_default(
            entropy: Self::Entropy
        ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> { ... } -
    pub fn generate_default() -> Result<GeneratedKey<Self, Ctx>, Self::Error> { ... } -}

    Trait that allows generating a key with the default options

    -

    This trait is automatically implemented if the GeneratableKey::Options implements Default.

    -

    Provided methods

    pub fn generate_with_entropy_default(
        entropy: Self::Entropy
    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error>
    [src]

    Generate a key with the default options and a given entropy

    -

    pub fn generate_default() -> Result<GeneratedKey<Self, Ctx>, Self::Error>[src]

    Generate a key with the default options and a random entropy

    -
    Loading content...

    Implementors

    impl<Ctx, K> GeneratableDefaultOptions<Ctx> for K where
        Ctx: ScriptContext,
        K: GeneratableKey<Ctx>,
        <K as GeneratableKey<Ctx>>::Options: Default
    [src]

    Automatic implementation of GeneratableDefaultOptions for GeneratableKeys where -Options implements Default

    -
    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.GeneratableKey.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.GeneratableKey.html deleted file mode 100644 index 5812454c1e..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.GeneratableKey.html +++ /dev/null @@ -1,22 +0,0 @@ -bdk::keys::GeneratableKey - Rust - -

    [][src]Trait bdk::keys::GeneratableKey

    pub trait GeneratableKey<Ctx: ScriptContext>: Sized {
    -    type Entropy: AsMut<[u8]> + Default;
    -    type Options;
    -    type Error: Debug;
    -    pub fn generate_with_entropy(
            options: Self::Options,
            entropy: Self::Entropy
        ) -> Result<GeneratedKey<Self, Ctx>, Self::Error>; - - pub fn generate(
            options: Self::Options
        ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> { ... } -}

    Trait for keys that can be generated

    -

    The same rules about ScriptContext and ValidNetworks from ToDescriptorKey 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 -ToDescriptorKey: the generated keys can be directly used in descriptors if Self is also -ToDescriptorKey.

    -

    Associated Types

    type Entropy: AsMut<[u8]> + Default[src]

    Type specifying the amount of entropy required e.g. [u8;32]

    -

    type Options[src]

    Extra options required by the generate_with_entropy

    -

    type Error: Debug[src]

    Returned error in case of failure

    -
    Loading content...

    Required methods

    pub fn generate_with_entropy(
        options: Self::Options,
        entropy: Self::Entropy
    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error>
    [src]

    Generate a key given the extra options and the entropy

    -
    Loading content...

    Provided methods

    pub fn generate(
        options: Self::Options
    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error>
    [src]

    Generate a key given the options with a random entropy

    -
    Loading content...

    Implementations on Foreign Types

    impl<Ctx: ScriptContext> GeneratableKey<Ctx> for Mnemonic[src]

    This is supported on crate feature keys-bip39 only.

    type Entropy = [u8; 32]

    type Options = (MnemonicType, Language)

    type Error = Option<ErrorKind>

    impl<Ctx: ScriptContext> GeneratableKey<Ctx> for ExtendedPrivKey[src]

    type Entropy = [u8; 32]

    type Options = ()

    type Error = Error

    impl<Ctx: ScriptContext> GeneratableKey<Ctx> for PrivateKey[src]

    type Entropy = [u8; 32]

    type Options = PrivateKeyGenerateOptions

    type Error = Error

    Loading content...

    Implementors

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ScriptContext.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ScriptContext.html deleted file mode 100644 index c81e63ce76..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ScriptContext.html +++ /dev/null @@ -1,78 +0,0 @@ -bdk::keys::ScriptContext - Rust - -

    []Trait bdk::keys::ScriptContext

    pub trait ScriptContext: Sealed + Clone + PartialEq<Self> + Eq + Ord + PartialOrd<Self> + Debug {
    -    pub fn check_terminal_non_malleable<Pk, Ctx>(
            _frag: &Terminal<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    ; -
    pub fn max_satisfaction_size<Pk, Ctx>(
            ms: &Miniscript<Pk, Ctx>
        ) -> Option<usize>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    ; - - pub fn check_witness<Pk, Ctx>(
            _witness: &[Vec<u8, Global>]
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn check_global_consensus_validity<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn check_global_policy_validity<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn check_local_consensus_validity<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn check_local_policy_validity<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn check_global_validity<Pk, Ctx>(
            ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn check_local_validity<Pk, Ctx>(
            ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn top_level_type_check<Pk, Ctx>(
            ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), Error>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn other_top_level_checks<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), Error>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    pub fn top_level_checks<Pk, Ctx>(
            ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), Error>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -}

    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 methods

    pub fn check_terminal_non_malleable<Pk, Ctx>(
        _frag: &Terminal<Pk, Ctx>
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    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.

    -

    pub fn max_satisfaction_size<Pk, Ctx>(ms: &Miniscript<Pk, Ctx>) -> Option<usize> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

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

    -
    Loading content...

    Provided methods

    pub fn check_witness<Pk, Ctx>(
        _witness: &[Vec<u8, Global>]
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    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.

    -

    pub fn check_global_consensus_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    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.

    -

    pub fn check_global_policy_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    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.

    -

    pub fn check_local_consensus_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    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.

    -

    pub fn check_local_policy_validity<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    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

    -

    pub fn check_global_validity<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

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

    -

    pub fn check_local_validity<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), ScriptContextError> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

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

    -

    pub fn top_level_type_check<Pk, Ctx>(
        ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), Error> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    Check whether the top-level is type B

    -

    pub fn other_top_level_checks<Pk, Ctx>(
        _ms: &Miniscript<Pk, Ctx>
    ) -> Result<(), Error> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    Other top level checks that are context specific

    -

    pub fn top_level_checks<Pk, Ctx>(ms: &Miniscript<Pk, Ctx>) -> Result<(), Error> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey

    Check top level consensus rules.

    -
    Loading content...

    Implementations on Foreign Types

    impl ScriptContext for Bare

    Loading content...

    Implementors

    impl ScriptContext for Legacy

    impl ScriptContext for Segwitv0

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ToDescriptorKey.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ToDescriptorKey.html deleted file mode 100644 index 54802814ca..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/trait.ToDescriptorKey.html +++ /dev/null @@ -1,112 +0,0 @@ -bdk::keys::ToDescriptorKey - Rust - -

    [][src]Trait bdk::keys::ToDescriptorKey

    pub trait ToDescriptorKey<Ctx: ScriptContext>: Sized {
    -    pub fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError>;
    -}

    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, KeyError, ScriptContext, ToDescriptorKey};
    -
    -pub struct MyKeyType {
    -    pubkey: PublicKey,
    -}
    -
    -impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for MyKeyType {
    -    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        self.pubkey.to_descriptor_key()
    -    }
    -}
    -

    Key type that is only valid on mainnet:

    - -
    -use bdk::bitcoin::PublicKey;
    -
    -use bdk::keys::{
    -    mainnet_network, DescriptorKey, DescriptorPublicKey, DescriptorSinglePub, KeyError,
    -    ScriptContext, ToDescriptorKey,
    -};
    -
    -pub struct MyKeyType {
    -    pubkey: PublicKey,
    -}
    -
    -impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for MyKeyType {
    -    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        Ok(DescriptorKey::from_public(
    -            DescriptorPublicKey::SinglePub(DescriptorSinglePub {
    -                origin: None,
    -                key: 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, KeyError, ScriptContext, ToDescriptorKey};
    -
    -pub struct MyKeyType {
    -    is_legacy: bool,
    -    pubkey: PublicKey,
    -}
    -
    -impl<Ctx: ScriptContext + 'static> ToDescriptorKey<Ctx> for MyKeyType {
    -    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        if Ctx::is_legacy() == self.is_legacy {
    -            self.pubkey.to_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.

    - -
    ⓘThis example deliberately fails to compile
    -use bdk::bitcoin::PublicKey;
    -use std::str::FromStr;
    -
    -use bdk::keys::{DescriptorKey, KeyError, ToDescriptorKey};
    -
    -pub struct MySegwitOnlyKeyType {
    -    pubkey: PublicKey,
    -}
    -
    -impl ToDescriptorKey<bdk::miniscript::Segwitv0> for MySegwitOnlyKeyType {
    -    fn to_descriptor_key(self) -> Result<DescriptorKey<bdk::miniscript::Segwitv0>, KeyError> {
    -        self.pubkey.to_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

    pub fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError>[src]

    Turn the key into a DescriptorKey within the requested ScriptContext

    -
    Loading content...

    Implementations on Foreign Types

    impl<Ctx: ScriptContext, T: DerivableKey<Ctx>> ToDescriptorKey<Ctx> for (T, DerivationPath)[src]

    impl<Ctx: ScriptContext, T: DerivableKey<Ctx>> ToDescriptorKey<Ctx> for (T, KeySource, DerivationPath)[src]

    impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for PublicKey[src]

    impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for PrivateKey[src]

    Loading content...

    Implementors

    impl<Ctx, K> ToDescriptorKey<Ctx> for GeneratedKey<K, Ctx> where
        Ctx: ScriptContext,
        K: ToDescriptorKey<Ctx>, 
    [src]

    impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorKey<Ctx>[src]

    The "identity" conversion is used internally by some bdk::fragments

    -

    impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorPublicKey[src]

    impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorSecretKey[src]

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/type.ValidNetworks.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/type.ValidNetworks.html deleted file mode 100644 index 9156edfb16..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/keys/type.ValidNetworks.html +++ /dev/null @@ -1,5 +0,0 @@ -bdk::keys::ValidNetworks - Rust - -

    [][src]Type Definition bdk::keys::ValidNetworks

    type ValidNetworks = HashSet<Network>;

    Set of valid networks for a key

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.descriptor!.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.descriptor!.html deleted file mode 100644 index 990e1ba2f8..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.descriptor!.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

    Redirecting to macro.descriptor.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.descriptor.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.descriptor.html deleted file mode 100644 index 58bf25b1ab..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.descriptor.html +++ /dev/null @@ -1,76 +0,0 @@ -bdk::descriptor - Rust - -

    [][src]Macro bdk::descriptor

    -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 )* ) ) => { ... };
    -}
    -

    Macro to write full descriptors with code

    -

    This macro expands to a Result of -DescriptorTemplateOut and Error

    -

    Example

    -

    Signature plus timelock, equivalent to: sh(wsh(and_v(v:pk(...), older(...))))

    - -
    -let my_key = bitcoin::PublicKey::from_str("02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c")?;
    -let my_timelock = 50;
    -let (my_descriptor, my_keys_map, networks) = bdk::descriptor!(sh ( wsh ( and_v (+v pk my_key), ( older my_timelock ))))?;
    -
    -

    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(...),sdv: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+d+v older my_timelock)
    -    )
    -}?;
    -
    -let b_items = vec![
    -    bdk::fragment!(pk my_key_1)?,
    -    bdk::fragment!(+s pk my_key_2)?,
    -    bdk::fragment!(+s+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/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.fragment!.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.fragment!.html deleted file mode 100644 index 1dbdb1fdc8..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.fragment!.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

    Redirecting to macro.fragment.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.fragment.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.fragment.html deleted file mode 100644 index d1031f5d0c..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/macro.fragment.html +++ /dev/null @@ -1,44 +0,0 @@ -bdk::fragment - Rust - -

    [][src]Macro bdk::fragment

    -macro_rules! fragment {
    -    ( +a $( $inner:tt )* ) => { ... };
    -    ( +s $( $inner:tt )* ) => { ... };
    -    ( +c $( $inner:tt )* ) => { ... };
    -    ( +d $( $inner:tt )* ) => { ... };
    -    ( +v $( $inner:tt )* ) => { ... };
    -    ( +j $( $inner:tt )* ) => { ... };
    -    ( +n $( $inner:tt )* ) => { ... };
    -    ( +t $( $inner:tt )* ) => { ... };
    -    ( +l $( $inner:tt )* ) => { ... };
    -    ( +u $( $inner:tt )* ) => { ... };
    -    ( true ) => { ... };
    -    ( false ) => { ... };
    -    ( pk_k $key:expr ) => { ... };
    -    ( pk $key:expr ) => { ... };
    -    ( pk_h $key_hash:expr ) => { ... };
    -    ( after $value:expr ) => { ... };
    -    ( older $value:expr ) => { ... };
    -    ( sha256 $hash:expr ) => { ... };
    -    ( hash256 $hash:expr ) => { ... };
    -    ( ripemd160 $hash:expr ) => { ... };
    -    ( hash160 $hash:expr ) => { ... };
    -    ( and_v ( $( $a:tt )* ), ( $( $b:tt )* ) ) => { ... };
    -    ( and_b ( $( $a:tt )* ), ( $( $b:tt )* ) ) => { ... };
    -    ( and_or ( $( $a:tt )* ), ( $( $b:tt )* ), ( $( $c:tt )* ) ) => { ... };
    -    ( or_b ( $( $a:tt )* ), ( $( $b:tt )* ) ) => { ... };
    -    ( or_d ( $( $a:tt )* ), ( $( $b:tt )* ) ) => { ... };
    -    ( or_c ( $( $a:tt )* ), ( $( $b:tt )* ) ) => { ... };
    -    ( or_i ( $( $a:tt )* ), ( $( $b:tt )* ) ) => { ... };
    -    ( thresh_vec $thresh:expr, $items:expr ) => { ... };
    -    ( thresh $thresh:expr $(, ( $( $item:tt )* ) )+ ) => { ... };
    -    ( multi_vec $thresh:expr, $keys:expr ) => { ... };
    -    ( multi $thresh:expr $(, $key:expr )+ ) => { ... };
    -    ( sortedmulti $( $inner:tt )* ) => { ... };
    -    ( sortedmulti_vec $( $inner:tt )* ) => { ... };
    -}
    -

    Macro to write descriptor fragments with code

    -

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

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/sidebar-items.js deleted file mode 100644 index bc49a753f3..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Error","Errors that can be thrown by the `Wallet`"],["KeychainKind","Types of keychains"]],"macro":[["descriptor","Macro to write full descriptors with code"],["fragment","Macro to write descriptor fragments with code"]],"mod":[["blockchain","Blockchain backends"],["database","Database types"],["descriptor","Descriptors"],["keys","Key formats"],["wallet","Wallet"]],"struct":[["FeeRate","Fee rate"],["TransactionDetails","A wallet transaction"],["UTXO","A wallet unspent output"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.FeeRate.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.FeeRate.html deleted file mode 100644 index 23ab6fa059..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.FeeRate.html +++ /dev/null @@ -1,51 +0,0 @@ -bdk::FeeRate - Rust - -

    [][src]Struct bdk::FeeRate

    pub struct FeeRate(_);

    Fee rate

    -

    Implementations

    impl FeeRate[src]

    pub fn from_btc_per_kvb(btc_per_kvb: f32) -> Self[src]

    Create a new instance of FeeRate given a float fee rate in btc/kvbytes

    -

    pub fn from_sat_per_vb(sat_per_vb: f32) -> Self[src]

    Create a new instance of FeeRate given a float fee rate in satoshi/vbyte

    -

    pub fn default_min_relay_fee() -> Self[src]

    Create a new FeeRate with the default min relay fee value

    -

    pub fn as_sat_vb(&self) -> f32[src]

    Return the value as satoshi/vbyte

    -

    Trait Implementations

    impl Clone for FeeRate[src]

    impl Copy for FeeRate[src]

    impl Debug for FeeRate[src]

    impl Default for FeeRate[src]

    impl PartialEq<FeeRate> for FeeRate[src]

    impl PartialOrd<FeeRate> for FeeRate[src]

    impl StructuralPartialEq for FeeRate[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.TransactionDetails.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.TransactionDetails.html deleted file mode 100644 index 52089b9ae3..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.TransactionDetails.html +++ /dev/null @@ -1,59 +0,0 @@ -bdk::TransactionDetails - Rust - -

    [][src]Struct bdk::TransactionDetails

    pub struct TransactionDetails {
    -    pub transaction: Option<Transaction>,
    -    pub txid: Txid,
    -    pub timestamp: u64,
    -    pub received: u64,
    -    pub sent: u64,
    -    pub fees: u64,
    -    pub height: Option<u32>,
    -}

    A wallet transaction

    -

    - Fields

    transaction: Option<Transaction>

    Optional transaction

    -
    txid: Txid

    Transaction id

    -
    timestamp: u64

    Timestamp

    -
    received: u64

    Received value (sats)

    -
    sent: u64

    Sent value (sats)

    -
    fees: u64

    Fee value (sats)

    -
    height: Option<u32>

    Confirmed in block height, None means unconfirmed

    -

    Trait Implementations

    impl Clone for TransactionDetails[src]

    impl Debug for TransactionDetails[src]

    impl Default for TransactionDetails[src]

    impl<'de> Deserialize<'de> for TransactionDetails[src]

    impl Eq for TransactionDetails[src]

    impl PartialEq<TransactionDetails> for TransactionDetails[src]

    impl Serialize for TransactionDetails[src]

    impl StructuralEq for TransactionDetails[src]

    impl StructuralPartialEq for TransactionDetails[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> DeserializeOwned for T where
        T: for<'de> Deserialize<'de>, 
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.UTXO.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.UTXO.html deleted file mode 100644 index cbdf664fe6..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/struct.UTXO.html +++ /dev/null @@ -1,50 +0,0 @@ -bdk::UTXO - Rust - -

    [][src]Struct bdk::UTXO

    pub struct UTXO {
    -    pub outpoint: OutPoint,
    -    pub txout: TxOut,
    -    pub keychain: KeychainKind,
    -}

    A wallet unspent output

    -

    - Fields

    outpoint: OutPoint

    Reference to a transaction output

    -
    txout: TxOut

    Transaction output

    -
    keychain: KeychainKind

    Type of keychain

    -

    Trait Implementations

    impl Clone for UTXO[src]

    impl Debug for UTXO[src]

    impl<'de> Deserialize<'de> for UTXO[src]

    impl Eq for UTXO[src]

    impl PartialEq<UTXO> for UTXO[src]

    impl Serialize for UTXO[src]

    impl StructuralEq for UTXO[src]

    impl StructuralPartialEq for UTXO[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> DeserializeOwned for T where
        T: for<'de> Deserialize<'de>, 
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/enum.KeychainKind.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/enum.KeychainKind.html deleted file mode 100644 index 8b0b5f9399..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/enum.KeychainKind.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

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

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/enum.ScriptType.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/enum.ScriptType.html deleted file mode 100644 index b10e9a3fe6..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/enum.ScriptType.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

    Redirecting to ../../bdk/enum.ScriptType.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.FeeRate.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.FeeRate.html deleted file mode 100644 index c8b0ec4f98..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.FeeRate.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

    Redirecting to ../../bdk/struct.FeeRate.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.TransactionDetails.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.TransactionDetails.html deleted file mode 100644 index 5db5e06868..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.TransactionDetails.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

    Redirecting to ../../bdk/struct.TransactionDetails.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.UTXO.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.UTXO.html deleted file mode 100644 index 1517bb40f5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/types/struct.UTXO.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

    Redirecting to ../../bdk/struct.UTXO.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/enum.AddressValidatorError.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/enum.AddressValidatorError.html deleted file mode 100644 index 19c2ae0bf1..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/enum.AddressValidatorError.html +++ /dev/null @@ -1,60 +0,0 @@ -bdk::wallet::address_validator::AddressValidatorError - Rust - -

    [][src]Enum bdk::wallet::address_validator::AddressValidatorError

    pub enum AddressValidatorError {
    -    UserRejected,
    -    ConnectionError,
    -    TimeoutError,
    -    InvalidScript,
    -    Message(String),
    -}

    Errors that can be returned to fail the validation of an address

    -

    - Variants

    -
    UserRejected

    User rejected the address

    -
    ConnectionError

    Network connection error

    -
    TimeoutError

    Network request timeout error

    -
    InvalidScript

    Invalid script

    -
    Message(String)

    A custom error message

    -

    Trait Implementations

    impl Clone for AddressValidatorError[src]

    impl Debug for AddressValidatorError[src]

    impl Display for AddressValidatorError[src]

    impl Eq for AddressValidatorError[src]

    impl Error for AddressValidatorError[src]

    impl From<AddressValidatorError> for Error[src]

    impl PartialEq<AddressValidatorError> for AddressValidatorError[src]

    impl StructuralEq for AddressValidatorError[src]

    impl StructuralPartialEq for AddressValidatorError[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/index.html deleted file mode 100644 index 8779ce0ce5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/index.html +++ /dev/null @@ -1,47 +0,0 @@ -bdk::wallet::address_validator - Rust - -

    [][src]Module bdk::wallet::address_validator

    Address validation callbacks

    -

    The typical usage of those callbacks is for displaying the newly-generated address on a -hardware wallet, so that the user can cross-check its correctness.

    -

    More generally speaking though, these callbacks can also be used to "do something" every time -an address is generated, without necessarily checking or validating it.

    -

    An address validator can be attached to a Wallet by using the -Wallet::add_address_validator method, and -whenever a new address is generated (either explicitly by the user with -Wallet::get_new_address or internally to create a change -address) all the attached validators will be polled, in sequence. All of them must complete -successfully to continue.

    -

    Example

    -
    -struct PrintAddressAndContinue;
    -
    -impl AddressValidator for PrintAddressAndContinue {
    -    fn validate(
    -        &self,
    -        keychain: KeychainKind,
    -        hd_keypaths: &HDKeyPaths,
    -        script: &Script
    -    ) -> Result<(), AddressValidatorError> {
    -        let address = Address::from_script(script, Network::Testnet)
    -            .as_ref()
    -            .map(Address::to_string)
    -            .unwrap_or(script.to_string());
    -        println!("New address of type {:?}: {}", keychain, address);
    -        println!("HD keypaths: {:#?}", hd_keypaths);
    -
    -        Ok(())
    -    }
    -}
    -
    -let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -wallet.add_address_validator(Arc::new(PrintAddressAndContinue));
    -
    -let address = wallet.get_new_address()?;
    -println!("Address: {}", address);
    -

    Enums

    -
    AddressValidatorError

    Errors that can be returned to fail the validation of an address

    -

    Traits

    -
    AddressValidator

    Trait to build address validators

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/sidebar-items.js deleted file mode 100644 index 58959ba340..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["AddressValidatorError","Errors that can be returned to fail the validation of an address"]],"trait":[["AddressValidator","Trait to build address validators"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/trait.AddressValidator.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/trait.AddressValidator.html deleted file mode 100644 index ccd57983bc..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/address_validator/trait.AddressValidator.html +++ /dev/null @@ -1,12 +0,0 @@ -bdk::wallet::address_validator::AddressValidator - Rust - -

    [][src]Trait bdk::wallet::address_validator::AddressValidator

    pub trait AddressValidator: Send + Sync {
    -    pub fn validate(
            &self,
            keychain: KeychainKind,
            hd_keypaths: &HDKeyPaths,
            script: &Script
        ) -> Result<(), AddressValidatorError>; -}

    Trait to build address validators

    -

    All the address validators attached to a wallet with Wallet::add_address_validator will be polled -every time an address (external or internal) is generated by the wallet. Errors returned in the -validator will be propagated up to the original caller that triggered the address generation.

    -

    For a usage example see this module's documentation.

    -

    Required methods

    pub fn validate(
        &self,
        keychain: KeychainKind,
        hd_keypaths: &HDKeyPaths,
        script: &Script
    ) -> Result<(), AddressValidatorError>
    [src]

    Validate or inspect an address

    -
    Loading content...

    Implementors

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/constant.TXIN_BASE_WEIGHT.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/constant.TXIN_BASE_WEIGHT.html deleted file mode 100644 index 424e9ede75..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/constant.TXIN_BASE_WEIGHT.html +++ /dev/null @@ -1,4 +0,0 @@ -bdk::wallet::coin_selection::TXIN_BASE_WEIGHT - Rust - -

    [][src]Constant bdk::wallet::coin_selection::TXIN_BASE_WEIGHT

    pub const TXIN_BASE_WEIGHT: usize = (32 + 4 + 4 + 1) * 4; // 0x0_000_000_000_000_0a4usize
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/index.html deleted file mode 100644 index 6c2eea8d97..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/index.html +++ /dev/null @@ -1,72 +0,0 @@ -bdk::wallet::coin_selection - Rust - -

    [][src]Module bdk::wallet::coin_selection

    Coin selection

    -

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

    -

    The coin selection algorithm is not globally part of a Wallet, instead it -is selected whenever a Wallet::create_tx call is made, through -the use of the TxBuilder structure, specifically with -TxBuilder::coin_selection method.

    -

    The DefaultCoinSelectionAlgorithm selects the default coin selection algorithm that -TxBuilder uses, if it's not explicitly overridden.

    -

    Example

    -
    -#[derive(Debug)]
    -struct AlwaysSpendEverything;
    -
    -impl<D: Database> CoinSelectionAlgorithm<D> for AlwaysSpendEverything {
    -    fn coin_select(
    -        &self,
    -        database: &D,
    -        required_utxos: Vec<(UTXO, usize)>,
    -        optional_utxos: Vec<(UTXO, usize)>,
    -        fee_rate: FeeRate,
    -        amount_needed: u64,
    -        fee_amount: f32,
    -    ) -> Result<CoinSelectionResult, bdk::Error> {
    -        let mut selected_amount = 0;
    -        let mut additional_weight = 0;
    -        let all_utxos_selected = required_utxos
    -            .into_iter().chain(optional_utxos)
    -            .scan((&mut selected_amount, &mut additional_weight), |(selected_amount, additional_weight), (utxo, weight)| {
    -                **selected_amount += utxo.txout.value;
    -                **additional_weight += TXIN_BASE_WEIGHT + weight;
    -
    -                Some(utxo)
    -            })
    -            .collect::<Vec<_>>();
    -        let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0;
    -
    -        if (fee_amount + additional_fees).ceil() as u64 + amount_needed > selected_amount {
    -            return Err(bdk::Error::InsufficientFunds);
    -        }
    -
    -        Ok(CoinSelectionResult {
    -            selected: all_utxos_selected,
    -            selected_amount,
    -            fee_amount: fee_amount + additional_fees,
    -        })
    -    }
    -}
    -
    -// create wallet, sync, ...
    -
    -let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -let (psbt, details) = wallet.create_tx(
    -    TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
    -        .coin_selection(AlwaysSpendEverything),
    -)?;
    -
    -// inspect, sign, broadcast, ...
    -
    -

    Structs

    -
    BranchAndBoundCoinSelection

    Branch and bound coin selection

    -
    CoinSelectionResult

    Result of a successful coin selection

    -
    LargestFirstCoinSelection

    Simple and dumb coin selection

    -

    Traits

    -
    CoinSelectionAlgorithm

    Trait for generalized coin selection algorithms

    -

    Type Definitions

    -
    DefaultCoinSelectionAlgorithm

    Default coin selection algorithm used by TxBuilder if not -overridden

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/sidebar-items.js deleted file mode 100644 index 8e7e293b89..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["BranchAndBoundCoinSelection","Branch and bound coin selection"],["CoinSelectionResult","Result of a successful coin selection"],["LargestFirstCoinSelection","Simple and dumb coin selection"]],"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/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html deleted file mode 100644 index 3bab787572..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html +++ /dev/null @@ -1,34 +0,0 @@ -bdk::wallet::coin_selection::BranchAndBoundCoinSelection - Rust - -

    [][src]Struct bdk::wallet::coin_selection::BranchAndBoundCoinSelection

    pub struct BranchAndBoundCoinSelection { /* fields omitted */ }

    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

    impl BranchAndBoundCoinSelection[src]

    pub fn new(size_of_change: u64) -> Self[src]

    Create new instance with target size for change output

    -

    Trait Implementations

    impl<D: Database> CoinSelectionAlgorithm<D> for BranchAndBoundCoinSelection[src]

    impl Debug for BranchAndBoundCoinSelection[src]

    impl Default for BranchAndBoundCoinSelection[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.CoinSelectionResult.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.CoinSelectionResult.html deleted file mode 100644 index ac4969b233..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.CoinSelectionResult.html +++ /dev/null @@ -1,38 +0,0 @@ -bdk::wallet::coin_selection::CoinSelectionResult - Rust - -

    [][src]Struct bdk::wallet::coin_selection::CoinSelectionResult

    pub struct CoinSelectionResult {
    -    pub selected: Vec<UTXO>,
    -    pub selected_amount: u64,
    -    pub fee_amount: f32,
    -}

    Result of a successful coin selection

    -

    - Fields

    selected: Vec<UTXO>

    List of outputs selected for use as inputs

    -
    selected_amount: u64

    Sum of the selected inputs' value

    -
    fee_amount: f32

    Total fee amount in satoshi

    -

    Trait Implementations

    impl Debug for CoinSelectionResult[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html deleted file mode 100644 index 3694261e76..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html +++ /dev/null @@ -1,34 +0,0 @@ -bdk::wallet::coin_selection::LargestFirstCoinSelection - Rust - -

    [][src]Struct bdk::wallet::coin_selection::LargestFirstCoinSelection

    pub struct LargestFirstCoinSelection;

    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

    impl<D: Database> CoinSelectionAlgorithm<D> for LargestFirstCoinSelection[src]

    impl Debug for LargestFirstCoinSelection[src]

    impl Default for LargestFirstCoinSelection[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html deleted file mode 100644 index d7b7b57eeb..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html +++ /dev/null @@ -1,23 +0,0 @@ -bdk::wallet::coin_selection::CoinSelectionAlgorithm - Rust - -

    [][src]Trait bdk::wallet::coin_selection::CoinSelectionAlgorithm

    pub trait CoinSelectionAlgorithm<D: Database>: Debug {
    -    pub fn coin_select(
            &self,
            database: &D,
            required_utxos: Vec<(UTXO, usize)>,
            optional_utxos: Vec<(UTXO, usize)>,
            fee_rate: FeeRate,
            amount_needed: u64,
            fee_amount: f32
        ) -> Result<CoinSelectionResult, Error>; -}

    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

    pub fn coin_select(
        &self,
        database: &D,
        required_utxos: Vec<(UTXO, usize)>,
        optional_utxos: Vec<(UTXO, usize)>,
        fee_rate: FeeRate,
        amount_needed: u64,
        fee_amount: f32
    ) -> Result<CoinSelectionResult, Error>
    [src]

    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 amount_needed with their -weight cost
    • -
    • optional_utxos: the remaining available utxos to satisfy amount_needed with their -weight cost
    • -
    • fee_rate: fee rate to use
    • -
    • amount_needed: the amount in satoshi to select
    • -
    • fee_amount: the amount of fees in satoshi already accumulated from adding outputs and -the transaction's header
    • -
    -
    Loading content...

    Implementors

    impl<D: Database> CoinSelectionAlgorithm<D> for BranchAndBoundCoinSelection[src]

    impl<D: Database> CoinSelectionAlgorithm<D> for LargestFirstCoinSelection[src]

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html deleted file mode 100644 index 0cb914590e..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html +++ /dev/null @@ -1,6 +0,0 @@ -bdk::wallet::coin_selection::DefaultCoinSelectionAlgorithm - Rust - -

    [][src]Type Definition bdk::wallet::coin_selection::DefaultCoinSelectionAlgorithm

    type DefaultCoinSelectionAlgorithm = BranchAndBoundCoinSelection;

    Default coin selection algorithm used by TxBuilder if not -overridden

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/index.html deleted file mode 100644 index bb91aa33f1..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/index.html +++ /dev/null @@ -1,36 +0,0 @@ -bdk::wallet::export - Rust - -

    [][src]Module bdk::wallet::export

    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 = WalletExport::from_str(import)?;
    -let wallet: OfflineWallet<_> = Wallet::new_offline(
    -    &import.descriptor(),
    -    import.change_descriptor().as_ref(),
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -)?;
    -

    Export a Wallet

    -
    -let wallet: OfflineWallet<_> = Wallet::new_offline(
    -    "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
    -    Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
    -    Network::Testnet,
    -    MemoryDatabase::default()
    -)?;
    -let export = WalletExport::export_wallet(&wallet, "exported wallet", true)
    -    .map_err(ToString::to_string)
    -    .map_err(bdk::Error::Generic)?;
    -
    -println!("Exported: {}", export.to_string());
    -

    Structs

    -
    WalletExport

    Structure that contains the export of a wallet

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/sidebar-items.js deleted file mode 100644 index 06abb3c4ee..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["WalletExport","Structure that contains the export of a wallet"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/struct.WalletExport.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/struct.WalletExport.html deleted file mode 100644 index cdef818514..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/export/struct.WalletExport.html +++ /dev/null @@ -1,53 +0,0 @@ -bdk::wallet::export::WalletExport - Rust - -

    [][src]Struct bdk::wallet::export::WalletExport

    pub struct WalletExport {
    -    pub blockheight: u32,
    -    pub label: String,
    -    // some fields omitted
    -}

    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

    impl WalletExport[src]

    pub fn export_wallet<B: BlockchainMarker, D: BatchDatabase>(
        wallet: &Wallet<B, D>,
        label: &str,
        include_blockheight: bool
    ) -> Result<Self, &'static str>
    [src]

    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 descriptor(&self) -> String[src]

    Return the external descriptor

    -

    pub fn change_descriptor(&self) -> Option<String>[src]

    Return the internal descriptor, if present

    -

    Trait Implementations

    impl Debug for WalletExport[src]

    impl<'de> Deserialize<'de> for WalletExport[src]

    impl FromStr for WalletExport[src]

    type Err = Error

    The associated error which can be returned from parsing.

    -

    impl Serialize for WalletExport[src]

    impl ToString for WalletExport[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> DeserializeOwned for T where
        T: for<'de> Deserialize<'de>, 
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/index.html deleted file mode 100644 index 7f20cd4daf..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/index.html +++ /dev/null @@ -1,19 +0,0 @@ -bdk::wallet - Rust - -

    [][src]Module bdk::wallet

    Wallet

    -

    This module defines the Wallet structure.

    -

    Modules

    -
    address_validator

    Address validation callbacks

    -
    coin_selection

    Coin selection

    -
    export

    Wallet export

    -
    signer

    Generalized signers

    -
    time

    Cross-platform time

    -
    tx_builder

    Transaction builder

    -

    Structs

    -
    Wallet

    A Bitcoin wallet

    -

    Traits

    -
    IsDust

    Trait to check if a value is below the dust limit

    -

    Type Definitions

    -
    OfflineWallet

    Type alias for a Wallet that uses OfflineBlockchain

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/sidebar-items.js deleted file mode 100644 index 811ec3c2b5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"mod":[["address_validator","Address validation callbacks"],["coin_selection","Coin selection"],["export","Wallet export"],["signer","Generalized signers"],["time","Cross-platform time"],["tx_builder","Transaction builder"]],"struct":[["Wallet","A Bitcoin wallet"]],"trait":[["IsDust","Trait to check if a value is below the dust limit"]],"type":[["OfflineWallet","Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/enum.SignerError.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/enum.SignerError.html deleted file mode 100644 index 7f44c5c3b9..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/enum.SignerError.html +++ /dev/null @@ -1,68 +0,0 @@ -bdk::wallet::signer::SignerError - Rust - -

    [][src]Enum bdk::wallet::signer::SignerError

    pub enum SignerError {
    -    MissingKey,
    -    InvalidKey,
    -    UserCanceled,
    -    InputIndexOutOfRange,
    -    MissingNonWitnessUtxo,
    -    InvalidNonWitnessUtxo,
    -    MissingWitnessUtxo,
    -    MissingWitnessScript,
    -    MissingHDKeypath,
    -}

    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 requied to sign this input

    -
    MissingHDKeypath

    The fingerprint and derivation path are missing from the psbt input

    -

    Trait Implementations

    impl Clone for SignerError[src]

    impl Debug for SignerError[src]

    impl Display for SignerError[src]

    impl Eq for SignerError[src]

    impl Error for SignerError[src]

    impl From<SignerError> for Error[src]

    impl PartialEq<SignerError> for SignerError[src]

    impl StructuralEq for SignerError[src]

    impl StructuralPartialEq for SignerError[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T> ToString for T where
        T: Display + ?Sized
    [src]

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/enum.SignerId.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/enum.SignerId.html deleted file mode 100644 index 1a404225cd..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/enum.SignerId.html +++ /dev/null @@ -1,63 +0,0 @@ -bdk::wallet::signer::SignerId - Rust - -

    [][src]Enum bdk::wallet::signer::SignerId

    pub enum SignerId {
    -    PkHash(Hash),
    -    Fingerprint(Fingerprint),
    -}

    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

    -

    Trait Implementations

    impl Clone for SignerId[src]

    impl Debug for SignerId[src]

    impl Eq for SignerId[src]

    impl From<Fingerprint> for SignerId[src]

    impl From<Hash> for SignerId[src]

    impl Hash for SignerId[src]

    impl Ord for SignerId[src]

    impl PartialEq<SignerId> for SignerId[src]

    impl PartialOrd<SignerId> for SignerId[src]

    impl StructuralEq for SignerId[src]

    impl StructuralPartialEq for SignerId[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/index.html deleted file mode 100644 index fee170e531..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/index.html +++ /dev/null @@ -1,58 +0,0 @@ -bdk::wallet::signer - Rust - -

    [][src]Module bdk::wallet::signer

    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 Signer for CustomSigner {
    -    fn sign(
    -        &self,
    -        psbt: &mut psbt::PartiallySignedTransaction,
    -        input_index: Option<usize>,
    -        _secp: &Secp256k1<All>,
    -    ) -> Result<(), SignerError> {
    -        let input_index = input_index.ok_or(SignerError::InputIndexOutOfRange)?;
    -        self.device.sign_input(psbt, input_index)?;
    -
    -        Ok(())
    -    }
    -
    -    fn sign_whole_tx(&self) -> bool {
    -        false
    -    }
    -}
    -
    -let custom_signer = CustomSigner::connect();
    -
    -let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -wallet.add_signer(
    -    KeychainKind::External,
    -    Fingerprint::from_str("e30f11b8").unwrap().into(),
    -    SignerOrdering(200),
    -    Arc::new(custom_signer)
    -);
    -
    -

    Structs

    -
    SignerOrdering

    Defines the order in which signers are called

    -
    SignersContainer

    Container for multiple signers

    -

    Enums

    -
    SignerError

    Signing error

    -
    SignerId

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

    -

    Traits

    -
    Signer

    Trait for signers

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/sidebar-items.js deleted file mode 100644 index 8f3e3d79b6..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["SignerError","Signing error"],["SignerId","Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among multiple of them"]],"struct":[["SignerOrdering","Defines the order in which signers are called"],["SignersContainer","Container for multiple signers"]],"trait":[["Signer","Trait for signers"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/struct.SignerOrdering.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/struct.SignerOrdering.html deleted file mode 100644 index 6bd85ccaf8..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/struct.SignerOrdering.html +++ /dev/null @@ -1,55 +0,0 @@ -bdk::wallet::signer::SignerOrdering - Rust - -

    [][src]Struct bdk::wallet::signer::SignerOrdering

    pub struct SignerOrdering(pub usize);

    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.

    -

    Trait Implementations

    impl Clone for SignerOrdering[src]

    impl Debug for SignerOrdering[src]

    impl Default for SignerOrdering[src]

    impl Eq for SignerOrdering[src]

    impl Ord for SignerOrdering[src]

    impl PartialEq<SignerOrdering> for SignerOrdering[src]

    impl PartialOrd<SignerOrdering> for SignerOrdering[src]

    impl StructuralEq for SignerOrdering[src]

    impl StructuralPartialEq for SignerOrdering[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/struct.SignersContainer.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/struct.SignersContainer.html deleted file mode 100644 index ebd6434357..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/struct.SignersContainer.html +++ /dev/null @@ -1,46 +0,0 @@ -bdk::wallet::signer::SignersContainer - Rust - -

    [][src]Struct bdk::wallet::signer::SignersContainer

    pub struct SignersContainer(_);

    Container for multiple signers

    -

    Implementations

    impl SignersContainer[src]

    pub fn as_key_map(&self, secp: &Secp256k1<All>) -> KeyMap[src]

    Create a map of public keys to secret keys

    -

    impl SignersContainer[src]

    pub fn new() -> Self[src]

    Default constructor

    -

    pub fn add_external(
        &mut self,
        id: SignerId,
        ordering: SignerOrdering,
        signer: Arc<dyn Signer>
    ) -> Option<Arc<dyn Signer>>
    [src]

    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 remove(
        &mut self,
        id: SignerId,
        ordering: SignerOrdering
    ) -> Option<Arc<dyn Signer>>
    [src]

    Removes a signer from the container and returns it

    -

    pub fn ids(&self) -> Vec<&SignerId>[src]

    Returns the list of identifiers of all the signers in the container

    -

    pub fn signers(&self) -> Vec<&Arc<dyn Signer>>[src]

    Returns the list of signers in the container, sorted by lowest to highest ordering

    -

    pub fn find(&self, id: SignerId) -> Option<&Arc<dyn Signer>>[src]

    Finds the signer with lowest ordering for a given id in the container.

    -

    Trait Implementations

    impl Clone for SignersContainer[src]

    impl Debug for SignersContainer[src]

    impl Default for SignersContainer[src]

    impl From<HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>> for SignersContainer[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/trait.Signer.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/trait.Signer.html deleted file mode 100644 index 95e96eab96..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/signer/trait.Signer.html +++ /dev/null @@ -1,22 +0,0 @@ -bdk::wallet::signer::Signer - Rust - -

    [][src]Trait bdk::wallet::signer::Signer

    pub trait Signer: Debug + Send + Sync {
    -    pub fn sign(
            &self,
            psbt: &mut PartiallySignedTransaction,
            input_index: Option<usize>,
            secp: &Secp256k1<All>
        ) -> Result<(), SignerError>; -
    pub fn sign_whole_tx(&self) -> bool; - - pub fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> { ... } -}

    Trait for signers

    -

    This trait can be implemented to provide customized signers to the wallet. For an example see -this module's documentation.

    -

    Required methods

    pub fn sign(
        &self,
        psbt: &mut PartiallySignedTransaction,
        input_index: Option<usize>,
        secp: &Secp256k1<All>
    ) -> Result<(), SignerError>
    [src]

    Sign a PSBT

    -

    The input_index argument is only provided if the wallet doesn't declare to sign the whole -transaction in one go (see Signer::sign_whole_tx). Otherwise its value is None and -can be ignored.

    -

    pub fn sign_whole_tx(&self) -> bool[src]

    Return whether or not the signer signs the whole transaction in one go instead of every -input individually

    -
    Loading content...

    Provided methods

    pub fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey>[src]

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

    -
    Loading content...

    Implementations on Foreign Types

    impl Signer for DescriptorXKey<ExtendedPrivKey>[src]

    impl Signer for PrivateKey[src]

    Loading content...

    Implementors

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html deleted file mode 100644 index 9d76dc92f8..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/struct.Wallet.html +++ /dev/null @@ -1,92 +0,0 @@ -bdk::wallet::Wallet - Rust - -

    [][src]Struct bdk::wallet::Wallet

    pub struct Wallet<B, D> { /* fields omitted */ }

    A Bitcoin wallet

    -

    A wallet takes descriptors, a database and a -blockchain and implements the basic functions that a Bitcoin wallets -needs to operate, like generating addresses, returning the balance, -creating transactions, etc.

    -

    A wallet can be either "online" if the blockchain type provided -implements Blockchain, or "offline" OfflineBlockchain is used. Offline wallets only expose -methods that don't need any interaction with the blockchain to work.

    -

    Implementations

    impl<B, D> Wallet<B, D> where
        B: BlockchainMarker,
        D: BatchDatabase
    [src]

    pub fn new_offline<E: ToWalletDescriptor>(
        descriptor: E,
        change_descriptor: Option<E>,
        network: Network,
        database: D
    ) -> Result<Self, Error>
    [src]

    Create a new "offline" wallet

    -

    pub fn get_new_address(&self) -> Result<Address, Error>[src]

    Return a newly generated address using the external descriptor

    -

    pub fn is_mine(&self, script: &Script) -> Result<bool, Error>[src]

    Return whether or not a script is part of this wallet (either internal or external)

    -

    pub fn list_unspent(&self) -> Result<Vec<UTXO>, Error>[src]

    Return the list of unspent outputs of this wallet

    -

    Note that this methods only operate on the internal database, which first needs to be -Wallet::sync manually.

    -

    pub fn list_transactions(
        &self,
        include_raw: bool
    ) -> Result<Vec<TransactionDetails>, Error>
    [src]

    Return the list of transactions made and received by the wallet

    -

    Optionally fill the TransactionDetails::transaction field with the raw transaction if -include_raw is true.

    -

    Note that this methods only operate on the internal database, which first needs to be -Wallet::sync manually.

    -

    pub fn get_balance(&self) -> Result<u64, Error>[src]

    Return the balance, meaning the sum of this wallet's unspent outputs' values

    -

    Note that this methods only operate on the internal database, which first needs to be -Wallet::sync manually.

    -

    pub fn add_signer(
        &mut self,
        keychain: KeychainKind,
        id: SignerId,
        ordering: SignerOrdering,
        signer: Arc<dyn Signer>
    )
    [src]

    Add an external signer

    -

    See the signer module for an example.

    -

    pub fn add_address_validator(&mut self, validator: Arc<dyn AddressValidator>)[src]

    Add an address validator

    -

    See the address_validator module for an example.

    -

    pub fn create_tx<Cs: CoinSelectionAlgorithm<D>>(
        &self,
        builder: TxBuilder<D, Cs, CreateTx>
    ) -> Result<(PSBT, TransactionDetails), Error>
    [src]

    Create a new transaction following the options specified in the builder

    -

    Example

    -
    -let (psbt, details) = wallet.create_tx(
    -    TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
    -)?;
    -// sign and broadcast ...
    -

    pub fn bump_fee<Cs: CoinSelectionAlgorithm<D>>(
        &self,
        txid: &Txid,
        builder: TxBuilder<D, Cs, BumpFee>
    ) -> Result<(PSBT, TransactionDetails), Error>
    [src]

    Bump the fee of a transaction following the options specified in the builder

    -

    Return an error if the transaction is already confirmed or doesn't explicitly signal RBF.

    -

    NOTE: if the original transaction was made with TxBuilder::set_single_recipient, -the TxBuilder::maintain_single_recipient flag should be enabled to correctly reduce the -only output's value in order to increase the fees.

    -

    If the builder specifies some utxos that must be spent, they will be added to the -transaction regardless of whether they are necessary or not to cover additional fees.

    -

    Example

    -
    -let txid = Txid::from_str("faff0a466b70f5d5f92bd757a92c1371d4838bdd5bc53a06764e2488e51ce8f8").unwrap();
    -let (psbt, details) = wallet.bump_fee(
    -    &txid,
    -    TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(5.0)),
    -)?;
    -// sign and broadcast ...
    -

    pub fn sign(
        &self,
        psbt: PSBT,
        assume_height: Option<u32>
    ) -> Result<(PSBT, bool), Error>
    [src]

    Sign a transaction with all the wallet's signers, in the order specified by every signer's -SignerOrdering

    -

    Example

    -
    -let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
    -

    pub fn policies(&self, keychain: KeychainKind) -> Result<Option<Policy>, Error>[src]

    Return the spending policies for the wallet's descriptor

    -

    pub fn public_descriptor(
        &self,
        keychain: KeychainKind
    ) -> Result<Option<ExtendedDescriptor>, Error>
    [src]

    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 finalize_psbt(
        &self,
        psbt: PSBT,
        assume_height: Option<u32>
    ) -> Result<(PSBT, bool), Error>
    [src]

    Try to finalize a PSBT

    -

    pub fn secp_ctx(&self) -> &Secp256k1<All>[src]

    Return the secp256k1 context used for all signing operations

    -

    impl<B, D> Wallet<B, D> where
        B: Blockchain,
        D: BatchDatabase
    [src]

    pub fn new<E: ToWalletDescriptor>(
        descriptor: E,
        change_descriptor: Option<E>,
        network: Network,
        database: D,
        client: B
    ) -> Result<Self, Error>
    [src]

    Create a new "online" wallet

    -

    pub fn sync<P: 'static + Progress>(
        &self,
        progress_update: P,
        max_address_param: Option<u32>
    ) -> Result<(), Error>
    [src]

    Sync the internal database with the blockchain

    -

    pub fn client(&self) -> Option<&B>[src]

    Return a reference to the internal blockchain client

    -

    pub fn network(&self) -> Network[src]

    Get the Bitcoin network the wallet is using.

    -

    pub fn broadcast(&self, tx: Transaction) -> Result<Txid, Error>[src]

    Broadcast a transaction to the network

    -

    Auto Trait Implementations

    impl<B, D> !RefUnwindSafe for Wallet<B, D>[src]

    impl<B, D> Send for Wallet<B, D> where
        B: Send,
        D: Send
    [src]

    impl<B, D> !Sync for Wallet<B, D>[src]

    impl<B, D> Unpin for Wallet<B, D> where
        B: Unpin,
        D: Unpin
    [src]

    impl<B, D> !UnwindSafe for Wallet<B, D>[src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/fn.get_timestamp.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/fn.get_timestamp.html deleted file mode 100644 index 7d78ed14eb..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/fn.get_timestamp.html +++ /dev/null @@ -1,5 +0,0 @@ -bdk::wallet::time::get_timestamp - Rust - -

    [][src]Function bdk::wallet::time::get_timestamp

    pub fn get_timestamp() -> u64

    Return the current timestamp in seconds

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/index.html deleted file mode 100644 index 29b8cd1da8..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/index.html +++ /dev/null @@ -1,11 +0,0 @@ -bdk::wallet::time - Rust - -

    [][src]Module bdk::wallet::time

    Cross-platform time

    -

    This module provides a function to get the current timestamp that works on all the platforms -supported by the library.

    -

    It can be useful to compare it with the timestamps found in -TransactionDetails.

    -

    Functions

    -
    get_timestamp

    Return the current timestamp in seconds

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/sidebar-items.js deleted file mode 100644 index 22164ef49f..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/time/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"fn":[["get_timestamp","Return the current timestamp in seconds"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/trait.IsDust.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/trait.IsDust.html deleted file mode 100644 index dade076dc1..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/trait.IsDust.html +++ /dev/null @@ -1,8 +0,0 @@ -bdk::wallet::IsDust - Rust - -

    [][src]Trait bdk::wallet::IsDust

    pub trait IsDust {
    -    pub fn is_dust(&self) -> bool;
    -}

    Trait to check if a value is below the dust limit

    -

    Required methods

    pub fn is_dust(&self) -> bool[src]

    Check whether or not a value is below dust limit

    -
    Loading content...

    Implementations on Foreign Types

    impl IsDust for u64[src]

    Loading content...

    Implementors

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html deleted file mode 100644 index 2bfd8fc4f6..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html +++ /dev/null @@ -1,63 +0,0 @@ -bdk::wallet::tx_builder::ChangeSpendPolicy - Rust - -

    [][src]Enum bdk::wallet::tx_builder::ChangeSpendPolicy

    pub enum ChangeSpendPolicy {
    -    ChangeAllowed,
    -    OnlyChange,
    -    ChangeForbidden,
    -}

    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

    impl Clone for ChangeSpendPolicy[src]

    impl Copy for ChangeSpendPolicy[src]

    impl Debug for ChangeSpendPolicy[src]

    impl Default for ChangeSpendPolicy[src]

    impl Eq for ChangeSpendPolicy[src]

    impl Hash for ChangeSpendPolicy[src]

    impl Ord for ChangeSpendPolicy[src]

    impl PartialEq<ChangeSpendPolicy> for ChangeSpendPolicy[src]

    impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy[src]

    impl StructuralEq for ChangeSpendPolicy[src]

    impl StructuralPartialEq for ChangeSpendPolicy[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/enum.TxOrdering.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/enum.TxOrdering.html deleted file mode 100644 index 26672be49f..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/enum.TxOrdering.html +++ /dev/null @@ -1,64 +0,0 @@ -bdk::wallet::tx_builder::TxOrdering - Rust - -

    [][src]Enum bdk::wallet::tx_builder::TxOrdering

    pub enum TxOrdering {
    -    Shuffle,
    -    Untouched,
    -    BIP69Lexicographic,
    -}

    Ordering of the transaction's inputs and outputs

    -

    - Variants

    -
    Shuffle

    Randomized (default)

    -
    Untouched

    Unchanged

    -
    BIP69Lexicographic

    BIP69 / Lexicographic

    -

    Implementations

    impl TxOrdering[src]

    pub fn sort_tx(&self, tx: &mut Transaction)[src]

    Sort transaction inputs and outputs by TxOrdering variant

    -

    Trait Implementations

    impl Clone for TxOrdering[src]

    impl Copy for TxOrdering[src]

    impl Debug for TxOrdering[src]

    impl Default for TxOrdering[src]

    impl Eq for TxOrdering[src]

    impl Hash for TxOrdering[src]

    impl Ord for TxOrdering[src]

    impl PartialEq<TxOrdering> for TxOrdering[src]

    impl PartialOrd<TxOrdering> for TxOrdering[src]

    impl StructuralEq for TxOrdering[src]

    impl StructuralPartialEq for TxOrdering[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<Q, K> Equivalent<K> for Q where
        K: Borrow<Q> + ?Sized,
        Q: Eq + ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/index.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/index.html deleted file mode 100644 index ae1593ff1b..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/index.html +++ /dev/null @@ -1,23 +0,0 @@ -bdk::wallet::tx_builder - Rust - -

    [][src]Module bdk::wallet::tx_builder

    Transaction builder

    -

    Example

    -
    -// Create a transaction with one output to `to_address` of 50_000 satoshi, with a custom fee rate
    -// of 5.0 satoshi/vbyte, only spending non-change outputs and with RBF signaling
    -// enabled
    -let builder = TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
    -    .fee_rate(FeeRate::from_sat_per_vb(5.0))
    -    .do_not_spend_change()
    -    .enable_rbf();
    -

    Structs

    -
    BumpFee

    Wallet::bump_fee context

    -
    CreateTx

    Wallet::create_tx context

    -
    TxBuilder

    A transaction builder

    -

    Enums

    -
    ChangeSpendPolicy

    Policy regarding the use of change outputs when creating a transaction

    -
    TxOrdering

    Ordering of the transaction's inputs and outputs

    -

    Traits

    -
    TxBuilderContext

    Context in which the TxBuilder is valid

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/sidebar-items.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/sidebar-items.js deleted file mode 100644 index 76461e4a13..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["ChangeSpendPolicy","Policy regarding the use of change outputs when creating a transaction"],["TxOrdering","Ordering of the transaction's inputs and outputs"]],"struct":[["BumpFee","`Wallet::bump_fee` context"],["CreateTx","`Wallet::create_tx` context"],["TxBuilder","A transaction builder"]],"trait":[["TxBuilderContext","Context in which the [`TxBuilder`] is valid"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.BumpFee.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.BumpFee.html deleted file mode 100644 index f7a5030e23..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.BumpFee.html +++ /dev/null @@ -1,37 +0,0 @@ -bdk::wallet::tx_builder::BumpFee - Rust - -

    [][src]Struct bdk::wallet::tx_builder::BumpFee

    pub struct BumpFee;

    Trait Implementations

    impl Clone for BumpFee[src]

    impl Debug for BumpFee[src]

    impl Default for BumpFee[src]

    impl TxBuilderContext for BumpFee[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.CreateTx.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.CreateTx.html deleted file mode 100644 index e333ecd81b..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.CreateTx.html +++ /dev/null @@ -1,37 +0,0 @@ -bdk::wallet::tx_builder::CreateTx - Rust - -

    [][src]Struct bdk::wallet::tx_builder::CreateTx

    pub struct CreateTx;

    Trait Implementations

    impl Clone for CreateTx[src]

    impl Debug for CreateTx[src]

    impl Default for CreateTx[src]

    impl TxBuilderContext for CreateTx[src]

    Auto Trait Implementations

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T> ToOwned for T where
        T: Clone
    [src]

    type Owned = T

    The resulting type after obtaining ownership.

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.TxBuilder.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.TxBuilder.html deleted file mode 100644 index dfad991d27..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/struct.TxBuilder.html +++ /dev/null @@ -1,152 +0,0 @@ -bdk::wallet::tx_builder::TxBuilder - Rust - -

    [][src]Struct bdk::wallet::tx_builder::TxBuilder

    pub struct TxBuilder<D: Database, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext> { /* fields omitted */ }

    A transaction builder

    -

    This structure contains the configuration that the wallet must follow to build a transaction.

    -

    For an example see this module's documentation;

    -

    Implementations

    impl<D: Database, Ctx: TxBuilderContext> TxBuilder<D, DefaultCoinSelectionAlgorithm, Ctx>[src]

    pub fn new() -> Self[src]

    Create an empty builder

    -

    impl<D: Database, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext> TxBuilder<D, Cs, Ctx>[src]

    pub fn fee_rate(self, fee_rate: FeeRate) -> Self[src]

    Set a custom fee rate

    -

    pub fn fee_absolute(self, fee_amount: u64) -> Self[src]

    Set an absolute fee

    -

    pub fn policy_path(
        self,
        policy_path: BTreeMap<String, Vec<usize>>,
        keychain: KeychainKind
    ) -> Self
    [src]

    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.

    - -
    -let mut path = BTreeMap::new();
    -path.insert("aabbccdd".to_string(), vec![0, 1]);
    -
    -let builder = TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
    -    .policy_path(path, KeychainKind::External);
    -

    pub fn utxos(self, utxos: Vec<OutPoint>) -> Self[src]

    Replace the internal list of utxos that must be spent with a new list

    -

    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(self, utxo: OutPoint) -> Self[src]

    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 manually_selected_only(self) -> Self[src]

    Only spend utxos added by add_utxo and utxos.

    -

    The wallet will not add additional utxos to the transaction even if they are needed to -make the transaction valid.

    -

    pub fn unspendable(self, unspendable: Vec<OutPoint>) -> Self[src]

    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::utxos and -TxBuilder::add_utxo have priority over these. See the docs of the two linked methods -for more details.

    -

    pub fn add_unspendable(self, unspendable: OutPoint) -> Self[src]

    Add a utxo to the internal list of unspendable utxos

    -

    It's important to note that the "must-be-spent" utxos added with TxBuilder::utxos and -TxBuilder::add_utxo have priority over this. See the docs of the two linked methods -for more details.

    -

    pub fn sighash(self, sighash: SigHashType) -> Self[src]

    Sign with a specific sig hash

    -

    Use this option very carefully

    -

    pub fn ordering(self, ordering: TxOrdering) -> Self[src]

    Choose the ordering for inputs and outputs of the transaction

    -

    pub fn nlocktime(self, locktime: u32) -> Self[src]

    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 version(self, version: i32) -> Self[src]

    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 do_not_spend_change(self) -> Self[src]

    Do not spend change outputs

    -

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

    -

    pub fn only_spend_change(self) -> Self[src]

    Only spend change outputs

    -

    This effectively adds all the non-change outputs to the "unspendable" list. See -TxBuilder::unspendable.

    -

    pub fn change_policy(self, change_policy: ChangeSpendPolicy) -> Self[src]

    pub fn force_non_witness_utxo(self) -> Self[src]

    Fill-in the psbt::Input::non_witness_utxo field even if the wallet only has SegWit -descriptors.

    -

    This is useful for signers which always require it, like Trezor hardware wallets.

    -

    pub fn include_output_redeem_witness_script(self) -> Self[src]

    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.

    -

    pub fn add_global_xpubs(self) -> Self[src]

    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 drain_wallet(self) -> Self[src]

    Spend all the available inputs. This respects filters like TxBuilder::unspendable and the change policy.

    -

    pub fn coin_selection<P: CoinSelectionAlgorithm<D>>(
        self,
        coin_selection: P
    ) -> TxBuilder<D, P, Ctx>
    [src]

    Choose the coin selection algorithm

    -

    Overrides the DefaultCoinSelectionAlgorithm.

    -

    impl<D: Database> TxBuilder<D, DefaultCoinSelectionAlgorithm, CreateTx>[src]

    pub fn with_recipients(recipients: Vec<(Script, u64)>) -> Self[src]

    Create a builder starting from a list of recipients

    -

    impl<D: Database, Cs: CoinSelectionAlgorithm<D>> TxBuilder<D, Cs, CreateTx>[src]

    pub fn set_recipients(self, recipients: Vec<(Script, u64)>) -> Self[src]

    Replace the recipients already added with a new list

    -

    pub fn add_recipient(self, script_pubkey: Script, amount: u64) -> Self[src]

    Add a recipient to the internal list

    -

    pub fn set_single_recipient(self, recipient: Script) -> Self[src]

    Set a single recipient that will get all the selected funds minus the fee. No change will -be created

    -

    This method overrides any recipient set with set_recipients or -add_recipient.

    -

    It can only be used in conjunction with drain_wallet to send the -entire content of the wallet (minus filters) to a single recipient or with a -list of manually selected UTXOs by enabling manually_selected_only -and selecting them with utxos or add_utxo.

    -

    When bumping the fees of a transaction made with this option, the user should remeber to -add maintain_single_recipient to correctly update the -single output instead of adding one more for the change.

    -

    pub fn enable_rbf(self) -> Self[src]

    Enable signaling RBF

    -

    This will use the default nSequence value of 0xFFFFFFFD.

    -

    pub fn enable_rbf_with_sequence(self, nsequence: u32) -> Self[src]

    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.

    -

    impl<D: Database> TxBuilder<D, DefaultCoinSelectionAlgorithm, BumpFee>[src]

    pub fn maintain_single_recipient(self) -> Self[src]

    Bump the fees of a transaction made with set_single_recipient

    -

    Unless extra inputs are specified with add_utxo or utxos, this flag will make -bump_fee reduce the value of the existing output, or fail if it would be consumed -entirely given the higher new fee rate.

    -

    If extra inputs are added and they are not entirely consumed in fees, a change output will not -be added; the existing output will simply grow in value.

    -

    Fails if the transaction has more than one outputs.

    -

    Trait Implementations

    impl<D: Debug + Database, Cs: Debug + CoinSelectionAlgorithm<D>, Ctx: Debug + TxBuilderContext> Debug for TxBuilder<D, Cs, Ctx>[src]

    impl<D: Database, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext> Default for TxBuilder<D, Cs, Ctx> where
        Cs: Default
    [src]

    Auto Trait Implementations

    impl<D, Cs, Ctx> RefUnwindSafe for TxBuilder<D, Cs, Ctx> where
        Cs: RefUnwindSafe,
        Ctx: RefUnwindSafe,
        D: RefUnwindSafe
    [src]

    impl<D, Cs, Ctx> Send for TxBuilder<D, Cs, Ctx> where
        Cs: Send,
        Ctx: Send,
        D: Send
    [src]

    impl<D, Cs, Ctx> Sync for TxBuilder<D, Cs, Ctx> where
        Cs: Sync,
        Ctx: Sync,
        D: Sync
    [src]

    impl<D, Cs, Ctx> Unpin for TxBuilder<D, Cs, Ctx> where
        Cs: Unpin,
        Ctx: Unpin,
        D: Unpin
    [src]

    impl<D, Cs, Ctx> UnwindSafe for TxBuilder<D, Cs, Ctx> where
        Cs: UnwindSafe,
        Ctx: UnwindSafe,
        D: UnwindSafe
    [src]

    Blanket Implementations

    impl<T> Any for T where
        T: 'static + ?Sized
    [src]

    impl<T> Borrow<T> for T where
        T: ?Sized
    [src]

    impl<T> BorrowMut<T> for T where
        T: ?Sized
    [src]

    impl<T> From<T> for T[src]

    impl<T> Instrument for T[src]

    impl<T> Instrument for T[src]

    impl<T, U> Into<U> for T where
        U: From<T>, 
    [src]

    impl<T> Pointable for T

    type Init = T

    The type for initializers.

    -

    impl<T> Same<T> for T

    type Output = T

    Should always be Self

    -

    impl<T, U> TryFrom<U> for T where
        U: Into<T>, 
    [src]

    type Error = Infallible

    The type returned in the event of a conversion error.

    -

    impl<T, U> TryInto<U> for T where
        U: TryFrom<T>, 
    [src]

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.

    -

    impl<V, T> VZip<V> for T where
        V: MultiLane<T>, 

    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/trait.TxBuilderContext.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/trait.TxBuilderContext.html deleted file mode 100644 index 081df97ad3..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/tx_builder/trait.TxBuilderContext.html +++ /dev/null @@ -1,5 +0,0 @@ -bdk::wallet::tx_builder::TxBuilderContext - Rust - -

    [][src]Trait bdk::wallet::tx_builder::TxBuilderContext

    pub trait TxBuilderContext: Debug + Default + Clone { }

    Context in which the TxBuilder is valid

    -

    Implementors

    impl TxBuilderContext for BumpFee[src]

    impl TxBuilderContext for CreateTx[src]

    Loading content...
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/type.OfflineWallet.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/type.OfflineWallet.html deleted file mode 100644 index cdc5549ea9..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/type.OfflineWallet.html +++ /dev/null @@ -1,5 +0,0 @@ -bdk::wallet::OfflineWallet - Rust - -

    [][src]Type Definition bdk::wallet::OfflineWallet

    type OfflineWallet<D> = Wallet<OfflineBlockchain, D>;

    Type alias for a Wallet that uses OfflineBlockchain

    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/utils/trait.IsDust.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/utils/trait.IsDust.html deleted file mode 100644 index 71ab5675d6..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/bdk/wallet/utils/trait.IsDust.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - -

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

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/brush.svg b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/brush.svg deleted file mode 100644 index ea266e856a..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/brush.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/dark.css b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/dark.css deleted file mode 100644 index 774d43d747..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/dark.css +++ /dev/null @@ -1 +0,0 @@ -body{background-color:#353535;color:#ddd;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:#ddd;}h1.fqn{border-bottom-color:#d2d2d2;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){border-bottom-color:#d2d2d2;}.in-band{background-color:#353535;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#2A2A2A;}pre{background-color:#2A2A2A;}.sidebar{background-color:#505050;}.logo-container.rust-logo>img{filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff)}*{scrollbar-color:rgb(64,65,67) #717171;}.sidebar{scrollbar-color:rgba(32,34,37,.6) transparent;}::-webkit-scrollbar-track{background-color:#717171;}::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar::-webkit-scrollbar-track{background-color:#717171;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar .current{background-color:#333;}.source .sidebar{background-color:#353535;}.sidebar .location{border-color:#fff;background:#575757;color:#DDD;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#444;}.line-numbers span{color:#3B91E2;}.line-numbers .line-highlighted{background-color:#0a042f !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#DDD;}.docblock table,.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#ddd;}.content .highlighted{color:#eee !important;background-color:#616161;}.content .highlighted a,.content .highlighted span{color:#eee !important;}.content .highlighted.trait{background-color:#013191;}.content .highlighted.traitalias{background-color:#013191;}.content .highlighted.mod,.content .highlighted.externcrate{background-color:#afc6e4;}.content .highlighted.mod{background-color:#803a1b;}.content .highlighted.externcrate{background-color:#396bac;}.content .highlighted.enum{background-color:#5b4e68;}.content .highlighted.struct{background-color:#194e9f;}.content .highlighted.union{background-color:#b7bd49;}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{background-color:#4950ed;}.content .highlighted.type{background-color:#38902c;}.content .highlighted.foreigntype{background-color:#b200d6;}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{background-color:#217d1c;}.content .highlighted.constant,.content .highlighted.static{background-color:#0063cc;}.content .highlighted.primitive{background-color:#00708a;}.content .highlighted.keyword{background-color:#884719;}.content .item-info::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#82b089;}.content span.struct,.content a.struct,.block a.current.struct{color:#2dbfb8;}.content span.type,.content a.type,.block a.current.type{color:#ff7f00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#dd7de8;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#09bd00;}.content span.union,.content a.union,.block a.current.union{color:#a6ae37;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#82a5c9;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#43aec7;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#bda000;}.content span.trait,.content a.trait,.block a.current.trait{color:#b78cf2;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#b397da;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#2BAB63;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}pre.rust .comment{color:#8d8d8b;}pre.rust .doccomment{color:#8ca375;}nav:not(.sidebar){border-bottom-color:#4e4e4e;}nav.main .current{border-top-color:#eee;border-bottom-color:#eee;}nav.main .separator{border-color:#eee;}a{color:#ddd;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.item-info a,#help a{color:#D2991D;}a.test-arrow{color:#dedede;}.collapse-toggle{color:#999;}#crate-search{color:#111;background-color:#f0f0f0;border-color:#000;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input{color:#111;background-color:#f0f0f0;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input:focus{border-color:#008dfd;}.search-focus:disabled{background-color:#c5c4c4;}#crate-search+.search-input:focus{box-shadow:0 0 8px 4px #078dd8;}.module-item .stab{color:#ddd;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;color:#2f2f2f;}.stab.deprecated{background:#F3DFFF;border-color:#7F0087;color:#2f2f2f;}.stab.portability{background:#C4ECFF;border-color:#7BA5DB;color:#2f2f2f;}.stab.portability>code{color:#ddd;}#help>div{background:#4d4d4d;border-color:#bfbfbf;}#help>div>span{border-bottom-color:#bfbfbf;}#help dt{border-color:#bfbfbf;background:rgba(0,0,0,0);color:black;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:#ddd;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#ab8ac1;}pre.rust .kw-2,pre.rust .prelude-ty{color:#769acb;}pre.rust .number,pre.rust .string{color:#83a300;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#ee6868;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#d97f26;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#4a4949;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label{color:#999;}:target>code,:target>.in-band{background-color:#494a3d;border-right:3px solid #bb7410;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.8);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.8);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.8);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.8);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip .tooltiptext{background-color:#000;color:#fff;border-color:#000;}.tooltip .tooltiptext::after{border-color:transparent black transparent transparent;}.notable-traits-tooltiptext{background-color:#111;border-color:#777;}#titles>button:not(.selected){background-color:#252525;border-top-color:#252525;}#titles>button:hover,#titles>button.selected{border-top-color:#0089ff;background-color:#353535;}#titles>button>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#505050;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#505050;border-right-color:#000;}#sidebar-filler{background-color:#505050;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu,.help-button{border-color:#e0e0e0;background:#f0f0f0;color:#000;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus,.help-button:hover,.help-button:focus{border-color:#ffb900;}#theme-choices{border-color:#e0e0e0;background-color:#353535;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#4e4e4e;}@media (max-width:700px){#theme-picker{background:#f0f0f0;}}#all-types{background-color:#505050;}#all-types:hover{background-color:#606060;}.search-results td span.alias{color:#fff;}.search-results td span.grey{color:#ccc;}#sidebar-toggle{background-color:#565656;}#sidebar-toggle:hover{background-color:#676767;}#source-sidebar{background-color:#565656;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#444;}div.files>.selected{background-color:#333;}.setting-line>.title{border-bottom-color:#ddd;} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/down-arrow.svg b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/down-arrow.svg deleted file mode 100644 index 35437e77a7..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/down-arrow.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon-16x16.png b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon-16x16.png deleted file mode 100644 index 7cfe6c1355..0000000000 Binary files a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon-16x16.png and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon-32x32.png b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon-32x32.png deleted file mode 100644 index 5109c1de8b..0000000000 Binary files a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon-32x32.png and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon.svg b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon.svg deleted file mode 100644 index 8b34b51198..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/favicon.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/alloc/string/trait.ToString.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/alloc/string/trait.ToString.js deleted file mode 100644 index 5f6129873e..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/alloc/string/trait.ToString.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl ToString for WalletExport","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.Blockchain.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.Blockchain.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.Blockchain.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.BlockchainMarker.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.BlockchainMarker.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.BlockchainMarker.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.ConfigurableBlockchain.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.ConfigurableBlockchain.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.ConfigurableBlockchain.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.Progress.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.Progress.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/blockchain/trait.Progress.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.BatchDatabase.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.BatchDatabase.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.BatchDatabase.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.BatchOperations.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.BatchOperations.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.BatchOperations.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.ConfigurableDatabase.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.ConfigurableDatabase.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.ConfigurableDatabase.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.Database.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.Database.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/database/trait.Database.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/template/trait.DescriptorTemplate.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/template/trait.DescriptorTemplate.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/template/trait.DescriptorTemplate.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ExtractPolicy.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ExtractPolicy.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ExtractPolicy.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.MiniscriptKey.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.MiniscriptKey.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.MiniscriptKey.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ToPublicKey.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ToPublicKey.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ToPublicKey.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ToWalletDescriptor.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ToWalletDescriptor.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/descriptor/trait.ToWalletDescriptor.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.DerivableKey.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.DerivableKey.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.DerivableKey.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ExtScriptContext.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ExtScriptContext.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ExtScriptContext.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.GeneratableDefaultOptions.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.GeneratableDefaultOptions.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.GeneratableDefaultOptions.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.GeneratableKey.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.GeneratableKey.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.GeneratableKey.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ScriptContext.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ScriptContext.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ScriptContext.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ToDescriptorKey.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ToDescriptorKey.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/keys/trait.ToDescriptorKey.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/signer/trait.Signer.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/signer/trait.Signer.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/signer/trait.Signer.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/trait.IsDust.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/trait.IsDust.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/trait.IsDust.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/tx_builder/trait.TxBuilderContext.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/tx_builder/trait.TxBuilderContext.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/bdk/wallet/tx_builder/trait.TxBuilderContext.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/clone/trait.Clone.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/clone/trait.Clone.js deleted file mode 100644 index a7ef0cbabd..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/clone/trait.Clone.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Clone for Capability","synthetic":false,"types":[]},{"text":"impl Clone for NoopProgress","synthetic":false,"types":[]},{"text":"impl Clone for LogProgress","synthetic":false,"types":[]},{"text":"impl Clone for PKOrF","synthetic":false,"types":[]},{"text":"impl Clone for SatisfiableItem","synthetic":false,"types":[]},{"text":"impl Clone for Satisfaction","synthetic":false,"types":[]},{"text":"impl Clone for Policy","synthetic":false,"types":[]},{"text":"impl Clone for Condition","synthetic":false,"types":[]},{"text":"impl Clone for ScriptContextEnum","synthetic":false,"types":[]},{"text":"impl Clone for PrivateKeyGenerateOptions","synthetic":false,"types":[]},{"text":"impl Clone for KeychainKind","synthetic":false,"types":[]},{"text":"impl Clone for FeeRate","synthetic":false,"types":[]},{"text":"impl Clone for UTXO","synthetic":false,"types":[]},{"text":"impl Clone for TransactionDetails","synthetic":false,"types":[]},{"text":"impl Clone for AddressValidatorError","synthetic":false,"types":[]},{"text":"impl Clone for SignerId","synthetic":false,"types":[]},{"text":"impl Clone for SignerError","synthetic":false,"types":[]},{"text":"impl Clone for SignerOrdering","synthetic":false,"types":[]},{"text":"impl Clone for SignersContainer","synthetic":false,"types":[]},{"text":"impl Clone for CreateTx","synthetic":false,"types":[]},{"text":"impl Clone for BumpFee","synthetic":false,"types":[]},{"text":"impl Clone for TxOrdering","synthetic":false,"types":[]},{"text":"impl Clone for ChangeSpendPolicy","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.Eq.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.Eq.js deleted file mode 100644 index 7e8d7dc356..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.Eq.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Eq for Capability","synthetic":false,"types":[]},{"text":"impl Eq for Condition","synthetic":false,"types":[]},{"text":"impl Eq for ScriptContextEnum","synthetic":false,"types":[]},{"text":"impl Eq for KeychainKind","synthetic":false,"types":[]},{"text":"impl Eq for UTXO","synthetic":false,"types":[]},{"text":"impl Eq for TransactionDetails","synthetic":false,"types":[]},{"text":"impl Eq for AddressValidatorError","synthetic":false,"types":[]},{"text":"impl Eq for SignerId","synthetic":false,"types":[]},{"text":"impl Eq for SignerError","synthetic":false,"types":[]},{"text":"impl Eq for SignerOrdering","synthetic":false,"types":[]},{"text":"impl Eq for TxOrdering","synthetic":false,"types":[]},{"text":"impl Eq for ChangeSpendPolicy","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.Ord.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.Ord.js deleted file mode 100644 index 66d7a0f62f..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.Ord.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Ord for Condition","synthetic":false,"types":[]},{"text":"impl Ord for SignerId","synthetic":false,"types":[]},{"text":"impl Ord for SignerOrdering","synthetic":false,"types":[]},{"text":"impl Ord for TxOrdering","synthetic":false,"types":[]},{"text":"impl Ord for ChangeSpendPolicy","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.PartialEq.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.PartialEq.js deleted file mode 100644 index 31a908a5b9..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.PartialEq.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl PartialEq<Capability> for Capability","synthetic":false,"types":[]},{"text":"impl PartialEq<Condition> for Condition","synthetic":false,"types":[]},{"text":"impl PartialEq<ScriptContextEnum> for ScriptContextEnum","synthetic":false,"types":[]},{"text":"impl PartialEq<KeychainKind> for KeychainKind","synthetic":false,"types":[]},{"text":"impl PartialEq<FeeRate> for FeeRate","synthetic":false,"types":[]},{"text":"impl PartialEq<UTXO> for UTXO","synthetic":false,"types":[]},{"text":"impl PartialEq<TransactionDetails> for TransactionDetails","synthetic":false,"types":[]},{"text":"impl PartialEq<AddressValidatorError> for AddressValidatorError","synthetic":false,"types":[]},{"text":"impl PartialEq<SignerId> for SignerId","synthetic":false,"types":[]},{"text":"impl PartialEq<SignerError> for SignerError","synthetic":false,"types":[]},{"text":"impl PartialEq<SignerOrdering> for SignerOrdering","synthetic":false,"types":[]},{"text":"impl PartialEq<TxOrdering> for TxOrdering","synthetic":false,"types":[]},{"text":"impl PartialEq<ChangeSpendPolicy> for ChangeSpendPolicy","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.PartialOrd.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.PartialOrd.js deleted file mode 100644 index dd7d82b585..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/cmp/trait.PartialOrd.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl PartialOrd<Condition> for Condition","synthetic":false,"types":[]},{"text":"impl PartialOrd<FeeRate> for FeeRate","synthetic":false,"types":[]},{"text":"impl PartialOrd<SignerId> for SignerId","synthetic":false,"types":[]},{"text":"impl PartialOrd<SignerOrdering> for SignerOrdering","synthetic":false,"types":[]},{"text":"impl PartialOrd<TxOrdering> for TxOrdering","synthetic":false,"types":[]},{"text":"impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/convert/trait.AsRef.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/convert/trait.AsRef.js deleted file mode 100644 index 5b2db4abf7..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/convert/trait.AsRef.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl AsRef<[u8]> for KeychainKind","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/convert/trait.From.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/convert/trait.From.js deleted file mode 100644 index 3d6411eda8..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/convert/trait.From.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<AddressValidatorError> for Error","synthetic":false,"types":[]},{"text":"impl From<PolicyError> for Error","synthetic":false,"types":[]},{"text":"impl From<SignerError> for Error","synthetic":false,"types":[]},{"text":"impl From<KeyError> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<EsploraError> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<CompactFiltersError> for Error","synthetic":false,"types":[]},{"text":"impl From<ElectrumBlockchain> for AnyBlockchain","synthetic":false,"types":[]},{"text":"impl From<EsploraBlockchain> for AnyBlockchain","synthetic":false,"types":[]},{"text":"impl From<CompactFiltersBlockchain> for AnyBlockchain","synthetic":false,"types":[]},{"text":"impl From<ElectrumBlockchainConfig> for AnyBlockchainConfig","synthetic":false,"types":[]},{"text":"impl From<EsploraBlockchainConfig> for AnyBlockchainConfig","synthetic":false,"types":[]},{"text":"impl From<CompactFiltersBlockchainConfig> for AnyBlockchainConfig","synthetic":false,"types":[]},{"text":"impl From<Client> for ElectrumBlockchain","synthetic":false,"types":[]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":[]},{"text":"impl From<ParseIntError> for EsploraError","synthetic":false,"types":[]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":[]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":[]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":[]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":[]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":[]},{"text":"impl From<SystemTimeError> for CompactFiltersError","synthetic":false,"types":[]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":[]},{"text":"impl From<MemoryDatabase> for AnyDatabase","synthetic":false,"types":[]},{"text":"impl From<Tree> for AnyDatabase","synthetic":false,"types":[]},{"text":"impl From<<MemoryDatabase as BatchDatabase>::Batch> for AnyBatch","synthetic":false,"types":[]},{"text":"impl From<<Tree as BatchDatabase>::Batch> for AnyBatch","synthetic":false,"types":[]},{"text":"impl From<()> for AnyDatabaseConfig","synthetic":false,"types":[]},{"text":"impl From<SledDbConfiguration> for AnyDatabaseConfig","synthetic":false,"types":[]},{"text":"impl From<KeyError> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<Error> for Error","synthetic":false,"types":[]},{"text":"impl From<PolicyError> for Error","synthetic":false,"types":[]},{"text":"impl From<bool> for Satisfaction","synthetic":false,"types":[]},{"text":"impl From<SatisfiableItem> for Policy","synthetic":false,"types":[]},{"text":"impl From<Error> for KeyError","synthetic":false,"types":[]},{"text":"impl From<Error> for KeyError","synthetic":false,"types":[]},{"text":"impl From<Hash> for SignerId","synthetic":false,"types":[]},{"text":"impl From<Fingerprint> for SignerId","synthetic":false,"types":[]},{"text":"impl From<HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>> for SignersContainer","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/default/trait.Default.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/default/trait.Default.js deleted file mode 100644 index 748e3f274e..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/default/trait.Default.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Default for Mempool","synthetic":false,"types":[]},{"text":"impl Default for MemoryDatabase","synthetic":false,"types":[]},{"text":"impl Default for PKOrF","synthetic":false,"types":[]},{"text":"impl Default for Condition","synthetic":false,"types":[]},{"text":"impl Default for PrivateKeyGenerateOptions","synthetic":false,"types":[]},{"text":"impl Default for FeeRate","synthetic":false,"types":[]},{"text":"impl Default for TransactionDetails","synthetic":false,"types":[]},{"text":"impl Default for LargestFirstCoinSelection","synthetic":false,"types":[]},{"text":"impl Default for BranchAndBoundCoinSelection","synthetic":false,"types":[]},{"text":"impl Default for SignerOrdering","synthetic":false,"types":[]},{"text":"impl Default for SignersContainer","synthetic":false,"types":[]},{"text":"impl Default for CreateTx","synthetic":false,"types":[]},{"text":"impl Default for BumpFee","synthetic":false,"types":[]},{"text":"impl<D: Database, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext> Default for TxBuilder<D, Cs, Ctx> where
        Cs: Default, 
    ","synthetic":false,"types":[]},{"text":"impl Default for TxOrdering","synthetic":false,"types":[]},{"text":"impl Default for ChangeSpendPolicy","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/fmt/trait.Debug.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/fmt/trait.Debug.js deleted file mode 100644 index b3638c12d9..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/fmt/trait.Debug.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Debug for Error","synthetic":false,"types":[]},{"text":"impl Debug for AnyBlockchainConfig","synthetic":false,"types":[]},{"text":"impl Debug for ElectrumBlockchainConfig","synthetic":false,"types":[]},{"text":"impl Debug for EsploraBlockchain","synthetic":false,"types":[]},{"text":"impl Debug for EsploraBlockchainConfig","synthetic":false,"types":[]},{"text":"impl Debug for EsploraError","synthetic":false,"types":[]},{"text":"impl Debug for Mempool","synthetic":false,"types":[]},{"text":"impl Debug for Peer","synthetic":false,"types":[]},{"text":"impl Debug for CompactFiltersBlockchain","synthetic":false,"types":[]},{"text":"impl Debug for BitcoinPeerConfig","synthetic":false,"types":[]},{"text":"impl Debug for CompactFiltersBlockchainConfig","synthetic":false,"types":[]},{"text":"impl Debug for CompactFiltersError","synthetic":false,"types":[]},{"text":"impl Debug for Capability","synthetic":false,"types":[]},{"text":"impl Debug for AnyDatabase","synthetic":false,"types":[]},{"text":"impl Debug for SledDbConfiguration","synthetic":false,"types":[]},{"text":"impl Debug for AnyDatabaseConfig","synthetic":false,"types":[]},{"text":"impl Debug for MemoryDatabase","synthetic":false,"types":[]},{"text":"impl Debug for Error","synthetic":false,"types":[]},{"text":"impl Debug for PKOrF","synthetic":false,"types":[]},{"text":"impl Debug for SatisfiableItem","synthetic":false,"types":[]},{"text":"impl Debug for Satisfaction","synthetic":false,"types":[]},{"text":"impl Debug for Policy","synthetic":false,"types":[]},{"text":"impl Debug for Condition","synthetic":false,"types":[]},{"text":"impl Debug for PolicyError","synthetic":false,"types":[]},{"text":"impl<Ctx: Debug + ScriptContext> Debug for DescriptorKey<Ctx>","synthetic":false,"types":[]},{"text":"impl Debug for ScriptContextEnum","synthetic":false,"types":[]},{"text":"impl Debug for PrivateKeyGenerateOptions","synthetic":false,"types":[]},{"text":"impl Debug for KeyError","synthetic":false,"types":[]},{"text":"impl Debug for KeychainKind","synthetic":false,"types":[]},{"text":"impl Debug for FeeRate","synthetic":false,"types":[]},{"text":"impl Debug for UTXO","synthetic":false,"types":[]},{"text":"impl Debug for TransactionDetails","synthetic":false,"types":[]},{"text":"impl Debug for AddressValidatorError","synthetic":false,"types":[]},{"text":"impl Debug for CoinSelectionResult","synthetic":false,"types":[]},{"text":"impl Debug for LargestFirstCoinSelection","synthetic":false,"types":[]},{"text":"impl Debug for BranchAndBoundCoinSelection","synthetic":false,"types":[]},{"text":"impl Debug for WalletExport","synthetic":false,"types":[]},{"text":"impl Debug for SignerId","synthetic":false,"types":[]},{"text":"impl Debug for SignerError","synthetic":false,"types":[]},{"text":"impl Debug for SignerOrdering","synthetic":false,"types":[]},{"text":"impl Debug for SignersContainer","synthetic":false,"types":[]},{"text":"impl Debug for CreateTx","synthetic":false,"types":[]},{"text":"impl Debug for BumpFee","synthetic":false,"types":[]},{"text":"impl<D: Debug + Database, Cs: Debug + CoinSelectionAlgorithm<D>, Ctx: Debug + TxBuilderContext> Debug for TxBuilder<D, Cs, Ctx>","synthetic":false,"types":[]},{"text":"impl Debug for TxOrdering","synthetic":false,"types":[]},{"text":"impl Debug for ChangeSpendPolicy","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/fmt/trait.Display.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/fmt/trait.Display.js deleted file mode 100644 index ce37b5523e..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/fmt/trait.Display.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Display for Error","synthetic":false,"types":[]},{"text":"impl Display for EsploraError","synthetic":false,"types":[]},{"text":"impl Display for CompactFiltersError","synthetic":false,"types":[]},{"text":"impl Display for Error","synthetic":false,"types":[]},{"text":"impl Display for PolicyError","synthetic":false,"types":[]},{"text":"impl Display for KeyError","synthetic":false,"types":[]},{"text":"impl Display for AddressValidatorError","synthetic":false,"types":[]},{"text":"impl Display for SignerError","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/hash/trait.Hash.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/hash/trait.Hash.js deleted file mode 100644 index 64f360015e..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/hash/trait.Hash.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Hash for Capability","synthetic":false,"types":[]},{"text":"impl Hash for Condition","synthetic":false,"types":[]},{"text":"impl Hash for KeychainKind","synthetic":false,"types":[]},{"text":"impl Hash for SignerId","synthetic":false,"types":[]},{"text":"impl Hash for TxOrdering","synthetic":false,"types":[]},{"text":"impl Hash for ChangeSpendPolicy","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Copy.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Copy.js deleted file mode 100644 index 243d52c881..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Copy.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Copy for Capability","synthetic":false,"types":[]},{"text":"impl Copy for Condition","synthetic":false,"types":[]},{"text":"impl Copy for ScriptContextEnum","synthetic":false,"types":[]},{"text":"impl Copy for PrivateKeyGenerateOptions","synthetic":false,"types":[]},{"text":"impl Copy for KeychainKind","synthetic":false,"types":[]},{"text":"impl Copy for FeeRate","synthetic":false,"types":[]},{"text":"impl Copy for TxOrdering","synthetic":false,"types":[]},{"text":"impl Copy for ChangeSpendPolicy","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Freeze.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Freeze.js deleted file mode 100644 index d8ca791082..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Freeze.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Freeze for Error","synthetic":true,"types":[]},{"text":"impl !Freeze for AnyBlockchain","synthetic":true,"types":[]},{"text":"impl Freeze for AnyBlockchainConfig","synthetic":true,"types":[]},{"text":"impl !Freeze for ElectrumBlockchain","synthetic":true,"types":[]},{"text":"impl Freeze for ElectrumBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Freeze for EsploraBlockchain","synthetic":true,"types":[]},{"text":"impl Freeze for EsploraBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Freeze for EsploraError","synthetic":true,"types":[]},{"text":"impl !Freeze for Mempool","synthetic":true,"types":[]},{"text":"impl Freeze for Peer","synthetic":true,"types":[]},{"text":"impl Freeze for CompactFiltersBlockchain","synthetic":true,"types":[]},{"text":"impl Freeze for BitcoinPeerConfig","synthetic":true,"types":[]},{"text":"impl Freeze for CompactFiltersBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Freeze for CompactFiltersError","synthetic":true,"types":[]},{"text":"impl Freeze for Capability","synthetic":true,"types":[]},{"text":"impl Freeze for OfflineBlockchain","synthetic":true,"types":[]},{"text":"impl Freeze for NoopProgress","synthetic":true,"types":[]},{"text":"impl Freeze for LogProgress","synthetic":true,"types":[]},{"text":"impl Freeze for AnyDatabase","synthetic":true,"types":[]},{"text":"impl Freeze for AnyBatch","synthetic":true,"types":[]},{"text":"impl Freeze for SledDbConfiguration","synthetic":true,"types":[]},{"text":"impl Freeze for AnyDatabaseConfig","synthetic":true,"types":[]},{"text":"impl Freeze for MemoryDatabase","synthetic":true,"types":[]},{"text":"impl Freeze for Error","synthetic":true,"types":[]},{"text":"impl Freeze for PKOrF","synthetic":true,"types":[]},{"text":"impl Freeze for SatisfiableItem","synthetic":true,"types":[]},{"text":"impl Freeze for Satisfaction","synthetic":true,"types":[]},{"text":"impl Freeze for Policy","synthetic":true,"types":[]},{"text":"impl Freeze for Condition","synthetic":true,"types":[]},{"text":"impl Freeze for PolicyError","synthetic":true,"types":[]},{"text":"impl<K> Freeze for P2PKH<K> where
        K: Freeze, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Freeze for P2WPKH_P2SH<K> where
        K: Freeze, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Freeze for P2WPKH<K> where
        K: Freeze, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Freeze for BIP44<K> where
        K: Freeze, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Freeze for BIP44Public<K> where
        K: Freeze, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Freeze for BIP49<K> where
        K: Freeze, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Freeze for BIP49Public<K> where
        K: Freeze, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Freeze for BIP84<K> where
        K: Freeze, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Freeze for BIP84Public<K> where
        K: Freeze, 
    ","synthetic":true,"types":[]},{"text":"impl<Ctx> Freeze for DescriptorKey<Ctx>","synthetic":true,"types":[]},{"text":"impl Freeze for ScriptContextEnum","synthetic":true,"types":[]},{"text":"impl<K, Ctx> Freeze for GeneratedKey<K, Ctx> where
        K: Freeze, 
    ","synthetic":true,"types":[]},{"text":"impl Freeze for PrivateKeyGenerateOptions","synthetic":true,"types":[]},{"text":"impl Freeze for KeyError","synthetic":true,"types":[]},{"text":"impl Freeze for KeychainKind","synthetic":true,"types":[]},{"text":"impl Freeze for FeeRate","synthetic":true,"types":[]},{"text":"impl Freeze for UTXO","synthetic":true,"types":[]},{"text":"impl Freeze for TransactionDetails","synthetic":true,"types":[]},{"text":"impl Freeze for AddressValidatorError","synthetic":true,"types":[]},{"text":"impl Freeze for CoinSelectionResult","synthetic":true,"types":[]},{"text":"impl Freeze for LargestFirstCoinSelection","synthetic":true,"types":[]},{"text":"impl Freeze for BranchAndBoundCoinSelection","synthetic":true,"types":[]},{"text":"impl Freeze for WalletExport","synthetic":true,"types":[]},{"text":"impl Freeze for SignerId","synthetic":true,"types":[]},{"text":"impl Freeze for SignerError","synthetic":true,"types":[]},{"text":"impl Freeze for SignerOrdering","synthetic":true,"types":[]},{"text":"impl Freeze for SignersContainer","synthetic":true,"types":[]},{"text":"impl Freeze for CreateTx","synthetic":true,"types":[]},{"text":"impl Freeze for BumpFee","synthetic":true,"types":[]},{"text":"impl<D, Cs, Ctx> Freeze for TxBuilder<D, Cs, Ctx> where
        Cs: Freeze, 
    ","synthetic":true,"types":[]},{"text":"impl Freeze for TxOrdering","synthetic":true,"types":[]},{"text":"impl Freeze for ChangeSpendPolicy","synthetic":true,"types":[]},{"text":"impl<B, D> !Freeze for Wallet<B, D>","synthetic":true,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Send.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Send.js deleted file mode 100644 index b500695f51..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Send.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Send for Error","synthetic":true,"types":[]},{"text":"impl Send for AnyBlockchain","synthetic":true,"types":[]},{"text":"impl Send for AnyBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Send for ElectrumBlockchain","synthetic":true,"types":[]},{"text":"impl Send for ElectrumBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Send for EsploraBlockchain","synthetic":true,"types":[]},{"text":"impl Send for EsploraBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Send for EsploraError","synthetic":true,"types":[]},{"text":"impl Send for Mempool","synthetic":true,"types":[]},{"text":"impl Send for Peer","synthetic":true,"types":[]},{"text":"impl Send for CompactFiltersBlockchain","synthetic":true,"types":[]},{"text":"impl Send for BitcoinPeerConfig","synthetic":true,"types":[]},{"text":"impl Send for CompactFiltersBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Send for CompactFiltersError","synthetic":true,"types":[]},{"text":"impl Send for Capability","synthetic":true,"types":[]},{"text":"impl Send for OfflineBlockchain","synthetic":true,"types":[]},{"text":"impl Send for NoopProgress","synthetic":true,"types":[]},{"text":"impl Send for LogProgress","synthetic":true,"types":[]},{"text":"impl !Send for AnyDatabase","synthetic":true,"types":[]},{"text":"impl !Send for AnyBatch","synthetic":true,"types":[]},{"text":"impl Send for SledDbConfiguration","synthetic":true,"types":[]},{"text":"impl Send for AnyDatabaseConfig","synthetic":true,"types":[]},{"text":"impl !Send for MemoryDatabase","synthetic":true,"types":[]},{"text":"impl Send for Error","synthetic":true,"types":[]},{"text":"impl Send for PKOrF","synthetic":true,"types":[]},{"text":"impl Send for SatisfiableItem","synthetic":true,"types":[]},{"text":"impl Send for Satisfaction","synthetic":true,"types":[]},{"text":"impl Send for Policy","synthetic":true,"types":[]},{"text":"impl Send for Condition","synthetic":true,"types":[]},{"text":"impl Send for PolicyError","synthetic":true,"types":[]},{"text":"impl<K> Send for P2PKH<K> where
        K: Send, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Send for P2WPKH_P2SH<K> where
        K: Send, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Send for P2WPKH<K> where
        K: Send, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Send for BIP44<K> where
        K: Send, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Send for BIP44Public<K> where
        K: Send, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Send for BIP49<K> where
        K: Send, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Send for BIP49Public<K> where
        K: Send, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Send for BIP84<K> where
        K: Send, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Send for BIP84Public<K> where
        K: Send, 
    ","synthetic":true,"types":[]},{"text":"impl<Ctx> Send for DescriptorKey<Ctx> where
        Ctx: Send, 
    ","synthetic":true,"types":[]},{"text":"impl Send for ScriptContextEnum","synthetic":true,"types":[]},{"text":"impl<K, Ctx> Send for GeneratedKey<K, Ctx> where
        Ctx: Send,
        K: Send, 
    ","synthetic":true,"types":[]},{"text":"impl Send for PrivateKeyGenerateOptions","synthetic":true,"types":[]},{"text":"impl Send for KeyError","synthetic":true,"types":[]},{"text":"impl Send for KeychainKind","synthetic":true,"types":[]},{"text":"impl Send for FeeRate","synthetic":true,"types":[]},{"text":"impl Send for UTXO","synthetic":true,"types":[]},{"text":"impl Send for TransactionDetails","synthetic":true,"types":[]},{"text":"impl Send for AddressValidatorError","synthetic":true,"types":[]},{"text":"impl Send for CoinSelectionResult","synthetic":true,"types":[]},{"text":"impl Send for LargestFirstCoinSelection","synthetic":true,"types":[]},{"text":"impl Send for BranchAndBoundCoinSelection","synthetic":true,"types":[]},{"text":"impl Send for WalletExport","synthetic":true,"types":[]},{"text":"impl Send for SignerId","synthetic":true,"types":[]},{"text":"impl Send for SignerError","synthetic":true,"types":[]},{"text":"impl Send for SignerOrdering","synthetic":true,"types":[]},{"text":"impl Send for SignersContainer","synthetic":true,"types":[]},{"text":"impl Send for CreateTx","synthetic":true,"types":[]},{"text":"impl Send for BumpFee","synthetic":true,"types":[]},{"text":"impl<D, Cs, Ctx> Send for TxBuilder<D, Cs, Ctx> where
        Cs: Send,
        Ctx: Send,
        D: Send, 
    ","synthetic":true,"types":[]},{"text":"impl Send for TxOrdering","synthetic":true,"types":[]},{"text":"impl Send for ChangeSpendPolicy","synthetic":true,"types":[]},{"text":"impl<B, D> Send for Wallet<B, D> where
        B: Send,
        D: Send, 
    ","synthetic":true,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.StructuralEq.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.StructuralEq.js deleted file mode 100644 index f127d77e7c..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.StructuralEq.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl StructuralEq for Capability","synthetic":false,"types":[]},{"text":"impl StructuralEq for Condition","synthetic":false,"types":[]},{"text":"impl StructuralEq for ScriptContextEnum","synthetic":false,"types":[]},{"text":"impl StructuralEq for KeychainKind","synthetic":false,"types":[]},{"text":"impl StructuralEq for UTXO","synthetic":false,"types":[]},{"text":"impl StructuralEq for TransactionDetails","synthetic":false,"types":[]},{"text":"impl StructuralEq for AddressValidatorError","synthetic":false,"types":[]},{"text":"impl StructuralEq for SignerId","synthetic":false,"types":[]},{"text":"impl StructuralEq for SignerError","synthetic":false,"types":[]},{"text":"impl StructuralEq for SignerOrdering","synthetic":false,"types":[]},{"text":"impl StructuralEq for TxOrdering","synthetic":false,"types":[]},{"text":"impl StructuralEq for ChangeSpendPolicy","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.StructuralPartialEq.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.StructuralPartialEq.js deleted file mode 100644 index 76d66b9984..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.StructuralPartialEq.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl StructuralPartialEq for Capability","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for Condition","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for ScriptContextEnum","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for KeychainKind","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for FeeRate","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for UTXO","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for TransactionDetails","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for AddressValidatorError","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for SignerId","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for SignerError","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for SignerOrdering","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for TxOrdering","synthetic":false,"types":[]},{"text":"impl StructuralPartialEq for ChangeSpendPolicy","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Sync.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Sync.js deleted file mode 100644 index a66b5513b1..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Sync.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Sync for Error","synthetic":true,"types":[]},{"text":"impl Sync for AnyBlockchain","synthetic":true,"types":[]},{"text":"impl Sync for AnyBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Sync for ElectrumBlockchain","synthetic":true,"types":[]},{"text":"impl Sync for ElectrumBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Sync for EsploraBlockchain","synthetic":true,"types":[]},{"text":"impl Sync for EsploraBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Sync for EsploraError","synthetic":true,"types":[]},{"text":"impl Sync for Mempool","synthetic":true,"types":[]},{"text":"impl Sync for Peer","synthetic":true,"types":[]},{"text":"impl Sync for CompactFiltersBlockchain","synthetic":true,"types":[]},{"text":"impl Sync for BitcoinPeerConfig","synthetic":true,"types":[]},{"text":"impl Sync for CompactFiltersBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Sync for CompactFiltersError","synthetic":true,"types":[]},{"text":"impl Sync for Capability","synthetic":true,"types":[]},{"text":"impl Sync for OfflineBlockchain","synthetic":true,"types":[]},{"text":"impl Sync for NoopProgress","synthetic":true,"types":[]},{"text":"impl Sync for LogProgress","synthetic":true,"types":[]},{"text":"impl !Sync for AnyDatabase","synthetic":true,"types":[]},{"text":"impl !Sync for AnyBatch","synthetic":true,"types":[]},{"text":"impl Sync for SledDbConfiguration","synthetic":true,"types":[]},{"text":"impl Sync for AnyDatabaseConfig","synthetic":true,"types":[]},{"text":"impl !Sync for MemoryDatabase","synthetic":true,"types":[]},{"text":"impl Sync for Error","synthetic":true,"types":[]},{"text":"impl Sync for PKOrF","synthetic":true,"types":[]},{"text":"impl Sync for SatisfiableItem","synthetic":true,"types":[]},{"text":"impl Sync for Satisfaction","synthetic":true,"types":[]},{"text":"impl Sync for Policy","synthetic":true,"types":[]},{"text":"impl Sync for Condition","synthetic":true,"types":[]},{"text":"impl Sync for PolicyError","synthetic":true,"types":[]},{"text":"impl<K> Sync for P2PKH<K> where
        K: Sync, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Sync for P2WPKH_P2SH<K> where
        K: Sync, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Sync for P2WPKH<K> where
        K: Sync, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Sync for BIP44<K> where
        K: Sync, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Sync for BIP44Public<K> where
        K: Sync, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Sync for BIP49<K> where
        K: Sync, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Sync for BIP49Public<K> where
        K: Sync, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Sync for BIP84<K> where
        K: Sync, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Sync for BIP84Public<K> where
        K: Sync, 
    ","synthetic":true,"types":[]},{"text":"impl<Ctx> Sync for DescriptorKey<Ctx> where
        Ctx: Sync, 
    ","synthetic":true,"types":[]},{"text":"impl Sync for ScriptContextEnum","synthetic":true,"types":[]},{"text":"impl<K, Ctx> Sync for GeneratedKey<K, Ctx> where
        Ctx: Sync,
        K: Sync, 
    ","synthetic":true,"types":[]},{"text":"impl Sync for PrivateKeyGenerateOptions","synthetic":true,"types":[]},{"text":"impl Sync for KeyError","synthetic":true,"types":[]},{"text":"impl Sync for KeychainKind","synthetic":true,"types":[]},{"text":"impl Sync for FeeRate","synthetic":true,"types":[]},{"text":"impl Sync for UTXO","synthetic":true,"types":[]},{"text":"impl Sync for TransactionDetails","synthetic":true,"types":[]},{"text":"impl Sync for AddressValidatorError","synthetic":true,"types":[]},{"text":"impl Sync for CoinSelectionResult","synthetic":true,"types":[]},{"text":"impl Sync for LargestFirstCoinSelection","synthetic":true,"types":[]},{"text":"impl Sync for BranchAndBoundCoinSelection","synthetic":true,"types":[]},{"text":"impl Sync for WalletExport","synthetic":true,"types":[]},{"text":"impl Sync for SignerId","synthetic":true,"types":[]},{"text":"impl Sync for SignerError","synthetic":true,"types":[]},{"text":"impl Sync for SignerOrdering","synthetic":true,"types":[]},{"text":"impl Sync for SignersContainer","synthetic":true,"types":[]},{"text":"impl Sync for CreateTx","synthetic":true,"types":[]},{"text":"impl Sync for BumpFee","synthetic":true,"types":[]},{"text":"impl<D, Cs, Ctx> Sync for TxBuilder<D, Cs, Ctx> where
        Cs: Sync,
        Ctx: Sync,
        D: Sync, 
    ","synthetic":true,"types":[]},{"text":"impl Sync for TxOrdering","synthetic":true,"types":[]},{"text":"impl Sync for ChangeSpendPolicy","synthetic":true,"types":[]},{"text":"impl<B, D> !Sync for Wallet<B, D>","synthetic":true,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Unpin.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Unpin.js deleted file mode 100644 index 4897f83303..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/marker/trait.Unpin.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Unpin for Error","synthetic":true,"types":[]},{"text":"impl Unpin for AnyBlockchain","synthetic":true,"types":[]},{"text":"impl Unpin for AnyBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Unpin for ElectrumBlockchain","synthetic":true,"types":[]},{"text":"impl Unpin for ElectrumBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Unpin for EsploraBlockchain","synthetic":true,"types":[]},{"text":"impl Unpin for EsploraBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Unpin for EsploraError","synthetic":true,"types":[]},{"text":"impl Unpin for Mempool","synthetic":true,"types":[]},{"text":"impl Unpin for Peer","synthetic":true,"types":[]},{"text":"impl Unpin for CompactFiltersBlockchain","synthetic":true,"types":[]},{"text":"impl Unpin for BitcoinPeerConfig","synthetic":true,"types":[]},{"text":"impl Unpin for CompactFiltersBlockchainConfig","synthetic":true,"types":[]},{"text":"impl Unpin for CompactFiltersError","synthetic":true,"types":[]},{"text":"impl Unpin for Capability","synthetic":true,"types":[]},{"text":"impl Unpin for OfflineBlockchain","synthetic":true,"types":[]},{"text":"impl Unpin for NoopProgress","synthetic":true,"types":[]},{"text":"impl Unpin for LogProgress","synthetic":true,"types":[]},{"text":"impl Unpin for AnyDatabase","synthetic":true,"types":[]},{"text":"impl Unpin for AnyBatch","synthetic":true,"types":[]},{"text":"impl Unpin for SledDbConfiguration","synthetic":true,"types":[]},{"text":"impl Unpin for AnyDatabaseConfig","synthetic":true,"types":[]},{"text":"impl Unpin for MemoryDatabase","synthetic":true,"types":[]},{"text":"impl Unpin for Error","synthetic":true,"types":[]},{"text":"impl Unpin for PKOrF","synthetic":true,"types":[]},{"text":"impl Unpin for SatisfiableItem","synthetic":true,"types":[]},{"text":"impl Unpin for Satisfaction","synthetic":true,"types":[]},{"text":"impl Unpin for Policy","synthetic":true,"types":[]},{"text":"impl Unpin for Condition","synthetic":true,"types":[]},{"text":"impl Unpin for PolicyError","synthetic":true,"types":[]},{"text":"impl<K> Unpin for P2PKH<K> where
        K: Unpin, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Unpin for P2WPKH_P2SH<K> where
        K: Unpin, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Unpin for P2WPKH<K> where
        K: Unpin, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Unpin for BIP44<K> where
        K: Unpin, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Unpin for BIP44Public<K> where
        K: Unpin, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Unpin for BIP49<K> where
        K: Unpin, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Unpin for BIP49Public<K> where
        K: Unpin, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Unpin for BIP84<K> where
        K: Unpin, 
    ","synthetic":true,"types":[]},{"text":"impl<K> Unpin for BIP84Public<K> where
        K: Unpin, 
    ","synthetic":true,"types":[]},{"text":"impl<Ctx> Unpin for DescriptorKey<Ctx> where
        Ctx: Unpin, 
    ","synthetic":true,"types":[]},{"text":"impl Unpin for ScriptContextEnum","synthetic":true,"types":[]},{"text":"impl<K, Ctx> Unpin for GeneratedKey<K, Ctx> where
        Ctx: Unpin,
        K: Unpin, 
    ","synthetic":true,"types":[]},{"text":"impl Unpin for PrivateKeyGenerateOptions","synthetic":true,"types":[]},{"text":"impl Unpin for KeyError","synthetic":true,"types":[]},{"text":"impl Unpin for KeychainKind","synthetic":true,"types":[]},{"text":"impl Unpin for FeeRate","synthetic":true,"types":[]},{"text":"impl Unpin for UTXO","synthetic":true,"types":[]},{"text":"impl Unpin for TransactionDetails","synthetic":true,"types":[]},{"text":"impl Unpin for AddressValidatorError","synthetic":true,"types":[]},{"text":"impl Unpin for CoinSelectionResult","synthetic":true,"types":[]},{"text":"impl Unpin for LargestFirstCoinSelection","synthetic":true,"types":[]},{"text":"impl Unpin for BranchAndBoundCoinSelection","synthetic":true,"types":[]},{"text":"impl Unpin for WalletExport","synthetic":true,"types":[]},{"text":"impl Unpin for SignerId","synthetic":true,"types":[]},{"text":"impl Unpin for SignerError","synthetic":true,"types":[]},{"text":"impl Unpin for SignerOrdering","synthetic":true,"types":[]},{"text":"impl Unpin for SignersContainer","synthetic":true,"types":[]},{"text":"impl Unpin for CreateTx","synthetic":true,"types":[]},{"text":"impl Unpin for BumpFee","synthetic":true,"types":[]},{"text":"impl<D, Cs, Ctx> Unpin for TxBuilder<D, Cs, Ctx> where
        Cs: Unpin,
        Ctx: Unpin,
        D: Unpin, 
    ","synthetic":true,"types":[]},{"text":"impl Unpin for TxOrdering","synthetic":true,"types":[]},{"text":"impl Unpin for ChangeSpendPolicy","synthetic":true,"types":[]},{"text":"impl<B, D> Unpin for Wallet<B, D> where
        B: Unpin,
        D: Unpin, 
    ","synthetic":true,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/ops/deref/trait.Deref.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/ops/deref/trait.Deref.js deleted file mode 100644 index 2f7bc5e869..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/ops/deref/trait.Deref.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl<K, Ctx: ScriptContext> Deref for GeneratedKey<K, Ctx>","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/str/traits/trait.FromStr.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/str/traits/trait.FromStr.js deleted file mode 100644 index b5dbd1e30a..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/core/str/traits/trait.FromStr.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl FromStr for WalletExport","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/serde/de/trait.Deserialize.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/serde/de/trait.Deserialize.js deleted file mode 100644 index 209a5d4358..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/serde/de/trait.Deserialize.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl<'de> Deserialize<'de> for AnyBlockchainConfig","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for ElectrumBlockchainConfig","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for EsploraBlockchainConfig","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for BitcoinPeerConfig","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for CompactFiltersBlockchainConfig","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for SledDbConfiguration","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for AnyDatabaseConfig","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for KeychainKind","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for UTXO","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for TransactionDetails","synthetic":false,"types":[]},{"text":"impl<'de> Deserialize<'de> for WalletExport","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/serde/ser/trait.Serialize.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/serde/ser/trait.Serialize.js deleted file mode 100644 index 9429b901e9..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/serde/ser/trait.Serialize.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Serialize for AnyBlockchainConfig","synthetic":false,"types":[]},{"text":"impl Serialize for ElectrumBlockchainConfig","synthetic":false,"types":[]},{"text":"impl Serialize for EsploraBlockchainConfig","synthetic":false,"types":[]},{"text":"impl Serialize for BitcoinPeerConfig","synthetic":false,"types":[]},{"text":"impl Serialize for CompactFiltersBlockchainConfig","synthetic":false,"types":[]},{"text":"impl Serialize for SledDbConfiguration","synthetic":false,"types":[]},{"text":"impl Serialize for AnyDatabaseConfig","synthetic":false,"types":[]},{"text":"impl Serialize for PKOrF","synthetic":false,"types":[]},{"text":"impl Serialize for SatisfiableItem","synthetic":false,"types":[]},{"text":"impl Serialize for Satisfaction","synthetic":false,"types":[]},{"text":"impl Serialize for Policy","synthetic":false,"types":[]},{"text":"impl Serialize for Condition","synthetic":false,"types":[]},{"text":"impl Serialize for KeychainKind","synthetic":false,"types":[]},{"text":"impl Serialize for UTXO","synthetic":false,"types":[]},{"text":"impl Serialize for TransactionDetails","synthetic":false,"types":[]},{"text":"impl Serialize for WalletExport","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/error/trait.Error.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/error/trait.Error.js deleted file mode 100644 index 70a9b18acb..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/error/trait.Error.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Error for Error","synthetic":false,"types":[]},{"text":"impl Error for EsploraError","synthetic":false,"types":[]},{"text":"impl Error for CompactFiltersError","synthetic":false,"types":[]},{"text":"impl Error for Error","synthetic":false,"types":[]},{"text":"impl Error for PolicyError","synthetic":false,"types":[]},{"text":"impl Error for KeyError","synthetic":false,"types":[]},{"text":"impl Error for AddressValidatorError","synthetic":false,"types":[]},{"text":"impl Error for SignerError","synthetic":false,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/panic/trait.RefUnwindSafe.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/panic/trait.RefUnwindSafe.js deleted file mode 100644 index c48e9d7209..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/panic/trait.RefUnwindSafe.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl !RefUnwindSafe for Error","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for AnyBlockchain","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for AnyBlockchainConfig","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for ElectrumBlockchain","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for ElectrumBlockchainConfig","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for EsploraBlockchain","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for EsploraBlockchainConfig","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for EsploraError","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for Mempool","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for Peer","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for CompactFiltersBlockchain","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for BitcoinPeerConfig","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for CompactFiltersBlockchainConfig","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for CompactFiltersError","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for Capability","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for OfflineBlockchain","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for NoopProgress","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for LogProgress","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for AnyDatabase","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for AnyBatch","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for SledDbConfiguration","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for AnyDatabaseConfig","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for MemoryDatabase","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for Error","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for PKOrF","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for SatisfiableItem","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for Satisfaction","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for Policy","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for Condition","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for PolicyError","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for P2PKH<K> where
        K: RefUnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for P2WPKH_P2SH<K> where
        K: RefUnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for P2WPKH<K> where
        K: RefUnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for BIP44<K> where
        K: RefUnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for BIP44Public<K> where
        K: RefUnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for BIP49<K> where
        K: RefUnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for BIP49Public<K> where
        K: RefUnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for BIP84<K> where
        K: RefUnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<K> RefUnwindSafe for BIP84Public<K> where
        K: RefUnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<Ctx> RefUnwindSafe for DescriptorKey<Ctx> where
        Ctx: RefUnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for ScriptContextEnum","synthetic":true,"types":[]},{"text":"impl<K, Ctx> RefUnwindSafe for GeneratedKey<K, Ctx> where
        Ctx: RefUnwindSafe,
        K: RefUnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for PrivateKeyGenerateOptions","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for KeyError","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for KeychainKind","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for FeeRate","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for UTXO","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for TransactionDetails","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for AddressValidatorError","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for CoinSelectionResult","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for LargestFirstCoinSelection","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for BranchAndBoundCoinSelection","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for WalletExport","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for SignerId","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for SignerError","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for SignerOrdering","synthetic":true,"types":[]},{"text":"impl !RefUnwindSafe for SignersContainer","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for CreateTx","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for BumpFee","synthetic":true,"types":[]},{"text":"impl<D, Cs, Ctx> RefUnwindSafe for TxBuilder<D, Cs, Ctx> where
        Cs: RefUnwindSafe,
        Ctx: RefUnwindSafe,
        D: RefUnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for TxOrdering","synthetic":true,"types":[]},{"text":"impl RefUnwindSafe for ChangeSpendPolicy","synthetic":true,"types":[]},{"text":"impl<B, D> !RefUnwindSafe for Wallet<B, D>","synthetic":true,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/panic/trait.UnwindSafe.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/panic/trait.UnwindSafe.js deleted file mode 100644 index a18b454332..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/implementors/std/panic/trait.UnwindSafe.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl !UnwindSafe for Error","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for AnyBlockchain","synthetic":true,"types":[]},{"text":"impl UnwindSafe for AnyBlockchainConfig","synthetic":true,"types":[]},{"text":"impl UnwindSafe for ElectrumBlockchain","synthetic":true,"types":[]},{"text":"impl UnwindSafe for ElectrumBlockchainConfig","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for EsploraBlockchain","synthetic":true,"types":[]},{"text":"impl UnwindSafe for EsploraBlockchainConfig","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for EsploraError","synthetic":true,"types":[]},{"text":"impl UnwindSafe for Mempool","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for Peer","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for CompactFiltersBlockchain","synthetic":true,"types":[]},{"text":"impl UnwindSafe for BitcoinPeerConfig","synthetic":true,"types":[]},{"text":"impl UnwindSafe for CompactFiltersBlockchainConfig","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for CompactFiltersError","synthetic":true,"types":[]},{"text":"impl UnwindSafe for Capability","synthetic":true,"types":[]},{"text":"impl UnwindSafe for OfflineBlockchain","synthetic":true,"types":[]},{"text":"impl UnwindSafe for NoopProgress","synthetic":true,"types":[]},{"text":"impl UnwindSafe for LogProgress","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for AnyDatabase","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for AnyBatch","synthetic":true,"types":[]},{"text":"impl UnwindSafe for SledDbConfiguration","synthetic":true,"types":[]},{"text":"impl UnwindSafe for AnyDatabaseConfig","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for MemoryDatabase","synthetic":true,"types":[]},{"text":"impl UnwindSafe for Error","synthetic":true,"types":[]},{"text":"impl UnwindSafe for PKOrF","synthetic":true,"types":[]},{"text":"impl UnwindSafe for SatisfiableItem","synthetic":true,"types":[]},{"text":"impl UnwindSafe for Satisfaction","synthetic":true,"types":[]},{"text":"impl UnwindSafe for Policy","synthetic":true,"types":[]},{"text":"impl UnwindSafe for Condition","synthetic":true,"types":[]},{"text":"impl UnwindSafe for PolicyError","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for P2PKH<K> where
        K: UnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for P2WPKH_P2SH<K> where
        K: UnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for P2WPKH<K> where
        K: UnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for BIP44<K> where
        K: UnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for BIP44Public<K> where
        K: UnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for BIP49<K> where
        K: UnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for BIP49Public<K> where
        K: UnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for BIP84<K> where
        K: UnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<K> UnwindSafe for BIP84Public<K> where
        K: UnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl<Ctx> UnwindSafe for DescriptorKey<Ctx> where
        Ctx: UnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl UnwindSafe for ScriptContextEnum","synthetic":true,"types":[]},{"text":"impl<K, Ctx> UnwindSafe for GeneratedKey<K, Ctx> where
        Ctx: UnwindSafe,
        K: UnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl UnwindSafe for PrivateKeyGenerateOptions","synthetic":true,"types":[]},{"text":"impl UnwindSafe for KeyError","synthetic":true,"types":[]},{"text":"impl UnwindSafe for KeychainKind","synthetic":true,"types":[]},{"text":"impl UnwindSafe for FeeRate","synthetic":true,"types":[]},{"text":"impl UnwindSafe for UTXO","synthetic":true,"types":[]},{"text":"impl UnwindSafe for TransactionDetails","synthetic":true,"types":[]},{"text":"impl UnwindSafe for AddressValidatorError","synthetic":true,"types":[]},{"text":"impl UnwindSafe for CoinSelectionResult","synthetic":true,"types":[]},{"text":"impl UnwindSafe for LargestFirstCoinSelection","synthetic":true,"types":[]},{"text":"impl UnwindSafe for BranchAndBoundCoinSelection","synthetic":true,"types":[]},{"text":"impl UnwindSafe for WalletExport","synthetic":true,"types":[]},{"text":"impl UnwindSafe for SignerId","synthetic":true,"types":[]},{"text":"impl UnwindSafe for SignerError","synthetic":true,"types":[]},{"text":"impl UnwindSafe for SignerOrdering","synthetic":true,"types":[]},{"text":"impl !UnwindSafe for SignersContainer","synthetic":true,"types":[]},{"text":"impl UnwindSafe for CreateTx","synthetic":true,"types":[]},{"text":"impl UnwindSafe for BumpFee","synthetic":true,"types":[]},{"text":"impl<D, Cs, Ctx> UnwindSafe for TxBuilder<D, Cs, Ctx> where
        Cs: UnwindSafe,
        Ctx: UnwindSafe,
        D: UnwindSafe, 
    ","synthetic":true,"types":[]},{"text":"impl UnwindSafe for TxOrdering","synthetic":true,"types":[]},{"text":"impl UnwindSafe for ChangeSpendPolicy","synthetic":true,"types":[]},{"text":"impl<B, D> !UnwindSafe for Wallet<B, D>","synthetic":true,"types":[]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/light.css b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/light.css deleted file mode 100644 index 5a9d516b52..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/light.css +++ /dev/null @@ -1 +0,0 @@ - body{background-color:white;color:black;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:black;}h1.fqn{border-bottom-color:#D5D5D5;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){border-bottom-color:#DDDDDD;}.in-band{background-color:white;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#F5F5F5;}pre{background-color:#F5F5F5;}.sidebar{background-color:#F1F1F1;}*{scrollbar-color:rgba(36,37,39,0.6) #e6e6e6;}.sidebar{scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;}.logo-container.rust-logo>img{}::-webkit-scrollbar-track{background-color:#ecebeb;}::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar::-webkit-scrollbar-track{background-color:#dcdcdc;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar .current{background-color:#fff;}.source .sidebar{background-color:#fff;}.sidebar .location{border-color:#000;background-color:#fff;color:#333;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#F5F5F5;}.line-numbers span{color:#c67e2d;}.line-numbers .line-highlighted{background-color:#f6fdb0 !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#ddd;}.docblock table,.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#4E4C4C;}.content .highlighted{color:#000 !important;background-color:#ccc;}.content .highlighted a,.content .highlighted span{color:#000 !important;}.content .highlighted.trait{background-color:#c7b6ff;}.content .highlighted.traitalias{background-color:#c7b6ff;}.content .highlighted.mod,.content .highlighted.externcrate{background-color:#afc6e4;}.content .highlighted.enum{background-color:#b4d1b9;}.content .highlighted.struct{background-color:#e7b1a0;}.content .highlighted.union{background-color:#b7bd49;}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{background-color:#c6afb3;}.content .highlighted.type{background-color:#ffc891;}.content .highlighted.foreigntype{background-color:#f5c4ff;}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{background-color:#8ce488;}.content .highlighted.constant,.content .highlighted.static{background-color:#c3e0ff;}.content .highlighted.primitive{background-color:#9aecff;}.content .highlighted.keyword{background-color:#f99650;}.content .item-info::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#508157;}.content span.struct,.content a.struct,.block a.current.struct{color:#ad448e;}.content span.type,.content a.type,.block a.current.type{color:#ba5d00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#cd00e2;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#068000;}.content span.union,.content a.union,.block a.current.union{color:#767b27;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#546e8a;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#2c8093;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#4d76ae;}.content span.trait,.content a.trait,.block a.current.trait{color:#7c5af3;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#6841f1;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#9a6e31;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}pre.rust .comment{color:#8E908C;}pre.rust .doccomment{color:#4D4D4C;}nav:not(.sidebar){border-bottom-color:#e0e0e0;}nav.main .current{border-top-color:#000;border-bottom-color:#000;}nav.main .separator{border:1px solid #000;}a{color:#000;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.item-info a,#help a{color:#3873AD;}a.test-arrow{color:#f5f5f5;}.collapse-toggle{color:#999;}#crate-search{color:#555;background-color:white;border-color:#e0e0e0;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input{color:#555;background-color:white;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input:focus{border-color:#66afe9;}.search-focus:disabled{background-color:#e6e6e6;}#crate-search+.search-input:focus{box-shadow:0 0 8px #078dd8;}.module-item .stab{color:#000;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;}.stab.deprecated{background:#F3DFFF;border-color:#7F0087;}.stab.portability{background:#C4ECFF;border-color:#7BA5DB;}.stab.portability>code{color:#000;}#help>div{background:#e9e9e9;border-color:#bfbfbf;}#help>div>span{border-bottom-color:#bfbfbf;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:black;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#8959A8;}pre.rust .kw-2,pre.rust .prelude-ty{color:#4271AE;}pre.rust .number,pre.rust .string{color:#718C00;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#C82829;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#B76514;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#c7c7c7;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label{color:#999;}:target>code,:target>.in-band{background:#FDFFD3;border-right:3px solid #ffb44c;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.5);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.5);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.5);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip .tooltiptext{background-color:#000;color:#fff;}.tooltip .tooltiptext::after{border-color:transparent black transparent transparent;}.notable-traits-tooltiptext{background-color:#eee;border-color:#999;}#titles>button:not(.selected){background-color:#e6e6e6;border-top-color:#e6e6e6;}#titles>button:hover,#titles>button.selected{background-color:#ffffff;border-top-color:#0089ff;}#titles>button>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#F1F1F1;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#F1F1F1;border-right-color:#000;}#sidebar-filler{background-color:#F1F1F1;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu,.help-button{border-color:#e0e0e0;background-color:#fff;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus,.help-button:hover,.help-button:focus{border-color:#717171;}#theme-choices{border-color:#ccc;background-color:#fff;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#eee;}@media (max-width:700px){#theme-picker{background:#fff;}}#all-types{background-color:#fff;}#all-types:hover{background-color:#f9f9f9;}.search-results td span.alias{color:#000;}.search-results td span.grey{color:#999;}#sidebar-toggle{background-color:#F1F1F1;}#sidebar-toggle:hover{background-color:#E0E0E0;}#source-sidebar{background-color:#F1F1F1;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#E0E0E0;}div.files>.selected{background-color:#fff;}.setting-line>.title{border-bottom-color:#D5D5D5;} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/main.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/main.js deleted file mode 100644 index 03cfb2cc39..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/main.js +++ /dev/null @@ -1,8 +0,0 @@ -if(!String.prototype.startsWith){String.prototype.startsWith=function(searchString,position){position=position||0;return this.indexOf(searchString,position)===position}}if(!String.prototype.endsWith){String.prototype.endsWith=function(suffix,length){var l=length||this.length;return this.indexOf(suffix,l-suffix.length)!==-1}}if(!DOMTokenList.prototype.add){DOMTokenList.prototype.add=function(className){if(className&&!hasClass(this,className)){if(this.className&&this.className.length>0){this.className+=" "+className}else{this.className=className}}}}if(!DOMTokenList.prototype.remove){DOMTokenList.prototype.remove=function(className){if(className&&this.className){this.className=(" "+this.className+" ").replace(" "+className+" "," ").trim()}}}function getVirtualKey(ev){if("key"in ev&&typeof ev.key!="undefined"){return ev.key}var c=ev.charCode||ev.keyCode;if(c==27){return"Escape"}return String.fromCharCode(c)}function getSearchInput(){return document.getElementsByClassName("search-input")[0]}function getSearchElement(){return document.getElementById("search")}function getThemesElement(){return document.getElementById("theme-choices")}function getThemePickerElement(){return document.getElementById("theme-picker")}function focusSearchBar(){getSearchInput().focus()}function defocusSearchBar(){getSearchInput().blur()}(function(){"use strict";var itemTypes=["mod","externcrate","import","struct","enum","fn","type","static","trait","impl","tymethod","method","structfield","variant","macro","primitive","associatedtype","constant","associatedconstant","union","foreigntype","keyword","existential","attr","derive","traitalias"];var disableShortcuts=getSettingValue("disable-shortcuts")==="true";var search_input=getSearchInput();var searchTimeout=null;var toggleAllDocsId="toggle-all-docs";var currentTab=0;var mouseMovedAfterSearch=true;var titleBeforeSearch=document.title;var searchTitle=null;function clearInputTimeout(){if(searchTimeout!==null){clearTimeout(searchTimeout);searchTimeout=null}}function getPageId(){if(window.location.hash){var tmp=window.location.hash.replace(/^#/,"");if(tmp.length>0){return tmp}}return null}function showSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){addClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];if(sidebar){addClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(!filler){var div=document.createElement("div");div.id="sidebar-filler";sidebar.appendChild(div)}}}function hideSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){removeClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(filler){filler.remove()}document.getElementsByTagName("body")[0].style.marginTop=""}function showSearchResults(search){if(search===null||typeof search==='undefined'){search=getSearchElement()}addClass(main,"hidden");removeClass(search,"hidden");mouseMovedAfterSearch=false;document.title=searchTitle}function hideSearchResults(search){if(search===null||typeof search==='undefined'){search=getSearchElement()}addClass(search,"hidden");removeClass(main,"hidden");document.title=titleBeforeSearch}var TY_PRIMITIVE=itemTypes.indexOf("primitive");var TY_KEYWORD=itemTypes.indexOf("keyword");function getQueryStringParams(){var params={};window.location.search.substring(1).split("&").map(function(s){var pair=s.split("=");params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params}function browserSupportsHistoryApi(){return window.history&&typeof window.history.pushState==="function"}function isHidden(elem){return elem.offsetHeight===0}var main=document.getElementById("main");var savedHash="";function handleHashes(ev){var elem;var search=getSearchElement();if(ev!==null&&search&&!hasClass(search,"hidden")&&ev.newURL){hideSearchResults(search);var hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(browserSupportsHistoryApi()){history.replaceState(hash,"","?search=#"+hash)}elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}if(savedHash!==window.location.hash){savedHash=window.location.hash;if(savedHash.length===0){return}elem=document.getElementById(savedHash.slice(1));if(!elem||!isHidden(elem)){return}var parent=elem.parentNode;if(parent&&hasClass(parent,"impl-items")){onEachLazy(parent.getElementsByClassName("collapsed"),function(e){if(e.parentNode===parent){e.click();return true}});if(isHidden(elem)){if(hasClass(parent.lastElementChild,"collapse-toggle")){parent.lastElementChild.click()}}}}}function highlightSourceLines(match,ev){if(typeof match==="undefined"){hideSidebar();match=window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/)}if(!match){return}var from=parseInt(match[1],10);var to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(to0){collapseDocs(collapses[0],"show")}}}}function getHelpElement(){buildHelperPopup();return document.getElementById("help")}function displayHelp(display,ev,help){help=help?help:getHelpElement();if(display===true){if(hasClass(help,"hidden")){ev.preventDefault();removeClass(help,"hidden");addClass(document.body,"blur")}}else if(hasClass(help,"hidden")===false){ev.preventDefault();addClass(help,"hidden");removeClass(document.body,"blur")}}function handleEscape(ev){var help=getHelpElement();var search=getSearchElement();if(hasClass(help,"hidden")===false){displayHelp(false,ev,help)}else if(hasClass(search,"hidden")===false){clearInputTimeout();ev.preventDefault();hideSearchResults(search)}defocusSearchBar();hideThemeButtonState()}function handleShortcut(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts===true){return}if(document.activeElement.tagName==="INPUT"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":displayHelp(false,ev);ev.preventDefault();focusSearchBar();break;case"+":case"-":ev.preventDefault();toggleAllDocs();break;case"?":displayHelp(true,ev);break;case"t":case"T":displayHelp(false,ev);ev.preventDefault();var themePicker=getThemePickerElement();themePicker.click();themePicker.focus();break;default:var themePicker=getThemePickerElement();if(themePicker.parentNode.contains(ev.target)){handleThemeKeyDown(ev)}}}}function handleThemeKeyDown(ev){var active=document.activeElement;var themes=getThemesElement();switch(getVirtualKey(ev)){case"ArrowUp":ev.preventDefault();if(active.previousElementSibling&&ev.target.id!=="theme-picker"){active.previousElementSibling.focus()}else{showThemeButtonState();themes.lastElementChild.focus()}break;case"ArrowDown":ev.preventDefault();if(active.nextElementSibling&&ev.target.id!=="theme-picker"){active.nextElementSibling.focus()}else{showThemeButtonState();themes.firstElementChild.focus()}break;case"Enter":case"Return":case"Space":if(ev.target.id==="theme-picker"&&themes.style.display==="none"){ev.preventDefault();showThemeButtonState();themes.firstElementChild.focus()}break;case"Home":ev.preventDefault();themes.firstElementChild.focus();break;case"End":ev.preventDefault();themes.lastElementChild.focus();break}}function findParentElement(elem,tagName){do{if(elem&&elem.tagName===tagName){return elem}elem=elem.parentNode}while(elem);return null}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);function resetMouseMoved(ev){mouseMovedAfterSearch=true}document.addEventListener("mousemove",resetMouseMoved);var handleSourceHighlight=(function(){var prev_line_id=0;var set_fragment=function(name){var x=window.scrollX,y=window.scrollY;if(browserSupportsHistoryApi()){history.replaceState(null,null,"#"+name);highlightSourceLines()}else{location.replace("#"+name)}window.scrollTo(x,y)};return function(ev){var cur_line_id=parseInt(ev.target.id,10);ev.preventDefault();if(ev.shiftKey&&prev_line_id){if(prev_line_id>cur_line_id){var tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());document.addEventListener("click",function(ev){if(hasClass(ev.target,"help-button")){displayHelp(true,ev)}else if(hasClass(ev.target,"collapse-toggle")){collapseDocs(ev.target,"toggle")}else if(hasClass(ev.target.parentNode,"collapse-toggle")){collapseDocs(ev.target.parentNode,"toggle")}else if(ev.target.tagName==="SPAN"&&hasClass(ev.target.parentNode,"line-numbers")){handleSourceHighlight(ev)}else if(hasClass(getHelpElement(),"hidden")===false){var help=getHelpElement();var is_inside_help_popup=ev.target!==help&&help.contains(ev.target);if(is_inside_help_popup===false){addClass(help,"hidden");removeClass(document.body,"blur")}}else{var a=findParentElement(ev.target,"A");if(a&&a.hash){expandSection(a.hash.replace(/^#/,""))}}});(function(){var x=document.getElementsByClassName("version-selector");if(x.length>0){x[0].onchange=function(){var i,match,url=document.location.href,stripped="",len=rootPath.match(/\.\.\//g).length+1;for(i=0;i-1){var obj=searchIndex[results[i].id];obj.lev=results[i].lev;if(isType!==true||obj.type){var res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=obj.displayPath+obj.name;obj.fullPath+="|"+obj.ty;obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}}return out}function sortResults(results,isType){var ar=[];for(var entry in results){if(hasOwnProperty(results,entry)){ar.push(results[entry])}}results=ar;var i;var nresults=results.length;for(i=0;ib?+1:-1)}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}if((aaa.item.ty===TY_PRIMITIVE&&bbb.item.ty!==TY_KEYWORD)||(aaa.item.ty===TY_KEYWORD&&bbb.item.ty!==TY_PRIMITIVE)){return-1}if((bbb.item.ty===TY_PRIMITIVE&&aaa.item.ty!==TY_PRIMITIVE)||(bbb.item.ty===TY_KEYWORD&&aaa.item.ty!==TY_KEYWORD)){return 1}a=(aaa.item.desc==="");b=(bbb.item.desc==="");if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});var length=results.length;for(i=0;i"));return{name:val.substring(0,val.indexOf("<")),generics:values.split(/\s*,\s*/),}}return{name:val,generics:[],}}function getObjectFromId(id){if(typeof id==="number"){return searchIndex[id]}return{'name':id}}function checkGenerics(obj,val){var lev_distance=MAX_LEV_DISTANCE+1;if(val.generics.length>0){if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>=val.generics.length){var elems=obj[GENERICS_DATA].slice(0);var total=0;var done=0;var vlength=val.generics.length;for(var y=0;yGENERICS_DATA&&obj[GENERICS_DATA].length>=val.generics.length){var elems=obj[GENERICS_DATA].slice(0);var allFound=true;for(var y=0;allFound===true&&yGENERICS_DATA&&obj[GENERICS_DATA].length!==0){var tmp_lev=checkGenerics(obj,val);if(tmp_lev<=MAX_LEV_DISTANCE){return tmp_lev}}else{return 0}}if(literalSearch===true){if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>0){var length=obj[GENERICS_DATA].length;for(x=0;xGENERICS_DATA&&obj[GENERICS_DATA].length>0){var olength=obj[GENERICS_DATA].length;for(x=0;x0){var length=obj.type[INPUTS_DATA].length;for(var i=0;iOUTPUT_DATA){var ret=obj.type[OUTPUT_DATA];if(typeof ret[0]==="string"){ret=[ret]}for(var x=0;xlength){return MAX_LEV_DISTANCE+1}for(var i=0;ilength){break}var lev_total=0;var aborted=false;for(var x=0;xMAX_LEV_DISTANCE){aborted=true;break}lev_total+=lev}if(aborted===false){ret_lev=Math.min(ret_lev,Math.round(lev_total/clength))}}return ret_lev}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER)return true;if(filter===type)return true;var name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function generateId(ty){if(ty.parent&&ty.parent.name){return itemTypes[ty.ty]+ty.path+ty.parent.name+ty.name}return itemTypes[ty.ty]+ty.path+ty.name}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,desc:item.desc,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,}}function handleAliases(ret,query,filterCrates){var aliases=[];var crateAliases=[];var i;if(filterCrates!==undefined){if(ALIASES[filterCrates]&&ALIASES[filterCrates][query.search]){for(i=0;iMAX_RESULTS){ret.others.pop()}};onEach(aliases,pushFunc);onEach(crateAliases,pushFunc)}var nSearchWords=searchWords.length;var i;var ty;var fullId;var returned;var in_args;if((val.charAt(0)==="\""||val.charAt(0)==="'")&&val.charAt(val.length-1)===val.charAt(0)){val=extractGenerics(val.substr(1,val.length-2));for(i=0;i")>-1){var trimmer=function(s){return s.trim()};var parts=val.split("->").map(trimmer);var input=parts[0];var inputs=input.split(",").map(trimmer).sort();for(i=0;i1?paths.length-1:1);var lev;for(j=0;j1){lev=checkPath(contains,paths[paths.length-1],ty);if(lev>MAX_LEV_DISTANCE){continue}else if(lev>0){lev_add=lev/10}}returned=MAX_LEV_DISTANCE+1;in_args=MAX_LEV_DISTANCE+1;var index=-1;lev=MAX_LEV_DISTANCE+1;fullId=generateId(ty);if(searchWords[j].indexOf(split[i])>-1||searchWords[j].indexOf(val)>-1||searchWords[j].replace(/_/g,"").indexOf(val)>-1){if(typePassesFilter(typeFilter,ty.ty)&&results[fullId]===undefined){index=searchWords[j].replace(/_/g,"").indexOf(val)}}if((lev=levenshtein(searchWords[j],val))<=MAX_LEV_DISTANCE){if(typePassesFilter(typeFilter,ty.ty)===false){lev=MAX_LEV_DISTANCE+1}else{lev+=1}}in_args=findArg(ty,valGenerics,false,typeFilter);returned=checkReturned(ty,valGenerics,false,typeFilter);lev+=lev_add;if(lev>0&&val.length>3&&searchWords[j].indexOf(val)>-1){if(val.length<6){lev-=1}else{lev=0}}if(in_args<=MAX_LEV_DISTANCE){if(results_in_args[fullId]===undefined){results_in_args[fullId]={id:j,index:index,lev:in_args,}}results_in_args[fullId].lev=Math.min(results_in_args[fullId].lev,in_args)}if(returned<=MAX_LEV_DISTANCE){if(results_returned[fullId]===undefined){results_returned[fullId]={id:j,index:index,lev:returned,}}results_returned[fullId].lev=Math.min(results_returned[fullId].lev,returned)}if(index!==-1||lev<=MAX_LEV_DISTANCE){if(index!==-1&&paths.length<2){lev=0}if(results[fullId]===undefined){results[fullId]={id:j,index:index,lev:lev,}}results[fullId].lev=Math.min(results[fullId].lev,lev)}}}var ret={"in_args":sortResults(results_in_args,true),"returned":sortResults(results_returned,true),"others":sortResults(results),};handleAliases(ret,query,filterCrates);return ret}function validateResult(name,path,keys,parent){for(var i=0;i-1||path.indexOf(keys[i])>-1||(parent!==undefined&&parent.name!==undefined&&parent.name.toLowerCase().indexOf(keys[i])>-1)||levenshtein(name,keys[i])<=MAX_LEV_DISTANCE)){return false}}return true}function getQuery(raw){var matches,type,query;query=raw;matches=query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);if(matches){type=matches[1].replace(/^const$/,"constant");query=query.substring(matches[0].length)}return{raw:raw,query:query,type:type,id:query+type}}function initSearchNav(){var hoverTimeout;var click_func=function(e){var el=e.target;while(el.tagName!=="TR"){el=el.parentNode}var dst=e.target.getElementsByTagName("a");if(dst.length<1){return}dst=dst[0];if(window.location.pathname===dst.pathname){hideSearchResults();document.location.href=dst.href}};var mouseover_func=function(e){if(mouseMovedAfterSearch){var el=e.target;while(el.tagName!=="TR"){el=el.parentNode}clearTimeout(hoverTimeout);hoverTimeout=setTimeout(function(){onEachLazy(document.getElementsByClassName("search-results"),function(e){onEachLazy(e.getElementsByClassName("result"),function(i_e){removeClass(i_e,"highlighted")})});addClass(el,"highlighted")},20)}};onEachLazy(document.getElementsByClassName("search-results"),function(e){onEachLazy(e.getElementsByClassName("result"),function(i_e){i_e.onclick=click_func;i_e.onmouseover=mouseover_func})});search_input.onkeydown=function(e){var actives=[[],[],[]];var current=0;onEachLazy(document.getElementById("results").childNodes,function(e){onEachLazy(e.getElementsByClassName("highlighted"),function(h_e){actives[current].push(h_e)});current+=1});if(e.which===38){if(e.ctrlKey){printTab(currentTab>0?currentTab-1:2)}else{if(!actives[currentTab].length||!actives[currentTab][0].previousElementSibling){return}addClass(actives[currentTab][0].previousElementSibling,"highlighted");removeClass(actives[currentTab][0],"highlighted")}e.preventDefault()}else if(e.which===40){if(e.ctrlKey){printTab(currentTab>1?0:currentTab+1)}else if(!actives[currentTab].length){var results=document.getElementById("results").childNodes;if(results.length>0){var res=results[currentTab].getElementsByClassName("result");if(res.length>0){addClass(res[0],"highlighted")}}}else if(actives[currentTab][0].nextElementSibling){addClass(actives[currentTab][0].nextElementSibling,"highlighted");removeClass(actives[currentTab][0],"highlighted")}e.preventDefault()}else if(e.which===13){if(actives[currentTab].length){document.location.href=actives[currentTab][0].getElementsByTagName("a")[0].href}}else if(e.which===16){}else if(actives[currentTab].length>0){removeClass(actives[currentTab][0],"highlighted")}}}function buildHrefAndPath(item){var displayPath;var href;var type=itemTypes[item.ty];var name=item.name;var path=item.path;if(type==="mod"){displayPath=path+"::";href=rootPath+path.replace(/::/g,"/")+"/"+name+"/index.html"}else if(type==="primitive"||type==="keyword"){displayPath="";href=rootPath+path.replace(/::/g,"/")+"/"+type+"."+name+".html"}else if(type==="externcrate"){displayPath="";href=rootPath+name+"/index.html"}else if(item.parent!==undefined){var myparent=item.parent;var anchor="#"+type+"."+name;var parentType=itemTypes[myparent.ty];var pageType=parentType;var pageName=myparent.name;if(parentType==="primitive"){displayPath=myparent.name+"::"}else if(type==="structfield"&&parentType==="variant"){var splitPath=item.path.split("::");var enumName=splitPath.pop();path=splitPath.join("::");displayPath=path+"::"+enumName+"::"+myparent.name+"::";anchor="#variant."+myparent.name+".field."+name;pageType="enum";pageName=enumName}else{displayPath=path+"::"+myparent.name+"::"}href=rootPath+path.replace(/::/g,"/")+"/"+pageType+"."+pageName+".html"+anchor}else{displayPath=item.path+"::";href=rootPath+item.path.replace(/::/g,"/")+"/"+type+"."+name+".html"}return[displayPath,href]}function escape(content){var h1=document.createElement("h1");h1.textContent=content;return h1.innerHTML}function pathSplitter(path){var tmp=""+path.replace(/::/g,"::");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}function addTab(array,query,display){var extraStyle="";if(display===false){extraStyle=" style=\"display: none;\""}var output="";var duplicates={};var length=0;if(array.length>0){output="";array.forEach(function(item){var name,type;name=item.name;type=itemTypes[item.ty];if(item.is_alias!==true){if(duplicates[item.fullPath]){return}duplicates[item.fullPath]=true}length+=1;output+=""});output+="
    "+""+(item.is_alias===true?(""+item.alias+"  - see "):"")+item.displayPath+""+name+""+""+""+item.desc+" 
    "}else{output="
    No results :(
    "+"Try on DuckDuckGo?

    "+"Or try looking in one of these:
    "}return[output,length]}function makeTabHeader(tabNb,text,nbElems){if(currentTab===tabNb){return""}return""}function showResults(results){var search=getSearchElement();if(results.others.length===1&&getSettingValue("go-to-only-result")==="true"&&(!search.firstChild||search.firstChild.innerText!==getSearchLoadingText())){var elem=document.createElement("a");elem.href=results.others[0].href;elem.style.display="none";document.body.appendChild(elem);elem.click();return}var query=getQuery(search_input.value);currentResults=query.id;var ret_others=addTab(results.others,query);var ret_in_args=addTab(results.in_args,query,false);var ret_returned=addTab(results.returned,query,false);var output="

    Results for "+escape(query.query)+(query.type?" (type: "+escape(query.type)+")":"")+"

    "+"
    "+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
    "+ret_others[0]+ret_in_args[0]+ret_returned[0]+"
    ";search.innerHTML=output;showSearchResults(search);var tds=search.getElementsByTagName("td");var td_width=0;if(tds.length>0){td_width=tds[0].offsetWidth}var width=search.offsetWidth-40-td_width;onEachLazy(search.getElementsByClassName("desc"),function(e){e.style.width=width+"px"});initSearchNav();var elems=document.getElementById("titles").childNodes;elems[0].onclick=function(){printTab(0)};elems[1].onclick=function(){printTab(1)};elems[2].onclick=function(){printTab(2)};printTab(currentTab)}function execSearch(query,searchWords,filterCrates){function getSmallest(arrays,positions,notDuplicates){var start=null;for(var it=0;itpositions[it]&&(start===null||start>arrays[it][positions[it]].lev)&&!notDuplicates[arrays[it][positions[it]].fullPath]){start=arrays[it][positions[it]].lev}}return start}function mergeArrays(arrays){var ret=[];var positions=[];var notDuplicates={};for(var x=0;xpositions[x]&&arrays[x][positions[x]].lev===smallest&&!notDuplicates[arrays[x][positions[x]].fullPath]){ret.push(arrays[x][positions[x]]);notDuplicates[arrays[x][positions[x]].fullPath]=true;positions[x]+=1}}}return ret}var queries=query.raw.split(",");var results={"in_args":[],"returned":[],"others":[],};for(var i=0;i1){return{"in_args":mergeArrays(results.in_args),"returned":mergeArrays(results.returned),"others":mergeArrays(results.others),}}return{"in_args":results.in_args[0],"returned":results.returned[0],"others":results.others[0],}}function getFilterCrates(){var elem=document.getElementById("crate-search");if(elem&&elem.value!=="All crates"&&hasOwnProperty(rawSearchIndex,elem.value)){return elem.value}return undefined}function search(e,forced){var params=getQueryStringParams();var query=getQuery(search_input.value.trim());if(e){e.preventDefault()}if(query.query.length===0){return}if(forced!==true&&query.id===currentResults){if(query.query.length>0){putBackSearch(search_input)}return}searchTitle="Results for "+query.query+" - Rust";if(browserSupportsHistoryApi()){if(!history.state&&!params.search){history.pushState(query,"","?search="+encodeURIComponent(query.raw))}else{history.replaceState(query,"","?search="+encodeURIComponent(query.raw))}}var filterCrates=getFilterCrates();showResults(execSearch(query,index,filterCrates))}function buildIndex(rawSearchIndex){searchIndex=[];var searchWords=[];var i;var currentIndex=0;for(var crate in rawSearchIndex){if(!hasOwnProperty(rawSearchIndex,crate)){continue}var crateSize=0;searchWords.push(crate);searchIndex.push({crate:crate,ty:1,name:crate,path:"",desc:rawSearchIndex[crate].doc,type:null,});currentIndex+=1;var items=rawSearchIndex[crate].i;var paths=rawSearchIndex[crate].p;var aliases=rawSearchIndex[crate].a;var len=paths.length;for(i=0;i0){search_input.value=params.search;search(e)}else{search_input.value="";hideSearchResults()}})}search()}index=buildIndex(rawSearchIndex);startSearch();if(rootPath==="../"||rootPath==="./"){var sidebar=document.getElementsByClassName("sidebar-elems")[0];if(sidebar){var div=document.createElement("div");div.className="block crate";div.innerHTML="

    Crates

    ";var ul=document.createElement("ul");div.appendChild(ul);var crates=[];for(var crate in rawSearchIndex){if(!hasOwnProperty(rawSearchIndex,crate)){continue}crates.push(crate)}crates.sort();for(var i=0;i','`').replace('','`');return x.innerText}window.initSidebarItems=function(items){var sidebar=document.getElementsByClassName("sidebar-elems")[0];var current=window.sidebarCurrent;function block(shortty,longty){var filtered=items[shortty];if(!filtered){return}var div=document.createElement("div");div.className="block "+shortty;var h3=document.createElement("h3");h3.textContent=longty;div.appendChild(h3);var ul=document.createElement("ul");var length=filtered.length;for(var i=0;i"+""+"
    "+code.outerHTML+"
    ";list.appendChild(display)}}};if(window.pending_implementors){window.register_implementors(window.pending_implementors)}function labelForToggleButton(sectionIsCollapsed){if(sectionIsCollapsed){return"+"}return"\u2212"}function onEveryMatchingChild(elem,className,func){if(elem&&className&&func){var length=elem.childNodes.length;var nodes=elem.childNodes;for(var i=0;i"+labelForToggleButton(sectionIsCollapsed)+"
    ]";return toggle}function createToggle(toggle,otherMessage,fontSize,extraClass,show){var span=document.createElement("span");span.className="toggle-label";if(show){span.style.display="none"}if(!otherMessage){span.innerHTML=" Expand description"}else{span.innerHTML=otherMessage}if(fontSize){span.style.fontSize=fontSize}var mainToggle=toggle.cloneNode(true);mainToggle.appendChild(span);var wrapper=document.createElement("div");wrapper.className="toggle-wrapper";if(!show){addClass(wrapper,"collapsed");var inner=mainToggle.getElementsByClassName("inner");if(inner&&inner.length>0){inner[0].innerHTML="+"}}if(extraClass){addClass(wrapper,extraClass)}wrapper.appendChild(mainToggle);return wrapper}(function(){var toggles=document.getElementById(toggleAllDocsId);if(toggles){toggles.onclick=toggleAllDocs}var toggle=createSimpleToggle(false);var hideMethodDocs=getSettingValue("auto-hide-method-docs")==="true";var hideImplementors=getSettingValue("auto-collapse-implementors")!=="false";var pageId=getPageId();var func=function(e){var next=e.nextElementSibling;if(next&&hasClass(next,"item-info")){next=next.nextElementSibling}if(!next){return}if(hasClass(next,"docblock")){var newToggle=toggle.cloneNode(true);insertAfter(newToggle,e.childNodes[e.childNodes.length-1]);if(hideMethodDocs===true&&hasClass(e,"method")===true){collapseDocs(newToggle,"hide",pageId)}}};var funcImpl=function(e){var next=e.nextElementSibling;if(next&&hasClass(next,"item-info")){next=next.nextElementSibling}if(next&&hasClass(next,"docblock")){next=next.nextElementSibling}if(!next){return}if(hasClass(e,"impl")&&(next.getElementsByClassName("method").length>0||next.getElementsByClassName("associatedconstant").length>0)){var newToggle=toggle.cloneNode(true);insertAfter(newToggle,e.childNodes[e.childNodes.length-1]);if(hideImplementors===true&&e.parentNode.id==="implementors-list"){collapseDocs(newToggle,"hide",pageId)}}};onEachLazy(document.getElementsByClassName("method"),func);onEachLazy(document.getElementsByClassName("associatedconstant"),func);onEachLazy(document.getElementsByClassName("impl"),funcImpl);var impl_call=function(){};if(hideMethodDocs===true){impl_call=function(e,newToggle){if(e.id.match(/^impl(?:-\d+)?$/)===null){if(hasClass(e,"impl")===true){collapseDocs(newToggle,"hide",pageId)}}}}var newToggle=document.createElement("a");newToggle.href="javascript:void(0)";newToggle.className="collapse-toggle hidden-default collapsed";newToggle.innerHTML="["+labelForToggleButton(true)+"] Show hidden undocumented items";function toggleClicked(){if(hasClass(this,"collapsed")){removeClass(this,"collapsed");onEachLazy(this.parentNode.getElementsByClassName("hidden"),function(x){if(hasClass(x,"content")===false){removeClass(x,"hidden");addClass(x,"x")}},true);this.innerHTML="["+labelForToggleButton(false)+"] Hide undocumented items"}else{addClass(this,"collapsed");onEachLazy(this.parentNode.getElementsByClassName("x"),function(x){if(hasClass(x,"content")===false){addClass(x,"hidden");removeClass(x,"x")}},true);this.innerHTML="["+labelForToggleButton(true)+"] Show hidden undocumented items"}}onEachLazy(document.getElementsByClassName("impl-items"),function(e){onEachLazy(e.getElementsByClassName("associatedconstant"),func);var hiddenElems=e.getElementsByClassName("hidden");var needToggle=false;var hlength=hiddenElems.length;for(var i=0;i"+getSearchLoadingText()+"";showSearchResults(search)}var sidebar_menu=document.getElementsByClassName("sidebar-menu")[0];if(sidebar_menu){sidebar_menu.onclick=function(){var sidebar=document.getElementsByClassName("sidebar")[0];if(hasClass(sidebar,"mobile")===true){hideSidebar()}else{showSidebar()}}}if(main){onEachLazy(main.getElementsByClassName("loading-content"),function(e){e.remove()});onEachLazy(main.childNodes,function(e){if(e.tagName==="H2"||e.tagName==="H3"){var nextTagName=e.nextElementSibling.tagName;if(nextTagName=="H2"||nextTagName=="H3"){e.nextElementSibling.style.display="flex"}else{e.nextElementSibling.style.display="block"}}})}function enableSearchInput(){if(search_input){search_input.removeAttribute('disabled')}}window.addSearchOptions=function(crates){var elem=document.getElementById("crate-search");if(!elem){enableSearchInput();return}var crates_text=[];if(Object.keys(crates).length>1){for(var crate in crates){if(hasOwnProperty(crates,crate)){crates_text.push(crate)}}}crates_text.sort(function(a,b){var lower_a=a.toLowerCase();var lower_b=b.toLowerCase();if(lower_alower_b){return 1}return 0});var savedCrate=getSettingValue("saved-filter-crate");for(var i=0;ithe rustdoc book.";var container=document.createElement("div");var shortcuts=[["?","Show this help dialog"],["S","Focus the search field"],["T","Focus the theme picker menu"],["↑","Move up in search results"],["↓","Move down in search results"],["ctrl + ↑ / ↓","Switch result tab"],["⏎","Go to active search result"],["+","Expand all sections"],["-","Collapse all sections"],].map(x=>"
    "+x[0].split(" ").map((y,index)=>(index&1)===0?""+y+"":y).join("")+"
    "+x[1]+"
    ").join("");var div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

    Keyboard Shortcuts

    "+shortcuts+"
    ";var infos=["Prefix searches with a type followed by a colon (e.g., fn:) to \ - restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \ - enum, trait, type, macro, \ - and const.","Search functions by type signature (e.g., vec -> usize or \ - * -> vec)","Search multiple things at once by splitting your query with comma (e.g., \ - str,u8 or String,struct:Vec,test)","You can look for items with an exact name by putting double quotes around \ - your request: \"string\"","Look for items inside another one by searching for a path: vec::Vec",].map(x=>"

    "+x+"

    ").join("");var div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

    Search Tricks

    "+infos;container.appendChild(book_info);container.appendChild(div_shortcuts);container.appendChild(div_infos);popup.appendChild(container);insertAfter(popup,getSearchElement());buildHelperPopup=function(){}}onHashChange(null);window.onhashchange=onHashChange}());window.onunload=function(){} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/normalize.css b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/normalize.css deleted file mode 100644 index 6d692b50ca..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/normalize.css +++ /dev/null @@ -1,2 +0,0 @@ - /*! normalize.css v3.0.0 | MIT License | git.io/normalize */ -html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/noscript.css b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/noscript.css deleted file mode 100644 index 5cbcb9016b..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/noscript.css +++ /dev/null @@ -1 +0,0 @@ - #main>h2+div,#main>h2+h3,#main>h3+div{display:block;}.loading-content{display:none;}#main>h2+div,#main>h3+div{display:block;}#main>h2+h3{display:flex;}#main .impl-items .hidden{display:block !important;} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/rust-logo.png b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/rust-logo.png deleted file mode 100644 index 74b4bd6950..0000000000 Binary files a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/rust-logo.png and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/rustdoc.css b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/rustdoc.css deleted file mode 100644 index 061171efd1..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/rustdoc.css +++ /dev/null @@ -1 +0,0 @@ - @font-face {font-family:'Fira Sans';font-style:normal;font-weight:400;src:local('Fira Sans'),url("FiraSans-Regular.woff") format('woff');}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:500;src:local('Fira Sans Medium'),url("FiraSans-Medium.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:normal;font-weight:400;src:local('Source Serif Pro'),url("SourceSerifPro-Regular.ttf.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:italic;font-weight:400;src:local('Source Serif Pro Italic'),url("SourceSerifPro-It.ttf.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:normal;font-weight:700;src:local('Source Serif Pro Bold'),url("SourceSerifPro-Bold.ttf.woff") format('woff');}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("SourceCodePro-Regular.woff") format('woff');}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("SourceCodePro-Semibold.woff") format('woff');}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}html{content:"";}@media (prefers-color-scheme:light){html{content:"light";}}@media (prefers-color-scheme:dark){html{content:"dark";}}body{font:16px/1.4 "Source Serif Pro",serif;margin:0;position:relative;padding:10px 15px 20px 15px;-webkit-font-feature-settings:"kern","liga";-moz-font-feature-settings:"kern","liga";font-feature-settings:"kern","liga";}h1{font-size:1.5em;}h2{font-size:1.4em;}h3{font-size:1.3em;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod):not(.notable),h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){font-weight:500;margin:20px 0 15px 0;padding-bottom:6px;}h1.fqn{border-bottom:1px dashed;margin-top:0;}h1.fqn>.in-band>a:hover{text-decoration:underline;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){border-bottom:1px solid;}h3.impl,h3.method,h4.method,h3.type,h4.type,h4.associatedconstant{flex-basis:100%;font-weight:600;margin-top:16px;margin-bottom:10px;position:relative;}h3.impl,h3.method,h3.type{padding-left:15px;}h1,h2,h3,h4,.sidebar,a.source,.search-input,.content table td:first-child>a,.collapse-toggle,div.item-list .out-of-band,#source-sidebar,#sidebar-toggle{font-family:"Fira Sans",sans-serif;}.content ul.crate a.crate{font:16px/1.6 "Fira Sans";}ol,ul{padding-left:25px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:.6em;}p{margin:0 0 .6em 0;}summary{outline:none;}code,pre,a.test-arrow{font-family:"Source Code Pro",monospace;}.docblock code,.docblock-short code{border-radius:3px;padding:0 0.1em;}.docblock pre code,.docblock-short pre code,.docblock code.spotlight{padding:0;}.docblock code.spotlight :last-child{padding-bottom:0.6em;}pre{padding:14px;}.source .content pre{padding:20px;}img{max-width:100%;}li{position:relative;}.source .content{margin-top:50px;max-width:none;overflow:visible;margin-left:0px;min-width:70em;}nav.sub{font-size:16px;text-transform:uppercase;}.sidebar{width:200px;position:fixed;left:0;top:0;bottom:0;overflow:auto;}*{scrollbar-width:initial;}.sidebar{scrollbar-width:thin;}::-webkit-scrollbar{width:12px;}.sidebar::-webkit-scrollbar{width:8px;}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0;}.sidebar .block>ul>li{margin-right:-10px;}.content,nav{max-width:960px;}.hidden{display:none !important;}.logo-container{height:100px;width:100px;position:relative;margin:20px auto;display:block;margin-top:10px;}.logo-container>img{max-width:100px;max-height:100px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);display:block;}.sidebar .location{border:1px solid;font-size:17px;margin:30px 10px 20px 10px;text-align:center;word-wrap:break-word;}.sidebar .version{font-size:15px;text-align:center;border-bottom:1px solid;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;}.location:empty{border:none;}.location a:first-child{font-weight:500;}.block{padding:0;margin-bottom:14px;}.block h2,.block h3{margin-top:0;margin-bottom:8px;text-align:center;}.block ul,.block li{margin:0 10px;padding:0;list-style:none;}.block a{display:block;text-overflow:ellipsis;overflow:hidden;line-height:15px;padding:7px 5px;font-size:14px;font-weight:300;transition:border 500ms ease-out;}.sidebar-title{border-top:1px solid;border-bottom:1px solid;text-align:center;font-size:17px;margin-bottom:5px;}.sidebar-links{margin-bottom:15px;}.sidebar-links>a{padding-left:10px;width:100%;}.sidebar-menu{display:none;}.content{padding:15px 0;}.source .content pre.rust{white-space:pre;overflow:auto;padding-left:0;}.rustdoc:not(.source) .example-wrap{display:inline-flex;margin-bottom:10px;position:relative;}.example-wrap{width:100%;}.example-wrap>pre.line-number{overflow:initial;border:1px solid;border-top-left-radius:5px;border-bottom-left-radius:5px;padding:13px 8px;text-align:right;}.rustdoc:not(.source) .example-wrap>pre.rust{width:100%;overflow-x:auto;}.rustdoc:not(.source) .example-wrap>pre{margin:0;}#search{margin-left:230px;position:relative;}#results{position:absolute;right:0;left:0;overflow:auto;}#results>table{width:100%;table-layout:fixed;margin-bottom:40px;}.content pre.line-numbers{float:left;border:none;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}.line-numbers span{cursor:pointer;}.docblock-short{overflow-wrap:anywhere;}.docblock-short p{display:inline;}.docblock-short p{overflow:hidden;text-overflow:ellipsis;margin:0;}.docblock code,.docblock-short code{white-space:pre-wrap;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom:1px solid;}#main>.docblock h1{font-size:1.3em;}#main>.docblock h2{font-size:1.15em;}#main>.docblock h3,#main>.docblock h4,#main>.docblock h5{font-size:1em;}#main>h2+div,#main>h2+h3,#main>h3+div{display:none;flex-wrap:wrap;}.docblock h1{font-size:1em;}.docblock h2{font-size:0.95em;}.docblock h3,.docblock h4,.docblock h5{font-size:0.9em;}.docblock{margin-left:24px;position:relative;}.content .out-of-band{float:right;font-size:23px;margin:0px;padding:0px;font-weight:normal;}h3.impl>.out-of-band{font-size:21px;}h4.method>.out-of-band{font-size:19px;}h4>code,h3>code,.invisible>code{max-width:calc(100% - 41px);display:block;}.invisible{width:100%;display:inline-block;}.content .in-band{margin:0px;padding:0px;}.in-band>code{display:inline-block;}#main{position:relative;}#main>.since{top:inherit;font-family:"Fira Sans",sans-serif;}.content table:not(.table-display){border-spacing:0 5px;}.content td{vertical-align:top;}.content td:first-child{padding-right:20px;}.content td p:first-child{margin-top:0;}.content td h1,.content td h2{margin-left:0;font-size:1.1em;}.content tr:first-child td{border-top:0;}.docblock table{margin:.5em 0;width:calc(100% - 2px);border:1px dashed;}.docblock table td{padding:.5em;border:1px dashed;}.docblock table th{padding:.5em;text-align:left;border:1px solid;}.fields+table{margin-bottom:1em;}.content .item-list{list-style-type:none;padding:0;}.content .multi-column{-moz-column-count:5;-moz-column-gap:2.5em;-webkit-column-count:5;-webkit-column-gap:2.5em;column-count:5;column-gap:2.5em;}.content .multi-column li{width:100%;display:inline-block;}.content .method{font-size:1em;position:relative;}.content .method .where,.content .fn .where,.content .where.fmt-newline{display:block;font-size:0.8em;}.content .methods>div:not(.notable-traits){margin-left:40px;margin-bottom:15px;}.content .docblock>.impl-items{margin-left:20px;margin-top:-34px;}.content .docblock>.impl-items>h4{border-bottom:0;}.content .docblock>.impl-items .table-display{margin:0;}.content .docblock>.impl-items table td{padding:0;}.toggle-wrapper.marg-left>.collapse-toggle{left:-24px;}.content .docblock>.impl-items .table-display,.impl-items table td{border:none;}.content .item-info code{font-size:90%;}.content .item-info{position:relative;margin-left:33px;margin-top:-13px;}.sub-variant>div>.item-info{margin-top:initial;}.content .item-info::before{content:'⬑';font-size:25px;position:absolute;top:-6px;left:-19px;}.content .impl-items .method,.content .impl-items>.type,.impl-items>.associatedconstant{margin-left:20px;}.content .impl-items .docblock,.content .impl-items .item-info{margin-bottom:.6em;}.content .impl-items>.item-info{margin-left:40px;}.methods>.item-info,.content .impl-items>.item-info{margin-top:-8px;}.impl-items{flex-basis:100%;}#main>.item-info{margin-top:0;}nav:not(.sidebar){border-bottom:1px solid;padding-bottom:10px;margin-bottom:10px;}nav.main{padding:20px 0;text-align:center;}nav.main .current{border-top:1px solid;border-bottom:1px solid;}nav.main .separator{border:1px solid;display:inline-block;height:23px;margin:0 20px;}nav.sum{text-align:right;}nav.sub form{display:inline;}nav.sub,.content{margin-left:230px;}a{text-decoration:none;background:transparent;}.small-section-header:hover>.anchor{display:initial;}.in-band:hover>.anchor,.impl:hover>.anchor{display:inline-block;position:absolute;}.anchor{display:none;position:absolute;left:-7px;}.anchor.field{left:-5px;}.small-section-header>.anchor{left:-28px;padding-right:10px;}.anchor:before{content:'\2002\00a7\2002';}.docblock a:not(.srclink):not(.test-arrow):hover,.docblock-short a:not(.srclink):not(.test-arrow):hover,.item-info a{text-decoration:underline;}.invisible>.srclink,h4>code+.srclink,h3>code+.srclink{position:absolute;top:0;right:0;font-size:17px;font-weight:normal;}.block a.current.crate{font-weight:500;}.search-container{position:relative;}.search-container>div{display:inline-flex;width:calc(100% - 63px);}#crate-search{margin-top:5px;padding:6px;padding-right:19px;flex:none;border:0;border-right:0;border-radius:4px 0 0 4px;outline:none;cursor:pointer;border-right:1px solid;-moz-appearance:none;-webkit-appearance:none;text-indent:0.01px;text-overflow:"";background-repeat:no-repeat;background-color:transparent;background-size:20px;background-position:calc(100% - 1px) 56%;}.search-container>.top-button{position:absolute;right:0;top:10px;}.search-input{-moz-box-sizing:border-box !important;box-sizing:border-box !important;outline:none;border:none;border-radius:1px;margin-top:5px;padding:10px 16px;font-size:17px;transition:border-color 300ms ease;transition:border-radius 300ms ease-in-out;transition:box-shadow 300ms ease-in-out;width:100%;}#crate-search+.search-input{border-radius:0 1px 1px 0;width:calc(100% - 32px);}.search-input:focus{border-radius:2px;border:0;outline:0;}.search-results .desc{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;display:block;}.search-results a{display:block;}.content .search-results td:first-child{padding-right:0;width:50%;}.content .search-results td:first-child a{padding-right:10px;}.content .search-results td:first-child a:after{clear:both;content:"";display:block;}.content .search-results td:first-child a span{float:left;}tr.result span.primitive::after{content:' (primitive type)';font-style:italic;}tr.result span.keyword::after{content:' (keyword)';font-style:italic;}body.blur>:not(#help){filter:blur(8px);-webkit-filter:blur(8px);opacity:.7;}#help{width:100%;height:100vh;position:fixed;top:0;left:0;display:flex;justify-content:center;align-items:center;}#help>div{flex:0 0 auto;box-shadow:0 0 6px rgba(0,0,0,.2);width:550px;height:auto;border:1px solid;}#help dt{float:left;clear:left;display:block;}#help>div>span{text-align:center;display:block;margin:10px 0;font-size:18px;border-bottom:1px solid #ccc;padding-bottom:4px;margin-bottom:6px;}#help dd{margin:5px 35px;}#help .infos{padding-left:0;}#help h1,#help h2{margin-top:0;}#help>div div{width:50%;float:left;padding:0 20px 20px 17px;;}.stab{display:table;border-width:1px;border-style:solid;padding:3px;margin-bottom:5px;font-size:90%;}.stab p{display:inline;}.stab summary{display:list-item;}.stab .emoji{font-size:1.5em;}.module-item .stab{border-radius:3px;display:inline-block;font-size:80%;line-height:1.2;margin-bottom:0;margin-right:.3em;padding:2px;vertical-align:text-bottom;}.module-item.unstable{opacity:0.65;}.since{font-weight:normal;font-size:initial;position:absolute;right:0;top:0;}.impl-items .since,.impl .since,.methods .since{flex-grow:0;padding-left:12px;padding-right:2px;position:initial;}.impl-items .srclink,.impl .srclink,.methods .srclink{flex-grow:0;font-size:17px;font-weight:normal;}.impl-items code,.impl code,.methods code{flex-grow:1;}.impl-items h4,h4.impl,h3.impl,.methods h3{display:flex;flex-basis:100%;font-size:16px;margin-bottom:12px;justify-content:space-between;}.variants_table{width:100%;}.variants_table tbody tr td:first-child{width:1%;}td.summary-column{width:100%;}.summary{padding-right:0px;}pre.rust .question-mark{font-weight:bold;}a.test-arrow{display:inline-block;position:absolute;padding:5px 10px 5px 10px;border-radius:5px;font-size:130%;top:5px;right:5px;z-index:1;}a.test-arrow:hover{text-decoration:none;}.section-header:hover a:before{position:absolute;left:-25px;padding-right:10px;content:'\2002\00a7\2002';}.section-header:hover a{text-decoration:none;}.section-header a{color:inherit;}.collapse-toggle{font-weight:300;position:absolute;left:-23px;top:0;}h3>.collapse-toggle,h4>.collapse-toggle{font-size:0.8em;top:5px;}.toggle-wrapper>.collapse-toggle{left:-24px;margin-top:0px;}.toggle-wrapper{position:relative;margin-top:0;}.toggle-wrapper.collapsed{height:25px;transition:height .2s;margin-bottom:.6em;}.collapse-toggle>.inner{display:inline-block;width:1.2ch;text-align:center;}.collapse-toggle.hidden-default{position:relative;margin-left:20px;}.since+.srclink{display:table-cell;padding-left:10px;}.item-spacer{width:100%;height:12px;}.out-of-band>span.since{position:initial;font-size:20px;margin-right:5px;}.toggle-wrapper>.collapse-toggle{left:0;}.variant+.toggle-wrapper+.docblock>p{margin-top:5px;}.sub-variant,.sub-variant>h3{margin-top:1px !important;}#main>.sub-variant>h3{font-size:15px;margin-left:25px;margin-bottom:5px;}.sub-variant>div{margin-left:20px;margin-bottom:10px;}.sub-variant>div>span{display:block;position:relative;}.toggle-label{display:inline-block;margin-left:4px;margin-top:3px;}.enum>.toggle-wrapper+.docblock,.struct>.toggle-wrapper+.docblock{margin-left:30px;margin-bottom:20px;margin-top:5px;}.docblock>.section-header:first-child{margin-left:15px;margin-top:0;}.docblock>.section-header:first-child:hover>a:before{left:-10px;}.enum>.collapsed,.struct>.collapsed{margin-bottom:25px;}#main>.variant,#main>.structfield{display:block;}.attributes{display:block;margin-top:0px !important;margin-right:0px;margin-bottom:0px !important;margin-left:30px;}.toggle-attributes.collapsed{margin-bottom:0;}.impl-items>.toggle-attributes{margin-left:20px;}.impl-items .attributes{font-weight:500;}:target>code{opacity:1;}.information{position:absolute;left:-25px;margin-top:7px;z-index:1;}.tooltip{position:relative;display:inline-block;cursor:pointer;}.tooltip .tooltiptext{width:120px;display:none;text-align:center;padding:5px 3px 3px 3px;border-radius:6px;margin-left:5px;top:-5px;left:105%;z-index:10;font-size:16px;}.tooltip .tooltiptext::after{content:" ";position:absolute;top:50%;left:16px;margin-top:-5px;border-width:5px;border-style:solid;}.tooltip:hover .tooltiptext{display:inline;}.tooltip.compile_fail,.tooltip.should_panic,.tooltip.ignore{font-weight:bold;font-size:20px;}.notable-traits-tooltip{display:inline-block;cursor:pointer;}.notable-traits:hover .notable-traits-tooltiptext,.notable-traits .notable-traits-tooltiptext.force-tooltip{display:inline-block;}.notable-traits .notable-traits-tooltiptext{display:none;padding:5px 3px 3px 3px;border-radius:6px;margin-left:5px;z-index:10;font-size:16px;cursor:default;position:absolute;border:1px solid;}.notable-traits-tooltip::after{content:"\00a0\00a0\00a0";}.notable-traits .notable,.notable-traits .docblock{margin:0;}.notable-traits .docblock code.content{margin:0;padding:0;font-size:20px;}pre.rust.rust-example-rendered{position:relative;}pre.rust{tab-size:4;-moz-tab-size:4;}.search-failed{text-align:center;margin-top:20px;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#titles{height:35px;}#titles>button{float:left;width:33.3%;text-align:center;font-size:18px;cursor:pointer;border:0;border-top:2px solid;}#titles>button:not(:last-child){margin-right:1px;width:calc(33.3% - 1px);}#titles>button>div.count{display:inline-block;font-size:16px;}.notable-traits{cursor:pointer;z-index:2;margin-left:5px;}h4>.notable-traits{position:absolute;left:-44px;top:2px;}#all-types{text-align:center;border:1px solid;margin:0 10px;margin-bottom:10px;display:block;border-radius:7px;}#all-types>p{margin:5px 0;}#sidebar-toggle{position:fixed;top:30px;left:300px;z-index:10;padding:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;cursor:pointer;font-weight:bold;transition:left .5s;font-size:1.2em;border:1px solid;border-left:0;}#source-sidebar{position:fixed;top:0;bottom:0;left:0;width:300px;z-index:1;overflow:auto;transition:left .5s;border-right:1px solid;}#source-sidebar>.title{font-size:1.5em;text-align:center;border-bottom:1px solid;margin-bottom:6px;}.theme-picker{position:absolute;left:211px;top:19px;}.theme-picker button{outline:none;}#settings-menu,.help-button{position:absolute;top:10px;}#settings-menu{right:0;outline:none;}.help-button{right:30px;font-family:"Fira Sans",sans-serif;text-align:center;font-size:17px;}#theme-picker,#settings-menu,.help-button{padding:4px;width:27px;height:29px;border:1px solid;border-radius:3px;cursor:pointer;}#theme-choices{display:none;position:absolute;left:0;top:28px;border:1px solid;border-radius:3px;z-index:1;cursor:pointer;}#theme-choices>button{border:none;width:100%;padding:4px 8px;text-align:center;background:rgba(0,0,0,0);}#theme-choices>button:not(:first-child){border-top:1px solid;}@media (min-width:701px){.information:first-child>.tooltip{margin-top:16px;}}@media (max-width:700px){body{padding-top:0px;}.rustdoc>.sidebar{height:45px;min-height:40px;margin:0;margin-left:-15px;padding:0 15px;position:static;z-index:11;}.sidebar>.location{float:right;margin:0px;margin-top:2px;padding:3px 10px 1px 10px;min-height:39px;background:inherit;text-align:left;font-size:24px;}.sidebar .location:empty{padding:0;}.sidebar .logo-container{width:35px;height:35px;margin-top:5px;margin-bottom:5px;float:left;margin-left:50px;}.sidebar .logo-container>img{max-width:35px;max-height:35px;}.sidebar-menu{position:fixed;z-index:10;font-size:2rem;cursor:pointer;width:45px;left:0;text-align:center;display:block;border-bottom:1px solid;border-right:1px solid;height:45px;}.rustdoc.source>.sidebar>.sidebar-menu{display:none;}.sidebar-elems{position:fixed;z-index:1;left:0;top:45px;bottom:0;overflow-y:auto;border-right:1px solid;display:none;}.sidebar>.block.version{border-bottom:none;margin-top:12px;}nav.sub{width:calc(100% - 32px);float:right;}.content{margin-left:0px;}#main{margin-top:45px;padding:0;}.content .in-band{width:100%;}.content h4>.out-of-band{position:inherit;}.toggle-wrapper>.collapse-toggle{left:0px;}.toggle-wrapper{height:1.5em;}#search{margin-left:0;}.content .impl-items .method,.content .impl-items>.type,.impl-items>.associatedconstant{display:flex;}.anchor{display:none !important;}h1.fqn{overflow:initial;}.theme-picker{left:10px;top:54px;z-index:1;}h4>.notable-traits{position:absolute;left:-22px;top:24px;}#titles>button>div.count{float:left;width:100%;}#titles{height:50px;}.sidebar.mobile{position:fixed;width:100%;margin-left:0;background-color:rgba(0,0,0,0);height:100%;}.sidebar{width:calc(100% + 30px);}.show-it{display:block;width:246px;}.show-it>.block.items{margin:8px 0;}.show-it>.block.items>ul{margin:0;}.show-it>.block.items>ul>li{text-align:center;margin:2px 0;}.show-it>.block.items>ul>li>a{font-size:21px;}#sidebar-filler{position:fixed;left:45px;width:calc(100% - 45px);top:0;height:45px;z-index:-1;border-bottom:1px solid;}.collapse-toggle{left:-20px;}.impl>.collapse-toggle{left:-10px;}#all-types{margin:10px;}#sidebar-toggle{top:100px;width:30px;font-size:1.5rem;text-align:center;padding:0;}#source-sidebar{z-index:11;}#main>.line-numbers{margin-top:0;}.notable-traits .notable-traits-tooltiptext{left:0;top:100%;}.help-button{display:none;}.search-container>div{width:calc(100% - 32px);}}@media print{nav.sub,.content .out-of-band,.collapse-toggle{display:none;}}@media (max-width:416px){#titles,#titles>button{height:73px;}#main{margin-top:100px;}#main>table:not(.table-display) td{word-break:break-word;width:50%;}.search-container>div{display:block;width:calc(100% - 37px);}#crate-search{width:100%;border-radius:4px;border:0;}#crate-search+.search-input{width:calc(100% + 71px);margin-left:-36px;}#theme-picker,#settings-menu{padding:5px;width:31px;height:31px;}#theme-picker{margin-top:-2px;}#settings-menu{top:7px;}}h3.notable{margin:0;margin-bottom:13px;font-size:19px;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px;border-radius:3px;box-shadow:inset 0 -1px 0;cursor:default;}.hidden-by-impl-hider,.hidden-by-usual-hider{display:none !important;}#implementations-list>h3>span.in-band{width:100%;}.table-display{width:100%;border:0;border-collapse:collapse;border-spacing:0;font-size:16px;}.table-display tr td:first-child{padding-right:0;}.table-display tr td:last-child{float:right;}.table-display .out-of-band{position:relative;font-size:19px;display:block;}#implementors-list>.impl-items .table-display .out-of-band{font-size:17px;}.table-display td:hover .anchor{display:block;top:2px;left:-5px;}#main>ul{padding-left:10px;}#main>ul>li{list-style:none;}.non-exhaustive{margin-bottom:1em;}div.children{padding-left:27px;display:none;}div.name{cursor:pointer;position:relative;margin-left:16px;}div.files>a{display:block;padding:0 3px;}div.files>a:hover,div.name:hover{background-color:#a14b4b;}div.name.expand+.children{display:block;}div.name::before{content:"\25B6";padding-left:4px;font-size:0.7em;position:absolute;left:-16px;top:4px;}div.name.expand::before{transform:rotate(90deg);left:-15px;top:2px;}.type-decl>pre>.toggle-wrapper.toggle-attributes.top-attr{margin-left:0 !important;}.type-decl>pre>.docblock.attributes.top-attr{margin-left:1.8em !important;}.type-decl>pre>.toggle-attributes{margin-left:2.2em;}.type-decl>pre>.docblock.attributes{margin-left:4em;} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/search-index.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/search-index.js deleted file mode 100644 index 328e2f87cd..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/search-index.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchIndex = JSON.parse('{\ -"bdk":{"doc":"A modern, lightweight, descriptor-based wallet library …","i":[[0,"blockchain","bdk","Blockchain backends",null,null],[0,"any","bdk::blockchain","Runtime-checked blockchain types",null,null],[4,"AnyBlockchain","bdk::blockchain::any","Type that can contain any of the [Blockchain] types …",null,null],[13,"Electrum","","Electrum client",0,null],[13,"Esplora","","Esplora client",0,null],[13,"CompactFilters","","Compact filters client",0,null],[4,"AnyBlockchainConfig","","Type that can contain any of the blockchain …",null,null],[13,"Electrum","","Electrum client",1,null],[13,"Esplora","","Esplora client",1,null],[13,"CompactFilters","","Compact filters client",1,null],[0,"electrum","bdk::blockchain","Electrum",null,null],[3,"ElectrumBlockchain","bdk::blockchain::electrum","Wrapper over an Electrum Client that implements the …",null,null],[3,"ElectrumBlockchainConfig","","Configuration for an [ElectrumBlockchain]",null,null],[12,"url","","URL of the Electrum server (such as ElectrumX, Esplora, …",2,null],[12,"socks5","","URL of the socks5 proxy server or a Tor service",2,null],[12,"retry","","Request retry count",2,null],[12,"timeout","","Request timeout (seconds)",2,null],[0,"esplora","bdk::blockchain","Esplora",null,null],[3,"EsploraBlockchain","bdk::blockchain::esplora","Structure that implements the logic to sync with Esplora",null,null],[11,"new","","Create a new instance of the client from a base URL",3,[[["option",4]]]],[3,"EsploraBlockchainConfig","","Configuration for an [EsploraBlockchain]",null,null],[12,"base_url","","Base URL of the esplora service",4,null],[12,"concurrency","","Number of parallel requests sent to the esplora service …",4,null],[4,"EsploraError","","Errors that can happen during a sync with […",null,null],[13,"Reqwest","","Error with the HTTP call",5,null],[13,"Parsing","","Invalid number returned",5,null],[13,"BitcoinEncoding","","Invalid Bitcoin data returned",5,null],[13,"Hex","","Invalid Hex data returned",5,null],[13,"TransactionNotFound","","Transaction not found",5,null],[13,"HeaderHeightNotFound","","Header height not found",5,null],[13,"HeaderHashNotFound","","Header hash not found",5,null],[0,"compact_filters","bdk::blockchain","Compact Filters",null,null],[3,"Mempool","bdk::blockchain::compact_filters","Container for unconfirmed, but valid Bitcoin transactions",null,null],[3,"Peer","","A Bitcoin peer",null,null],[3,"CompactFiltersBlockchain","","Structure implementing the required blockchain traits",null,null],[11,"new","","Construct a new instance given a list of peers, a path to …",6,[[["peer",3],["asref",8],["option",4],["vec",3],["path",3]],[["compactfilterserror",4],["result",4]]]],[3,"BitcoinPeerConfig","","Data to connect to a Bitcoin P2P peer",null,null],[12,"address","","Peer address such as 127.0.0.1:18333",7,null],[12,"socks5","","Optional socks5 proxy",7,null],[12,"socks5_credentials","","Optional socks5 proxy credentials",7,null],[3,"CompactFiltersBlockchainConfig","","Configuration for a [CompactFiltersBlockchain]",null,null],[12,"peers","","List of peers to try to connect to for asking headers and …",8,null],[12,"network","","Network used",8,null],[12,"storage_dir","","Storage dir to save partially downloaded headers and full …",8,null],[12,"skip_blocks","","Optionally skip initial skip_blocks blocks (default: 0)",8,null],[4,"CompactFiltersError","","An error that can occur during sync with a […",null,null],[13,"InvalidResponse","","A peer sent an invalid or unexpected response",9,null],[13,"InvalidHeaders","","The headers returned are invalid",9,null],[13,"InvalidFilterHeader","","The compact filter headers returned are invalid",9,null],[13,"InvalidFilter","","The compact filter returned is invalid",9,null],[13,"MissingBlock","","The peer is missing a block in the valid chain",9,null],[13,"DataCorruption","","The data stored in the block filters storage are corrupted",9,null],[13,"NotConnected","","A peer is not connected",9,null],[13,"Timeout","","A peer took too long to reply to one of our messages",9,null],[13,"NoPeers","","No peers have been specified",9,null],[13,"DB","","Internal database error",9,null],[13,"IO","","Internal I/O error",9,null],[13,"BIP158","","Invalid BIP158 filter",9,null],[13,"Time","","Internal system time error",9,null],[13,"Global","","Wrapper for [crate::error::Error]",9,null],[4,"Capability","bdk::blockchain","Capabilities that can be supported by a [Blockchain] …",null,null],[13,"FullHistory","","Can recover the full history of a wallet and not only the …",10,null],[13,"GetAnyTx","","Can fetch any historical transaction given its txid",10,null],[13,"AccurateFees","","Can compute accurate fees for the transactions found …",10,null],[8,"BlockchainMarker","","Marker trait for a blockchain backend",null,null],[3,"OfflineBlockchain","","Type that only implements [BlockchainMarker] and is …",null,null],[8,"Blockchain","","Trait that defines the actions that must be supported by …",null,null],[10,"get_capabilities","","Return the set of [Capability] supported by this backend",11,[[],[["hashset",3],["capability",4]]]],[10,"setup","","Setup the backend and populate the internal database for …",11,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"sync","","Populate the internal database with transactions and UTXOs",11,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[10,"get_tx","","Fetch a transaction from the blockchain given its txid",11,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[10,"broadcast","","Broadcast a transaction",11,[[["transaction",3]],[["error",4],["result",4]]]],[10,"get_height","","Return the current height",11,[[],[["result",4],["error",4]]]],[10,"estimate_fee","","Estimate the fee rate required to confirm a transaction …",11,[[],[["feerate",3],["error",4],["result",4]]]],[8,"ConfigurableBlockchain","","Trait for [Blockchain] types that can be created given a …",null,null],[16,"Config","","Type that contains the configuration",12,null],[10,"from_config","","Create a new instance given a configuration",12,[[],[["result",4],["error",4]]]],[6,"ProgressData","","Data sent with a progress update over a [channel]",null,null],[8,"Progress","","Trait for types that can receive and process progress …",null,null],[10,"update","","Send a new progress update",13,[[["string",3],["option",4]],[["error",4],["result",4]]]],[5,"progress","","Shortcut to create a [channel] (pair of [Sender] and […",null,[[]]],[3,"NoopProgress","","Type that implements [Progress] and drops every update …",null,null],[5,"noop_progress","","Create a new instance of [NoopProgress]",null,[[],["noopprogress",3]]],[3,"LogProgress","","Type that implements [Progress] and logs at level INFO …",null,null],[5,"log_progress","","Create a nwe instance of [LogProgress]",null,[[],["logprogress",3]]],[0,"database","bdk","Database types",null,null],[0,"any","bdk::database","Runtime-checked database types",null,null],[4,"AnyDatabase","bdk::database::any","Type that can contain any of the [Database] types defined …",null,null],[13,"Memory","","In-memory ephemeral database",14,null],[13,"Sled","","Simple key-value embedded database based on [sled]",14,null],[4,"AnyBatch","","Type that contains any of the [BatchDatabase::Batch] …",null,null],[13,"Memory","","In-memory ephemeral database",15,null],[13,"Sled","","Simple key-value embedded database based on [sled]",15,null],[3,"SledDbConfiguration","","Configuration type for a [sled::Tree] database",null,null],[12,"path","","Main directory of the db",16,null],[12,"tree_name","","Name of the database tree, a separated namespace for the …",16,null],[4,"AnyDatabaseConfig","","Type that can contain any of the database configurations …",null,null],[13,"Memory","","Memory database has no config",17,null],[13,"Sled","","Simple key-value embedded database based on [sled]",17,null],[0,"memory","bdk::database","In-memory ephemeral database",null,null],[3,"MemoryDatabase","bdk::database::memory","In-memory ephemeral database",null,null],[11,"new","","Create a new empty database",18,[[]]],[8,"BatchOperations","bdk::database","Trait for operations that can be batched",null,null],[10,"set_script_pubkey","","Store a script_pubkey along with its keychain and child …",19,[[["script",3],["keychainkind",4]],[["error",4],["result",4]]]],[10,"set_utxo","","Store a [UTXO]",19,[[["utxo",3]],[["error",4],["result",4]]]],[10,"set_raw_tx","","Store a raw transaction",19,[[["transaction",3]],[["error",4],["result",4]]]],[10,"set_tx","","Store the metadata of a transaction",19,[[["transactiondetails",3]],[["error",4],["result",4]]]],[10,"set_last_index","","Store the last derivation index for a given keychain.",19,[[["keychainkind",4]],[["error",4],["result",4]]]],[10,"del_script_pubkey_from_path","","Delete a script_pubkey given the keychain and its child …",19,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[10,"del_path_from_script_pubkey","","Delete the data related to a specific script_pubkey, …",19,[[["script",3]],[["error",4],["result",4],["option",4]]]],[10,"del_utxo","","Delete a [UTXO] given its [OutPoint]",19,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[10,"del_raw_tx","","Delete a raw transaction given its [Txid]",19,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[10,"del_tx","","Delete the metadata of a transaction and optionally the …",19,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[10,"del_last_index","","Delete the last derivation index for a keychain.",19,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[8,"Database","","Trait for reading data from a database",null,null],[10,"check_descriptor_checksum","","Read and checks the descriptor checksum for a given …",20,[[["asref",8],["keychainkind",4]],[["error",4],["result",4]]]],[10,"iter_script_pubkeys","","Return the list of script_pubkeys",20,[[["option",4],["keychainkind",4]],[["vec",3],["result",4],["error",4]]]],[10,"iter_utxos","","Return the list of [UTXO]s",20,[[],[["result",4],["vec",3],["error",4]]]],[10,"iter_raw_txs","","Return the list of raw transactions",20,[[],[["vec",3],["result",4],["error",4]]]],[10,"iter_txs","","Return the list of transactions metadata",20,[[],[["error",4],["result",4],["vec",3]]]],[10,"get_script_pubkey_from_path","","Fetch a script_pubkey given the child number of a …",20,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[10,"get_path_from_script_pubkey","","Fetch the keychain and child number of a given …",20,[[["script",3]],[["error",4],["result",4],["option",4]]]],[10,"get_utxo","","Fetch a [UTXO] given its [OutPoint]",20,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[10,"get_raw_tx","","Fetch a raw transaction given its [Txid]",20,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[10,"get_tx","","Fetch the transaction metadata and optionally also the …",20,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[10,"get_last_index","","Return the last defivation index for a keychain.",20,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[10,"increment_last_index","","Increment the last derivation index for a keychain and …",20,[[["keychainkind",4]],[["result",4],["error",4]]]],[8,"BatchDatabase","","Trait for a database that supports batch operations",null,null],[16,"Batch","","Container for the operations",21,null],[10,"begin_batch","","Create a new batch container",21,[[]]],[10,"commit_batch","","Consume and apply a batch of operations",21,[[],[["error",4],["result",4]]]],[8,"ConfigurableDatabase","","Trait for [Database] types that can be created given a …",null,null],[16,"Config","","Type that contains the configuration",22,null],[10,"from_config","","Create a new instance given a configuration",22,[[],[["result",4],["error",4]]]],[0,"descriptor","bdk","Descriptors",null,null],[6,"KeyMap","bdk::descriptor","Alias type for a map of public key to secret key",null,null],[4,"Descriptor","","Script descriptor",null,null],[13,"Bare","","A raw scriptpubkey (including pay-to-pubkey) under Legacy …",23,null],[13,"Pk","","Pay-to-Pubkey",23,null],[13,"Pkh","","Pay-to-PubKey-Hash",23,null],[13,"Wpkh","","Pay-to-Witness-PubKey-Hash",23,null],[13,"ShWpkh","","Pay-to-Witness-PubKey-Hash inside P2SH",23,null],[13,"Sh","","Pay-to-ScriptHash with Legacy context",23,null],[13,"Wsh","","Pay-to-Witness-ScriptHash with Segwitv0 context",23,null],[13,"ShWsh","","P2SH-P2WSH with Segwitv0 context",23,null],[13,"ShSortedMulti","","Sortedmulti under P2SH",23,null],[13,"WshSortedMulti","","Sortedmulti under P2WSH",23,null],[13,"ShWshSortedMulti","","Sortedmulti under P2SH-P2WSH",23,null],[4,"Legacy","","Legacy ScriptContext To be used as P2SH scripts For …",null,null],[3,"Miniscript","","Top-level script AST type",null,null],[12,"node","","A node in the Abstract Syntax Tree(",24,null],[12,"ty","","The correctness and malleability type information for the …",24,null],[12,"ext","","Additional information helpful for extra analysis.",24,null],[8,"MiniscriptKey","","Public key trait which can be converted to Hash type",null,null],[11,"is_uncompressed","","Check if the publicKey is uncompressed. The default …",25,[[]]],[16,"Hash","","The associated Hash type with the publicKey",25,null],[10,"to_pubkeyhash","","Converts an object to PublicHash",25,[[]]],[8,"ScriptContext","","The ScriptContext for Miniscript. Additional type …",null,null],[10,"check_terminal_non_malleable","","Depending on ScriptContext, fragments can be malleable. …",26,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_witness","","Check whether the given satisfaction is valid under the …",26,[[],[["scriptcontexterror",4],["result",4]]]],[10,"max_satisfaction_size","","Depending on script context, the size of a satifaction …",26,[[["miniscript",3]],["option",4]]],[11,"check_global_consensus_validity","","Depending on script Context, some of the Terminals might …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_global_policy_validity","","Depending on script Context, some of the script resource …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_consensus_validity","","Consensus rules at the Miniscript satisfaction time. It …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_policy_validity","","Policy rules at the Miniscript satisfaction time. It is …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_global_validity","","Check the consensus + policy(if not disabled) rules that …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_validity","","Check the consensus + policy(if not disabled) rules …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"top_level_type_check","","Check whether the top-level is type B",26,[[["miniscript",3]],[["error",4],["result",4]]]],[11,"other_top_level_checks","","Other top level checks that are context specific",26,[[["miniscript",3]],[["error",4],["result",4]]]],[11,"top_level_checks","","Check top level consensus rules.",26,[[["miniscript",3]],[["error",4],["result",4]]]],[4,"Segwitv0","","Segwitv0 ScriptContext",null,null],[4,"Terminal","","All AST elements",null,null],[13,"True","","1",27,null],[13,"False","","0",27,null],[13,"PkK","","",27,null],[13,"PkH","","DUP HASH160 EQUALVERIFY",27,null],[13,"After","","n CHECKLOCKTIMEVERIFY",27,null],[13,"Older","","n CHECKSEQUENCEVERIFY",27,null],[13,"Sha256","","SIZE 32 EQUALVERIFY SHA256 EQUAL",27,null],[13,"Hash256","","SIZE 32 EQUALVERIFY HASH256 EQUAL",27,null],[13,"Ripemd160","","SIZE 32 EQUALVERIFY RIPEMD160 EQUAL",27,null],[13,"Hash160","","SIZE 32 EQUALVERIFY HASH160 EQUAL",27,null],[13,"Alt","","TOALTSTACK [E] FROMALTSTACK",27,null],[13,"Swap","","SWAP [E1]",27,null],[13,"Check","","[Kt]/[Ke] CHECKSIG",27,null],[13,"DupIf","","DUP IF [V] ENDIF",27,null],[13,"Verify","","[T] VERIFY",27,null],[13,"NonZero","","SIZE 0NOTEQUAL IF [Fn] ENDIF",27,null],[13,"ZeroNotEqual","","[X] 0NOTEQUAL",27,null],[13,"AndV","","[V] [T]/[V]/[F]/[Kt]",27,null],[13,"AndB","","[E] [W] BOOLAND",27,null],[13,"AndOr","","[various] NOTIF [various] ELSE [various] ENDIF",27,null],[13,"OrB","","[E] [W] BOOLOR",27,null],[13,"OrD","","[E] IFDUP NOTIF [T]/[E] ENDIF",27,null],[13,"OrC","","[E] NOTIF [V] ENDIF",27,null],[13,"OrI","","IF [various] ELSE [various] ENDIF",27,null],[13,"Thresh","","[E] ([W] ADD)* k EQUAL",27,null],[13,"Multi","","k ()* n CHECKMULTISIG",27,null],[8,"ToPublicKey","","Trait describing public key types which can be converted …",null,null],[10,"to_public_key","","Converts an object to a public key C represents …",28,[[],["publickey",3]]],[11,"serialized_len","","Computes the size of a public key when serialized in a …",28,[[]]],[10,"hash_to_hash160","","Converts a hashed version of the public key to a hash160 …",28,[[],["hash",3]]],[0,"checksum","","Descriptor checksum",null,null],[5,"get_checksum","bdk::descriptor::checksum","Compute the checksum of a descriptor",null,[[],[["result",4],["string",3],["error",4]]]],[0,"error","bdk::descriptor","Descriptor errors",null,null],[4,"Error","bdk::descriptor::error","Errors related to the parsing and usage of descriptors",null,null],[13,"InvalidHDKeyPath","","Invalid HD Key path, such as having a wildcard but a …",29,null],[13,"Key","","Error thrown while working with keys",29,null],[13,"Policy","","Error while extracting and manipulating policies",29,null],[13,"InvalidDescriptorCharacter","","Invalid character found in the descriptor checksum",29,null],[13,"BIP32","","BIP32 error",29,null],[13,"Base58","","Error during base58 decoding",29,null],[13,"PK","","Key-related error",29,null],[13,"Miniscript","","Miniscript error",29,null],[13,"Hex","","Hex decoding error",29,null],[0,"policy","bdk::descriptor","Descriptor policy",null,null],[3,"PKOrF","bdk::descriptor::policy","Raw public key or extended key fingerprint",null,null],[4,"SatisfiableItem","","An item that needs to be satisfied",null,null],[13,"Signature","","Signature for a raw public key",30,null],[13,"SignatureKey","","Signature for an extended key fingerprint",30,null],[13,"SHA256Preimage","","SHA256 preimage hash",30,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","The digest value",31,null],[13,"HASH256Preimage","bdk::descriptor::policy","Double SHA256 preimage hash",30,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","The digest value",32,null],[13,"RIPEMD160Preimage","bdk::descriptor::policy","RIPEMD160 preimage hash",30,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","The digest value",33,null],[13,"HASH160Preimage","bdk::descriptor::policy","SHA256 then RIPEMD160 preimage hash",30,null],[12,"hash","bdk::descriptor::policy::SatisfiableItem","The digest value",34,null],[13,"AbsoluteTimelock","bdk::descriptor::policy","Absolute timeclock timestamp",30,null],[12,"value","bdk::descriptor::policy::SatisfiableItem","The timestamp value",35,null],[13,"RelativeTimelock","bdk::descriptor::policy","Relative timelock locktime",30,null],[12,"value","bdk::descriptor::policy::SatisfiableItem","The locktime value",36,null],[13,"Multisig","bdk::descriptor::policy","Multi-signature public keys with threshold count",30,null],[12,"keys","bdk::descriptor::policy::SatisfiableItem","The raw public key or extended key fingerprint",37,null],[12,"threshold","","The required threshold count",37,null],[13,"Thresh","bdk::descriptor::policy","Threshold items with threshold count",30,null],[12,"items","bdk::descriptor::policy::SatisfiableItem","The policy items",38,null],[12,"threshold","","The required threshold count",38,null],[11,"is_leaf","bdk::descriptor::policy","Returns whether the [SatisfiableItem] is a leaf item",30,[[]]],[11,"id","","Returns a unique id for the [SatisfiableItem]",30,[[],["string",3]]],[6,"ConditionMap","","Type for a map of sets of [Condition] items keyed by each …",null,null],[6,"FoldedConditionMap","","Type for a map of folded sets of [Condition] items keyed …",null,null],[4,"Satisfaction","","Represent if and how much a policy item is satisfied by …",null,null],[13,"Partial","","Only a partial satisfaction of some kind of threshold …",39,null],[12,"n","bdk::descriptor::policy::Satisfaction","Total number of items",40,null],[12,"m","","Threshold",40,null],[12,"items","","The items that can be satisfied by the descriptor",40,null],[12,"sorted","","Whether the items are sorted in lexicographic order (used …",40,null],[12,"conditions","","Extra conditions that also need to be satisfied",40,null],[13,"PartialComplete","bdk::descriptor::policy","Can reach the threshold of some kind of threshold policy",39,null],[12,"n","bdk::descriptor::policy::Satisfaction","Total number of items",41,null],[12,"m","","Threshold",41,null],[12,"items","","The items that can be satisfied by the descriptor",41,null],[12,"sorted","","Whether the items are sorted in lexicographic order (used …",41,null],[12,"conditions","","Extra conditions that also need to be satisfied",41,null],[13,"Complete","bdk::descriptor::policy","Can satisfy the policy item",39,null],[12,"condition","bdk::descriptor::policy::Satisfaction","Extra conditions that also need to be satisfied",42,null],[13,"None","bdk::descriptor::policy","Cannot satisfy or contribute to the policy item",39,null],[11,"is_leaf","","Returns whether the [Satisfaction] is a leaf item",39,[[]]],[3,"Policy","","Descriptor spending policy",null,null],[12,"id","","Identifier for this policy node",43,null],[12,"item","","Type of this policy node",43,null],[12,"satisfaction","","How a much given PSBT already satisfies this polcy node …",43,null],[12,"contribution","","How the wallet\'s descriptor can satisfy this policy node",43,null],[3,"Condition","","An extra condition that must be satisfied but that is out …",null,null],[12,"csv","","Optional CheckSequenceVerify condition",44,null],[12,"timelock","","Optional timelock condition",44,null],[11,"is_null","","Returns true if there are no extra conditions to verify",44,[[]]],[4,"PolicyError","","Errors that can happen while extracting and manipulating …",null,null],[13,"NotEnoughItemsSelected","","Not enough items are selected to satisfy a […",45,null],[13,"TooManyItemsSelected","","Too many items are selected to satisfy a […",45,null],[13,"IndexOutOfRange","","Index out of range for an item to satisfy a […",45,null],[13,"AddOnLeaf","","Can not add to an item that is [Satisfaction::None] or […",45,null],[13,"AddOnPartialComplete","","Can not add to an item that is […",45,null],[13,"MixedTimelockUnits","","Can not merge CSV or timelock values unless both are less …",45,null],[13,"IncompatibleConditions","","Incompatible conditions (not currently used)",45,null],[11,"requires_path","","Return whether or not a specific path in the policy tree …",43,[[]]],[11,"get_condition","","Return the conditions that are set by the spending policy …",43,[[["btreemap",3]],[["condition",3],["result",4],["policyerror",4]]]],[0,"template","bdk::descriptor","Descriptor templates",null,null],[6,"DescriptorTemplateOut","bdk::descriptor::template","Type alias for the return type of [DescriptorTemplate], …",null,null],[8,"DescriptorTemplate","","Trait for descriptor templates that can be built into a …",null,null],[10,"build","","Build the complete descriptor",46,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[3,"P2PKH","","P2PKH template. Expands to a descriptor pkh(key)",null,null],[12,"0","","",47,null],[3,"P2WPKH_P2SH","","P2WPKH-P2SH template. Expands to a descriptor …",null,null],[12,"0","","",48,null],[3,"P2WPKH","","P2WPKH template. Expands to a descriptor wpkh(key)",null,null],[12,"0","","",49,null],[3,"BIP44","","BIP44 template. Expands to pkh(key/44\'/0\'/0\'/{0,1}/*)",null,null],[12,"0","","",50,null],[12,"1","","",50,null],[3,"BIP44Public","","BIP44 public template. Expands to pkh(key/{0,1}/*)",null,null],[12,"0","","",51,null],[12,"1","","",51,null],[12,"2","","",51,null],[3,"BIP49","","BIP49 template. Expands to sh(wpkh(key/49\'/0\'/0\'/{0,1}/*))",null,null],[12,"0","","",52,null],[12,"1","","",52,null],[3,"BIP49Public","","BIP49 public template. Expands to sh(wpkh(key/{0,1}/*))",null,null],[12,"0","","",53,null],[12,"1","","",53,null],[12,"2","","",53,null],[3,"BIP84","","BIP84 template. Expands to wpkh(key/84\'/0\'/0\'/{0,1}/*)",null,null],[12,"0","","",54,null],[12,"1","","",54,null],[3,"BIP84Public","","BIP84 public template. Expands to wpkh(key/{0,1}/*)",null,null],[12,"0","","",55,null],[12,"1","","",55,null],[12,"2","","",55,null],[6,"ExtendedDescriptor","bdk::descriptor","Alias for a [Descriptor] that can contain extended keys …",null,null],[6,"HDKeyPaths","","Alias for the type of maps that represent derivation …",null,null],[8,"ToWalletDescriptor","","Trait for types which can be converted into an […",null,null],[10,"to_wallet_descriptor","","Convert to wallet descriptor",56,[[["network",4]],[["result",4],["keyerror",4]]]],[8,"ExtractPolicy","","Trait implemented on [Descriptor]s to add a method to …",null,null],[10,"extract_policy","","Extract the spending [policy]",57,[[["signerscontainer",3],["secp256k1",3]],[["result",4],["error",4],["option",4]]]],[0,"keys","bdk","Key formats",null,null],[4,"DescriptorPublicKey","bdk::keys","The MiniscriptKey corresponding to Descriptors. This can …",null,null],[13,"SinglePub","","Single Public Key",58,null],[13,"XPub","","Xpub",58,null],[4,"DescriptorSecretKey","","A Secret Key that can be either a single key or an Xprv",null,null],[13,"SinglePriv","","Single Secret Key",59,null],[13,"XPrv","","Xprv",59,null],[3,"DescriptorSinglePriv","","A Single Descriptor Secret Key with optional origin …",null,null],[12,"origin","","Origin information",60,null],[12,"key","","The key",60,null],[3,"DescriptorSinglePub","","A Single Descriptor Key with optional origin information",null,null],[12,"origin","","Origin information",61,null],[12,"key","","The key",61,null],[3,"SortedMultiVec","","Contents of a \\\"sortedmulti\\\" descriptor",null,null],[12,"k","","signatures required",62,null],[12,"pks","","public keys inside sorted Multi",62,null],[8,"ScriptContext","","The ScriptContext for Miniscript. Additional type …",null,null],[10,"check_terminal_non_malleable","","Depending on ScriptContext, fragments can be malleable. …",26,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_witness","","Check whether the given satisfaction is valid under the …",26,[[],[["scriptcontexterror",4],["result",4]]]],[10,"max_satisfaction_size","","Depending on script context, the size of a satifaction …",26,[[["miniscript",3]],["option",4]]],[11,"check_global_consensus_validity","","Depending on script Context, some of the Terminals might …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_global_policy_validity","","Depending on script Context, some of the script resource …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_consensus_validity","","Consensus rules at the Miniscript satisfaction time. It …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_policy_validity","","Policy rules at the Miniscript satisfaction time. It is …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_global_validity","","Check the consensus + policy(if not disabled) rules that …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_validity","","Check the consensus + policy(if not disabled) rules …",26,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"top_level_type_check","","Check whether the top-level is type B",26,[[["miniscript",3]],[["error",4],["result",4]]]],[11,"other_top_level_checks","","Other top level checks that are context specific",26,[[["miniscript",3]],[["error",4],["result",4]]]],[11,"top_level_checks","","Check top level consensus rules.",26,[[["miniscript",3]],[["error",4],["result",4]]]],[0,"bip39","","BIP-0039",null,null],[6,"MnemonicWithPassphrase","bdk::keys::bip39","Type for a BIP39 mnemonic with an optional passphrase",null,null],[6,"ValidNetworks","bdk::keys","Set of valid networks for a key",null,null],[5,"any_network","","Create a set containing mainnet, testnet and regtest",null,[[],["validnetworks",6]]],[5,"mainnet_network","","Create a set only containing mainnet",null,[[],["validnetworks",6]]],[5,"test_networks","","Create a set containing testnet and regtest",null,[[],["validnetworks",6]]],[5,"merge_networks","","Compute the intersection of two sets",null,[[["validnetworks",6]],["validnetworks",6]]],[4,"DescriptorKey","","Container for public or secret keys",null,null],[11,"from_public","","Create an instance given a public key and a set of valid …",63,[[["descriptorpublickey",4],["validnetworks",6]]]],[11,"from_secret","","Create an instance given a secret key and a set of valid …",63,[[["descriptorsecretkey",4],["validnetworks",6]]]],[11,"override_valid_networks","","Override the computed set of valid networks",63,[[["validnetworks",6]]]],[4,"ScriptContextEnum","","Enum representation of the known valid [ScriptContext]s",null,null],[13,"Legacy","","Legacy scripts",64,null],[13,"Segwitv0","","Segwitv0 scripts",64,null],[11,"is_legacy","","Returns whether the script context is […",64,[[]]],[11,"is_segwit_v0","","Returns whether the script context is […",64,[[]]],[8,"ExtScriptContext","","Trait that adds extra useful methods to [ScriptContext]s",null,null],[10,"as_enum","","Returns the [ScriptContext] as a [ScriptContextEnum]",65,[[],["scriptcontextenum",4]]],[11,"is_legacy","","Returns whether the script context is Legacy",65,[[]]],[11,"is_segwit_v0","","Returns whether the script context is Segwitv0",65,[[]]],[8,"ToDescriptorKey","","Trait for objects that can be turned into a public or …",null,null],[10,"to_descriptor_key","","Turn the key into a [DescriptorKey] within the requested […",66,[[],[["result",4],["descriptorkey",4],["keyerror",4]]]],[8,"DerivableKey","","Trait for keys that can be derived.",null,null],[10,"add_metadata","","Add a extra metadata, consume self and turn it into a […",67,[[["keysource",6],["derivationpath",3],["option",4]],[["result",4],["descriptorkey",4],["keyerror",4]]]],[3,"GeneratedKey","","Output of a [GeneratableKey] key generation",null,null],[11,"into_key","","Consumes self and returns the key",68,[[]]],[8,"GeneratableKey","","Trait for keys that can be generated",null,null],[16,"Entropy","","Type specifying the amount of entropy required e.g. [u8;32…",69,null],[16,"Options","","Extra options required by the generate_with_entropy",69,null],[16,"Error","","Returned error in case of failure",69,null],[10,"generate_with_entropy","","Generate a key given the extra options and the entropy",69,[[],[["result",4],["generatedkey",3]]]],[11,"generate","","Generate a key given the options with a random entropy",69,[[],[["result",4],["generatedkey",3]]]],[8,"GeneratableDefaultOptions","","Trait that allows generating a key with the default …",null,null],[11,"generate_with_entropy_default","","Generate a key with the default options and a given …",70,[[],[["result",4],["generatedkey",3]]]],[11,"generate_default","","Generate a key with the default options and a random …",70,[[],[["result",4],["generatedkey",3]]]],[3,"PrivateKeyGenerateOptions","","Options for generating a [PrivateKey]",null,null],[12,"compressed","","Whether the generated key should be \\\"compressed\\\" or not",71,null],[4,"KeyError","","Errors thrown while working with keys",null,null],[13,"InvalidScriptContext","","The key cannot exist in the given script context",72,null],[13,"InvalidNetwork","","The key is not valid for the given network",72,null],[13,"InvalidChecksum","","The key has an invalid checksum",72,null],[13,"Message","","Custom error message",72,null],[13,"BIP32","","BIP32 error",72,null],[13,"Miniscript","","Miniscript error",72,null],[0,"wallet","bdk","Wallet",null,null],[0,"address_validator","bdk::wallet","Address validation callbacks",null,null],[4,"AddressValidatorError","bdk::wallet::address_validator","Errors that can be returned to fail the validation of an …",null,null],[13,"UserRejected","","User rejected the address",73,null],[13,"ConnectionError","","Network connection error",73,null],[13,"TimeoutError","","Network request timeout error",73,null],[13,"InvalidScript","","Invalid script",73,null],[13,"Message","","A custom error message",73,null],[8,"AddressValidator","","Trait to build address validators",null,null],[10,"validate","","Validate or inspect an address",74,[[["script",3],["hdkeypaths",6],["keychainkind",4]],[["addressvalidatorerror",4],["result",4]]]],[0,"coin_selection","bdk::wallet","Coin selection",null,null],[6,"DefaultCoinSelectionAlgorithm","bdk::wallet::coin_selection","Default coin selection algorithm used by TxBuilder if not …",null,null],[3,"CoinSelectionResult","","Result of a successful coin selection",null,null],[12,"selected","","List of outputs selected for use as inputs",75,null],[12,"selected_amount","","Sum of the selected inputs\' value",75,null],[12,"fee_amount","","Total fee amount in satoshi",75,null],[8,"CoinSelectionAlgorithm","","Trait for generalized coin selection algorithms",null,null],[10,"coin_select","","Perform the coin selection",76,[[["feerate",3],["vec",3]],[["result",4],["error",4],["coinselectionresult",3]]]],[3,"LargestFirstCoinSelection","","Simple and dumb coin selection",null,null],[3,"BranchAndBoundCoinSelection","","Branch and bound coin selection",null,null],[11,"new","","Create new instance with target size for change output",77,[[]]],[0,"export","bdk::wallet","Wallet export",null,null],[3,"WalletExport","bdk::wallet::export","Structure that contains the export of a wallet",null,null],[12,"blockheight","","Earliest block to rescan when looking for the wallet\'s …",78,null],[12,"label","","Arbitrary label for the wallet",78,null],[11,"export_wallet","","Export a wallet",78,[[["wallet",3]],["result",4]]],[11,"descriptor","","Return the external descriptor",78,[[],["string",3]]],[11,"change_descriptor","","Return the internal descriptor, if present",78,[[],[["string",3],["option",4]]]],[0,"signer","bdk::wallet","Generalized signers",null,null],[4,"SignerId","bdk::wallet::signer","Identifier of a signer in the SignersContainers. Used as …",null,null],[13,"PkHash","","Bitcoin HASH160 (RIPEMD160 after SHA256) hash of an ECDSA …",79,null],[13,"Fingerprint","","The fingerprint of a BIP32 extended key",79,null],[4,"SignerError","","Signing error",null,null],[13,"MissingKey","","The private key is missing for the required public key",80,null],[13,"InvalidKey","","The private key in use has the right fingerprint but …",80,null],[13,"UserCanceled","","The user canceled the operation",80,null],[13,"InputIndexOutOfRange","","Input index is out of range",80,null],[13,"MissingNonWitnessUtxo","","The non_witness_utxo field of the transaction is required …",80,null],[13,"InvalidNonWitnessUtxo","","The non_witness_utxo specified is invalid",80,null],[13,"MissingWitnessUtxo","","The witness_utxo field of the transaction is required to …",80,null],[13,"MissingWitnessScript","","The witness_script field of the transaction is requied to …",80,null],[13,"MissingHDKeypath","","The fingerprint and derivation path are missing from the …",80,null],[8,"Signer","","Trait for signers",null,null],[10,"sign","","Sign a PSBT",81,[[["secp256k1",3],["partiallysignedtransaction",3],["option",4]],[["signererror",4],["result",4]]]],[10,"sign_whole_tx","","Return whether or not the signer signs the whole …",81,[[]]],[11,"descriptor_secret_key","","Return the secret key for the signer",81,[[],[["option",4],["descriptorsecretkey",4]]]],[3,"SignerOrdering","","Defines the order in which signers are called",null,null],[12,"0","","",82,null],[3,"SignersContainer","","Container for multiple signers",null,null],[11,"as_key_map","","Create a map of public keys to secret keys",83,[[["secp256k1",3]],["keymap",6]]],[11,"new","","Default constructor",83,[[]]],[11,"add_external","","Adds an external signer to the container for the …",83,[[["signer",8],["arc",3],["signerordering",3],["signerid",4]],[["arc",3],["option",4]]]],[11,"remove","","Removes a signer from the container and returns it",83,[[["signerordering",3],["signerid",4]],[["arc",3],["option",4]]]],[11,"ids","","Returns the list of identifiers of all the signers in the …",83,[[],[["signerid",4],["vec",3]]]],[11,"signers","","Returns the list of signers in the container, sorted by …",83,[[],[["vec",3],["arc",3]]]],[11,"find","","Finds the signer with lowest ordering for a given id in …",83,[[["signerid",4]],[["option",4],["arc",3]]]],[0,"time","bdk::wallet","Cross-platform time",null,null],[5,"get_timestamp","bdk::wallet::time","Return the current timestamp in seconds",null,[[]]],[0,"tx_builder","bdk::wallet","Transaction builder",null,null],[8,"TxBuilderContext","bdk::wallet::tx_builder","Context in which the [TxBuilder] is valid",null,null],[3,"CreateTx","","Wallet::create_tx context",null,null],[3,"BumpFee","","Wallet::bump_fee context",null,null],[3,"TxBuilder","","A transaction builder",null,null],[11,"new","","Create an empty builder",84,[[]]],[11,"fee_rate","","Set a custom fee rate",84,[[["feerate",3]]]],[11,"fee_absolute","","Set an absolute fee",84,[[]]],[11,"policy_path","","Set the policy path to use while creating the transaction …",84,[[["string",3],["btreemap",3],["vec",3],["keychainkind",4]]]],[11,"utxos","","Replace the internal list of utxos that must be spent …",84,[[["vec",3],["outpoint",3]]]],[11,"add_utxo","","Add a utxo to the internal list of utxos that must be …",84,[[["outpoint",3]]]],[11,"manually_selected_only","","Only spend utxos added by add_utxo and utxos.",84,[[]]],[11,"unspendable","","Replace the internal list of unspendable utxos with a new …",84,[[["vec",3],["outpoint",3]]]],[11,"add_unspendable","","Add a utxo to the internal list of unspendable utxos",84,[[["outpoint",3]]]],[11,"sighash","","Sign with a specific sig hash",84,[[["sighashtype",4]]]],[11,"ordering","","Choose the ordering for inputs and outputs of the …",84,[[["txordering",4]]]],[11,"nlocktime","","Use a specific nLockTime while creating the transaction",84,[[]]],[11,"version","","Build a transaction with a specific version",84,[[]]],[11,"do_not_spend_change","","Do not spend change outputs",84,[[]]],[11,"only_spend_change","","Only spend change outputs",84,[[]]],[11,"change_policy","","Set a specific [ChangeSpendPolicy]. See […",84,[[["changespendpolicy",4]]]],[11,"force_non_witness_utxo","","Fill-in the psbt::Input::non_witness_utxo field even if …",84,[[]]],[11,"include_output_redeem_witness_script","","Fill-in the psbt::Output::redeem_script and …",84,[[]]],[11,"add_global_xpubs","","Fill-in the PSBT_GLOBAL_XPUB field with the extended keys …",84,[[]]],[11,"drain_wallet","","Spend all the available inputs. This respects filters …",84,[[]]],[11,"coin_selection","","Choose the coin selection algorithm",84,[[["coinselectionalgorithm",8]],[["coinselectionalgorithm",8],["txbuilder",3]]]],[11,"with_recipients","","Create a builder starting from a list of recipients",84,[[["vec",3]]]],[11,"set_recipients","","Replace the recipients already added with a new list",84,[[["vec",3]]]],[11,"add_recipient","","Add a recipient to the internal list",84,[[["script",3]]]],[11,"set_single_recipient","","Set a single recipient that will get all the selected …",84,[[["script",3]]]],[11,"enable_rbf","","Enable signaling RBF",84,[[]]],[11,"enable_rbf_with_sequence","","Enable signaling RBF with a specific nSequence value",84,[[]]],[11,"maintain_single_recipient","","Bump the fees of a transaction made with …",84,[[]]],[4,"TxOrdering","","Ordering of the transaction\'s inputs and outputs",null,null],[13,"Shuffle","","Randomized (default)",85,null],[13,"Untouched","","Unchanged",85,null],[13,"BIP69Lexicographic","","BIP69 / Lexicographic",85,null],[11,"sort_tx","","Sort transaction inputs and outputs by [TxOrdering] …",85,[[["transaction",3]]]],[4,"ChangeSpendPolicy","","Policy regarding the use of change outputs when creating …",null,null],[13,"ChangeAllowed","","Use both change and non-change outputs (default)",86,null],[13,"OnlyChange","","Only use change outputs (see [TxBuilder::only_spend_change…",86,null],[13,"ChangeForbidden","","Only use non-change outputs (see […",86,null],[8,"IsDust","bdk::wallet","Trait to check if a value is below the dust limit",null,null],[10,"is_dust","","Check whether or not a value is below dust limit",87,[[]]],[6,"OfflineWallet","","Type alias for a [Wallet] that uses [OfflineBlockchain]",null,null],[3,"Wallet","","A Bitcoin wallet",null,null],[11,"new_offline","","Create a new \\\"offline\\\" wallet",88,[[["option",4],["network",4],["towalletdescriptor",8]],[["result",4],["error",4]]]],[11,"get_new_address","","Return a newly generated address using the external …",88,[[],[["address",3],["result",4],["error",4]]]],[11,"is_mine","","Return whether or not a script is part of this wallet …",88,[[["script",3]],[["result",4],["error",4]]]],[11,"list_unspent","","Return the list of unspent outputs of this wallet",88,[[],[["result",4],["vec",3],["error",4]]]],[11,"list_transactions","","Return the list of transactions made and received by the …",88,[[],[["error",4],["result",4],["vec",3]]]],[11,"get_balance","","Return the balance, meaning the sum of this wallet\'s …",88,[[],[["error",4],["result",4]]]],[11,"add_signer","","Add an external signer",88,[[["keychainkind",4],["signer",8],["arc",3],["signerordering",3],["signerid",4]]]],[11,"add_address_validator","","Add an address validator",88,[[["arc",3],["addressvalidator",8]]]],[11,"create_tx","","Create a new transaction following the options specified …",88,[[["coinselectionalgorithm",8],["txbuilder",3],["createtx",3]],[["result",4],["error",4]]]],[11,"bump_fee","","Bump the fee of a transaction following the options …",88,[[["txid",3],["coinselectionalgorithm",8],["txbuilder",3],["bumpfee",3]],[["result",4],["error",4]]]],[11,"sign","","Sign a transaction with all the wallet\'s signers, in the …",88,[[["option",4],["psbt",3]],[["result",4],["error",4]]]],[11,"policies","","Return the spending policies for the wallet\'s descriptor",88,[[["keychainkind",4]],[["error",4],["result",4],["option",4]]]],[11,"public_descriptor","","Return the \\\"public\\\" version of the wallet\'s descriptor, …",88,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"finalize_psbt","","Try to finalize a PSBT",88,[[["option",4],["psbt",3]],[["result",4],["error",4]]]],[11,"secp_ctx","","Return the secp256k1 context used for all signing …",88,[[],["secp256k1",3]]],[11,"new","","Create a new \\\"online\\\" wallet",88,[[["option",4],["network",4],["towalletdescriptor",8]],[["result",4],["error",4]]]],[11,"sync","","Sync the internal database with the blockchain",88,[[["option",4],["progress",8]],[["error",4],["result",4]]]],[11,"client","","Return a reference to the internal blockchain client",88,[[],["option",4]]],[11,"network","","Get the Bitcoin network the wallet is using.",88,[[],["network",4]]],[11,"broadcast","","Broadcast a transaction to the network",88,[[["transaction",3]],[["error",4],["result",4],["txid",3]]]],[4,"Error","bdk","Errors that can be thrown by the Wallet",null,null],[13,"InvalidU32Bytes","","Wrong number of bytes found when trying to convert to u32",89,null],[13,"Generic","","Generic error",89,null],[13,"ScriptDoesntHaveAddressForm","","This error is thrown when trying to convert Bare and …",89,null],[13,"SingleRecipientMultipleOutputs","","Found multiple outputs when single_recipient option has …",89,null],[13,"SingleRecipientNoInputs","","single_recipient option is selected but neither …",89,null],[13,"NoRecipients","","Cannot build a tx without recipients",89,null],[13,"NoUtxosSelected","","manually_selected_only option is selected but no utxo has …",89,null],[13,"OutputBelowDustLimit","","Output created is under the dust limit, 546 satoshis",89,null],[13,"InsufficientFunds","","Wallet\'s UTXO set is not enough to cover recipient\'s …",89,null],[13,"BnBTotalTriesExceeded","","Branch and bound coin selection possible attempts with …",89,null],[13,"BnBNoExactMatch","","Branch and bound coin selection tries to avoid needing a …",89,null],[13,"UnknownUTXO","","Happens when trying to spend an UTXO that is not in the …",89,null],[13,"TransactionNotFound","","Thrown when a tx is not found in the internal database",89,null],[13,"TransactionConfirmed","","Happens when trying to bump a transaction that is already …",89,null],[13,"IrreplaceableTransaction","","Trying to replace a tx that has a sequence >= 0xFFFFFFFE",89,null],[13,"FeeRateTooLow","","When bumping a tx the fee rate requested is lower than …",89,null],[12,"required","bdk::Error","Required fee rate (satoshi/vbyte)",90,null],[13,"FeeTooLow","bdk","When bumping a tx the absolute fee requested is lower …",89,null],[12,"required","bdk::Error","Required fee absolute value (satoshi)",91,null],[13,"MissingKeyOrigin","bdk","In order to use the TxBuilder::add_global_xpubs option …",89,null],[13,"Key","","Error while working with keys",89,null],[13,"ChecksumMismatch","","Descriptor checksum mismatch",89,null],[13,"SpendingPolicyRequired","","Spending policy is not compatible with this KeychainKind",89,null],[13,"InvalidPolicyPathError","","Error while extracting and manipulating policies",89,null],[13,"Signer","","Signing error",89,null],[13,"OfflineClient","","Thrown when trying to call a method that requires a …",89,null],[13,"InvalidProgressValue","","Progress value must be between 0.0 (included) and 100.0 …",89,null],[13,"ProgressUpdateError","","Progress update error (maybe the channel has been closed)",89,null],[13,"InvalidOutpoint","","Requested outpoint doesn\'t exist in the tx (vout greater …",89,null],[13,"Descriptor","","Error related to the parsing and usage of descriptors",89,null],[13,"AddressValidator","","Error that can be returned to fail the validation of an …",89,null],[13,"Encode","","Encoding error",89,null],[13,"Miniscript","","Miniscript error",89,null],[13,"BIP32","","BIP32 error",89,null],[13,"Secp256k1","","An ECDSA error",89,null],[13,"JSON","","Error serializing or deserializing JSON data",89,null],[13,"Hex","","Hex decoding error",89,null],[13,"PSBT","","Partially signed bitcoin transaction error",89,null],[13,"Electrum","","Electrum client error",89,null],[13,"Esplora","","Esplora client error",89,null],[13,"CompactFilters","","Compact filters client error)",89,null],[13,"Sled","","Sled database error",89,null],[4,"KeychainKind","","Types of keychains",null,null],[13,"External","","External",92,null],[13,"Internal","","Internal, usually used for change outputs",92,null],[3,"FeeRate","","Fee rate",null,null],[3,"UTXO","","A wallet unspent output",null,null],[12,"outpoint","","Reference to a transaction output",93,null],[12,"txout","","Transaction output",93,null],[12,"keychain","","Type of keychain",93,null],[3,"TransactionDetails","","A wallet transaction",null,null],[12,"transaction","","Optional transaction",94,null],[12,"txid","","Transaction id",94,null],[12,"timestamp","","Timestamp",94,null],[12,"received","","Received value (sats)",94,null],[12,"sent","","Sent value (sats)",94,null],[12,"fees","","Fee value (sats)",94,null],[12,"height","","Confirmed in block height, None means unconfirmed",94,null],[14,"descriptor","","Macro to write full descriptors with code",null,null],[14,"fragment","","Macro to write descriptor fragments with code",null,null],[11,"from","","",89,[[]]],[11,"into","","",89,[[]]],[11,"to_string","","",89,[[],["string",3]]],[11,"borrow","","",89,[[]]],[11,"borrow_mut","","",89,[[]]],[11,"try_from","","",89,[[],["result",4]]],[11,"try_into","","",89,[[],["result",4]]],[11,"type_id","","",89,[[],["typeid",3]]],[11,"vzip","","",89,[[]]],[11,"init","","",89,[[]]],[11,"deref","","",89,[[]]],[11,"deref_mut","","",89,[[]]],[11,"drop","","",89,[[]]],[11,"from","bdk::blockchain::any","",0,[[]]],[11,"into","","",0,[[]]],[11,"borrow","","",0,[[]]],[11,"borrow_mut","","",0,[[]]],[11,"try_from","","",0,[[],["result",4]]],[11,"try_into","","",0,[[],["result",4]]],[11,"type_id","","",0,[[],["typeid",3]]],[11,"vzip","","",0,[[]]],[11,"init","","",0,[[]]],[11,"deref","","",0,[[]]],[11,"deref_mut","","",0,[[]]],[11,"drop","","",0,[[]]],[11,"from","","",1,[[]]],[11,"into","","",1,[[]]],[11,"borrow","","",1,[[]]],[11,"borrow_mut","","",1,[[]]],[11,"try_from","","",1,[[],["result",4]]],[11,"try_into","","",1,[[],["result",4]]],[11,"type_id","","",1,[[],["typeid",3]]],[11,"vzip","","",1,[[]]],[11,"init","","",1,[[]]],[11,"deref","","",1,[[]]],[11,"deref_mut","","",1,[[]]],[11,"drop","","",1,[[]]],[11,"from","bdk::blockchain::electrum","",95,[[]]],[11,"into","","",95,[[]]],[11,"borrow","","",95,[[]]],[11,"borrow_mut","","",95,[[]]],[11,"try_from","","",95,[[],["result",4]]],[11,"try_into","","",95,[[],["result",4]]],[11,"type_id","","",95,[[],["typeid",3]]],[11,"vzip","","",95,[[]]],[11,"init","","",95,[[]]],[11,"deref","","",95,[[]]],[11,"deref_mut","","",95,[[]]],[11,"drop","","",95,[[]]],[11,"from","","",2,[[]]],[11,"into","","",2,[[]]],[11,"borrow","","",2,[[]]],[11,"borrow_mut","","",2,[[]]],[11,"try_from","","",2,[[],["result",4]]],[11,"try_into","","",2,[[],["result",4]]],[11,"type_id","","",2,[[],["typeid",3]]],[11,"vzip","","",2,[[]]],[11,"init","","",2,[[]]],[11,"deref","","",2,[[]]],[11,"deref_mut","","",2,[[]]],[11,"drop","","",2,[[]]],[11,"from","bdk::blockchain::esplora","",3,[[]]],[11,"into","","",3,[[]]],[11,"borrow","","",3,[[]]],[11,"borrow_mut","","",3,[[]]],[11,"try_from","","",3,[[],["result",4]]],[11,"try_into","","",3,[[],["result",4]]],[11,"type_id","","",3,[[],["typeid",3]]],[11,"vzip","","",3,[[]]],[11,"init","","",3,[[]]],[11,"deref","","",3,[[]]],[11,"deref_mut","","",3,[[]]],[11,"drop","","",3,[[]]],[11,"from","","",4,[[]]],[11,"into","","",4,[[]]],[11,"borrow","","",4,[[]]],[11,"borrow_mut","","",4,[[]]],[11,"try_from","","",4,[[],["result",4]]],[11,"try_into","","",4,[[],["result",4]]],[11,"type_id","","",4,[[],["typeid",3]]],[11,"vzip","","",4,[[]]],[11,"init","","",4,[[]]],[11,"deref","","",4,[[]]],[11,"deref_mut","","",4,[[]]],[11,"drop","","",4,[[]]],[11,"from","","",5,[[]]],[11,"into","","",5,[[]]],[11,"to_string","","",5,[[],["string",3]]],[11,"borrow","","",5,[[]]],[11,"borrow_mut","","",5,[[]]],[11,"try_from","","",5,[[],["result",4]]],[11,"try_into","","",5,[[],["result",4]]],[11,"type_id","","",5,[[],["typeid",3]]],[11,"vzip","","",5,[[]]],[11,"init","","",5,[[]]],[11,"deref","","",5,[[]]],[11,"deref_mut","","",5,[[]]],[11,"drop","","",5,[[]]],[11,"from","bdk::blockchain::compact_filters","",96,[[]]],[11,"into","","",96,[[]]],[11,"borrow","","",96,[[]]],[11,"borrow_mut","","",96,[[]]],[11,"try_from","","",96,[[],["result",4]]],[11,"try_into","","",96,[[],["result",4]]],[11,"type_id","","",96,[[],["typeid",3]]],[11,"vzip","","",96,[[]]],[11,"init","","",96,[[]]],[11,"deref","","",96,[[]]],[11,"deref_mut","","",96,[[]]],[11,"drop","","",96,[[]]],[11,"from","","",97,[[]]],[11,"into","","",97,[[]]],[11,"borrow","","",97,[[]]],[11,"borrow_mut","","",97,[[]]],[11,"try_from","","",97,[[],["result",4]]],[11,"try_into","","",97,[[],["result",4]]],[11,"type_id","","",97,[[],["typeid",3]]],[11,"vzip","","",97,[[]]],[11,"init","","",97,[[]]],[11,"deref","","",97,[[]]],[11,"deref_mut","","",97,[[]]],[11,"drop","","",97,[[]]],[11,"from","","",6,[[]]],[11,"into","","",6,[[]]],[11,"borrow","","",6,[[]]],[11,"borrow_mut","","",6,[[]]],[11,"try_from","","",6,[[],["result",4]]],[11,"try_into","","",6,[[],["result",4]]],[11,"type_id","","",6,[[],["typeid",3]]],[11,"vzip","","",6,[[]]],[11,"init","","",6,[[]]],[11,"deref","","",6,[[]]],[11,"deref_mut","","",6,[[]]],[11,"drop","","",6,[[]]],[11,"from","","",7,[[]]],[11,"into","","",7,[[]]],[11,"borrow","","",7,[[]]],[11,"borrow_mut","","",7,[[]]],[11,"try_from","","",7,[[],["result",4]]],[11,"try_into","","",7,[[],["result",4]]],[11,"type_id","","",7,[[],["typeid",3]]],[11,"vzip","","",7,[[]]],[11,"init","","",7,[[]]],[11,"deref","","",7,[[]]],[11,"deref_mut","","",7,[[]]],[11,"drop","","",7,[[]]],[11,"from","","",8,[[]]],[11,"into","","",8,[[]]],[11,"borrow","","",8,[[]]],[11,"borrow_mut","","",8,[[]]],[11,"try_from","","",8,[[],["result",4]]],[11,"try_into","","",8,[[],["result",4]]],[11,"type_id","","",8,[[],["typeid",3]]],[11,"vzip","","",8,[[]]],[11,"init","","",8,[[]]],[11,"deref","","",8,[[]]],[11,"deref_mut","","",8,[[]]],[11,"drop","","",8,[[]]],[11,"from","","",9,[[]]],[11,"into","","",9,[[]]],[11,"to_string","","",9,[[],["string",3]]],[11,"borrow","","",9,[[]]],[11,"borrow_mut","","",9,[[]]],[11,"try_from","","",9,[[],["result",4]]],[11,"try_into","","",9,[[],["result",4]]],[11,"type_id","","",9,[[],["typeid",3]]],[11,"vzip","","",9,[[]]],[11,"init","","",9,[[]]],[11,"deref","","",9,[[]]],[11,"deref_mut","","",9,[[]]],[11,"drop","","",9,[[]]],[11,"from","bdk::blockchain","",10,[[]]],[11,"into","","",10,[[]]],[11,"to_owned","","",10,[[]]],[11,"clone_into","","",10,[[]]],[11,"borrow","","",10,[[]]],[11,"borrow_mut","","",10,[[]]],[11,"try_from","","",10,[[],["result",4]]],[11,"try_into","","",10,[[],["result",4]]],[11,"type_id","","",10,[[],["typeid",3]]],[11,"vzip","","",10,[[]]],[11,"equivalent","","",10,[[]]],[11,"init","","",10,[[]]],[11,"deref","","",10,[[]]],[11,"deref_mut","","",10,[[]]],[11,"drop","","",10,[[]]],[11,"from","","",98,[[]]],[11,"into","","",98,[[]]],[11,"borrow","","",98,[[]]],[11,"borrow_mut","","",98,[[]]],[11,"try_from","","",98,[[],["result",4]]],[11,"try_into","","",98,[[],["result",4]]],[11,"type_id","","",98,[[],["typeid",3]]],[11,"vzip","","",98,[[]]],[11,"init","","",98,[[]]],[11,"deref","","",98,[[]]],[11,"deref_mut","","",98,[[]]],[11,"drop","","",98,[[]]],[11,"from","","",99,[[]]],[11,"into","","",99,[[]]],[11,"to_owned","","",99,[[]]],[11,"clone_into","","",99,[[]]],[11,"borrow","","",99,[[]]],[11,"borrow_mut","","",99,[[]]],[11,"try_from","","",99,[[],["result",4]]],[11,"try_into","","",99,[[],["result",4]]],[11,"type_id","","",99,[[],["typeid",3]]],[11,"vzip","","",99,[[]]],[11,"init","","",99,[[]]],[11,"deref","","",99,[[]]],[11,"deref_mut","","",99,[[]]],[11,"drop","","",99,[[]]],[11,"from","","",100,[[]]],[11,"into","","",100,[[]]],[11,"to_owned","","",100,[[]]],[11,"clone_into","","",100,[[]]],[11,"borrow","","",100,[[]]],[11,"borrow_mut","","",100,[[]]],[11,"try_from","","",100,[[],["result",4]]],[11,"try_into","","",100,[[],["result",4]]],[11,"type_id","","",100,[[],["typeid",3]]],[11,"vzip","","",100,[[]]],[11,"init","","",100,[[]]],[11,"deref","","",100,[[]]],[11,"deref_mut","","",100,[[]]],[11,"drop","","",100,[[]]],[11,"from","bdk::database::any","",14,[[]]],[11,"into","","",14,[[]]],[11,"borrow","","",14,[[]]],[11,"borrow_mut","","",14,[[]]],[11,"try_from","","",14,[[],["result",4]]],[11,"try_into","","",14,[[],["result",4]]],[11,"type_id","","",14,[[],["typeid",3]]],[11,"vzip","","",14,[[]]],[11,"init","","",14,[[]]],[11,"deref","","",14,[[]]],[11,"deref_mut","","",14,[[]]],[11,"drop","","",14,[[]]],[11,"from","","",15,[[]]],[11,"into","","",15,[[]]],[11,"borrow","","",15,[[]]],[11,"borrow_mut","","",15,[[]]],[11,"try_from","","",15,[[],["result",4]]],[11,"try_into","","",15,[[],["result",4]]],[11,"type_id","","",15,[[],["typeid",3]]],[11,"vzip","","",15,[[]]],[11,"init","","",15,[[]]],[11,"deref","","",15,[[]]],[11,"deref_mut","","",15,[[]]],[11,"drop","","",15,[[]]],[11,"from","","",16,[[]]],[11,"into","","",16,[[]]],[11,"borrow","","",16,[[]]],[11,"borrow_mut","","",16,[[]]],[11,"try_from","","",16,[[],["result",4]]],[11,"try_into","","",16,[[],["result",4]]],[11,"type_id","","",16,[[],["typeid",3]]],[11,"vzip","","",16,[[]]],[11,"init","","",16,[[]]],[11,"deref","","",16,[[]]],[11,"deref_mut","","",16,[[]]],[11,"drop","","",16,[[]]],[11,"from","","",17,[[]]],[11,"into","","",17,[[]]],[11,"borrow","","",17,[[]]],[11,"borrow_mut","","",17,[[]]],[11,"try_from","","",17,[[],["result",4]]],[11,"try_into","","",17,[[],["result",4]]],[11,"type_id","","",17,[[],["typeid",3]]],[11,"vzip","","",17,[[]]],[11,"init","","",17,[[]]],[11,"deref","","",17,[[]]],[11,"deref_mut","","",17,[[]]],[11,"drop","","",17,[[]]],[11,"from","bdk::database::memory","",18,[[]]],[11,"into","","",18,[[]]],[11,"borrow","","",18,[[]]],[11,"borrow_mut","","",18,[[]]],[11,"try_from","","",18,[[],["result",4]]],[11,"try_into","","",18,[[],["result",4]]],[11,"type_id","","",18,[[],["typeid",3]]],[11,"vzip","","",18,[[]]],[11,"init","","",18,[[]]],[11,"deref","","",18,[[]]],[11,"deref_mut","","",18,[[]]],[11,"drop","","",18,[[]]],[11,"from","bdk::descriptor","",23,[[]]],[11,"into","","",23,[[]]],[11,"to_owned","","",23,[[]]],[11,"clone_into","","",23,[[]]],[11,"to_string","","",23,[[],["string",3]]],[11,"borrow","","",23,[[]]],[11,"borrow_mut","","",23,[[]]],[11,"try_from","","",23,[[],["result",4]]],[11,"try_into","","",23,[[],["result",4]]],[11,"type_id","","",23,[[],["typeid",3]]],[11,"vzip","","",23,[[]]],[11,"equivalent","","",23,[[]]],[11,"init","","",23,[[]]],[11,"deref","","",23,[[]]],[11,"deref_mut","","",23,[[]]],[11,"drop","","",23,[[]]],[11,"as_enum","","",101,[[],["scriptcontextenum",4]]],[11,"from","","",101,[[]]],[11,"into","","",101,[[]]],[11,"to_owned","","",101,[[]]],[11,"clone_into","","",101,[[]]],[11,"borrow","","",101,[[]]],[11,"borrow_mut","","",101,[[]]],[11,"try_from","","",101,[[],["result",4]]],[11,"try_into","","",101,[[],["result",4]]],[11,"type_id","","",101,[[],["typeid",3]]],[11,"vzip","","",101,[[]]],[11,"equivalent","","",101,[[]]],[11,"init","","",101,[[]]],[11,"deref","","",101,[[]]],[11,"deref_mut","","",101,[[]]],[11,"drop","","",101,[[]]],[11,"from","","",24,[[]]],[11,"into","","",24,[[]]],[11,"to_owned","","",24,[[]]],[11,"clone_into","","",24,[[]]],[11,"to_string","","",24,[[],["string",3]]],[11,"borrow","","",24,[[]]],[11,"borrow_mut","","",24,[[]]],[11,"try_from","","",24,[[],["result",4]]],[11,"try_into","","",24,[[],["result",4]]],[11,"type_id","","",24,[[],["typeid",3]]],[11,"vzip","","",24,[[]]],[11,"equivalent","","",24,[[]]],[11,"init","","",24,[[]]],[11,"deref","","",24,[[]]],[11,"deref_mut","","",24,[[]]],[11,"drop","","",24,[[]]],[11,"as_enum","","",102,[[],["scriptcontextenum",4]]],[11,"from","","",102,[[]]],[11,"into","","",102,[[]]],[11,"to_owned","","",102,[[]]],[11,"clone_into","","",102,[[]]],[11,"borrow","","",102,[[]]],[11,"borrow_mut","","",102,[[]]],[11,"try_from","","",102,[[],["result",4]]],[11,"try_into","","",102,[[],["result",4]]],[11,"type_id","","",102,[[],["typeid",3]]],[11,"vzip","","",102,[[]]],[11,"equivalent","","",102,[[]]],[11,"init","","",102,[[]]],[11,"deref","","",102,[[]]],[11,"deref_mut","","",102,[[]]],[11,"drop","","",102,[[]]],[11,"from","","",27,[[]]],[11,"into","","",27,[[]]],[11,"to_owned","","",27,[[]]],[11,"clone_into","","",27,[[]]],[11,"to_string","","",27,[[],["string",3]]],[11,"borrow","","",27,[[]]],[11,"borrow_mut","","",27,[[]]],[11,"try_from","","",27,[[],["result",4]]],[11,"try_into","","",27,[[],["result",4]]],[11,"type_id","","",27,[[],["typeid",3]]],[11,"vzip","","",27,[[]]],[11,"equivalent","","",27,[[]]],[11,"init","","",27,[[]]],[11,"deref","","",27,[[]]],[11,"deref_mut","","",27,[[]]],[11,"drop","","",27,[[]]],[11,"from","bdk::descriptor::error","",29,[[]]],[11,"into","","",29,[[]]],[11,"to_string","","",29,[[],["string",3]]],[11,"borrow","","",29,[[]]],[11,"borrow_mut","","",29,[[]]],[11,"try_from","","",29,[[],["result",4]]],[11,"try_into","","",29,[[],["result",4]]],[11,"type_id","","",29,[[],["typeid",3]]],[11,"vzip","","",29,[[]]],[11,"init","","",29,[[]]],[11,"deref","","",29,[[]]],[11,"deref_mut","","",29,[[]]],[11,"drop","","",29,[[]]],[11,"from","bdk::descriptor::policy","",103,[[]]],[11,"into","","",103,[[]]],[11,"to_owned","","",103,[[]]],[11,"clone_into","","",103,[[]]],[11,"borrow","","",103,[[]]],[11,"borrow_mut","","",103,[[]]],[11,"try_from","","",103,[[],["result",4]]],[11,"try_into","","",103,[[],["result",4]]],[11,"type_id","","",103,[[],["typeid",3]]],[11,"vzip","","",103,[[]]],[11,"init","","",103,[[]]],[11,"deref","","",103,[[]]],[11,"deref_mut","","",103,[[]]],[11,"drop","","",103,[[]]],[11,"from","","",30,[[]]],[11,"into","","",30,[[]]],[11,"to_owned","","",30,[[]]],[11,"clone_into","","",30,[[]]],[11,"borrow","","",30,[[]]],[11,"borrow_mut","","",30,[[]]],[11,"try_from","","",30,[[],["result",4]]],[11,"try_into","","",30,[[],["result",4]]],[11,"type_id","","",30,[[],["typeid",3]]],[11,"vzip","","",30,[[]]],[11,"init","","",30,[[]]],[11,"deref","","",30,[[]]],[11,"deref_mut","","",30,[[]]],[11,"drop","","",30,[[]]],[11,"from","","",39,[[]]],[11,"into","","",39,[[]]],[11,"to_owned","","",39,[[]]],[11,"clone_into","","",39,[[]]],[11,"borrow","","",39,[[]]],[11,"borrow_mut","","",39,[[]]],[11,"try_from","","",39,[[],["result",4]]],[11,"try_into","","",39,[[],["result",4]]],[11,"type_id","","",39,[[],["typeid",3]]],[11,"vzip","","",39,[[]]],[11,"init","","",39,[[]]],[11,"deref","","",39,[[]]],[11,"deref_mut","","",39,[[]]],[11,"drop","","",39,[[]]],[11,"from","","",43,[[]]],[11,"into","","",43,[[]]],[11,"to_owned","","",43,[[]]],[11,"clone_into","","",43,[[]]],[11,"borrow","","",43,[[]]],[11,"borrow_mut","","",43,[[]]],[11,"try_from","","",43,[[],["result",4]]],[11,"try_into","","",43,[[],["result",4]]],[11,"type_id","","",43,[[],["typeid",3]]],[11,"vzip","","",43,[[]]],[11,"init","","",43,[[]]],[11,"deref","","",43,[[]]],[11,"deref_mut","","",43,[[]]],[11,"drop","","",43,[[]]],[11,"from","","",44,[[]]],[11,"into","","",44,[[]]],[11,"to_owned","","",44,[[]]],[11,"clone_into","","",44,[[]]],[11,"borrow","","",44,[[]]],[11,"borrow_mut","","",44,[[]]],[11,"try_from","","",44,[[],["result",4]]],[11,"try_into","","",44,[[],["result",4]]],[11,"type_id","","",44,[[],["typeid",3]]],[11,"vzip","","",44,[[]]],[11,"equivalent","","",44,[[]]],[11,"init","","",44,[[]]],[11,"deref","","",44,[[]]],[11,"deref_mut","","",44,[[]]],[11,"drop","","",44,[[]]],[11,"from","","",45,[[]]],[11,"into","","",45,[[]]],[11,"to_string","","",45,[[],["string",3]]],[11,"borrow","","",45,[[]]],[11,"borrow_mut","","",45,[[]]],[11,"try_from","","",45,[[],["result",4]]],[11,"try_into","","",45,[[],["result",4]]],[11,"type_id","","",45,[[],["typeid",3]]],[11,"vzip","","",45,[[]]],[11,"init","","",45,[[]]],[11,"deref","","",45,[[]]],[11,"deref_mut","","",45,[[]]],[11,"drop","","",45,[[]]],[11,"to_wallet_descriptor","bdk::descriptor::template","",47,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",47,[[]]],[11,"into","","",47,[[]]],[11,"borrow","","",47,[[]]],[11,"borrow_mut","","",47,[[]]],[11,"try_from","","",47,[[],["result",4]]],[11,"try_into","","",47,[[],["result",4]]],[11,"type_id","","",47,[[],["typeid",3]]],[11,"vzip","","",47,[[]]],[11,"init","","",47,[[]]],[11,"deref","","",47,[[]]],[11,"deref_mut","","",47,[[]]],[11,"drop","","",47,[[]]],[11,"to_wallet_descriptor","","",48,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",48,[[]]],[11,"into","","",48,[[]]],[11,"borrow","","",48,[[]]],[11,"borrow_mut","","",48,[[]]],[11,"try_from","","",48,[[],["result",4]]],[11,"try_into","","",48,[[],["result",4]]],[11,"type_id","","",48,[[],["typeid",3]]],[11,"vzip","","",48,[[]]],[11,"init","","",48,[[]]],[11,"deref","","",48,[[]]],[11,"deref_mut","","",48,[[]]],[11,"drop","","",48,[[]]],[11,"to_wallet_descriptor","","",49,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",49,[[]]],[11,"into","","",49,[[]]],[11,"borrow","","",49,[[]]],[11,"borrow_mut","","",49,[[]]],[11,"try_from","","",49,[[],["result",4]]],[11,"try_into","","",49,[[],["result",4]]],[11,"type_id","","",49,[[],["typeid",3]]],[11,"vzip","","",49,[[]]],[11,"init","","",49,[[]]],[11,"deref","","",49,[[]]],[11,"deref_mut","","",49,[[]]],[11,"drop","","",49,[[]]],[11,"to_wallet_descriptor","","",50,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",50,[[]]],[11,"into","","",50,[[]]],[11,"borrow","","",50,[[]]],[11,"borrow_mut","","",50,[[]]],[11,"try_from","","",50,[[],["result",4]]],[11,"try_into","","",50,[[],["result",4]]],[11,"type_id","","",50,[[],["typeid",3]]],[11,"vzip","","",50,[[]]],[11,"init","","",50,[[]]],[11,"deref","","",50,[[]]],[11,"deref_mut","","",50,[[]]],[11,"drop","","",50,[[]]],[11,"to_wallet_descriptor","","",51,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",51,[[]]],[11,"into","","",51,[[]]],[11,"borrow","","",51,[[]]],[11,"borrow_mut","","",51,[[]]],[11,"try_from","","",51,[[],["result",4]]],[11,"try_into","","",51,[[],["result",4]]],[11,"type_id","","",51,[[],["typeid",3]]],[11,"vzip","","",51,[[]]],[11,"init","","",51,[[]]],[11,"deref","","",51,[[]]],[11,"deref_mut","","",51,[[]]],[11,"drop","","",51,[[]]],[11,"to_wallet_descriptor","","",52,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",52,[[]]],[11,"into","","",52,[[]]],[11,"borrow","","",52,[[]]],[11,"borrow_mut","","",52,[[]]],[11,"try_from","","",52,[[],["result",4]]],[11,"try_into","","",52,[[],["result",4]]],[11,"type_id","","",52,[[],["typeid",3]]],[11,"vzip","","",52,[[]]],[11,"init","","",52,[[]]],[11,"deref","","",52,[[]]],[11,"deref_mut","","",52,[[]]],[11,"drop","","",52,[[]]],[11,"to_wallet_descriptor","","",53,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",53,[[]]],[11,"into","","",53,[[]]],[11,"borrow","","",53,[[]]],[11,"borrow_mut","","",53,[[]]],[11,"try_from","","",53,[[],["result",4]]],[11,"try_into","","",53,[[],["result",4]]],[11,"type_id","","",53,[[],["typeid",3]]],[11,"vzip","","",53,[[]]],[11,"init","","",53,[[]]],[11,"deref","","",53,[[]]],[11,"deref_mut","","",53,[[]]],[11,"drop","","",53,[[]]],[11,"to_wallet_descriptor","","",54,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",54,[[]]],[11,"into","","",54,[[]]],[11,"borrow","","",54,[[]]],[11,"borrow_mut","","",54,[[]]],[11,"try_from","","",54,[[],["result",4]]],[11,"try_into","","",54,[[],["result",4]]],[11,"type_id","","",54,[[],["typeid",3]]],[11,"vzip","","",54,[[]]],[11,"init","","",54,[[]]],[11,"deref","","",54,[[]]],[11,"deref_mut","","",54,[[]]],[11,"drop","","",54,[[]]],[11,"to_wallet_descriptor","","",55,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"from","","",55,[[]]],[11,"into","","",55,[[]]],[11,"borrow","","",55,[[]]],[11,"borrow_mut","","",55,[[]]],[11,"try_from","","",55,[[],["result",4]]],[11,"try_into","","",55,[[],["result",4]]],[11,"type_id","","",55,[[],["typeid",3]]],[11,"vzip","","",55,[[]]],[11,"init","","",55,[[]]],[11,"deref","","",55,[[]]],[11,"deref_mut","","",55,[[]]],[11,"drop","","",55,[[]]],[11,"from","bdk::keys","",58,[[]]],[11,"into","","",58,[[]]],[11,"to_owned","","",58,[[]]],[11,"clone_into","","",58,[[]]],[11,"to_string","","",58,[[],["string",3]]],[11,"borrow","","",58,[[]]],[11,"borrow_mut","","",58,[[]]],[11,"try_from","","",58,[[],["result",4]]],[11,"try_into","","",58,[[],["result",4]]],[11,"type_id","","",58,[[],["typeid",3]]],[11,"vzip","","",58,[[]]],[11,"equivalent","","",58,[[]]],[11,"init","","",58,[[]]],[11,"deref","","",58,[[]]],[11,"deref_mut","","",58,[[]]],[11,"drop","","",58,[[]]],[11,"from","","",59,[[]]],[11,"into","","",59,[[]]],[11,"to_string","","",59,[[],["string",3]]],[11,"borrow","","",59,[[]]],[11,"borrow_mut","","",59,[[]]],[11,"try_from","","",59,[[],["result",4]]],[11,"try_into","","",59,[[],["result",4]]],[11,"type_id","","",59,[[],["typeid",3]]],[11,"vzip","","",59,[[]]],[11,"init","","",59,[[]]],[11,"deref","","",59,[[]]],[11,"deref_mut","","",59,[[]]],[11,"drop","","",59,[[]]],[11,"from","","",60,[[]]],[11,"into","","",60,[[]]],[11,"borrow","","",60,[[]]],[11,"borrow_mut","","",60,[[]]],[11,"try_from","","",60,[[],["result",4]]],[11,"try_into","","",60,[[],["result",4]]],[11,"type_id","","",60,[[],["typeid",3]]],[11,"vzip","","",60,[[]]],[11,"init","","",60,[[]]],[11,"deref","","",60,[[]]],[11,"deref_mut","","",60,[[]]],[11,"drop","","",60,[[]]],[11,"from","","",61,[[]]],[11,"into","","",61,[[]]],[11,"to_owned","","",61,[[]]],[11,"clone_into","","",61,[[]]],[11,"borrow","","",61,[[]]],[11,"borrow_mut","","",61,[[]]],[11,"try_from","","",61,[[],["result",4]]],[11,"try_into","","",61,[[],["result",4]]],[11,"type_id","","",61,[[],["typeid",3]]],[11,"vzip","","",61,[[]]],[11,"equivalent","","",61,[[]]],[11,"init","","",61,[[]]],[11,"deref","","",61,[[]]],[11,"deref_mut","","",61,[[]]],[11,"drop","","",61,[[]]],[11,"from","","",62,[[]]],[11,"into","","",62,[[]]],[11,"to_owned","","",62,[[]]],[11,"clone_into","","",62,[[]]],[11,"to_string","","",62,[[],["string",3]]],[11,"borrow","","",62,[[]]],[11,"borrow_mut","","",62,[[]]],[11,"try_from","","",62,[[],["result",4]]],[11,"try_into","","",62,[[],["result",4]]],[11,"type_id","","",62,[[],["typeid",3]]],[11,"vzip","","",62,[[]]],[11,"equivalent","","",62,[[]]],[11,"init","","",62,[[]]],[11,"deref","","",62,[[]]],[11,"deref_mut","","",62,[[]]],[11,"drop","","",62,[[]]],[11,"from","","",63,[[]]],[11,"into","","",63,[[]]],[11,"borrow","","",63,[[]]],[11,"borrow_mut","","",63,[[]]],[11,"try_from","","",63,[[],["result",4]]],[11,"try_into","","",63,[[],["result",4]]],[11,"type_id","","",63,[[],["typeid",3]]],[11,"vzip","","",63,[[]]],[11,"init","","",63,[[]]],[11,"deref","","",63,[[]]],[11,"deref_mut","","",63,[[]]],[11,"drop","","",63,[[]]],[11,"from","","",64,[[]]],[11,"into","","",64,[[]]],[11,"to_owned","","",64,[[]]],[11,"clone_into","","",64,[[]]],[11,"borrow","","",64,[[]]],[11,"borrow_mut","","",64,[[]]],[11,"try_from","","",64,[[],["result",4]]],[11,"try_into","","",64,[[],["result",4]]],[11,"type_id","","",64,[[],["typeid",3]]],[11,"vzip","","",64,[[]]],[11,"equivalent","","",64,[[]]],[11,"init","","",64,[[]]],[11,"deref","","",64,[[]]],[11,"deref_mut","","",64,[[]]],[11,"drop","","",64,[[]]],[11,"from","","",68,[[]]],[11,"into","","",68,[[]]],[11,"borrow","","",68,[[]]],[11,"borrow_mut","","",68,[[]]],[11,"try_from","","",68,[[],["result",4]]],[11,"try_into","","",68,[[],["result",4]]],[11,"type_id","","",68,[[],["typeid",3]]],[11,"vzip","","",68,[[]]],[11,"init","","",68,[[]]],[11,"deref","","",68,[[]]],[11,"deref_mut","","",68,[[]]],[11,"drop","","",68,[[]]],[11,"from","","",71,[[]]],[11,"into","","",71,[[]]],[11,"to_owned","","",71,[[]]],[11,"clone_into","","",71,[[]]],[11,"borrow","","",71,[[]]],[11,"borrow_mut","","",71,[[]]],[11,"try_from","","",71,[[],["result",4]]],[11,"try_into","","",71,[[],["result",4]]],[11,"type_id","","",71,[[],["typeid",3]]],[11,"vzip","","",71,[[]]],[11,"init","","",71,[[]]],[11,"deref","","",71,[[]]],[11,"deref_mut","","",71,[[]]],[11,"drop","","",71,[[]]],[11,"from","","",72,[[]]],[11,"into","","",72,[[]]],[11,"to_string","","",72,[[],["string",3]]],[11,"borrow","","",72,[[]]],[11,"borrow_mut","","",72,[[]]],[11,"try_from","","",72,[[],["result",4]]],[11,"try_into","","",72,[[],["result",4]]],[11,"type_id","","",72,[[],["typeid",3]]],[11,"vzip","","",72,[[]]],[11,"init","","",72,[[]]],[11,"deref","","",72,[[]]],[11,"deref_mut","","",72,[[]]],[11,"drop","","",72,[[]]],[11,"from","bdk","",92,[[]]],[11,"into","","",92,[[]]],[11,"to_owned","","",92,[[]]],[11,"clone_into","","",92,[[]]],[11,"borrow","","",92,[[]]],[11,"borrow_mut","","",92,[[]]],[11,"try_from","","",92,[[],["result",4]]],[11,"try_into","","",92,[[],["result",4]]],[11,"type_id","","",92,[[],["typeid",3]]],[11,"write_base32","","",92,[[],["result",4]]],[11,"base32_len","","",92,[[]]],[11,"check_base32","","",92,[[],[["result",4],["vec",3]]]],[11,"vzip","","",92,[[]]],[11,"equivalent","","",92,[[]]],[11,"init","","",92,[[]]],[11,"deref","","",92,[[]]],[11,"deref_mut","","",92,[[]]],[11,"drop","","",92,[[]]],[11,"from","","",104,[[]]],[11,"into","","",104,[[]]],[11,"to_owned","","",104,[[]]],[11,"clone_into","","",104,[[]]],[11,"borrow","","",104,[[]]],[11,"borrow_mut","","",104,[[]]],[11,"try_from","","",104,[[],["result",4]]],[11,"try_into","","",104,[[],["result",4]]],[11,"type_id","","",104,[[],["typeid",3]]],[11,"vzip","","",104,[[]]],[11,"init","","",104,[[]]],[11,"deref","","",104,[[]]],[11,"deref_mut","","",104,[[]]],[11,"drop","","",104,[[]]],[11,"from","","",93,[[]]],[11,"into","","",93,[[]]],[11,"to_owned","","",93,[[]]],[11,"clone_into","","",93,[[]]],[11,"borrow","","",93,[[]]],[11,"borrow_mut","","",93,[[]]],[11,"try_from","","",93,[[],["result",4]]],[11,"try_into","","",93,[[],["result",4]]],[11,"type_id","","",93,[[],["typeid",3]]],[11,"vzip","","",93,[[]]],[11,"equivalent","","",93,[[]]],[11,"init","","",93,[[]]],[11,"deref","","",93,[[]]],[11,"deref_mut","","",93,[[]]],[11,"drop","","",93,[[]]],[11,"from","","",94,[[]]],[11,"into","","",94,[[]]],[11,"to_owned","","",94,[[]]],[11,"clone_into","","",94,[[]]],[11,"borrow","","",94,[[]]],[11,"borrow_mut","","",94,[[]]],[11,"try_from","","",94,[[],["result",4]]],[11,"try_into","","",94,[[],["result",4]]],[11,"type_id","","",94,[[],["typeid",3]]],[11,"vzip","","",94,[[]]],[11,"equivalent","","",94,[[]]],[11,"init","","",94,[[]]],[11,"deref","","",94,[[]]],[11,"deref_mut","","",94,[[]]],[11,"drop","","",94,[[]]],[11,"from","bdk::wallet::address_validator","",73,[[]]],[11,"into","","",73,[[]]],[11,"to_owned","","",73,[[]]],[11,"clone_into","","",73,[[]]],[11,"to_string","","",73,[[],["string",3]]],[11,"borrow","","",73,[[]]],[11,"borrow_mut","","",73,[[]]],[11,"try_from","","",73,[[],["result",4]]],[11,"try_into","","",73,[[],["result",4]]],[11,"type_id","","",73,[[],["typeid",3]]],[11,"vzip","","",73,[[]]],[11,"equivalent","","",73,[[]]],[11,"init","","",73,[[]]],[11,"deref","","",73,[[]]],[11,"deref_mut","","",73,[[]]],[11,"drop","","",73,[[]]],[11,"from","bdk::wallet::coin_selection","",75,[[]]],[11,"into","","",75,[[]]],[11,"borrow","","",75,[[]]],[11,"borrow_mut","","",75,[[]]],[11,"try_from","","",75,[[],["result",4]]],[11,"try_into","","",75,[[],["result",4]]],[11,"type_id","","",75,[[],["typeid",3]]],[11,"vzip","","",75,[[]]],[11,"init","","",75,[[]]],[11,"deref","","",75,[[]]],[11,"deref_mut","","",75,[[]]],[11,"drop","","",75,[[]]],[11,"from","","",105,[[]]],[11,"into","","",105,[[]]],[11,"borrow","","",105,[[]]],[11,"borrow_mut","","",105,[[]]],[11,"try_from","","",105,[[],["result",4]]],[11,"try_into","","",105,[[],["result",4]]],[11,"type_id","","",105,[[],["typeid",3]]],[11,"vzip","","",105,[[]]],[11,"init","","",105,[[]]],[11,"deref","","",105,[[]]],[11,"deref_mut","","",105,[[]]],[11,"drop","","",105,[[]]],[11,"from","","",77,[[]]],[11,"into","","",77,[[]]],[11,"borrow","","",77,[[]]],[11,"borrow_mut","","",77,[[]]],[11,"try_from","","",77,[[],["result",4]]],[11,"try_into","","",77,[[],["result",4]]],[11,"type_id","","",77,[[],["typeid",3]]],[11,"vzip","","",77,[[]]],[11,"init","","",77,[[]]],[11,"deref","","",77,[[]]],[11,"deref_mut","","",77,[[]]],[11,"drop","","",77,[[]]],[11,"from","bdk::wallet::export","",78,[[]]],[11,"into","","",78,[[]]],[11,"borrow","","",78,[[]]],[11,"borrow_mut","","",78,[[]]],[11,"try_from","","",78,[[],["result",4]]],[11,"try_into","","",78,[[],["result",4]]],[11,"type_id","","",78,[[],["typeid",3]]],[11,"vzip","","",78,[[]]],[11,"init","","",78,[[]]],[11,"deref","","",78,[[]]],[11,"deref_mut","","",78,[[]]],[11,"drop","","",78,[[]]],[11,"from","bdk::wallet::signer","",79,[[]]],[11,"into","","",79,[[]]],[11,"to_owned","","",79,[[]]],[11,"clone_into","","",79,[[]]],[11,"borrow","","",79,[[]]],[11,"borrow_mut","","",79,[[]]],[11,"try_from","","",79,[[],["result",4]]],[11,"try_into","","",79,[[],["result",4]]],[11,"type_id","","",79,[[],["typeid",3]]],[11,"vzip","","",79,[[]]],[11,"equivalent","","",79,[[]]],[11,"init","","",79,[[]]],[11,"deref","","",79,[[]]],[11,"deref_mut","","",79,[[]]],[11,"drop","","",79,[[]]],[11,"from","","",80,[[]]],[11,"into","","",80,[[]]],[11,"to_owned","","",80,[[]]],[11,"clone_into","","",80,[[]]],[11,"to_string","","",80,[[],["string",3]]],[11,"borrow","","",80,[[]]],[11,"borrow_mut","","",80,[[]]],[11,"try_from","","",80,[[],["result",4]]],[11,"try_into","","",80,[[],["result",4]]],[11,"type_id","","",80,[[],["typeid",3]]],[11,"vzip","","",80,[[]]],[11,"equivalent","","",80,[[]]],[11,"init","","",80,[[]]],[11,"deref","","",80,[[]]],[11,"deref_mut","","",80,[[]]],[11,"drop","","",80,[[]]],[11,"from","","",82,[[]]],[11,"into","","",82,[[]]],[11,"to_owned","","",82,[[]]],[11,"clone_into","","",82,[[]]],[11,"borrow","","",82,[[]]],[11,"borrow_mut","","",82,[[]]],[11,"try_from","","",82,[[],["result",4]]],[11,"try_into","","",82,[[],["result",4]]],[11,"type_id","","",82,[[],["typeid",3]]],[11,"vzip","","",82,[[]]],[11,"equivalent","","",82,[[]]],[11,"init","","",82,[[]]],[11,"deref","","",82,[[]]],[11,"deref_mut","","",82,[[]]],[11,"drop","","",82,[[]]],[11,"from","","",83,[[]]],[11,"into","","",83,[[]]],[11,"to_owned","","",83,[[]]],[11,"clone_into","","",83,[[]]],[11,"borrow","","",83,[[]]],[11,"borrow_mut","","",83,[[]]],[11,"try_from","","",83,[[],["result",4]]],[11,"try_into","","",83,[[],["result",4]]],[11,"type_id","","",83,[[],["typeid",3]]],[11,"vzip","","",83,[[]]],[11,"init","","",83,[[]]],[11,"deref","","",83,[[]]],[11,"deref_mut","","",83,[[]]],[11,"drop","","",83,[[]]],[11,"from","bdk::wallet::tx_builder","",106,[[]]],[11,"into","","",106,[[]]],[11,"to_owned","","",106,[[]]],[11,"clone_into","","",106,[[]]],[11,"borrow","","",106,[[]]],[11,"borrow_mut","","",106,[[]]],[11,"try_from","","",106,[[],["result",4]]],[11,"try_into","","",106,[[],["result",4]]],[11,"type_id","","",106,[[],["typeid",3]]],[11,"vzip","","",106,[[]]],[11,"init","","",106,[[]]],[11,"deref","","",106,[[]]],[11,"deref_mut","","",106,[[]]],[11,"drop","","",106,[[]]],[11,"from","","",107,[[]]],[11,"into","","",107,[[]]],[11,"to_owned","","",107,[[]]],[11,"clone_into","","",107,[[]]],[11,"borrow","","",107,[[]]],[11,"borrow_mut","","",107,[[]]],[11,"try_from","","",107,[[],["result",4]]],[11,"try_into","","",107,[[],["result",4]]],[11,"type_id","","",107,[[],["typeid",3]]],[11,"vzip","","",107,[[]]],[11,"init","","",107,[[]]],[11,"deref","","",107,[[]]],[11,"deref_mut","","",107,[[]]],[11,"drop","","",107,[[]]],[11,"from","","",84,[[]]],[11,"into","","",84,[[]]],[11,"borrow","","",84,[[]]],[11,"borrow_mut","","",84,[[]]],[11,"try_from","","",84,[[],["result",4]]],[11,"try_into","","",84,[[],["result",4]]],[11,"type_id","","",84,[[],["typeid",3]]],[11,"vzip","","",84,[[]]],[11,"init","","",84,[[]]],[11,"deref","","",84,[[]]],[11,"deref_mut","","",84,[[]]],[11,"drop","","",84,[[]]],[11,"from","","",85,[[]]],[11,"into","","",85,[[]]],[11,"to_owned","","",85,[[]]],[11,"clone_into","","",85,[[]]],[11,"borrow","","",85,[[]]],[11,"borrow_mut","","",85,[[]]],[11,"try_from","","",85,[[],["result",4]]],[11,"try_into","","",85,[[],["result",4]]],[11,"type_id","","",85,[[],["typeid",3]]],[11,"vzip","","",85,[[]]],[11,"equivalent","","",85,[[]]],[11,"init","","",85,[[]]],[11,"deref","","",85,[[]]],[11,"deref_mut","","",85,[[]]],[11,"drop","","",85,[[]]],[11,"from","","",86,[[]]],[11,"into","","",86,[[]]],[11,"to_owned","","",86,[[]]],[11,"clone_into","","",86,[[]]],[11,"borrow","","",86,[[]]],[11,"borrow_mut","","",86,[[]]],[11,"try_from","","",86,[[],["result",4]]],[11,"try_into","","",86,[[],["result",4]]],[11,"type_id","","",86,[[],["typeid",3]]],[11,"vzip","","",86,[[]]],[11,"equivalent","","",86,[[]]],[11,"init","","",86,[[]]],[11,"deref","","",86,[[]]],[11,"deref_mut","","",86,[[]]],[11,"drop","","",86,[[]]],[11,"from","bdk::wallet","",88,[[]]],[11,"into","","",88,[[]]],[11,"borrow","","",88,[[]]],[11,"borrow_mut","","",88,[[]]],[11,"try_from","","",88,[[],["result",4]]],[11,"try_into","","",88,[[],["result",4]]],[11,"type_id","","",88,[[],["typeid",3]]],[11,"vzip","","",88,[[]]],[11,"init","","",88,[[]]],[11,"deref","","",88,[[]]],[11,"deref_mut","","",88,[[]]],[11,"drop","","",88,[[]]],[11,"from_str","bdk::descriptor","",23,[[],[["result",4],["descriptor",4],["error",4]]]],[11,"from_str","bdk::keys","",59,[[],[["result",4],["descriptorsecretkey",4]]]],[11,"from_str","","",58,[[],[["descriptorpublickey",4],["result",4]]]],[11,"from_str","bdk::descriptor","Parse a Miniscript from string and perform sanity checks …",24,[[],[["miniscript",3],["result",4],["error",4]]]],[11,"hash","bdk::keys","",58,[[]]],[11,"hash","","",61,[[]]],[11,"hash","bdk::descriptor","",27,[[]]],[11,"hash","","",24,[[]]],[11,"eq","","",27,[[["terminal",4]]]],[11,"ne","","",27,[[["terminal",4]]]],[11,"eq","bdk::keys","",58,[[["descriptorpublickey",4]]]],[11,"ne","","",58,[[["descriptorpublickey",4]]]],[11,"eq","bdk::descriptor","",101,[[["legacy",4]]]],[11,"eq","","",24,[[["miniscript",3]]]],[11,"eq","","",23,[[["descriptor",4]]]],[11,"ne","","",23,[[["descriptor",4]]]],[11,"eq","bdk::keys","",61,[[["descriptorsinglepub",3]]]],[11,"ne","","",61,[[["descriptorsinglepub",3]]]],[11,"eq","bdk::descriptor","",102,[[["segwitv0",4]]]],[11,"eq","bdk::keys","",62,[[["sortedmultivec",3]]]],[11,"ne","","",62,[[["sortedmultivec",3]]]],[11,"cmp","bdk::descriptor","",101,[[["legacy",4]],["ordering",4]]],[11,"cmp","bdk::keys","",61,[[["descriptorsinglepub",3]],["ordering",4]]],[11,"cmp","","",62,[[["sortedmultivec",3]],["ordering",4]]],[11,"cmp","bdk::descriptor","",24,[[["miniscript",3]],["ordering",4]]],[11,"cmp","","",102,[[["segwitv0",4]],["ordering",4]]],[11,"cmp","","",23,[[["descriptor",4]],["ordering",4]]],[11,"cmp","bdk::keys","",58,[[["descriptorpublickey",4]],["ordering",4]]],[11,"cmp","bdk::descriptor","",27,[[["terminal",4]],["ordering",4]]],[11,"check_terminal_non_malleable","","",101,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_witness","","",101,[[],[["scriptcontexterror",4],["result",4]]]],[11,"check_global_consensus_validity","","",101,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_consensus_validity","","",101,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_policy_validity","","",101,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"max_satisfaction_size","","",101,[[["miniscript",3]],["option",4]]],[11,"check_terminal_non_malleable","","",102,[[["terminal",4]],[["scriptcontexterror",4],["result",4]]]],[11,"check_witness","","",102,[[],[["scriptcontexterror",4],["result",4]]]],[11,"check_global_consensus_validity","","",102,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_consensus_validity","","",102,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_global_policy_validity","","",102,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"check_local_policy_validity","","",102,[[["miniscript",3]],[["scriptcontexterror",4],["result",4]]]],[11,"max_satisfaction_size","","",102,[[["miniscript",3]],["option",4]]],[11,"clone","","",102,[[],["segwitv0",4]]],[11,"clone","","",24,[[],["miniscript",3]]],[11,"clone","bdk::keys","",62,[[],["sortedmultivec",3]]],[11,"clone","bdk::descriptor","",27,[[],["terminal",4]]],[11,"clone","bdk::keys","",61,[[],["descriptorsinglepub",3]]],[11,"clone","bdk::descriptor","",23,[[],["descriptor",4]]],[11,"clone","","",101,[[],["legacy",4]]],[11,"clone","bdk::keys","",58,[[],["descriptorpublickey",4]]],[11,"fmt","bdk::descriptor","",27,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::keys","",60,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::descriptor","",102,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::keys","",58,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","","",62,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::descriptor","",23,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::keys","",59,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::descriptor","",24,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","","",101,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::keys","",61,[[["formatter",3]],[["error",3],["result",4]]]],[11,"to_pubkeyhash","","",58,[[],["descriptorpublickey",4]]],[11,"partial_cmp","","",58,[[["descriptorpublickey",4]],[["option",4],["ordering",4]]]],[11,"lt","","",58,[[["descriptorpublickey",4]]]],[11,"le","","",58,[[["descriptorpublickey",4]]]],[11,"gt","","",58,[[["descriptorpublickey",4]]]],[11,"ge","","",58,[[["descriptorpublickey",4]]]],[11,"partial_cmp","","",62,[[["sortedmultivec",3]],[["option",4],["ordering",4]]]],[11,"lt","","",62,[[["sortedmultivec",3]]]],[11,"le","","",62,[[["sortedmultivec",3]]]],[11,"gt","","",62,[[["sortedmultivec",3]]]],[11,"ge","","",62,[[["sortedmultivec",3]]]],[11,"partial_cmp","bdk::descriptor","",102,[[["segwitv0",4]],[["option",4],["ordering",4]]]],[11,"partial_cmp","","",24,[[["miniscript",3]],[["option",4],["ordering",4]]]],[11,"partial_cmp","bdk::keys","",61,[[["descriptorsinglepub",3]],[["option",4],["ordering",4]]]],[11,"lt","","",61,[[["descriptorsinglepub",3]]]],[11,"le","","",61,[[["descriptorsinglepub",3]]]],[11,"gt","","",61,[[["descriptorsinglepub",3]]]],[11,"ge","","",61,[[["descriptorsinglepub",3]]]],[11,"partial_cmp","bdk::descriptor","",101,[[["legacy",4]],[["option",4],["ordering",4]]]],[11,"partial_cmp","","",23,[[["descriptor",4]],[["option",4],["ordering",4]]]],[11,"lt","","",23,[[["descriptor",4]]]],[11,"le","","",23,[[["descriptor",4]]]],[11,"gt","","",23,[[["descriptor",4]]]],[11,"ge","","",23,[[["descriptor",4]]]],[11,"partial_cmp","","",27,[[["terminal",4]],[["option",4],["ordering",4]]]],[11,"lt","","",27,[[["terminal",4]]]],[11,"le","","",27,[[["terminal",4]]]],[11,"gt","","",27,[[["terminal",4]]]],[11,"ge","","",27,[[["terminal",4]]]],[11,"lift","bdk::keys","",62,[[],[["result",4],["policy",4],["error",4]]]],[11,"lift","bdk::descriptor","",24,[[],[["result",4],["policy",4],["error",4]]]],[11,"lift","","",23,[[],[["result",4],["policy",4],["error",4]]]],[11,"lift","","",27,[[],[["result",4],["policy",4],["error",4]]]],[11,"to_public_key","bdk::keys","",58,[[["descriptorpublickeyctx",3]],["publickey",3]]],[11,"hash_to_hash160","","",58,[[["descriptorpublickeyctx",3]],["hash",3]]],[11,"fmt","bdk::descriptor","",24,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","","",23,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::keys","",62,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::descriptor","",27,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","bdk::keys","",59,[[["formatter",3]],[["error",3],["result",4]]]],[11,"fmt","","",58,[[["formatter",3]],[["error",3],["result",4]]]],[11,"from_tree","bdk::descriptor","",27,[[["tree",3]],[["result",4],["terminal",4],["error",4]]]],[11,"from_tree","","Parse an expression tree into a Miniscript. As a general …",24,[[["tree",3]],[["miniscript",3],["result",4],["error",4]]]],[11,"from_tree","","Parse an expression tree into a descriptor",23,[[["tree",3]],[["result",4],["descriptor",4],["error",4]]]],[11,"from_config","bdk::blockchain::any","",0,[[],[["result",4],["error",4]]]],[11,"from_config","bdk::blockchain::electrum","",95,[[],[["result",4],["error",4]]]],[11,"from_config","bdk::blockchain::esplora","",3,[[],[["result",4],["error",4]]]],[11,"from_config","bdk::blockchain::compact_filters","",6,[[],[["result",4],["error",4]]]],[11,"update","bdk::blockchain","",99,[[["string",3],["option",4]],[["error",4],["result",4]]]],[11,"update","","",100,[[["string",3],["option",4]],[["error",4],["result",4]]]],[11,"set_script_pubkey","bdk::database::any","",14,[[["script",3],["keychainkind",4]],[["error",4],["result",4]]]],[11,"set_utxo","","",14,[[["utxo",3]],[["error",4],["result",4]]]],[11,"set_raw_tx","","",14,[[["transaction",3]],[["error",4],["result",4]]]],[11,"set_tx","","",14,[[["transactiondetails",3]],[["error",4],["result",4]]]],[11,"set_last_index","","",14,[[["keychainkind",4]],[["error",4],["result",4]]]],[11,"del_script_pubkey_from_path","","",14,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"del_path_from_script_pubkey","","",14,[[["script",3]],[["error",4],["result",4],["option",4]]]],[11,"del_utxo","","",14,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[11,"del_raw_tx","","",14,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"del_tx","","",14,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"del_last_index","","",14,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"set_script_pubkey","","",15,[[["script",3],["keychainkind",4]],[["error",4],["result",4]]]],[11,"set_utxo","","",15,[[["utxo",3]],[["error",4],["result",4]]]],[11,"set_raw_tx","","",15,[[["transaction",3]],[["error",4],["result",4]]]],[11,"set_tx","","",15,[[["transactiondetails",3]],[["error",4],["result",4]]]],[11,"set_last_index","","",15,[[["keychainkind",4]],[["error",4],["result",4]]]],[11,"del_script_pubkey_from_path","","",15,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"del_path_from_script_pubkey","","",15,[[["script",3]],[["error",4],["result",4],["option",4]]]],[11,"del_utxo","","",15,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[11,"del_raw_tx","","",15,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"del_tx","","",15,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"del_last_index","","",15,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"set_script_pubkey","bdk::database::memory","",18,[[["script",3],["keychainkind",4]],[["error",4],["result",4]]]],[11,"set_utxo","","",18,[[["utxo",3]],[["error",4],["result",4]]]],[11,"set_raw_tx","","",18,[[["transaction",3]],[["error",4],["result",4]]]],[11,"set_tx","","",18,[[["transactiondetails",3]],[["error",4],["result",4]]]],[11,"set_last_index","","",18,[[["keychainkind",4]],[["error",4],["result",4]]]],[11,"del_script_pubkey_from_path","","",18,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"del_path_from_script_pubkey","","",18,[[["script",3]],[["error",4],["result",4],["option",4]]]],[11,"del_utxo","","",18,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[11,"del_raw_tx","","",18,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"del_tx","","",18,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"del_last_index","","",18,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"check_descriptor_checksum","bdk::database::any","",14,[[["asref",8],["keychainkind",4]],[["error",4],["result",4]]]],[11,"iter_script_pubkeys","","",14,[[["option",4],["keychainkind",4]],[["vec",3],["result",4],["error",4]]]],[11,"iter_utxos","","",14,[[],[["result",4],["vec",3],["error",4]]]],[11,"iter_raw_txs","","",14,[[],[["vec",3],["result",4],["error",4]]]],[11,"iter_txs","","",14,[[],[["error",4],["result",4],["vec",3]]]],[11,"get_script_pubkey_from_path","","",14,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"get_path_from_script_pubkey","","",14,[[["script",3]],[["error",4],["result",4],["option",4]]]],[11,"get_utxo","","",14,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[11,"get_raw_tx","","",14,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"get_tx","","",14,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"get_last_index","","",14,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"increment_last_index","","",14,[[["keychainkind",4]],[["result",4],["error",4]]]],[11,"check_descriptor_checksum","bdk::database::memory","",18,[[["asref",8],["keychainkind",4]],[["error",4],["result",4]]]],[11,"iter_script_pubkeys","","",18,[[["option",4],["keychainkind",4]],[["vec",3],["result",4],["error",4]]]],[11,"iter_utxos","","",18,[[],[["result",4],["vec",3],["error",4]]]],[11,"iter_raw_txs","","",18,[[],[["vec",3],["result",4],["error",4]]]],[11,"iter_txs","","",18,[[],[["error",4],["result",4],["vec",3]]]],[11,"get_script_pubkey_from_path","","",18,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"get_path_from_script_pubkey","","",18,[[["script",3]],[["error",4],["result",4],["option",4]]]],[11,"get_utxo","","",18,[[["outpoint",3]],[["result",4],["option",4],["error",4]]]],[11,"get_raw_tx","","",18,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"get_tx","","",18,[[["txid",3]],[["option",4],["result",4],["error",4]]]],[11,"get_last_index","","",18,[[["keychainkind",4]],[["result",4],["option",4],["error",4]]]],[11,"increment_last_index","","",18,[[["keychainkind",4]],[["result",4],["error",4]]]],[11,"begin_batch","bdk::database::any","",14,[[]]],[11,"commit_batch","","",14,[[],[["error",4],["result",4]]]],[11,"begin_batch","bdk::database::memory","",18,[[]]],[11,"commit_batch","","",18,[[],[["error",4],["result",4]]]],[11,"from_config","bdk::database::any","",14,[[],[["result",4],["error",4]]]],[11,"from_config","bdk::database::memory","",18,[[],[["result",4],["error",4]]]],[11,"build","bdk::descriptor::template","",47,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"build","","",48,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"build","","",49,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"build","","",50,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"build","","",51,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"build","","",52,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"build","","",53,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"build","","",54,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"build","","",55,[[],[["descriptortemplateout",6],["result",4],["keyerror",4]]]],[11,"to_wallet_descriptor","bdk","",108,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"to_wallet_descriptor","","",109,[[["network",4]],[["result",4],["keyerror",4]]]],[11,"extract_policy","bdk::descriptor","",24,[[["signerscontainer",3],["secp256k1",3]],[["result",4],["error",4],["option",4]]]],[11,"extract_policy","","",23,[[["signerscontainer",3],["secp256k1",3]],[["result",4],["error",4],["option",4]]]],[11,"to_descriptor_key","bdk::keys","",68,[[],[["result",4],["descriptorkey",4],["keyerror",4]]]],[11,"to_descriptor_key","","",63,[[],[["result",4],["descriptorkey",4],["keyerror",4]]]],[11,"to_descriptor_key","","",58,[[],[["result",4],["descriptorkey",4],["keyerror",4]]]],[11,"to_descriptor_key","","",59,[[],[["result",4],["descriptorkey",4],["keyerror",4]]]],[11,"add_metadata","bdk","",110,[[["keysource",6],["derivationpath",3],["option",4]],[["result",4],["descriptorkey",4],["keyerror",4]]]],[11,"add_metadata","bdk::keys","",68,[[["keysource",6],["derivationpath",3],["option",4]],[["result",4],["descriptorkey",4],["keyerror",4]]]],[11,"coin_select","bdk::wallet::coin_selection","",105,[[["feerate",3],["vec",3]],[["result",4],["error",4],["coinselectionresult",3]]]],[11,"coin_select","","",77,[[["feerate",3],["vec",3]],[["result",4],["error",4],["coinselectionresult",3]]]],[11,"get_capabilities","bdk::blockchain::any","",0,[[],[["hashset",3],["capability",4]]]],[11,"setup","","",0,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"sync","","",0,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"get_tx","","",0,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"broadcast","","",0,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",0,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",0,[[],[["feerate",3],["error",4],["result",4]]]],[11,"get_capabilities","bdk::blockchain::electrum","",95,[[],[["hashset",3],["capability",4]]]],[11,"setup","","",95,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"get_tx","","",95,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"broadcast","","",95,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",95,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",95,[[],[["feerate",3],["error",4],["result",4]]]],[11,"get_capabilities","bdk::blockchain::esplora","",3,[[],[["hashset",3],["capability",4]]]],[11,"setup","","",3,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"get_tx","","",3,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"broadcast","","",3,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",3,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",3,[[],[["feerate",3],["error",4],["result",4]]]],[11,"get_capabilities","bdk::blockchain::compact_filters","",6,[[],[["hashset",3],["capability",4]]]],[11,"setup","","",6,[[["progress",8],["option",4]],[["error",4],["result",4]]]],[11,"get_tx","","",6,[[["txid",3]],[["result",4],["option",4],["error",4]]]],[11,"broadcast","","",6,[[["transaction",3]],[["error",4],["result",4]]]],[11,"get_height","","",6,[[],[["result",4],["error",4]]]],[11,"estimate_fee","","",6,[[],[["feerate",3],["error",4],["result",4]]]],[11,"as_ref","bdk","",92,[[]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["addressvalidatorerror",4]]]],[11,"from","","",89,[[["policyerror",4]]]],[11,"from","","",89,[[["signererror",4]]]],[11,"from","","",89,[[["keyerror",4]],["error",4]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["error",3]]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["esploraerror",4]]]],[11,"from","","",89,[[["error",4]]]],[11,"from","","",89,[[["compactfilterserror",4]]]],[11,"from","bdk::blockchain::any","",0,[[["electrumblockchain",3]]]],[11,"from","","",0,[[["esplorablockchain",3]]]],[11,"from","","",0,[[["compactfiltersblockchain",3]]]],[11,"from","","",1,[[["electrumblockchainconfig",3]]]],[11,"from","","",1,[[["esplorablockchainconfig",3]]]],[11,"from","","",1,[[["compactfiltersblockchainconfig",3]]]],[11,"from","bdk::blockchain::electrum","",95,[[["client",3]]]],[11,"from","bdk::blockchain::esplora","",5,[[["error",3]]]],[11,"from","","",5,[[["parseinterror",3]]]],[11,"from","","",5,[[["error",4]]]],[11,"from","","",5,[[["error",4]]]],[11,"from","bdk::blockchain::compact_filters","",9,[[["error",3]]]],[11,"from","","",9,[[["error",3]]]],[11,"from","","",9,[[["error",4]]]],[11,"from","","",9,[[["systemtimeerror",3]]]],[11,"from","","",9,[[["error",4]]]],[11,"from","bdk::database::any","",14,[[["memorydatabase",3]]]],[11,"from","","",14,[[["tree",3]]]],[11,"from","","",15,[[]]],[11,"from","","",15,[[]]],[11,"from","","",17,[[]]],[11,"from","","",17,[[["sleddbconfiguration",3]]]],[11,"from","bdk::descriptor::error","",29,[[["keyerror",4]],["error",4]]],[11,"from","","",29,[[["error",4]]]],[11,"from","","",29,[[["error",4]]]],[11,"from","","",29,[[["error",4]]]],[11,"from","","",29,[[["error",4]]]],[11,"from","","",29,[[["error",4]]]],[11,"from","","",29,[[["policyerror",4]]]],[11,"from","bdk::descriptor::policy","",39,[[]]],[11,"from","","",43,[[["satisfiableitem",4]]]],[11,"from","bdk::keys","",72,[[["error",4]]]],[11,"from","","",72,[[["error",4]]]],[11,"from","bdk::wallet::signer","",79,[[["hash",3]],["signerid",4]]],[11,"from","","",79,[[["fingerprint",3]],["signerid",4]]],[11,"from","","",83,[[["keymap",6]],["signerscontainer",3]]],[11,"clone","bdk::blockchain","",10,[[],["capability",4]]],[11,"clone","","",99,[[],["noopprogress",3]]],[11,"clone","","",100,[[],["logprogress",3]]],[11,"clone","bdk::descriptor::policy","",103,[[],["pkorf",3]]],[11,"clone","","",30,[[],["satisfiableitem",4]]],[11,"clone","","",39,[[],["satisfaction",4]]],[11,"clone","","",43,[[],["policy",3]]],[11,"clone","","",44,[[],["condition",3]]],[11,"clone","bdk::keys","",64,[[],["scriptcontextenum",4]]],[11,"clone","","",71,[[],["privatekeygenerateoptions",3]]],[11,"clone","bdk","",92,[[],["keychainkind",4]]],[11,"clone","","",104,[[],["feerate",3]]],[11,"clone","","",93,[[],["utxo",3]]],[11,"clone","","",94,[[],["transactiondetails",3]]],[11,"clone","bdk::wallet::address_validator","",73,[[],["addressvalidatorerror",4]]],[11,"clone","bdk::wallet::signer","",79,[[],["signerid",4]]],[11,"clone","","",80,[[],["signererror",4]]],[11,"clone","","",82,[[],["signerordering",3]]],[11,"clone","","",83,[[],["signerscontainer",3]]],[11,"clone","bdk::wallet::tx_builder","",106,[[],["createtx",3]]],[11,"clone","","",107,[[],["bumpfee",3]]],[11,"clone","","",85,[[],["txordering",4]]],[11,"clone","","",86,[[],["changespendpolicy",4]]],[11,"default","bdk::blockchain::compact_filters","",96,[[],["mempool",3]]],[11,"default","bdk::database::memory","",18,[[],["memorydatabase",3]]],[11,"default","bdk::descriptor::policy","",103,[[],["pkorf",3]]],[11,"default","","",44,[[],["condition",3]]],[11,"default","bdk::keys","",71,[[]]],[11,"default","bdk","",104,[[]]],[11,"default","","",94,[[],["transactiondetails",3]]],[11,"default","bdk::wallet::coin_selection","",105,[[],["largestfirstcoinselection",3]]],[11,"default","","",77,[[]]],[11,"default","bdk::wallet::signer","",82,[[]]],[11,"default","","",83,[[],["signerscontainer",3]]],[11,"default","bdk::wallet::tx_builder","",106,[[],["createtx",3]]],[11,"default","","",107,[[],["bumpfee",3]]],[11,"default","","",84,[[]]],[11,"default","","",85,[[]]],[11,"default","","",86,[[]]],[11,"cmp","bdk::descriptor::policy","",44,[[["condition",3]],["ordering",4]]],[11,"cmp","bdk::wallet::signer","",79,[[["signerid",4]],["ordering",4]]],[11,"cmp","","",82,[[["signerordering",3]],["ordering",4]]],[11,"cmp","bdk::wallet::tx_builder","",85,[[["txordering",4]],["ordering",4]]],[11,"cmp","","",86,[[["changespendpolicy",4]],["ordering",4]]],[11,"eq","bdk::blockchain","",10,[[["capability",4]]]],[11,"eq","bdk::descriptor::policy","",44,[[["condition",3]]]],[11,"ne","","",44,[[["condition",3]]]],[11,"eq","bdk::keys","",64,[[["scriptcontextenum",4]]]],[11,"eq","bdk","",92,[[["keychainkind",4]]]],[11,"eq","","",104,[[["feerate",3]]]],[11,"ne","","",104,[[["feerate",3]]]],[11,"eq","","",93,[[["utxo",3]]]],[11,"ne","","",93,[[["utxo",3]]]],[11,"eq","","",94,[[["transactiondetails",3]]]],[11,"ne","","",94,[[["transactiondetails",3]]]],[11,"eq","bdk::wallet::address_validator","",73,[[["addressvalidatorerror",4]]]],[11,"ne","","",73,[[["addressvalidatorerror",4]]]],[11,"eq","bdk::wallet::signer","",79,[[["signerid",4]]]],[11,"ne","","",79,[[["signerid",4]]]],[11,"eq","","",80,[[["signererror",4]]]],[11,"eq","","",82,[[["signerordering",3]]]],[11,"ne","","",82,[[["signerordering",3]]]],[11,"eq","bdk::wallet::tx_builder","",85,[[["txordering",4]]]],[11,"eq","","",86,[[["changespendpolicy",4]]]],[11,"partial_cmp","bdk::descriptor::policy","",44,[[["condition",3]],[["ordering",4],["option",4]]]],[11,"lt","","",44,[[["condition",3]]]],[11,"le","","",44,[[["condition",3]]]],[11,"gt","","",44,[[["condition",3]]]],[11,"ge","","",44,[[["condition",3]]]],[11,"partial_cmp","bdk","",104,[[["feerate",3]],[["ordering",4],["option",4]]]],[11,"lt","","",104,[[["feerate",3]]]],[11,"le","","",104,[[["feerate",3]]]],[11,"gt","","",104,[[["feerate",3]]]],[11,"ge","","",104,[[["feerate",3]]]],[11,"partial_cmp","bdk::wallet::signer","",79,[[["signerid",4]],[["ordering",4],["option",4]]]],[11,"lt","","",79,[[["signerid",4]]]],[11,"le","","",79,[[["signerid",4]]]],[11,"gt","","",79,[[["signerid",4]]]],[11,"ge","","",79,[[["signerid",4]]]],[11,"partial_cmp","","",82,[[["signerordering",3]],[["ordering",4],["option",4]]]],[11,"lt","","",82,[[["signerordering",3]]]],[11,"le","","",82,[[["signerordering",3]]]],[11,"gt","","",82,[[["signerordering",3]]]],[11,"ge","","",82,[[["signerordering",3]]]],[11,"partial_cmp","bdk::wallet::tx_builder","",85,[[["txordering",4]],[["ordering",4],["option",4]]]],[11,"partial_cmp","","",86,[[["changespendpolicy",4]],[["ordering",4],["option",4]]]],[11,"to_string","bdk::wallet::export","",78,[[],["string",3]]],[11,"deref","bdk::keys","",68,[[]]],[11,"fmt","bdk","",89,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::any","",1,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::electrum","",2,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::esplora","",3,[[["formatter",3]],["result",6]]],[11,"fmt","","",4,[[["formatter",3]],["result",6]]],[11,"fmt","","",5,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::compact_filters","",96,[[["formatter",3]],["result",6]]],[11,"fmt","","",97,[[["formatter",3]],["result",6]]],[11,"fmt","","",6,[[["formatter",3]],["result",6]]],[11,"fmt","","",7,[[["formatter",3]],["result",6]]],[11,"fmt","","",8,[[["formatter",3]],["result",6]]],[11,"fmt","","",9,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain","",10,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::database::any","",14,[[["formatter",3]],["result",6]]],[11,"fmt","","",16,[[["formatter",3]],["result",6]]],[11,"fmt","","",17,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::database::memory","",18,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::error","",29,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::policy","",103,[[["formatter",3]],["result",6]]],[11,"fmt","","",30,[[["formatter",3]],["result",6]]],[11,"fmt","","",39,[[["formatter",3]],["result",6]]],[11,"fmt","","",43,[[["formatter",3]],["result",6]]],[11,"fmt","","",44,[[["formatter",3]],["result",6]]],[11,"fmt","","",45,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::keys","",63,[[["formatter",3]],["result",6]]],[11,"fmt","","",64,[[["formatter",3]],["result",6]]],[11,"fmt","","",71,[[["formatter",3]],["result",6]]],[11,"fmt","","",72,[[["formatter",3]],["result",6]]],[11,"fmt","bdk","",92,[[["formatter",3]],["result",6]]],[11,"fmt","","",104,[[["formatter",3]],["result",6]]],[11,"fmt","","",93,[[["formatter",3]],["result",6]]],[11,"fmt","","",94,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::address_validator","",73,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::coin_selection","",75,[[["formatter",3]],["result",6]]],[11,"fmt","","",105,[[["formatter",3]],["result",6]]],[11,"fmt","","",77,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::export","",78,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::signer","",79,[[["formatter",3]],["result",6]]],[11,"fmt","","",80,[[["formatter",3]],["result",6]]],[11,"fmt","","",82,[[["formatter",3]],["result",6]]],[11,"fmt","","",83,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::tx_builder","",106,[[["formatter",3]],["result",6]]],[11,"fmt","","",107,[[["formatter",3]],["result",6]]],[11,"fmt","","",84,[[["formatter",3]],["result",6]]],[11,"fmt","","",85,[[["formatter",3]],["result",6]]],[11,"fmt","","",86,[[["formatter",3]],["result",6]]],[11,"fmt","bdk","",89,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::esplora","",5,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::blockchain::compact_filters","",9,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::error","",29,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::descriptor::policy","",45,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::keys","",72,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::address_validator","",73,[[["formatter",3]],["result",6]]],[11,"fmt","bdk::wallet::signer","",80,[[["formatter",3]],["result",6]]],[11,"hash","bdk::blockchain","",10,[[]]],[11,"hash","bdk::descriptor::policy","",44,[[]]],[11,"hash","bdk","",92,[[]]],[11,"hash","bdk::wallet::signer","",79,[[]]],[11,"hash","bdk::wallet::tx_builder","",85,[[]]],[11,"hash","","",86,[[]]],[11,"from_str","bdk::wallet::export","",78,[[],["result",4]]],[11,"serialize","bdk::blockchain::any","",1,[[],["result",4]]],[11,"serialize","bdk::blockchain::electrum","",2,[[],["result",4]]],[11,"serialize","bdk::blockchain::esplora","",4,[[],["result",4]]],[11,"serialize","bdk::blockchain::compact_filters","",7,[[],["result",4]]],[11,"serialize","","",8,[[],["result",4]]],[11,"serialize","bdk::database::any","",16,[[],["result",4]]],[11,"serialize","","",17,[[],["result",4]]],[11,"serialize","bdk::descriptor::policy","",103,[[],["result",4]]],[11,"serialize","","",30,[[],["result",4]]],[11,"serialize","","",39,[[],["result",4]]],[11,"serialize","","",43,[[],["result",4]]],[11,"serialize","","",44,[[],["result",4]]],[11,"serialize","bdk","",92,[[],["result",4]]],[11,"serialize","","",93,[[],["result",4]]],[11,"serialize","","",94,[[],["result",4]]],[11,"serialize","bdk::wallet::export","",78,[[],["result",4]]],[11,"deserialize","bdk::blockchain::any","",1,[[],["result",4]]],[11,"deserialize","bdk::blockchain::electrum","",2,[[],["result",4]]],[11,"deserialize","bdk::blockchain::esplora","",4,[[],["result",4]]],[11,"deserialize","bdk::blockchain::compact_filters","",7,[[],["result",4]]],[11,"deserialize","","",8,[[],["result",4]]],[11,"deserialize","bdk::database::any","",16,[[],["result",4]]],[11,"deserialize","","",17,[[],["result",4]]],[11,"deserialize","bdk","",92,[[],["result",4]]],[11,"deserialize","","",93,[[],["result",4]]],[11,"deserialize","","",94,[[],["result",4]]],[11,"deserialize","bdk::wallet::export","",78,[[],["result",4]]],[11,"add_tx","bdk::blockchain::compact_filters","Add a transaction to the mempool",96,[[["transaction",3]]]],[11,"get_tx","","Look-up a transaction in the mempool given an [Inventory] …",96,[[["inventory",4]],[["option",4],["transaction",3]]]],[11,"has_tx","","Return whether or not the mempool contains a transaction …",96,[[["txid",3]]]],[11,"iter_txs","","Return the list of transactions contained in the mempool",96,[[],[["vec",3],["transaction",3]]]],[11,"connect","","Connect to a peer over a plaintext TCP connection",97,[[["tosocketaddrs",8],["network",4],["arc",3],["mempool",3]],[["compactfilterserror",4],["result",4]]]],[11,"connect_proxy","","Connect to a peer through a SOCKS5 proxy, optionally by …",97,[[["tosocketaddrs",8],["totargetaddr",8],["option",4],["network",4],["arc",3],["mempool",3]],[["compactfilterserror",4],["result",4]]]],[11,"get_version","","Return the [VersionMessage] sent by the peer",97,[[],["versionmessage",3]]],[11,"get_network","","Return the Bitcoin [Network] in use",97,[[],["network",4]]],[11,"get_mempool","","Return the mempool used by this peer",97,[[],[["arc",3],["mempool",3]]]],[11,"is_connected","","Return whether or not the peer is still connected",97,[[]]],[11,"send","","Send a raw Bitcoin message to the peer",97,[[["networkmessage",4]],[["result",4],["compactfilterserror",4]]]],[11,"recv","","Waits for a specific incoming Bitcoin message, optionally …",97,[[["duration",3],["option",4]],[["option",4],["compactfilterserror",4],["result",4]]]],[11,"translate_pk","bdk::descriptor","Convert a descriptor using abstract keys to one using …",23,[[],[["descriptor",4],["result",4]]]],[11,"sanity_check","","Whether the descriptor is safe Checks whether all the …",23,[[],[["error",4],["result",4]]]],[11,"address","","Computes the Bitcoin address of the descriptor, if one …",23,[[["network",4]],[["address",3],["option",4]]]],[11,"script_pubkey","","Computes the scriptpubkey of the descriptor to_pk_ctx …",23,[[],["script",3]]],[11,"unsigned_script_sig","","Computes the scriptSig that will be in place for an …",23,[[],["script",3]]],[11,"witness_script","","Computes the \\\"witness script\\\" of the descriptor, i.e. the …",23,[[],["script",3]]],[11,"get_satisfication","","Returns satisfying witness and scriptSig to spend an …",23,[[],[["error",4],["result",4]]]],[11,"satisfy","","Attempts to produce a satisfying witness and scriptSig to …",23,[[["txin",3]],[["error",4],["result",4]]]],[11,"max_satisfaction_weight","","Computes an upper bound on the weight of a satisfying …",23,[[],["option",4]]],[11,"script_code","","Get the scriptCode of a transaction output.",23,[[],["script",3]]],[11,"derive","","Derives all wildcard keys in the descriptor using the …",23,[[["childnumber",4]],[["descriptorpublickey",4],["descriptor",4]]]],[11,"parse_descriptor","","Parse a descriptor that may contain secret keys",23,[[],[["error",4],["result",4]]]],[11,"to_string_with_secret","","Serialize a descriptor to string with its secret keys",23,[[["hashmap",3]],["string",3]]],[11,"requires_sig","","Whether all spend paths of miniscript require a signature",24,[[]]],[11,"is_non_malleable","","Whether the miniscript is malleable",24,[[]]],[11,"within_resource_limits","","Whether the miniscript can exceed the resource …",24,[[]]],[11,"has_mixed_timelocks","","Whether the miniscript contains a combination of timelocks",24,[[]]],[11,"has_repeated_keys","","Whether the miniscript has repeated Pk or Pkh",24,[[]]],[11,"sanity_check","","Check whether the underlying Miniscript is safe under the …",24,[[],[["result",4],["analysiserror",4]]]],[11,"iter","","Creates a new [Iter] iterator that will iterate over all […",24,[[],["iter",3]]],[11,"iter_pk","","Creates a new [PkIter] iterator that will iterate over …",24,[[],["pkiter",3]]],[11,"iter_pkh","","Creates a new [PkhIter] iterator that will iterate over …",24,[[],["pkhiter",3]]],[11,"iter_pk_pkh","","Creates a new [PkPkhIter] iterator that will iterate over …",24,[[],["pkpkhiter",3]]],[11,"branches","","Enumerates all child nodes of the current AST node (self) …",24,[[],[["miniscript",3],["global",3],["vec",3]]]],[11,"get_nth_child","","Returns child node with given index, if any",24,[[],[["miniscript",3],["option",4]]]],[11,"get_leaf_pk","","Returns Vec with cloned version of all public keys from …",24,[[],[["global",3],["vec",3]]]],[11,"get_leaf_pkh","","Returns Vec with hashes of all public keys from the …",24,[[],[["global",3],["vec",3]]]],[11,"get_leaf_pk_pkh","","Returns Vec of [PkPkh] entries, representing either …",24,[[],[["global",3],["vec",3],["pkpkh",4]]]],[11,"get_nth_pk","","Returns Option::Some with cloned n\'th public key from the …",24,[[],["option",4]]],[11,"get_nth_pkh","","Returns Option::Some with hash of n\'th public key from …",24,[[],["option",4]]],[11,"get_nth_pk_pkh","","Returns Option::Some with hash of n\'th public key or hash …",24,[[],[["option",4],["pkpkh",4]]]],[11,"from_ast","","Add type information(Type and Extdata) to Miniscript …",24,[[["terminal",4]],[["miniscript",3],["result",4],["error",4]]]],[11,"into_inner","","Extracts the AstElem representing the root of the …",24,[[],["terminal",4]]],[11,"as_inner","","Get a reference to the inner AstElem representing the …",24,[[],["terminal",4]]],[11,"parse_insane","","Attempt to parse an insane(scripts don\'t clear sanity …",24,[[["script",3]],[["result",4],["miniscript",3],["error",4]]]],[11,"parse","","Attempt to parse a Script into Miniscript representation. …",24,[[["script",3]],[["result",4],["miniscript",3],["error",4]]]],[11,"encode","","Encode as a Bitcoin script",24,[[],["script",3]]],[11,"script_size","","Size, in bytes of the script-pubkey. If this Miniscript …",24,[[]]],[11,"max_satisfaction_witness_elements","","Maximum number of witness elements used to satisfy the …",24,[[],["option",4]]],[11,"max_satisfaction_size","","Maximum size, in bytes, of a satisfying witness. For …",24,[[],["option",4]]],[11,"translate_pk","","This will panic if translatefpk returns an uncompressed …",24,[[],[["miniscript",3],["result",4]]]],[11,"from_str_insane","","Attempt to parse an insane(scripts don\'t clear sanity …",24,[[],[["miniscript",3],["result",4],["error",4]]]],[11,"satisfy","","Attempt to produce non-malleable satisfying witness for …",24,[[],[["vec",3],["result",4],["error",4]]]],[11,"satisfy_malleable","","Attempt to produce a malleable satisfying witness for the …",24,[[],[["vec",3],["result",4],["error",4]]]],[11,"lift_check","","Lifting corresponds conversion of miniscript into Policy […",24,[[],[["lifterror",4],["result",4]]]],[11,"translate_pk","","Convert an AST element with one public key type to one of …",27,[[],[["terminal",4],["result",4]]]],[11,"encode","","Encode the element as a fragment of Bitcoin Script. The …",27,[[["builder",3]],["builder",3]]],[11,"script_size","","Size, in bytes of the script-pubkey. If this Miniscript …",27,[[]]],[11,"derive","bdk::keys","Derives the specified child key if self is a wildcard …",58,[[["childnumber",4]],["descriptorpublickey",4]]],[11,"as_public","","Return the public version of this key, by applying either …",59,[[["secp256k1",3]],[["result",4],["descriptorpublickey",4],["descriptorkeyparseerror",3]]]],[11,"new","","Create a new instance of SortedMultiVec given a list of …",62,[[["global",3],["vec",3]],[["error",4],["sortedmultivec",3],["result",4]]]],[11,"translate_pk","","This will panic if translatefpk returns an uncompressed …",62,[[],[["result",4],["sortedmultivec",3]]]],[11,"sorted_node","","Create Terminal::Multi containing sorted pubkeys",62,[[],["terminal",4]]],[11,"encode","","Encode as a Bitcoin script",62,[[],["script",3]]],[11,"satisfy","","Attempt to produce a satisfying witness for the witness …",62,[[],[["vec",3],["result",4],["error",4]]]],[11,"script_size","","Size, in bytes of the script-pubkey. If this Miniscript …",62,[[]]],[11,"max_satisfaction_witness_elements","","Maximum number of witness elements used to satisfy the …",62,[[]]],[11,"max_satisfaction_size","","Maximum size, in bytes, of a satisfying witness. For …",62,[[]]],[11,"as_byte","bdk","Return [KeychainKind] as a byte",92,[[]]],[11,"from_btc_per_kvb","","Create a new instance of [FeeRate] given a float fee rate …",104,[[]]],[11,"from_sat_per_vb","","Create a new instance of [FeeRate] given a float fee rate …",104,[[]]],[11,"default_min_relay_fee","","Create a new [FeeRate] with the default min relay fee …",104,[[]]],[11,"as_sat_vb","","Return the value as satoshi/vbyte",104,[[]]]],"p":[[4,"AnyBlockchain"],[4,"AnyBlockchainConfig"],[3,"ElectrumBlockchainConfig"],[3,"EsploraBlockchain"],[3,"EsploraBlockchainConfig"],[4,"EsploraError"],[3,"CompactFiltersBlockchain"],[3,"BitcoinPeerConfig"],[3,"CompactFiltersBlockchainConfig"],[4,"CompactFiltersError"],[4,"Capability"],[8,"Blockchain"],[8,"ConfigurableBlockchain"],[8,"Progress"],[4,"AnyDatabase"],[4,"AnyBatch"],[3,"SledDbConfiguration"],[4,"AnyDatabaseConfig"],[3,"MemoryDatabase"],[8,"BatchOperations"],[8,"Database"],[8,"BatchDatabase"],[8,"ConfigurableDatabase"],[4,"Descriptor"],[3,"Miniscript"],[8,"MiniscriptKey"],[8,"ScriptContext"],[4,"Terminal"],[8,"ToPublicKey"],[4,"Error"],[4,"SatisfiableItem"],[13,"SHA256Preimage"],[13,"HASH256Preimage"],[13,"RIPEMD160Preimage"],[13,"HASH160Preimage"],[13,"AbsoluteTimelock"],[13,"RelativeTimelock"],[13,"Multisig"],[13,"Thresh"],[4,"Satisfaction"],[13,"Partial"],[13,"PartialComplete"],[13,"Complete"],[3,"Policy"],[3,"Condition"],[4,"PolicyError"],[8,"DescriptorTemplate"],[3,"P2PKH"],[3,"P2WPKH_P2SH"],[3,"P2WPKH"],[3,"BIP44"],[3,"BIP44Public"],[3,"BIP49"],[3,"BIP49Public"],[3,"BIP84"],[3,"BIP84Public"],[8,"ToWalletDescriptor"],[8,"ExtractPolicy"],[4,"DescriptorPublicKey"],[4,"DescriptorSecretKey"],[3,"DescriptorSinglePriv"],[3,"DescriptorSinglePub"],[3,"SortedMultiVec"],[4,"DescriptorKey"],[4,"ScriptContextEnum"],[8,"ExtScriptContext"],[8,"ToDescriptorKey"],[8,"DerivableKey"],[3,"GeneratedKey"],[8,"GeneratableKey"],[8,"GeneratableDefaultOptions"],[3,"PrivateKeyGenerateOptions"],[4,"KeyError"],[4,"AddressValidatorError"],[8,"AddressValidator"],[3,"CoinSelectionResult"],[8,"CoinSelectionAlgorithm"],[3,"BranchAndBoundCoinSelection"],[3,"WalletExport"],[4,"SignerId"],[4,"SignerError"],[8,"Signer"],[3,"SignerOrdering"],[3,"SignersContainer"],[3,"TxBuilder"],[4,"TxOrdering"],[4,"ChangeSpendPolicy"],[8,"IsDust"],[3,"Wallet"],[4,"Error"],[13,"FeeRateTooLow"],[13,"FeeTooLow"],[4,"KeychainKind"],[3,"UTXO"],[3,"TransactionDetails"],[3,"ElectrumBlockchain"],[3,"Mempool"],[3,"Peer"],[3,"OfflineBlockchain"],[3,"NoopProgress"],[3,"LogProgress"],[4,"Legacy"],[4,"Segwitv0"],[3,"PKOrF"],[3,"FeeRate"],[3,"LargestFirstCoinSelection"],[3,"CreateTx"],[3,"BumpFee"],[6,"ExtendedDescriptor"],[6,"DescriptorTemplateOut"],[6,"MnemonicWithPassphrase"]]}\ -}'); -addSearchOptions(searchIndex);initSearch(searchIndex); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.css b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.css deleted file mode 100644 index 670986588e..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.css +++ /dev/null @@ -1 +0,0 @@ -.setting-line{padding:5px;position:relative;}.setting-line>div{display:inline-block;vertical-align:top;font-size:17px;padding-top:2px;}.setting-line>.title{font-size:19px;width:100%;max-width:none;border-bottom:1px solid;}.toggle{position:relative;display:inline-block;width:45px;height:27px;margin-right:20px;}.toggle input{opacity:0;position:absolute;}.select-wrapper{float:right;position:relative;height:27px;min-width:25%;}.select-wrapper select{appearance:none;-moz-appearance:none;-webkit-appearance:none;background:none;border:2px solid #ccc;padding-right:28px;width:100%;}.select-wrapper img{pointer-events:none;position:absolute;right:0;bottom:0;background:#ccc;height:100%;width:28px;padding:0px 4px;}.select-wrapper select option{color:initial;}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.3s;transition:.3s;}.slider:before{position:absolute;content:"";height:19px;width:19px;left:4px;bottom:4px;background-color:white;-webkit-transition:.3s;transition:.3s;}input:checked+.slider{background-color:#2196F3;}input:focus+.slider{box-shadow:0 0 0 2px #0a84ff,0 0 0 6px rgba(10,132,255,0.3);}input:checked+.slider:before{-webkit-transform:translateX(19px);-ms-transform:translateX(19px);transform:translateX(19px);}.setting-line>.sub-settings{padding-left:42px;width:100%;display:block;} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.html deleted file mode 100644 index ad50d10b1c..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.html +++ /dev/null @@ -1,6 +0,0 @@ -Rustdoc settings - -

    Rustdoc settings

    Theme preferences
    Use system theme
    Preferred dark theme
    Preferred light theme
    -
    Auto-hide item declarations
    Auto-hide structs declaration
    Auto-hide enums declaration
    Auto-hide unions declaration
    Auto-hide traits declaration
    Auto-hide macros declaration
    -
    Auto-hide item attributes.
    Auto-hide item methods' documentation
    Auto-hide trait implementation documentation
    Auto-hide implementors of a trait
    Directly go to item in search if there is only one result
    Show line numbers on code examples
    Disable keyboard shortcuts
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.js deleted file mode 100644 index b4d6fdcd78..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/settings.js +++ /dev/null @@ -1 +0,0 @@ -(function(){function changeSetting(settingName,value){updateLocalStorage("rustdoc-"+settingName,value);switch(settingName){case"preferred-dark-theme":case"preferred-light-theme":case"use-system-theme":updateSystemTheme();break}}function handleKey(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey){return}switch(getVirtualKey(ev)){case"Enter":case"Return":case"Space":ev.target.checked=!ev.target.checked;ev.preventDefault();break}}function setEvents(){onEachLazy(document.getElementsByClassName("slider"),function(elem){var toggle=elem.previousElementSibling;var settingId=toggle.id;var settingValue=getSettingValue(settingId);if(settingValue!==null){toggle.checked=settingValue==="true"}toggle.onchange=function(){changeSetting(this.id,this.checked)};toggle.onkeyup=handleKey;toggle.onkeyrelease=handleKey});onEachLazy(document.getElementsByClassName("select-wrapper"),function(elem){var select=elem.getElementsByTagName("select")[0];var settingId=select.id;var settingValue=getSettingValue(settingId);if(settingValue!==null){select.value=settingValue}select.onchange=function(){changeSetting(this.id,this.value)}})}window.addEventListener("DOMContentLoaded",setEvents)})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/source-files.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/source-files.js deleted file mode 100644 index 1d8e89293a..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/source-files.js +++ /dev/null @@ -1,3 +0,0 @@ -var N = null;var sourcesIndex = {}; -sourcesIndex["bdk"] = {"name":"","dirs":[{"name":"blockchain","dirs":[{"name":"compact_filters","files":["mod.rs","peer.rs","store.rs","sync.rs"]}],"files":["any.rs","electrum.rs","esplora.rs","mod.rs","utils.rs"]},{"name":"database","files":["any.rs","keyvalue.rs","memory.rs","mod.rs"]},{"name":"descriptor","files":["checksum.rs","dsl.rs","error.rs","mod.rs","policy.rs","template.rs"]},{"name":"keys","files":["bip39.rs","mod.rs"]},{"name":"psbt","files":["mod.rs"]},{"name":"wallet","files":["address_validator.rs","coin_selection.rs","export.rs","mod.rs","signer.rs","time.rs","tx_builder.rs","utils.rs"]}],"files":["error.rs","lib.rs","types.rs"]}; -createSourceSidebar(); diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/source-script.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/source-script.js deleted file mode 100644 index de663ca5a9..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/source-script.js +++ /dev/null @@ -1 +0,0 @@ -function getCurrentFilePath(){var parts=window.location.pathname.split("/");var rootPathParts=window.rootPath.split("/");for(var i=0;i"){sidebar.style.left="";this.style.left="";child.innerText="<";updateLocalStorage("rustdoc-source-sidebar-show","true")}else{sidebar.style.left="-300px";this.style.left="0";child.innerText=">";updateLocalStorage("rustdoc-source-sidebar-show","false")}}function createSidebarToggle(){var sidebarToggle=document.createElement("div");sidebarToggle.id="sidebar-toggle";sidebarToggle.onclick=toggleSidebar;var inner1=document.createElement("div");inner1.style.position="relative";var inner2=document.createElement("div");inner2.style.paddingTop="3px";if(getCurrentValue("rustdoc-source-sidebar-show")==="true"){inner2.innerText="<"}else{inner2.innerText=">";sidebarToggle.style.left="0"}inner1.appendChild(inner2);sidebarToggle.appendChild(inner1);return sidebarToggle}function createSourceSidebar(){if(window.rootPath.endsWith("/")===false){window.rootPath+="/"}var main=document.getElementById("main");var sidebarToggle=createSidebarToggle();main.insertBefore(sidebarToggle,main.firstChild);var sidebar=document.createElement("div");sidebar.id="source-sidebar";if(getCurrentValue("rustdoc-source-sidebar-show")!=="true"){sidebar.style.left="-300px"}var currentFile=getCurrentFilePath();var hasFoundFile=false;var title=document.createElement("div");title.className="title";title.innerText="Files";sidebar.appendChild(title);Object.keys(sourcesIndex).forEach(function(key){sourcesIndex[key].name=key;hasFoundFile=createDirEntry(sourcesIndex[key],sidebar,"",currentFile,hasFoundFile)});main.insertBefore(sidebar,main.firstChild);var selected_elem=sidebar.getElementsByClassName("selected")[0];if(typeof selected_elem!=="undefined"){selected_elem.focus()}} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/any.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/any.rs.html deleted file mode 100644 index 44fe66832a..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/any.rs.html +++ /dev/null @@ -1,470 +0,0 @@ -any.rs - source - -
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Runtime-checked blockchain types
    -//!
    -//! This module provides the implementation of [`AnyBlockchain`] which allows switching the
    -//! inner [`Blockchain`] type at runtime.
    -//!
    -//! ## Example
    -//!
    -//! In this example both `wallet_electrum` and `wallet_esplora` have the same type of
    -//! `Wallet<AnyBlockchain, MemoryDatabase>`. This means that they could both, for instance, be
    -//! assigned to a struct member.
    -//!
    -//! ```no_run
    -//! # use bitcoin::Network;
    -//! # use bdk::blockchain::*;
    -//! # use bdk::database::MemoryDatabase;
    -//! # use bdk::Wallet;
    -//! # #[cfg(feature = "electrum")]
    -//! # {
    -//! let electrum_blockchain = ElectrumBlockchain::from(electrum_client::Client::new("...")?);
    -//! let wallet_electrum: Wallet<AnyBlockchain, _> = Wallet::new(
    -//!     "...",
    -//!     None,
    -//!     Network::Testnet,
    -//!     MemoryDatabase::default(),
    -//!     electrum_blockchain.into(),
    -//! )?;
    -//! # }
    -//!
    -//! # #[cfg(feature = "esplora")]
    -//! # {
    -//! let esplora_blockchain = EsploraBlockchain::new("...", None);
    -//! let wallet_esplora: Wallet<AnyBlockchain, _> = Wallet::new(
    -//!     "...",
    -//!     None,
    -//!     Network::Testnet,
    -//!     MemoryDatabase::default(),
    -//!     esplora_blockchain.into(),
    -//! )?;
    -//! # }
    -//!
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -//!
    -//! When paired with the use of [`ConfigurableBlockchain`], it allows creating wallets with any
    -//! blockchain type supported using a single line of code:
    -//!
    -//! ```no_run
    -//! # use bitcoin::Network;
    -//! # use bdk::blockchain::*;
    -//! # use bdk::database::MemoryDatabase;
    -//! # use bdk::Wallet;
    -//! let config = serde_json::from_str("...")?;
    -//! let blockchain = AnyBlockchain::from_config(&config)?;
    -//! let wallet = Wallet::new(
    -//!     "...",
    -//!     None,
    -//!     Network::Testnet,
    -//!     MemoryDatabase::default(),
    -//!     blockchain,
    -//! )?;
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use super::*;
    -
    -macro_rules! impl_from {
    -    ( $from:ty, $to:ty, $variant:ident, $( $cfg:tt )* ) => {
    -        $( $cfg )*
    -        impl From<$from> for $to {
    -            fn from(inner: $from) -> Self {
    -                <$to>::$variant(inner)
    -            }
    -        }
    -    };
    -}
    -
    -macro_rules! impl_inner_method {
    -    ( $self:expr, $name:ident $(, $args:expr)* ) => {
    -        match $self {
    -            #[cfg(feature = "electrum")]
    -            AnyBlockchain::Electrum(inner) => inner.$name( $($args, )* ),
    -            #[cfg(feature = "esplora")]
    -            AnyBlockchain::Esplora(inner) => inner.$name( $($args, )* ),
    -            #[cfg(feature = "compact_filters")]
    -            AnyBlockchain::CompactFilters(inner) => inner.$name( $($args, )* ),
    -        }
    -    }
    -}
    -
    -/// Type that can contain any of the [`Blockchain`] types defined by the library
    -///
    -/// It allows switching backend at runtime
    -///
    -/// See [this module](crate::blockchain::any)'s documentation for a usage example.
    -pub enum AnyBlockchain {
    -    #[cfg(feature = "electrum")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
    -    /// Electrum client
    -    Electrum(electrum::ElectrumBlockchain),
    -    #[cfg(feature = "esplora")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
    -    /// Esplora client
    -    Esplora(esplora::EsploraBlockchain),
    -    #[cfg(feature = "compact_filters")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
    -    /// Compact filters client
    -    CompactFilters(compact_filters::CompactFiltersBlockchain),
    -}
    -
    -#[maybe_async]
    -impl Blockchain for AnyBlockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        maybe_await!(impl_inner_method!(self, get_capabilities))
    -    }
    -
    -    fn setup<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        stop_gap: Option<usize>,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        maybe_await!(impl_inner_method!(
    -            self,
    -            setup,
    -            stop_gap,
    -            database,
    -            progress_update
    -        ))
    -    }
    -    fn sync<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        stop_gap: Option<usize>,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        maybe_await!(impl_inner_method!(
    -            self,
    -            sync,
    -            stop_gap,
    -            database,
    -            progress_update
    -        ))
    -    }
    -
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        maybe_await!(impl_inner_method!(self, get_tx, txid))
    -    }
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        maybe_await!(impl_inner_method!(self, broadcast, tx))
    -    }
    -
    -    fn get_height(&self) -> Result<u32, Error> {
    -        maybe_await!(impl_inner_method!(self, get_height))
    -    }
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
    -        maybe_await!(impl_inner_method!(self, estimate_fee, target))
    -    }
    -}
    -
    -impl_from!(electrum::ElectrumBlockchain, AnyBlockchain, Electrum, #[cfg(feature = "electrum")]);
    -impl_from!(esplora::EsploraBlockchain, AnyBlockchain, Esplora, #[cfg(feature = "esplora")]);
    -impl_from!(compact_filters::CompactFiltersBlockchain, AnyBlockchain, CompactFilters, #[cfg(feature = "compact_filters")]);
    -
    -/// Type that can contain any of the blockchain configurations defined by the library
    -///
    -/// This allows storing a single configuration that can be loaded into an [`AnyBlockchain`]
    -/// instance. Wallets that plan to offer users the ability to switch blockchain backend at runtime
    -/// will find this particularly useful.
    -#[derive(Debug, serde::Serialize, serde::Deserialize)]
    -pub enum AnyBlockchainConfig {
    -    #[cfg(feature = "electrum")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
    -    /// Electrum client
    -    Electrum(electrum::ElectrumBlockchainConfig),
    -    #[cfg(feature = "esplora")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
    -    /// Esplora client
    -    Esplora(esplora::EsploraBlockchainConfig),
    -    #[cfg(feature = "compact_filters")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
    -    /// Compact filters client
    -    CompactFilters(compact_filters::CompactFiltersBlockchainConfig),
    -}
    -
    -impl ConfigurableBlockchain for AnyBlockchain {
    -    type Config = AnyBlockchainConfig;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        Ok(match config {
    -            #[cfg(feature = "electrum")]
    -            AnyBlockchainConfig::Electrum(inner) => {
    -                AnyBlockchain::Electrum(electrum::ElectrumBlockchain::from_config(inner)?)
    -            }
    -            #[cfg(feature = "esplora")]
    -            AnyBlockchainConfig::Esplora(inner) => {
    -                AnyBlockchain::Esplora(esplora::EsploraBlockchain::from_config(inner)?)
    -            }
    -            #[cfg(feature = "compact_filters")]
    -            AnyBlockchainConfig::CompactFilters(inner) => AnyBlockchain::CompactFilters(
    -                compact_filters::CompactFiltersBlockchain::from_config(inner)?,
    -            ),
    -        })
    -    }
    -}
    -
    -impl_from!(electrum::ElectrumBlockchainConfig, AnyBlockchainConfig, Electrum, #[cfg(feature = "electrum")]);
    -impl_from!(esplora::EsploraBlockchainConfig, AnyBlockchainConfig, Esplora, #[cfg(feature = "esplora")]);
    -impl_from!(compact_filters::CompactFiltersBlockchainConfig, AnyBlockchainConfig, CompactFilters, #[cfg(feature = "compact_filters")]);
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/mod.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/mod.rs.html deleted file mode 100644 index f9b808e361..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/mod.rs.html +++ /dev/null @@ -1,1166 +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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Compact Filters
    -//!
    -//! This module contains a multithreaded implementation of an [`Blockchain`] backend that
    -//! uses BIP157 (aka "Neutrino") to populate the wallet's [database](crate::database::Database)
    -//! by downloading compact filters from the P2P network.
    -//!
    -//! Since there are currently very few peers "in the wild" that advertise the required service
    -//! flag, this implementation requires that one or more known peers are provided by the user.
    -//! No dns or other kinds of peer discovery are done internally.
    -//!
    -//! Moreover, this module doesn't currently support detecting and resolving conflicts between
    -//! messages received by different peers. Thus, it's recommended to use this module by only
    -//! connecting to a single peer at a time, optionally by opening multiple connections if it's
    -//! desirable to use multiple threads at once to sync in parallel.
    -//!
    -//! This is an **EXPERIMENTAL** feature, API and other major changes are expected.
    -//!
    -//! ## Example
    -//!
    -//! ```no_run
    -//! # use std::sync::Arc;
    -//! # use bitcoin::*;
    -//! # use bdk::*;
    -//! # use bdk::blockchain::compact_filters::*;
    -//! let num_threads = 4;
    -//!
    -//! let mempool = Arc::new(Mempool::default());
    -//! let peers = (0..num_threads)
    -//!     .map(|_| {
    -//!         Peer::connect(
    -//!             "btcd-mainnet.lightning.computer:8333",
    -//!             Arc::clone(&mempool),
    -//!             Network::Bitcoin,
    -//!         )
    -//!     })
    -//!     .collect::<Result<_, _>>()?;
    -//! let blockchain = CompactFiltersBlockchain::new(peers, "./wallet-filters", Some(500_000))?;
    -//! # Ok::<(), CompactFiltersError>(())
    -//! ```
    -
    -use std::collections::HashSet;
    -use std::fmt;
    -use std::path::Path;
    -use std::sync::atomic::{AtomicUsize, Ordering};
    -use std::sync::{Arc, Mutex};
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -use bitcoin::network::message_blockdata::Inventory;
    -use bitcoin::{Network, OutPoint, Transaction, Txid};
    -
    -use rocksdb::{Options, SliceTransform, DB};
    -
    -mod peer;
    -mod store;
    -mod sync;
    -
    -use super::{Blockchain, Capability, ConfigurableBlockchain, Progress};
    -use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
    -use crate::error::Error;
    -use crate::types::{KeychainKind, TransactionDetails, UTXO};
    -use crate::FeeRate;
    -
    -use peer::*;
    -use store::*;
    -use sync::*;
    -
    -pub use peer::{Mempool, Peer};
    -
    -const SYNC_HEADERS_COST: f32 = 1.0;
    -const SYNC_FILTERS_COST: f32 = 11.6 * 1_000.0;
    -const PROCESS_BLOCKS_COST: f32 = 20_000.0;
    -
    -/// Structure implementing the required blockchain traits
    -///
    -/// ## Example
    -/// See the [`blockchain::compact_filters`](crate::blockchain::compact_filters) module for a usage example.
    -#[derive(Debug)]
    -pub struct CompactFiltersBlockchain {
    -    peers: Vec<Arc<Peer>>,
    -    headers: Arc<ChainStore<Full>>,
    -    skip_blocks: Option<usize>,
    -}
    -
    -impl CompactFiltersBlockchain {
    -    /// Construct a new instance given a list of peers, a path to store headers and block
    -    /// filters downloaded during the sync and optionally a number of blocks to ignore starting
    -    /// from the genesis while scanning for the wallet's outputs.
    -    ///
    -    /// For each [`Peer`] specified a new thread will be spawned to download and verify the filters
    -    /// in parallel. It's currently recommended to only connect to a single peer to avoid
    -    /// inconsistencies in the data returned, optionally with multiple connections in parallel to
    -    /// speed-up the sync process.
    -    pub fn new<P: AsRef<Path>>(
    -        peers: Vec<Peer>,
    -        storage_dir: P,
    -        skip_blocks: Option<usize>,
    -    ) -> Result<Self, CompactFiltersError> {
    -        if peers.is_empty() {
    -            return Err(CompactFiltersError::NoPeers);
    -        }
    -
    -        let mut opts = Options::default();
    -        opts.create_if_missing(true);
    -        opts.set_prefix_extractor(SliceTransform::create_fixed_prefix(16));
    -
    -        let network = peers[0].get_network();
    -
    -        let cfs = DB::list_cf(&opts, &storage_dir).unwrap_or(vec!["default".to_string()]);
    -        let db = DB::open_cf(&opts, &storage_dir, &cfs)?;
    -        let headers = Arc::new(ChainStore::new(db, network)?);
    -
    -        // try to recover partial snapshots
    -        for cf_name in &cfs {
    -            if !cf_name.starts_with("_headers:") {
    -                continue;
    -            }
    -
    -            info!("Trying to recover: {:?}", cf_name);
    -            headers.recover_snapshot(cf_name)?;
    -        }
    -
    -        Ok(CompactFiltersBlockchain {
    -            peers: peers.into_iter().map(Arc::new).collect(),
    -            headers,
    -            skip_blocks,
    -        })
    -    }
    -
    -    /// Process a transaction by looking for inputs that spend from a UTXO in the database or
    -    /// outputs that send funds to a know script_pubkey.
    -    fn process_tx<D: BatchDatabase>(
    -        &self,
    -        database: &mut D,
    -        tx: &Transaction,
    -        height: Option<u32>,
    -        timestamp: u64,
    -        internal_max_deriv: &mut Option<u32>,
    -        external_max_deriv: &mut Option<u32>,
    -    ) -> Result<(), Error> {
    -        let mut updates = database.begin_batch();
    -
    -        let mut incoming: u64 = 0;
    -        let mut outgoing: u64 = 0;
    -
    -        let mut inputs_sum: u64 = 0;
    -        let mut outputs_sum: u64 = 0;
    -
    -        // look for our own inputs
    -        for (i, input) in tx.input.iter().enumerate() {
    -            if let Some(previous_output) = database.get_previous_output(&input.previous_output)? {
    -                inputs_sum += previous_output.value;
    -
    -                if database.is_mine(&previous_output.script_pubkey)? {
    -                    outgoing += previous_output.value;
    -
    -                    debug!("{} input #{} is mine, removing from utxo", tx.txid(), i);
    -                    updates.del_utxo(&input.previous_output)?;
    -                }
    -            }
    -        }
    -
    -        for (i, output) in tx.output.iter().enumerate() {
    -            // to compute the fees later
    -            outputs_sum += output.value;
    -
    -            // this output is ours, we have a path to derive it
    -            if let Some((keychain, child)) =
    -                database.get_path_from_script_pubkey(&output.script_pubkey)?
    -            {
    -                debug!("{} output #{} is mine, adding utxo", tx.txid(), i);
    -                updates.set_utxo(&UTXO {
    -                    outpoint: OutPoint::new(tx.txid(), i as u32),
    -                    txout: output.clone(),
    -                    keychain,
    -                })?;
    -                incoming += output.value;
    -
    -                if keychain == KeychainKind::Internal
    -                    && (internal_max_deriv.is_none() || child > internal_max_deriv.unwrap_or(0))
    -                {
    -                    *internal_max_deriv = Some(child);
    -                } else if keychain == KeychainKind::External
    -                    && (external_max_deriv.is_none() || child > external_max_deriv.unwrap_or(0))
    -                {
    -                    *external_max_deriv = Some(child);
    -                }
    -            }
    -        }
    -
    -        if incoming > 0 || outgoing > 0 {
    -            let tx = TransactionDetails {
    -                txid: tx.txid(),
    -                transaction: Some(tx.clone()),
    -                received: incoming,
    -                sent: outgoing,
    -                height,
    -                timestamp,
    -                fees: inputs_sum.checked_sub(outputs_sum).unwrap_or(0),
    -            };
    -
    -            info!("Saving tx {}", tx.txid);
    -            updates.set_tx(&tx)?;
    -        }
    -
    -        database.commit_batch(updates)?;
    -
    -        Ok(())
    -    }
    -}
    -
    -impl Blockchain for CompactFiltersBlockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        vec![Capability::FullHistory].into_iter().collect()
    -    }
    -
    -    fn setup<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        _stop_gap: Option<usize>, // TODO: move to electrum and esplora only
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        let first_peer = &self.peers[0];
    -
    -        let skip_blocks = self.skip_blocks.unwrap_or(0);
    -
    -        let cf_sync = Arc::new(CFSync::new(Arc::clone(&self.headers), skip_blocks, 0x00)?);
    -
    -        let initial_height = self.headers.get_height()?;
    -        let total_bundles = (first_peer.get_version().start_height as usize)
    -            .checked_sub(skip_blocks)
    -            .map(|x| x / 1000)
    -            .unwrap_or(0)
    -            + 1;
    -        let expected_bundles_to_sync = total_bundles
    -            .checked_sub(cf_sync.pruned_bundles()?)
    -            .unwrap_or(0);
    -
    -        let headers_cost = (first_peer.get_version().start_height as usize)
    -            .checked_sub(initial_height)
    -            .unwrap_or(0) as f32
    -            * SYNC_HEADERS_COST;
    -        let filters_cost = expected_bundles_to_sync as f32 * SYNC_FILTERS_COST;
    -
    -        let total_cost = headers_cost + filters_cost + PROCESS_BLOCKS_COST;
    -
    -        if let Some(snapshot) = sync::sync_headers(
    -            Arc::clone(&first_peer),
    -            Arc::clone(&self.headers),
    -            |new_height| {
    -                let local_headers_cost =
    -                    new_height.checked_sub(initial_height).unwrap_or(0) as f32 * SYNC_HEADERS_COST;
    -                progress_update.update(
    -                    local_headers_cost / total_cost * 100.0,
    -                    Some(format!("Synced headers to {}", new_height)),
    -                )
    -            },
    -        )? {
    -            if snapshot.work()? > self.headers.work()? {
    -                info!("Applying snapshot with work: {}", snapshot.work()?);
    -                self.headers.apply_snapshot(snapshot)?;
    -            }
    -        }
    -
    -        let synced_height = self.headers.get_height()?;
    -        let buried_height = synced_height
    -            .checked_sub(sync::BURIED_CONFIRMATIONS)
    -            .unwrap_or(0);
    -        info!("Synced headers to height: {}", synced_height);
    -
    -        cf_sync.prepare_sync(Arc::clone(&first_peer))?;
    -
    -        let all_scripts = Arc::new(
    -            database
    -                .iter_script_pubkeys(None)?
    -                .into_iter()
    -                .map(|s| s.to_bytes())
    -                .collect::<Vec<_>>(),
    -        );
    -
    -        let last_synced_block = Arc::new(Mutex::new(synced_height));
    -        let synced_bundles = Arc::new(AtomicUsize::new(0));
    -        let progress_update = Arc::new(Mutex::new(progress_update));
    -
    -        let mut threads = Vec::with_capacity(self.peers.len());
    -        for peer in &self.peers {
    -            let cf_sync = Arc::clone(&cf_sync);
    -            let peer = Arc::clone(&peer);
    -            let headers = Arc::clone(&self.headers);
    -            let all_scripts = Arc::clone(&all_scripts);
    -            let last_synced_block = Arc::clone(&last_synced_block);
    -            let progress_update = Arc::clone(&progress_update);
    -            let synced_bundles = Arc::clone(&synced_bundles);
    -
    -            let thread = std::thread::spawn(move || {
    -                cf_sync.capture_thread_for_sync(
    -                    peer,
    -                    |block_hash, filter| {
    -                        if !filter
    -                            .match_any(block_hash, &mut all_scripts.iter().map(AsRef::as_ref))?
    -                        {
    -                            return Ok(false);
    -                        }
    -
    -                        let block_height = headers.get_height_for(block_hash)?.unwrap_or(0);
    -                        let saved_correct_block = match headers.get_full_block(block_height)? {
    -                            Some(block) if &block.block_hash() == block_hash => true,
    -                            _ => false,
    -                        };
    -
    -                        if saved_correct_block {
    -                            Ok(false)
    -                        } else {
    -                            let mut last_synced_block = last_synced_block.lock().unwrap();
    -
    -                            // If we download a block older than `last_synced_block`, we update it so that
    -                            // we know to delete and re-process all txs starting from that height
    -                            if block_height < *last_synced_block {
    -                                *last_synced_block = block_height;
    -                            }
    -
    -                            Ok(true)
    -                        }
    -                    },
    -                    |index| {
    -                        let synced_bundles = synced_bundles.fetch_add(1, Ordering::SeqCst);
    -                        let local_filters_cost = synced_bundles as f32 * SYNC_FILTERS_COST;
    -                        progress_update.lock().unwrap().update(
    -                            (headers_cost + local_filters_cost) / total_cost * 100.0,
    -                            Some(format!(
    -                                "Synced filters {} - {}",
    -                                index * 1000 + 1,
    -                                (index + 1) * 1000
    -                            )),
    -                        )
    -                    },
    -                )
    -            });
    -
    -            threads.push(thread);
    -        }
    -
    -        for t in threads {
    -            t.join().unwrap()?;
    -        }
    -
    -        progress_update.lock().unwrap().update(
    -            (headers_cost + filters_cost) / total_cost * 100.0,
    -            Some("Processing downloaded blocks and mempool".into()),
    -        )?;
    -
    -        // delete all txs newer than last_synced_block
    -        let last_synced_block = *last_synced_block.lock().unwrap();
    -        log::debug!(
    -            "Dropping transactions newer than `last_synced_block` = {}",
    -            last_synced_block
    -        );
    -        let mut updates = database.begin_batch();
    -        for details in database.iter_txs(false)? {
    -            match details.height {
    -                Some(height) if (height as usize) < last_synced_block => continue,
    -                _ => updates.del_tx(&details.txid, false)?,
    -            };
    -        }
    -        database.commit_batch(updates)?;
    -
    -        first_peer.ask_for_mempool()?;
    -
    -        let mut internal_max_deriv = None;
    -        let mut external_max_deriv = None;
    -
    -        for (height, block) in self.headers.iter_full_blocks()? {
    -            for tx in &block.txdata {
    -                self.process_tx(
    -                    database,
    -                    tx,
    -                    Some(height as u32),
    -                    0,
    -                    &mut internal_max_deriv,
    -                    &mut external_max_deriv,
    -                )?;
    -            }
    -        }
    -        for tx in first_peer.get_mempool().iter_txs().iter() {
    -            self.process_tx(
    -                database,
    -                tx,
    -                None,
    -                0,
    -                &mut internal_max_deriv,
    -                &mut external_max_deriv,
    -            )?;
    -        }
    -
    -        let current_ext = database
    -            .get_last_index(KeychainKind::External)?
    -            .unwrap_or(0);
    -        let first_ext_new = external_max_deriv.map(|x| x + 1).unwrap_or(0);
    -        if first_ext_new > current_ext {
    -            info!("Setting external index to {}", first_ext_new);
    -            database.set_last_index(KeychainKind::External, first_ext_new)?;
    -        }
    -
    -        let current_int = database
    -            .get_last_index(KeychainKind::Internal)?
    -            .unwrap_or(0);
    -        let first_int_new = internal_max_deriv.map(|x| x + 1).unwrap_or(0);
    -        if first_int_new > current_int {
    -            info!("Setting internal index to {}", first_int_new);
    -            database.set_last_index(KeychainKind::Internal, first_int_new)?;
    -        }
    -
    -        info!("Dropping blocks until {}", buried_height);
    -        self.headers.delete_blocks_until(buried_height)?;
    -
    -        progress_update
    -            .lock()
    -            .unwrap()
    -            .update(100.0, Some("Done".into()))?;
    -
    -        Ok(())
    -    }
    -
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        Ok(self.peers[0]
    -            .get_mempool()
    -            .get_tx(&Inventory::Transaction(*txid)))
    -    }
    -
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        self.peers[0].broadcast_tx(tx.clone())?;
    -
    -        Ok(())
    -    }
    -
    -    fn get_height(&self) -> Result<u32, Error> {
    -        Ok(self.headers.get_height()? as u32)
    -    }
    -
    -    fn estimate_fee(&self, _target: usize) -> Result<FeeRate, Error> {
    -        // TODO
    -        Ok(FeeRate::default())
    -    }
    -}
    -
    -/// Data to connect to a Bitcoin P2P peer
    -#[derive(Debug, serde::Deserialize, serde::Serialize)]
    -pub struct BitcoinPeerConfig {
    -    /// Peer address such as 127.0.0.1:18333
    -    pub address: String,
    -    /// Optional socks5 proxy
    -    pub socks5: Option<String>,
    -    /// Optional socks5 proxy credentials
    -    pub socks5_credentials: Option<(String, String)>,
    -}
    -
    -/// Configuration for a [`CompactFiltersBlockchain`]
    -#[derive(Debug, serde::Deserialize, serde::Serialize)]
    -pub struct CompactFiltersBlockchainConfig {
    -    /// List of peers to try to connect to for asking headers and filters
    -    pub peers: Vec<BitcoinPeerConfig>,
    -    /// Network used
    -    pub network: Network,
    -    /// Storage dir to save partially downloaded headers and full blocks
    -    pub storage_dir: String,
    -    /// Optionally skip initial `skip_blocks` blocks (default: 0)
    -    pub skip_blocks: Option<usize>,
    -}
    -
    -impl ConfigurableBlockchain for CompactFiltersBlockchain {
    -    type Config = CompactFiltersBlockchainConfig;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        let mempool = Arc::new(Mempool::default());
    -        let peers = config
    -            .peers
    -            .iter()
    -            .map(|peer_conf| match &peer_conf.socks5 {
    -                None => Peer::connect(&peer_conf.address, Arc::clone(&mempool), config.network),
    -                Some(proxy) => Peer::connect_proxy(
    -                    peer_conf.address.as_str(),
    -                    proxy,
    -                    peer_conf
    -                        .socks5_credentials
    -                        .as_ref()
    -                        .map(|(a, b)| (a.as_str(), b.as_str())),
    -                    Arc::clone(&mempool),
    -                    config.network,
    -                ),
    -            })
    -            .collect::<Result<_, _>>()?;
    -
    -        Ok(CompactFiltersBlockchain::new(
    -            peers,
    -            &config.storage_dir,
    -            config.skip_blocks,
    -        )?)
    -    }
    -}
    -
    -/// An error that can occur during sync with a [`CompactFiltersBlockchain`]
    -#[derive(Debug)]
    -pub enum CompactFiltersError {
    -    /// A peer sent an invalid or unexpected response
    -    InvalidResponse,
    -    /// The headers returned are invalid
    -    InvalidHeaders,
    -    /// The compact filter headers returned are invalid
    -    InvalidFilterHeader,
    -    /// The compact filter returned is invalid
    -    InvalidFilter,
    -    /// The peer is missing a block in the valid chain
    -    MissingBlock,
    -    /// The data stored in the block filters storage are corrupted
    -    DataCorruption,
    -
    -    /// A peer is not connected
    -    NotConnected,
    -    /// A peer took too long to reply to one of our messages
    -    Timeout,
    -
    -    /// No peers have been specified
    -    NoPeers,
    -
    -    /// Internal database error
    -    DB(rocksdb::Error),
    -    /// Internal I/O error
    -    IO(std::io::Error),
    -    /// Invalid BIP158 filter
    -    BIP158(bitcoin::util::bip158::Error),
    -    /// Internal system time error
    -    Time(std::time::SystemTimeError),
    -
    -    /// Wrapper for [`crate::error::Error`]
    -    Global(Box<crate::error::Error>),
    -}
    -
    -impl fmt::Display for CompactFiltersError {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for CompactFiltersError {}
    -
    -impl_error!(rocksdb::Error, DB, CompactFiltersError);
    -impl_error!(std::io::Error, IO, CompactFiltersError);
    -impl_error!(bitcoin::util::bip158::Error, BIP158, CompactFiltersError);
    -impl_error!(std::time::SystemTimeError, Time, CompactFiltersError);
    -
    -impl From<crate::error::Error> for CompactFiltersError {
    -    fn from(err: crate::error::Error) -> Self {
    -        CompactFiltersError::Global(Box::new(err))
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/peer.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/peer.rs.html deleted file mode 100644 index 16eba3f0d0..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/peer.rs.html +++ /dev/null @@ -1,1106 +0,0 @@ -peer.rs - source - -
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -482
    -483
    -484
    -485
    -486
    -487
    -488
    -489
    -490
    -491
    -492
    -493
    -494
    -495
    -496
    -497
    -498
    -499
    -500
    -501
    -502
    -503
    -504
    -505
    -506
    -507
    -508
    -509
    -510
    -511
    -512
    -513
    -514
    -515
    -516
    -517
    -518
    -519
    -520
    -521
    -522
    -523
    -524
    -525
    -526
    -527
    -528
    -529
    -530
    -531
    -532
    -533
    -534
    -535
    -536
    -537
    -538
    -539
    -540
    -541
    -542
    -543
    -544
    -545
    -546
    -547
    -548
    -549
    -550
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use std::collections::HashMap;
    -use std::net::{TcpStream, ToSocketAddrs};
    -use std::sync::{Arc, Condvar, Mutex, RwLock};
    -use std::thread;
    -use std::time::{Duration, SystemTime, UNIX_EPOCH};
    -
    -use socks::{Socks5Stream, ToTargetAddr};
    -
    -use rand::{thread_rng, Rng};
    -
    -use bitcoin::consensus::Encodable;
    -use bitcoin::hash_types::BlockHash;
    -use bitcoin::hashes::Hash;
    -use bitcoin::network::constants::ServiceFlags;
    -use bitcoin::network::message::{NetworkMessage, RawNetworkMessage};
    -use bitcoin::network::message_blockdata::*;
    -use bitcoin::network::message_filter::*;
    -use bitcoin::network::message_network::VersionMessage;
    -use bitcoin::network::stream_reader::StreamReader;
    -use bitcoin::network::Address;
    -use bitcoin::{Block, Network, Transaction, Txid};
    -
    -use super::CompactFiltersError;
    -
    -type ResponsesMap = HashMap<&'static str, Arc<(Mutex<Vec<NetworkMessage>>, Condvar)>>;
    -
    -pub(crate) const TIMEOUT_SECS: u64 = 30;
    -
    -/// Container for unconfirmed, but valid Bitcoin transactions
    -///
    -/// It is normally shared between [`Peer`]s with the use of [`Arc`], so that transactions are not
    -/// duplicated in memory.
    -#[derive(Debug, Default)]
    -pub struct Mempool {
    -    txs: RwLock<HashMap<Txid, Transaction>>,
    -}
    -
    -impl Mempool {
    -    /// Add a transaction to the mempool
    -    ///
    -    /// Note that this doesn't propagate the transaction to other
    -    /// peers. To do that, [`broadcast`](crate::blockchain::Blockchain::broadcast) should be used.
    -    pub fn add_tx(&self, tx: Transaction) {
    -        self.txs.write().unwrap().insert(tx.txid(), tx);
    -    }
    -
    -    /// Look-up a transaction in the mempool given an [`Inventory`] request
    -    pub fn get_tx(&self, inventory: &Inventory) -> Option<Transaction> {
    -        let txid = match inventory {
    -            Inventory::Error | Inventory::Block(_) | Inventory::WitnessBlock(_) => return None,
    -            Inventory::Transaction(txid) => *txid,
    -            Inventory::WitnessTransaction(wtxid) => Txid::from_inner(wtxid.into_inner()),
    -        };
    -        self.txs.read().unwrap().get(&txid).cloned()
    -    }
    -
    -    /// Return whether or not the mempool contains a transaction with a given txid
    -    pub fn has_tx(&self, txid: &Txid) -> bool {
    -        self.txs.read().unwrap().contains_key(txid)
    -    }
    -
    -    /// Return the list of transactions contained in the mempool
    -    pub fn iter_txs(&self) -> Vec<Transaction> {
    -        self.txs.read().unwrap().values().cloned().collect()
    -    }
    -}
    -
    -/// A Bitcoin peer
    -#[derive(Debug)]
    -pub struct Peer {
    -    writer: Arc<Mutex<TcpStream>>,
    -    responses: Arc<RwLock<ResponsesMap>>,
    -
    -    reader_thread: thread::JoinHandle<()>,
    -    connected: Arc<RwLock<bool>>,
    -
    -    mempool: Arc<Mempool>,
    -
    -    version: VersionMessage,
    -    network: Network,
    -}
    -
    -impl Peer {
    -    /// Connect to a peer over a plaintext TCP connection
    -    ///
    -    /// This function internally spawns a new thread that will monitor incoming messages from the
    -    /// peer, and optionally reply to some of them transparently, like [pings](bitcoin::network::message::NetworkMessage::Ping)
    -    pub fn connect<A: ToSocketAddrs>(
    -        address: A,
    -        mempool: Arc<Mempool>,
    -        network: Network,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let stream = TcpStream::connect(address)?;
    -
    -        Peer::from_stream(stream, mempool, network)
    -    }
    -
    -    /// Connect to a peer through a SOCKS5 proxy, optionally by using some credentials, specified
    -    /// as a tuple of `(username, password)`
    -    ///
    -    /// This function internally spawns a new thread that will monitor incoming messages from the
    -    /// peer, and optionally reply to some of them transparently, like [pings](NetworkMessage::Ping)
    -    pub fn connect_proxy<T: ToTargetAddr, P: ToSocketAddrs>(
    -        target: T,
    -        proxy: P,
    -        credentials: Option<(&str, &str)>,
    -        mempool: Arc<Mempool>,
    -        network: Network,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let socks_stream = if let Some((username, password)) = credentials {
    -            Socks5Stream::connect_with_password(proxy, target, username, password)?
    -        } else {
    -            Socks5Stream::connect(proxy, target)?
    -        };
    -
    -        Peer::from_stream(socks_stream.into_inner(), mempool, network)
    -    }
    -
    -    /// Create a [`Peer`] from an already connected TcpStream
    -    fn from_stream(
    -        stream: TcpStream,
    -        mempool: Arc<Mempool>,
    -        network: Network,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let writer = Arc::new(Mutex::new(stream.try_clone()?));
    -        let responses: Arc<RwLock<ResponsesMap>> = Arc::new(RwLock::new(HashMap::new()));
    -        let connected = Arc::new(RwLock::new(true));
    -
    -        let mut locked_writer = writer.lock().unwrap();
    -
    -        let reader_thread_responses = Arc::clone(&responses);
    -        let reader_thread_writer = Arc::clone(&writer);
    -        let reader_thread_mempool = Arc::clone(&mempool);
    -        let reader_thread_connected = Arc::clone(&connected);
    -        let reader_thread = thread::spawn(move || {
    -            Self::reader_thread(
    -                network,
    -                stream,
    -                reader_thread_responses,
    -                reader_thread_writer,
    -                reader_thread_mempool,
    -                reader_thread_connected,
    -            )
    -        });
    -
    -        let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() as i64;
    -        let nonce = thread_rng().gen();
    -        let receiver = Address::new(&locked_writer.peer_addr()?, ServiceFlags::NONE);
    -        let sender = Address {
    -            services: ServiceFlags::NONE,
    -            address: [0u16; 8],
    -            port: 0,
    -        };
    -
    -        Self::_send(
    -            &mut locked_writer,
    -            network.magic(),
    -            NetworkMessage::Version(VersionMessage::new(
    -                ServiceFlags::WITNESS,
    -                timestamp,
    -                receiver,
    -                sender,
    -                nonce,
    -                "MagicalBitcoinWallet".into(),
    -                0,
    -            )),
    -        )?;
    -        let version = if let NetworkMessage::Version(version) =
    -            Self::_recv(&responses, "version", None)?.unwrap()
    -        {
    -            version
    -        } else {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        };
    -
    -        if let NetworkMessage::Verack = Self::_recv(&responses, "verack", None)?.unwrap() {
    -            Self::_send(&mut locked_writer, network.magic(), NetworkMessage::Verack)?;
    -        } else {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        }
    -
    -        std::mem::drop(locked_writer);
    -
    -        Ok(Peer {
    -            writer,
    -            reader_thread,
    -            responses,
    -            connected,
    -            mempool,
    -            network,
    -            version,
    -        })
    -    }
    -
    -    /// Send a Bitcoin network message
    -    fn _send(
    -        writer: &mut TcpStream,
    -        magic: u32,
    -        payload: NetworkMessage,
    -    ) -> Result<(), CompactFiltersError> {
    -        log::trace!("==> {:?}", payload);
    -
    -        let raw_message = RawNetworkMessage { magic, payload };
    -
    -        raw_message
    -            .consensus_encode(writer)
    -            .map_err(|_| CompactFiltersError::DataCorruption)?;
    -
    -        Ok(())
    -    }
    -
    -    /// Wait for a specific incoming Bitcoin message, optionally with a timeout
    -    fn _recv(
    -        responses: &Arc<RwLock<ResponsesMap>>,
    -        wait_for: &'static str,
    -        timeout: Option<Duration>,
    -    ) -> Result<Option<NetworkMessage>, CompactFiltersError> {
    -        let message_resp = {
    -            let mut lock = responses.write().unwrap();
    -            let message_resp = lock.entry(wait_for).or_default();
    -            Arc::clone(&message_resp)
    -        };
    -
    -        let (lock, cvar) = &*message_resp;
    -
    -        let mut messages = lock.lock().unwrap();
    -        while messages.is_empty() {
    -            match timeout {
    -                None => messages = cvar.wait(messages).unwrap(),
    -                Some(t) => {
    -                    let result = cvar.wait_timeout(messages, t).unwrap();
    -                    if result.1.timed_out() {
    -                        return Ok(None);
    -                    }
    -
    -                    messages = result.0;
    -                }
    -            }
    -        }
    -
    -        Ok(messages.pop())
    -    }
    -
    -    /// Return the [`VersionMessage`] sent by the peer
    -    pub fn get_version(&self) -> &VersionMessage {
    -        &self.version
    -    }
    -
    -    /// Return the Bitcoin [`Network`] in use
    -    pub fn get_network(&self) -> Network {
    -        self.network
    -    }
    -
    -    /// Return the mempool used by this peer
    -    pub fn get_mempool(&self) -> Arc<Mempool> {
    -        Arc::clone(&self.mempool)
    -    }
    -
    -    /// Return whether or not the peer is still connected
    -    pub fn is_connected(&self) -> bool {
    -        *self.connected.read().unwrap()
    -    }
    -
    -    /// Internal function called once the `reader_thread` is spawned
    -    fn reader_thread(
    -        network: Network,
    -        connection: TcpStream,
    -        reader_thread_responses: Arc<RwLock<ResponsesMap>>,
    -        reader_thread_writer: Arc<Mutex<TcpStream>>,
    -        reader_thread_mempool: Arc<Mempool>,
    -        reader_thread_connected: Arc<RwLock<bool>>,
    -    ) {
    -        macro_rules! check_disconnect {
    -            ($call:expr) => {
    -                match $call {
    -                    Ok(good) => good,
    -                    Err(e) => {
    -                        log::debug!("Error {:?}", e);
    -                        *reader_thread_connected.write().unwrap() = false;
    -
    -                        break;
    -                    }
    -                }
    -            };
    -        }
    -
    -        let mut reader = StreamReader::new(connection, None);
    -        loop {
    -            let raw_message: RawNetworkMessage = check_disconnect!(reader.read_next());
    -
    -            let in_message = if raw_message.magic != network.magic() {
    -                continue;
    -            } else {
    -                raw_message.payload
    -            };
    -
    -            log::trace!("<== {:?}", in_message);
    -
    -            match in_message {
    -                NetworkMessage::Ping(nonce) => {
    -                    check_disconnect!(Self::_send(
    -                        &mut reader_thread_writer.lock().unwrap(),
    -                        network.magic(),
    -                        NetworkMessage::Pong(nonce),
    -                    ));
    -
    -                    continue;
    -                }
    -                NetworkMessage::Alert(_) => continue,
    -                NetworkMessage::GetData(ref inv) => {
    -                    let (found, not_found): (Vec<_>, Vec<_>) = inv
    -                        .into_iter()
    -                        .map(|item| (*item, reader_thread_mempool.get_tx(item)))
    -                        .partition(|(_, d)| d.is_some());
    -                    for (_, found_tx) in found {
    -                        check_disconnect!(Self::_send(
    -                            &mut reader_thread_writer.lock().unwrap(),
    -                            network.magic(),
    -                            NetworkMessage::Tx(found_tx.unwrap()),
    -                        ));
    -                    }
    -
    -                    if !not_found.is_empty() {
    -                        check_disconnect!(Self::_send(
    -                            &mut reader_thread_writer.lock().unwrap(),
    -                            network.magic(),
    -                            NetworkMessage::NotFound(
    -                                not_found.into_iter().map(|(i, _)| i).collect(),
    -                            ),
    -                        ));
    -                    }
    -                }
    -                _ => {}
    -            }
    -
    -            let message_resp = {
    -                let mut lock = reader_thread_responses.write().unwrap();
    -                let message_resp = lock.entry(in_message.cmd()).or_default();
    -                Arc::clone(&message_resp)
    -            };
    -
    -            let (lock, cvar) = &*message_resp;
    -            let mut messages = lock.lock().unwrap();
    -            messages.push(in_message);
    -            cvar.notify_all();
    -        }
    -    }
    -
    -    /// Send a raw Bitcoin message to the peer
    -    pub fn send(&self, payload: NetworkMessage) -> Result<(), CompactFiltersError> {
    -        let mut writer = self.writer.lock().unwrap();
    -        Self::_send(&mut writer, self.network.magic(), payload)
    -    }
    -
    -    /// Waits for a specific incoming Bitcoin message, optionally with a timeout
    -    pub fn recv(
    -        &self,
    -        wait_for: &'static str,
    -        timeout: Option<Duration>,
    -    ) -> Result<Option<NetworkMessage>, CompactFiltersError> {
    -        Self::_recv(&self.responses, wait_for, timeout)
    -    }
    -}
    -
    -pub trait CompactFiltersPeer {
    -    fn get_cf_checkpt(
    -        &self,
    -        filter_type: u8,
    -        stop_hash: BlockHash,
    -    ) -> Result<CFCheckpt, CompactFiltersError>;
    -    fn get_cf_headers(
    -        &self,
    -        filter_type: u8,
    -        start_height: u32,
    -        stop_hash: BlockHash,
    -    ) -> Result<CFHeaders, CompactFiltersError>;
    -    fn get_cf_filters(
    -        &self,
    -        filter_type: u8,
    -        start_height: u32,
    -        stop_hash: BlockHash,
    -    ) -> Result<(), CompactFiltersError>;
    -    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError>;
    -}
    -
    -impl CompactFiltersPeer for Peer {
    -    fn get_cf_checkpt(
    -        &self,
    -        filter_type: u8,
    -        stop_hash: BlockHash,
    -    ) -> Result<CFCheckpt, CompactFiltersError> {
    -        self.send(NetworkMessage::GetCFCheckpt(GetCFCheckpt {
    -            filter_type,
    -            stop_hash,
    -        }))?;
    -
    -        let response = self
    -            .recv("cfcheckpt", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -            .ok_or(CompactFiltersError::Timeout)?;
    -        let response = match response {
    -            NetworkMessage::CFCheckpt(response) => response,
    -            _ => return Err(CompactFiltersError::InvalidResponse),
    -        };
    -
    -        if response.filter_type != filter_type {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        }
    -
    -        Ok(response)
    -    }
    -
    -    fn get_cf_headers(
    -        &self,
    -        filter_type: u8,
    -        start_height: u32,
    -        stop_hash: BlockHash,
    -    ) -> Result<CFHeaders, CompactFiltersError> {
    -        self.send(NetworkMessage::GetCFHeaders(GetCFHeaders {
    -            filter_type,
    -            start_height,
    -            stop_hash,
    -        }))?;
    -
    -        let response = self
    -            .recv("cfheaders", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -            .ok_or(CompactFiltersError::Timeout)?;
    -        let response = match response {
    -            NetworkMessage::CFHeaders(response) => response,
    -            _ => return Err(CompactFiltersError::InvalidResponse),
    -        };
    -
    -        if response.filter_type != filter_type {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        }
    -
    -        Ok(response)
    -    }
    -
    -    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError> {
    -        let response = self
    -            .recv("cfilter", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -            .ok_or(CompactFiltersError::Timeout)?;
    -        let response = match response {
    -            NetworkMessage::CFilter(response) => response,
    -            _ => return Err(CompactFiltersError::InvalidResponse),
    -        };
    -
    -        Ok(response)
    -    }
    -
    -    fn get_cf_filters(
    -        &self,
    -        filter_type: u8,
    -        start_height: u32,
    -        stop_hash: BlockHash,
    -    ) -> Result<(), CompactFiltersError> {
    -        self.send(NetworkMessage::GetCFilters(GetCFilters {
    -            filter_type,
    -            start_height,
    -            stop_hash,
    -        }))?;
    -
    -        Ok(())
    -    }
    -}
    -
    -pub trait InvPeer {
    -    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError>;
    -    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError>;
    -    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError>;
    -}
    -
    -impl InvPeer for Peer {
    -    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError> {
    -        self.send(NetworkMessage::GetData(vec![Inventory::WitnessBlock(
    -            block_hash,
    -        )]))?;
    -
    -        match self.recv("block", Some(Duration::from_secs(TIMEOUT_SECS)))? {
    -            None => Ok(None),
    -            Some(NetworkMessage::Block(response)) => Ok(Some(response)),
    -            _ => Err(CompactFiltersError::InvalidResponse),
    -        }
    -    }
    -
    -    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError> {
    -        self.send(NetworkMessage::MemPool)?;
    -        let inv = match self.recv("inv", Some(Duration::from_secs(5)))? {
    -            None => return Ok(()), // empty mempool
    -            Some(NetworkMessage::Inv(inv)) => inv,
    -            _ => return Err(CompactFiltersError::InvalidResponse),
    -        };
    -
    -        let getdata = inv
    -            .iter()
    -            .cloned()
    -            .filter(|item| match item {
    -                Inventory::Transaction(txid) if !self.mempool.has_tx(txid) => true,
    -                _ => false,
    -            })
    -            .collect::<Vec<_>>();
    -        let num_txs = getdata.len();
    -        self.send(NetworkMessage::GetData(getdata))?;
    -
    -        for _ in 0..num_txs {
    -            let tx = self
    -                .recv("tx", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -                .ok_or(CompactFiltersError::Timeout)?;
    -            let tx = match tx {
    -                NetworkMessage::Tx(tx) => tx,
    -                _ => return Err(CompactFiltersError::InvalidResponse),
    -            };
    -
    -            self.mempool.add_tx(tx);
    -        }
    -
    -        Ok(())
    -    }
    -
    -    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError> {
    -        self.mempool.add_tx(tx.clone());
    -        self.send(NetworkMessage::Tx(tx))?;
    -
    -        Ok(())
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/store.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/store.rs.html deleted file mode 100644 index 35d649a23b..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/store.rs.html +++ /dev/null @@ -1,1814 +0,0 @@ -store.rs - source - -
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -482
    -483
    -484
    -485
    -486
    -487
    -488
    -489
    -490
    -491
    -492
    -493
    -494
    -495
    -496
    -497
    -498
    -499
    -500
    -501
    -502
    -503
    -504
    -505
    -506
    -507
    -508
    -509
    -510
    -511
    -512
    -513
    -514
    -515
    -516
    -517
    -518
    -519
    -520
    -521
    -522
    -523
    -524
    -525
    -526
    -527
    -528
    -529
    -530
    -531
    -532
    -533
    -534
    -535
    -536
    -537
    -538
    -539
    -540
    -541
    -542
    -543
    -544
    -545
    -546
    -547
    -548
    -549
    -550
    -551
    -552
    -553
    -554
    -555
    -556
    -557
    -558
    -559
    -560
    -561
    -562
    -563
    -564
    -565
    -566
    -567
    -568
    -569
    -570
    -571
    -572
    -573
    -574
    -575
    -576
    -577
    -578
    -579
    -580
    -581
    -582
    -583
    -584
    -585
    -586
    -587
    -588
    -589
    -590
    -591
    -592
    -593
    -594
    -595
    -596
    -597
    -598
    -599
    -600
    -601
    -602
    -603
    -604
    -605
    -606
    -607
    -608
    -609
    -610
    -611
    -612
    -613
    -614
    -615
    -616
    -617
    -618
    -619
    -620
    -621
    -622
    -623
    -624
    -625
    -626
    -627
    -628
    -629
    -630
    -631
    -632
    -633
    -634
    -635
    -636
    -637
    -638
    -639
    -640
    -641
    -642
    -643
    -644
    -645
    -646
    -647
    -648
    -649
    -650
    -651
    -652
    -653
    -654
    -655
    -656
    -657
    -658
    -659
    -660
    -661
    -662
    -663
    -664
    -665
    -666
    -667
    -668
    -669
    -670
    -671
    -672
    -673
    -674
    -675
    -676
    -677
    -678
    -679
    -680
    -681
    -682
    -683
    -684
    -685
    -686
    -687
    -688
    -689
    -690
    -691
    -692
    -693
    -694
    -695
    -696
    -697
    -698
    -699
    -700
    -701
    -702
    -703
    -704
    -705
    -706
    -707
    -708
    -709
    -710
    -711
    -712
    -713
    -714
    -715
    -716
    -717
    -718
    -719
    -720
    -721
    -722
    -723
    -724
    -725
    -726
    -727
    -728
    -729
    -730
    -731
    -732
    -733
    -734
    -735
    -736
    -737
    -738
    -739
    -740
    -741
    -742
    -743
    -744
    -745
    -746
    -747
    -748
    -749
    -750
    -751
    -752
    -753
    -754
    -755
    -756
    -757
    -758
    -759
    -760
    -761
    -762
    -763
    -764
    -765
    -766
    -767
    -768
    -769
    -770
    -771
    -772
    -773
    -774
    -775
    -776
    -777
    -778
    -779
    -780
    -781
    -782
    -783
    -784
    -785
    -786
    -787
    -788
    -789
    -790
    -791
    -792
    -793
    -794
    -795
    -796
    -797
    -798
    -799
    -800
    -801
    -802
    -803
    -804
    -805
    -806
    -807
    -808
    -809
    -810
    -811
    -812
    -813
    -814
    -815
    -816
    -817
    -818
    -819
    -820
    -821
    -822
    -823
    -824
    -825
    -826
    -827
    -828
    -829
    -830
    -831
    -832
    -833
    -834
    -835
    -836
    -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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use std::convert::TryInto;
    -use std::fmt;
    -use std::io::{Read, Write};
    -use std::marker::PhantomData;
    -use std::ops::Deref;
    -use std::sync::Arc;
    -use std::sync::RwLock;
    -
    -use rand::distributions::Alphanumeric;
    -use rand::{thread_rng, Rng};
    -
    -use rocksdb::{Direction, IteratorMode, ReadOptions, WriteBatch, DB};
    -
    -use bitcoin::consensus::{deserialize, encode::VarInt, serialize, Decodable, Encodable};
    -use bitcoin::hash_types::FilterHash;
    -use bitcoin::hashes::hex::FromHex;
    -use bitcoin::hashes::{sha256d, Hash};
    -use bitcoin::util::bip158::BlockFilter;
    -use bitcoin::util::uint::Uint256;
    -use bitcoin::Block;
    -use bitcoin::BlockHash;
    -use bitcoin::BlockHeader;
    -use bitcoin::Network;
    -
    -use super::CompactFiltersError;
    -
    -lazy_static! {
    -    static ref MAINNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A29AB5F49FFFF001D1DAC2B7C0101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
    -    static ref TESTNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4ADAE5494DFFFF001D1AA4AE180101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
    -    static ref REGTEST_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4ADAE5494DFFFF7F20020000000101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
    -}
    -
    -pub trait StoreType: Default + fmt::Debug {}
    -
    -#[derive(Default, Debug)]
    -pub struct Full;
    -impl StoreType for Full {}
    -#[derive(Default, Debug)]
    -pub struct Snapshot;
    -impl StoreType for Snapshot {}
    -
    -pub enum StoreEntry {
    -    BlockHeader(Option<usize>),
    -    Block(Option<usize>),
    -    BlockHeaderIndex(Option<BlockHash>),
    -    CFilterTable((u8, Option<usize>)),
    -}
    -
    -impl StoreEntry {
    -    pub fn get_prefix(&self) -> Vec<u8> {
    -        match self {
    -            StoreEntry::BlockHeader(_) => b"z",
    -            StoreEntry::Block(_) => b"x",
    -            StoreEntry::BlockHeaderIndex(_) => b"i",
    -            StoreEntry::CFilterTable(_) => b"t",
    -        }
    -        .to_vec()
    -    }
    -
    -    pub fn get_key(&self) -> Vec<u8> {
    -        let mut prefix = self.get_prefix();
    -        match self {
    -            StoreEntry::BlockHeader(Some(height)) => {
    -                prefix.extend_from_slice(&height.to_be_bytes())
    -            }
    -            StoreEntry::Block(Some(height)) => prefix.extend_from_slice(&height.to_be_bytes()),
    -            StoreEntry::BlockHeaderIndex(Some(hash)) => {
    -                prefix.extend_from_slice(&hash.into_inner())
    -            }
    -            StoreEntry::CFilterTable((filter_type, bundle_index)) => {
    -                prefix.push(*filter_type);
    -                if let Some(bundle_index) = bundle_index {
    -                    prefix.extend_from_slice(&bundle_index.to_be_bytes());
    -                }
    -            }
    -            _ => {}
    -        }
    -
    -        prefix
    -    }
    -}
    -
    -pub trait SerializeDb: Sized {
    -    fn serialize(&self) -> Vec<u8>;
    -    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError>;
    -}
    -
    -impl<T> SerializeDb for T
    -where
    -    T: Encodable + Decodable,
    -{
    -    fn serialize(&self) -> Vec<u8> {
    -        serialize(self)
    -    }
    -
    -    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError> {
    -        Ok(deserialize(data).map_err(|_| CompactFiltersError::DataCorruption)?)
    -    }
    -}
    -
    -impl Encodable for FilterHeader {
    -    fn consensus_encode<W: Write>(
    -        &self,
    -        mut e: W,
    -    ) -> Result<usize, bitcoin::consensus::encode::Error> {
    -        let mut written = self.prev_header_hash.consensus_encode(&mut e)?;
    -        written += self.filter_hash.consensus_encode(&mut e)?;
    -        Ok(written)
    -    }
    -}
    -
    -impl Decodable for FilterHeader {
    -    fn consensus_decode<D: Read>(mut d: D) -> Result<Self, bitcoin::consensus::encode::Error> {
    -        let prev_header_hash = FilterHeaderHash::consensus_decode(&mut d)?;
    -        let filter_hash = FilterHash::consensus_decode(&mut d)?;
    -
    -        Ok(FilterHeader {
    -            prev_header_hash,
    -            filter_hash,
    -        })
    -    }
    -}
    -
    -impl Encodable for BundleStatus {
    -    fn consensus_encode<W: Write>(
    -        &self,
    -        mut e: W,
    -    ) -> Result<usize, bitcoin::consensus::encode::Error> {
    -        let mut written = 0;
    -
    -        match self {
    -            BundleStatus::Init => {
    -                written += 0x00u8.consensus_encode(&mut e)?;
    -            }
    -            BundleStatus::CFHeaders { cf_headers } => {
    -                written += 0x01u8.consensus_encode(&mut e)?;
    -                written += VarInt(cf_headers.len() as u64).consensus_encode(&mut e)?;
    -                for header in cf_headers {
    -                    written += header.consensus_encode(&mut e)?;
    -                }
    -            }
    -            BundleStatus::CFilters { cf_filters } => {
    -                written += 0x02u8.consensus_encode(&mut e)?;
    -                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
    -                for filter in cf_filters {
    -                    written += filter.consensus_encode(&mut e)?;
    -                }
    -            }
    -            BundleStatus::Processed { cf_filters } => {
    -                written += 0x03u8.consensus_encode(&mut e)?;
    -                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
    -                for filter in cf_filters {
    -                    written += filter.consensus_encode(&mut e)?;
    -                }
    -            }
    -            BundleStatus::Pruned => {
    -                written += 0x04u8.consensus_encode(&mut e)?;
    -            }
    -            BundleStatus::Tip { cf_filters } => {
    -                written += 0x05u8.consensus_encode(&mut e)?;
    -                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
    -                for filter in cf_filters {
    -                    written += filter.consensus_encode(&mut e)?;
    -                }
    -            }
    -        }
    -
    -        Ok(written)
    -    }
    -}
    -
    -impl Decodable for BundleStatus {
    -    fn consensus_decode<D: Read>(mut d: D) -> Result<Self, bitcoin::consensus::encode::Error> {
    -        let byte_type = u8::consensus_decode(&mut d)?;
    -        match byte_type {
    -            0x00 => Ok(BundleStatus::Init),
    -            0x01 => {
    -                let num = VarInt::consensus_decode(&mut d)?;
    -                let num = num.0 as usize;
    -
    -                let mut cf_headers = Vec::with_capacity(num);
    -                for _ in 0..num {
    -                    cf_headers.push(FilterHeader::consensus_decode(&mut d)?);
    -                }
    -
    -                Ok(BundleStatus::CFHeaders { cf_headers })
    -            }
    -            0x02 => {
    -                let num = VarInt::consensus_decode(&mut d)?;
    -                let num = num.0 as usize;
    -
    -                let mut cf_filters = Vec::with_capacity(num);
    -                for _ in 0..num {
    -                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
    -                }
    -
    -                Ok(BundleStatus::CFilters { cf_filters })
    -            }
    -            0x03 => {
    -                let num = VarInt::consensus_decode(&mut d)?;
    -                let num = num.0 as usize;
    -
    -                let mut cf_filters = Vec::with_capacity(num);
    -                for _ in 0..num {
    -                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
    -                }
    -
    -                Ok(BundleStatus::Processed { cf_filters })
    -            }
    -            0x04 => Ok(BundleStatus::Pruned),
    -            0x05 => {
    -                let num = VarInt::consensus_decode(&mut d)?;
    -                let num = num.0 as usize;
    -
    -                let mut cf_filters = Vec::with_capacity(num);
    -                for _ in 0..num {
    -                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
    -                }
    -
    -                Ok(BundleStatus::Tip { cf_filters })
    -            }
    -            _ => Err(bitcoin::consensus::encode::Error::ParseFailed(
    -                "Invalid byte type",
    -            )),
    -        }
    -    }
    -}
    -
    -pub struct ChainStore<T: StoreType> {
    -    store: Arc<RwLock<DB>>,
    -    cf_name: String,
    -    min_height: usize,
    -    network: Network,
    -    phantom: PhantomData<T>,
    -}
    -
    -impl ChainStore<Full> {
    -    pub fn new(store: DB, network: Network) -> Result<Self, CompactFiltersError> {
    -        let genesis = match network {
    -            Network::Bitcoin => MAINNET_GENESIS.deref(),
    -            Network::Testnet => TESTNET_GENESIS.deref(),
    -            Network::Regtest => REGTEST_GENESIS.deref(),
    -        };
    -
    -        let cf_name = "default".to_string();
    -        let cf_handle = store.cf_handle(&cf_name).unwrap();
    -
    -        let genesis_key = StoreEntry::BlockHeader(Some(0)).get_key();
    -
    -        if store.get_pinned_cf(cf_handle, &genesis_key)?.is_none() {
    -            let mut batch = WriteBatch::default();
    -            batch.put_cf(
    -                cf_handle,
    -                genesis_key,
    -                (genesis.header, genesis.header.work()).serialize(),
    -            );
    -            batch.put_cf(
    -                cf_handle,
    -                StoreEntry::BlockHeaderIndex(Some(genesis.block_hash())).get_key(),
    -                &0usize.to_be_bytes(),
    -            );
    -            store.write(batch)?;
    -        }
    -
    -        Ok(ChainStore {
    -            store: Arc::new(RwLock::new(store)),
    -            cf_name,
    -            min_height: 0,
    -            network,
    -            phantom: PhantomData,
    -        })
    -    }
    -
    -    pub fn get_locators(&self) -> Result<Vec<(BlockHash, usize)>, CompactFiltersError> {
    -        let mut step = 1;
    -        let mut index = self.get_height()?;
    -        let mut answer = Vec::new();
    -
    -        let store_read = self.store.read().unwrap();
    -        let cf_handle = store_read.cf_handle(&self.cf_name).unwrap();
    -
    -        loop {
    -            if answer.len() > 10 {
    -                step *= 2;
    -            }
    -
    -            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(
    -                &store_read
    -                    .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(index)).get_key())?
    -                    .unwrap(),
    -            )?;
    -            answer.push((header.block_hash(), index));
    -
    -            if let Some(new_index) = index.checked_sub(step) {
    -                index = new_index;
    -            } else {
    -                break;
    -            }
    -        }
    -
    -        Ok(answer)
    -    }
    -
    -    pub fn start_snapshot(&self, from: usize) -> Result<ChainStore<Snapshot>, CompactFiltersError> {
    -        let new_cf_name: String = thread_rng().sample_iter(&Alphanumeric).take(16).collect();
    -        let new_cf_name = format!("_headers:{}", new_cf_name);
    -
    -        let mut write_store = self.store.write().unwrap();
    -
    -        write_store.create_cf(&new_cf_name, &Default::default())?;
    -
    -        let cf_handle = write_store.cf_handle(&self.cf_name).unwrap();
    -        let new_cf_handle = write_store.cf_handle(&new_cf_name).unwrap();
    -
    -        let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(
    -            &write_store
    -                .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
    -                .ok_or(CompactFiltersError::DataCorruption)?,
    -        )?;
    -
    -        let mut batch = WriteBatch::default();
    -        batch.put_cf(
    -            new_cf_handle,
    -            StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
    -            &from.to_be_bytes(),
    -        );
    -        batch.put_cf(
    -            new_cf_handle,
    -            StoreEntry::BlockHeader(Some(from)).get_key(),
    -            (header, work).serialize(),
    -        );
    -        write_store.write(batch)?;
    -
    -        let store = Arc::clone(&self.store);
    -        Ok(ChainStore {
    -            store,
    -            cf_name: new_cf_name,
    -            min_height: from,
    -            network: self.network,
    -            phantom: PhantomData,
    -        })
    -    }
    -
    -    pub fn recover_snapshot(&self, cf_name: &str) -> Result<(), CompactFiltersError> {
    -        let mut write_store = self.store.write().unwrap();
    -        let snapshot_cf_handle = write_store.cf_handle(cf_name).unwrap();
    -
    -        let prefix = StoreEntry::BlockHeader(None).get_key();
    -        let mut iterator = write_store.prefix_iterator_cf(snapshot_cf_handle, prefix);
    -
    -        let min_height = match iterator
    -            .next()
    -            .and_then(|(k, _)| k[1..].try_into().ok())
    -            .map(|bytes| usize::from_be_bytes(bytes))
    -        {
    -            None => {
    -                std::mem::drop(iterator);
    -                write_store.drop_cf(cf_name).ok();
    -
    -                return Ok(());
    -            }
    -            Some(x) => x,
    -        };
    -        std::mem::drop(iterator);
    -        std::mem::drop(write_store);
    -
    -        let snapshot = ChainStore {
    -            store: Arc::clone(&self.store),
    -            cf_name: cf_name.into(),
    -            min_height,
    -            network: self.network,
    -            phantom: PhantomData,
    -        };
    -        if snapshot.work()? > self.work()? {
    -            self.apply_snapshot(snapshot)?;
    -        }
    -
    -        Ok(())
    -    }
    -
    -    pub fn apply_snapshot(
    -        &self,
    -        snaphost: ChainStore<Snapshot>,
    -    ) -> Result<(), CompactFiltersError> {
    -        let mut batch = WriteBatch::default();
    -
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -        let snapshot_cf_handle = read_store.cf_handle(&snaphost.cf_name).unwrap();
    -
    -        let from_key = StoreEntry::BlockHeader(Some(snaphost.min_height)).get_key();
    -        let to_key = StoreEntry::BlockHeader(Some(usize::MAX)).get_key();
    -
    -        let mut opts = ReadOptions::default();
    -        opts.set_iterate_upper_bound(to_key.clone());
    -
    -        log::debug!("Removing items");
    -        batch.delete_range_cf(cf_handle, &from_key, &to_key);
    -        for (_, v) in read_store.iterator_cf_opt(
    -            cf_handle,
    -            opts,
    -            IteratorMode::From(&from_key, Direction::Forward),
    -        ) {
    -            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
    -
    -            batch.delete_cf(
    -                cf_handle,
    -                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
    -            );
    -        }
    -
    -        // Delete full blocks overriden by snapshot
    -        let from_key = StoreEntry::Block(Some(snaphost.min_height)).get_key();
    -        let to_key = StoreEntry::Block(Some(usize::MAX)).get_key();
    -        batch.delete_range(&from_key, &to_key);
    -
    -        log::debug!("Copying over new items");
    -        for (k, v) in read_store.iterator_cf(snapshot_cf_handle, IteratorMode::Start) {
    -            batch.put_cf(cf_handle, k, v);
    -        }
    -
    -        read_store.write(batch)?;
    -
    -        std::mem::drop(snapshot_cf_handle);
    -        std::mem::drop(cf_handle);
    -        std::mem::drop(read_store);
    -
    -        self.store.write().unwrap().drop_cf(&snaphost.cf_name)?;
    -
    -        Ok(())
    -    }
    -
    -    pub fn get_height_for(
    -        &self,
    -        block_hash: &BlockHash,
    -    ) -> Result<Option<usize>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let key = StoreEntry::BlockHeaderIndex(Some(block_hash.clone())).get_key();
    -        let data = read_store.get_pinned_cf(cf_handle, key)?;
    -        Ok(data
    -            .map(|data| {
    -                Ok::<_, CompactFiltersError>(usize::from_be_bytes(
    -                    data.as_ref()
    -                        .try_into()
    -                        .map_err(|_| CompactFiltersError::DataCorruption)?,
    -                ))
    -            })
    -            .transpose()?)
    -    }
    -
    -    pub fn get_block_hash(&self, height: usize) -> Result<Option<BlockHash>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let key = StoreEntry::BlockHeader(Some(height)).get_key();
    -        let data = read_store.get_pinned_cf(cf_handle, key)?;
    -        Ok(data
    -            .map(|data| {
    -                let (header, _): (BlockHeader, Uint256) =
    -                    deserialize(&data).map_err(|_| CompactFiltersError::DataCorruption)?;
    -                Ok::<_, CompactFiltersError>(header.block_hash())
    -            })
    -            .transpose()?)
    -    }
    -
    -    pub fn save_full_block(&self, block: &Block, height: usize) -> Result<(), CompactFiltersError> {
    -        let key = StoreEntry::Block(Some(height)).get_key();
    -        self.store.read().unwrap().put(key, block.serialize())?;
    -
    -        Ok(())
    -    }
    -
    -    pub fn get_full_block(&self, height: usize) -> Result<Option<Block>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -
    -        let key = StoreEntry::Block(Some(height)).get_key();
    -        let opt_block = read_store.get_pinned(key)?;
    -
    -        Ok(opt_block
    -            .map(|data| deserialize(&data))
    -            .transpose()
    -            .map_err(|_| CompactFiltersError::DataCorruption)?)
    -    }
    -
    -    pub fn delete_blocks_until(&self, height: usize) -> Result<(), CompactFiltersError> {
    -        let from_key = StoreEntry::Block(Some(0)).get_key();
    -        let to_key = StoreEntry::Block(Some(height)).get_key();
    -
    -        let mut batch = WriteBatch::default();
    -        batch.delete_range(&from_key, &to_key);
    -
    -        self.store.read().unwrap().write(batch)?;
    -
    -        Ok(())
    -    }
    -
    -    pub fn iter_full_blocks(&self) -> Result<Vec<(usize, Block)>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -
    -        let prefix = StoreEntry::Block(None).get_key();
    -
    -        let iterator = read_store.prefix_iterator(&prefix);
    -        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
    -        // have the right prefix
    -        iterator
    -            .filter(|(k, _)| k.starts_with(&prefix))
    -            .map(|(k, v)| {
    -                let height: usize = usize::from_be_bytes(
    -                    k[1..]
    -                        .try_into()
    -                        .map_err(|_| CompactFiltersError::DataCorruption)?,
    -                );
    -                let block = SerializeDb::deserialize(&v)?;
    -
    -                Ok((height, block))
    -            })
    -            .collect::<Result<_, _>>()
    -    }
    -}
    -
    -impl<T: StoreType> ChainStore<T> {
    -    pub fn work(&self) -> Result<Uint256, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let prefix = StoreEntry::BlockHeader(None).get_key();
    -        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
    -
    -        Ok(iterator
    -            .last()
    -            .map(|(_, v)| -> Result<_, CompactFiltersError> {
    -                let (_, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
    -
    -                Ok(work)
    -            })
    -            .transpose()?
    -            .unwrap_or_default())
    -    }
    -
    -    pub fn get_height(&self) -> Result<usize, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let prefix = StoreEntry::BlockHeader(None).get_key();
    -        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
    -
    -        Ok(iterator
    -            .last()
    -            .map(|(k, _)| -> Result<_, CompactFiltersError> {
    -                let height = usize::from_be_bytes(
    -                    k[1..]
    -                        .try_into()
    -                        .map_err(|_| CompactFiltersError::DataCorruption)?,
    -                );
    -
    -                Ok(height)
    -            })
    -            .transpose()?
    -            .unwrap_or_default())
    -    }
    -
    -    pub fn get_tip_hash(&self) -> Result<Option<BlockHash>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let prefix = StoreEntry::BlockHeader(None).get_key();
    -        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
    -
    -        Ok(iterator
    -            .last()
    -            .map(|(_, v)| -> Result<_, CompactFiltersError> {
    -                let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
    -
    -                Ok(header.block_hash())
    -            })
    -            .transpose()?)
    -    }
    -
    -    pub fn apply(
    -        &mut self,
    -        from: usize,
    -        headers: Vec<BlockHeader>,
    -    ) -> Result<BlockHash, CompactFiltersError> {
    -        let mut batch = WriteBatch::default();
    -
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let (mut last_hash, mut accumulated_work) = read_store
    -            .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
    -            .map(|result| {
    -                let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&result)?;
    -                Ok::<_, CompactFiltersError>((header.block_hash(), work))
    -            })
    -            .transpose()?
    -            .ok_or(CompactFiltersError::DataCorruption)?;
    -
    -        for (index, header) in headers.into_iter().enumerate() {
    -            if header.prev_blockhash != last_hash {
    -                return Err(CompactFiltersError::InvalidHeaders);
    -            }
    -
    -            last_hash = header.block_hash();
    -            accumulated_work = accumulated_work + header.work();
    -
    -            let height = from + index + 1;
    -            batch.put_cf(
    -                cf_handle,
    -                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
    -                &(height).to_be_bytes(),
    -            );
    -            batch.put_cf(
    -                cf_handle,
    -                StoreEntry::BlockHeader(Some(height)).get_key(),
    -                (header, accumulated_work).serialize(),
    -            );
    -        }
    -
    -        std::mem::drop(cf_handle);
    -        std::mem::drop(read_store);
    -
    -        self.store.write().unwrap().write(batch)?;
    -        Ok(last_hash)
    -    }
    -}
    -
    -impl<T: StoreType> fmt::Debug for ChainStore<T> {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        f.debug_struct(&format!("ChainStore<{:?}>", T::default()))
    -            .field("cf_name", &self.cf_name)
    -            .field("min_height", &self.min_height)
    -            .field("network", &self.network)
    -            .field("headers_height", &self.get_height())
    -            .field("tip_hash", &self.get_tip_hash())
    -            .finish()
    -    }
    -}
    -
    -pub type FilterHeaderHash = FilterHash;
    -
    -#[derive(Debug, Clone)]
    -pub struct FilterHeader {
    -    prev_header_hash: FilterHeaderHash,
    -    filter_hash: FilterHash,
    -}
    -
    -impl FilterHeader {
    -    fn header_hash(&self) -> FilterHeaderHash {
    -        let mut hash_data = self.filter_hash.into_inner().to_vec();
    -        hash_data.extend_from_slice(&self.prev_header_hash);
    -        sha256d::Hash::hash(&hash_data).into()
    -    }
    -}
    -
    -pub enum BundleStatus {
    -    Init,
    -    CFHeaders { cf_headers: Vec<FilterHeader> },
    -    CFilters { cf_filters: Vec<Vec<u8>> },
    -    Processed { cf_filters: Vec<Vec<u8>> },
    -    Tip { cf_filters: Vec<Vec<u8>> },
    -    Pruned,
    -}
    -
    -pub struct CFStore {
    -    store: Arc<RwLock<DB>>,
    -    filter_type: u8,
    -}
    -
    -type BundleEntry = (BundleStatus, FilterHeaderHash);
    -
    -impl CFStore {
    -    pub fn new(
    -        headers_store: &ChainStore<Full>,
    -        filter_type: u8,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let cf_store = CFStore {
    -            store: Arc::clone(&headers_store.store),
    -            filter_type,
    -        };
    -
    -        let genesis = match headers_store.network {
    -            Network::Bitcoin => MAINNET_GENESIS.deref(),
    -            Network::Testnet => TESTNET_GENESIS.deref(),
    -            Network::Regtest => REGTEST_GENESIS.deref(),
    -        };
    -
    -        let filter = BlockFilter::new_script_filter(genesis, |utxo| {
    -            Err(bitcoin::util::bip158::Error::UtxoMissing(*utxo))
    -        })?;
    -        let first_key = StoreEntry::CFilterTable((filter_type, Some(0))).get_key();
    -
    -        // Add the genesis' filter
    -        {
    -            let read_store = cf_store.store.read().unwrap();
    -            if read_store.get_pinned(&first_key)?.is_none() {
    -                read_store.put(
    -                    &first_key,
    -                    (BundleStatus::Init, filter.filter_id(&FilterHash::default())).serialize(),
    -                )?;
    -            }
    -        }
    -
    -        Ok(cf_store)
    -    }
    -
    -    pub fn get_filter_type(&self) -> u8 {
    -        self.filter_type
    -    }
    -
    -    pub fn get_bundles(&self) -> Result<Vec<BundleEntry>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -
    -        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
    -        let iterator = read_store.prefix_iterator(&prefix);
    -
    -        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
    -        // have the right prefix
    -        iterator
    -            .filter(|(k, _)| k.starts_with(&prefix))
    -            .map(|(_, data)| BundleEntry::deserialize(&data))
    -            .collect::<Result<_, _>>()
    -    }
    -
    -    pub fn get_checkpoints(&self) -> Result<Vec<FilterHash>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -
    -        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
    -        let iterator = read_store.prefix_iterator(&prefix);
    -
    -        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
    -        // have the right prefix
    -        Ok(iterator
    -            .filter(|(k, _)| k.starts_with(&prefix))
    -            .skip(1)
    -            .map(|(_, data)| Ok::<_, CompactFiltersError>(BundleEntry::deserialize(&data)?.1))
    -            .collect::<Result<_, _>>()?)
    -    }
    -
    -    pub fn replace_checkpoints(
    -        &self,
    -        checkpoints: Vec<FilterHash>,
    -    ) -> Result<(), CompactFiltersError> {
    -        let current_checkpoints = self.get_checkpoints()?;
    -
    -        let mut equal_bundles = 0;
    -        for (index, (our, their)) in current_checkpoints
    -            .iter()
    -            .zip(checkpoints.iter())
    -            .enumerate()
    -        {
    -            equal_bundles = index;
    -
    -            if our != their {
    -                break;
    -            }
    -        }
    -
    -        let read_store = self.store.read().unwrap();
    -        let mut batch = WriteBatch::default();
    -
    -        for (index, filter_hash) in checkpoints.iter().enumerate().skip(equal_bundles) {
    -            let key = StoreEntry::CFilterTable((self.filter_type, Some(index + 1))).get_key(); // +1 to skip the genesis' filter
    -
    -            if let Some((BundleStatus::Tip { .. }, _)) = read_store
    -                .get_pinned(&key)?
    -                .map(|data| BundleEntry::deserialize(&data))
    -                .transpose()?
    -            {
    -                println!("Keeping bundle #{} as Tip", index);
    -            } else {
    -                batch.put(&key, (BundleStatus::Init, *filter_hash).serialize());
    -            }
    -        }
    -
    -        read_store.write(batch)?;
    -
    -        Ok(())
    -    }
    -
    -    pub fn advance_to_cf_headers(
    -        &self,
    -        bundle: usize,
    -        checkpoint_hash: FilterHeaderHash,
    -        filter_headers: Vec<FilterHash>,
    -    ) -> Result<BundleStatus, CompactFiltersError> {
    -        let mut last_hash = checkpoint_hash;
    -        let cf_headers = filter_headers
    -            .into_iter()
    -            .map(|filter_hash| {
    -                let filter_header = FilterHeader {
    -                    prev_header_hash: last_hash,
    -                    filter_hash,
    -                };
    -                last_hash = filter_header.header_hash();
    -
    -                filter_header
    -            })
    -            .collect();
    -
    -        let read_store = self.store.read().unwrap();
    -
    -        let next_key = StoreEntry::CFilterTable((self.filter_type, Some(bundle + 1))).get_key(); // +1 to skip the genesis' filter
    -        if let Some((_, next_checkpoint)) = read_store
    -            .get_pinned(&next_key)?
    -            .map(|data| BundleEntry::deserialize(&data))
    -            .transpose()?
    -        {
    -            // check connection with the next bundle if present
    -            if last_hash != next_checkpoint {
    -                return Err(CompactFiltersError::InvalidFilterHeader);
    -            }
    -        }
    -
    -        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
    -        let value = (BundleStatus::CFHeaders { cf_headers }, checkpoint_hash);
    -
    -        read_store.put(key, value.serialize())?;
    -
    -        Ok(value.0)
    -    }
    -
    -    pub fn advance_to_cf_filters(
    -        &self,
    -        bundle: usize,
    -        checkpoint_hash: FilterHeaderHash,
    -        headers: Vec<FilterHeader>,
    -        filters: Vec<(usize, Vec<u8>)>,
    -    ) -> Result<BundleStatus, CompactFiltersError> {
    -        let cf_filters = filters
    -            .into_iter()
    -            .zip(headers.iter())
    -            .map(|((_, filter_content), header)| {
    -                if header.filter_hash != sha256d::Hash::hash(&filter_content).into() {
    -                    return Err(CompactFiltersError::InvalidFilter);
    -                }
    -
    -                Ok::<_, CompactFiltersError>(filter_content)
    -            })
    -            .collect::<Result<_, _>>()?;
    -
    -        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
    -        let value = (BundleStatus::CFilters { cf_filters }, checkpoint_hash);
    -
    -        let read_store = self.store.read().unwrap();
    -        read_store.put(key, value.serialize())?;
    -
    -        Ok(value.0)
    -    }
    -
    -    pub fn prune_filters(
    -        &self,
    -        bundle: usize,
    -        checkpoint_hash: FilterHeaderHash,
    -    ) -> Result<BundleStatus, CompactFiltersError> {
    -        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
    -        let value = (BundleStatus::Pruned, checkpoint_hash);
    -
    -        let read_store = self.store.read().unwrap();
    -        read_store.put(key, value.serialize())?;
    -
    -        Ok(value.0)
    -    }
    -
    -    pub fn mark_as_tip(
    -        &self,
    -        bundle: usize,
    -        cf_filters: Vec<Vec<u8>>,
    -        checkpoint_hash: FilterHeaderHash,
    -    ) -> Result<BundleStatus, CompactFiltersError> {
    -        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
    -        let value = (BundleStatus::Tip { cf_filters }, checkpoint_hash);
    -
    -        let read_store = self.store.read().unwrap();
    -        read_store.put(key, value.serialize())?;
    -
    -        Ok(value.0)
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/sync.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/sync.rs.html deleted file mode 100644 index 3ac0bf5529..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/compact_filters/sync.rs.html +++ /dev/null @@ -1,632 +0,0 @@ -sync.rs - source - -
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use std::collections::{BTreeMap, HashMap, VecDeque};
    -use std::sync::{Arc, Mutex};
    -use std::time::Duration;
    -
    -use bitcoin::hash_types::{BlockHash, FilterHash};
    -use bitcoin::network::message::NetworkMessage;
    -use bitcoin::network::message_blockdata::GetHeadersMessage;
    -use bitcoin::util::bip158::BlockFilter;
    -
    -use super::peer::*;
    -use super::store::*;
    -use super::CompactFiltersError;
    -use crate::error::Error;
    -
    -pub(crate) const BURIED_CONFIRMATIONS: usize = 100;
    -
    -pub struct CFSync {
    -    headers_store: Arc<ChainStore<Full>>,
    -    cf_store: Arc<CFStore>,
    -    skip_blocks: usize,
    -    bundles: Mutex<VecDeque<(BundleStatus, FilterHash, usize)>>,
    -}
    -
    -impl CFSync {
    -    pub fn new(
    -        headers_store: Arc<ChainStore<Full>>,
    -        skip_blocks: usize,
    -        filter_type: u8,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let cf_store = Arc::new(CFStore::new(&headers_store, filter_type)?);
    -
    -        Ok(CFSync {
    -            headers_store,
    -            cf_store,
    -            skip_blocks,
    -            bundles: Mutex::new(VecDeque::new()),
    -        })
    -    }
    -
    -    pub fn pruned_bundles(&self) -> Result<usize, CompactFiltersError> {
    -        Ok(self
    -            .cf_store
    -            .get_bundles()?
    -            .into_iter()
    -            .skip(self.skip_blocks / 1000)
    -            .fold(0, |acc, (status, _)| match status {
    -                BundleStatus::Pruned => acc + 1,
    -                _ => acc,
    -            }))
    -    }
    -
    -    pub fn prepare_sync(&self, peer: Arc<Peer>) -> Result<(), CompactFiltersError> {
    -        let mut bundles_lock = self.bundles.lock().unwrap();
    -
    -        let resp = peer.get_cf_checkpt(
    -            self.cf_store.get_filter_type(),
    -            self.headers_store.get_tip_hash()?.unwrap(),
    -        )?;
    -        self.cf_store.replace_checkpoints(resp.filter_headers)?;
    -
    -        bundles_lock.clear();
    -        for (index, (status, checkpoint)) in self.cf_store.get_bundles()?.into_iter().enumerate() {
    -            bundles_lock.push_back((status, checkpoint, index));
    -        }
    -
    -        Ok(())
    -    }
    -
    -    pub fn capture_thread_for_sync<F, Q>(
    -        &self,
    -        peer: Arc<Peer>,
    -        process: F,
    -        completed_bundle: Q,
    -    ) -> Result<(), CompactFiltersError>
    -    where
    -        F: Fn(&BlockHash, &BlockFilter) -> Result<bool, CompactFiltersError>,
    -        Q: Fn(usize) -> Result<(), Error>,
    -    {
    -        let current_height = self.headers_store.get_height()?; // TODO: we should update it in case headers_store is also updated
    -
    -        loop {
    -            let (mut status, checkpoint, index) = match self.bundles.lock().unwrap().pop_front() {
    -                None => break,
    -                Some(x) => x,
    -            };
    -
    -            log::debug!(
    -                "Processing bundle #{} - height {} to {}",
    -                index,
    -                index * 1000 + 1,
    -                (index + 1) * 1000
    -            );
    -
    -            let process_received_filters =
    -                |expected_filters| -> Result<BTreeMap<usize, Vec<u8>>, CompactFiltersError> {
    -                    let mut filters_map = BTreeMap::new();
    -                    for _ in 0..expected_filters {
    -                        let filter = peer.pop_cf_filter_resp()?;
    -                        if filter.filter_type != self.cf_store.get_filter_type() {
    -                            return Err(CompactFiltersError::InvalidResponse);
    -                        }
    -
    -                        match self.headers_store.get_height_for(&filter.block_hash)? {
    -                            Some(height) => filters_map.insert(height, filter.filter),
    -                            None => return Err(CompactFiltersError::InvalidFilter),
    -                        };
    -                    }
    -
    -                    Ok(filters_map)
    -                };
    -
    -            let start_height = index * 1000 + 1;
    -            let mut already_processed = 0;
    -
    -            if start_height < self.skip_blocks {
    -                status = self.cf_store.prune_filters(index, checkpoint)?;
    -            }
    -
    -            let stop_height = std::cmp::min(current_height, start_height + 999);
    -            let stop_hash = self.headers_store.get_block_hash(stop_height)?.unwrap();
    -
    -            if let BundleStatus::Init = status {
    -                log::trace!("status: Init");
    -
    -                let resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
    -
    -                assert!(resp.previous_filter == checkpoint);
    -                status =
    -                    self.cf_store
    -                        .advance_to_cf_headers(index, checkpoint, resp.filter_hashes)?;
    -            }
    -            if let BundleStatus::Tip { cf_filters } = status {
    -                log::trace!("status: Tip (beginning) ");
    -
    -                already_processed = cf_filters.len();
    -                let headers_resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
    -
    -                let cf_headers = match self.cf_store.advance_to_cf_headers(
    -                    index,
    -                    checkpoint,
    -                    headers_resp.filter_hashes,
    -                )? {
    -                    BundleStatus::CFHeaders { cf_headers } => cf_headers,
    -                    _ => return Err(CompactFiltersError::InvalidResponse),
    -                };
    -
    -                peer.get_cf_filters(
    -                    self.cf_store.get_filter_type(),
    -                    (start_height + cf_filters.len()) as u32,
    -                    stop_hash,
    -                )?;
    -                let expected_filters = stop_height - start_height + 1 - cf_filters.len();
    -                let filters_map = process_received_filters(expected_filters)?;
    -                let filters = cf_filters
    -                    .into_iter()
    -                    .enumerate()
    -                    .chain(filters_map.into_iter())
    -                    .collect();
    -                status = self
    -                    .cf_store
    -                    .advance_to_cf_filters(index, checkpoint, cf_headers, filters)?;
    -            }
    -            if let BundleStatus::CFHeaders { cf_headers } = status {
    -                log::trace!("status: CFHeaders");
    -
    -                peer.get_cf_filters(
    -                    self.cf_store.get_filter_type(),
    -                    start_height as u32,
    -                    stop_hash,
    -                )?;
    -                let expected_filters = stop_height - start_height + 1;
    -                let filters_map = process_received_filters(expected_filters)?;
    -                status = self.cf_store.advance_to_cf_filters(
    -                    index,
    -                    checkpoint,
    -                    cf_headers,
    -                    filters_map.into_iter().collect(),
    -                )?;
    -            }
    -            if let BundleStatus::CFilters { cf_filters } = status {
    -                log::trace!("status: CFilters");
    -
    -                let last_sync_buried_height = (start_height + already_processed)
    -                    .checked_sub(BURIED_CONFIRMATIONS)
    -                    .unwrap_or(0);
    -
    -                for (filter_index, filter) in cf_filters.iter().enumerate() {
    -                    let height = filter_index + start_height;
    -
    -                    // do not download blocks that were already "buried" since the last sync
    -                    if height < last_sync_buried_height {
    -                        continue;
    -                    }
    -
    -                    let block_hash = self.headers_store.get_block_hash(height)?.unwrap();
    -
    -                    // TODO: also download random blocks?
    -                    if process(&block_hash, &BlockFilter::new(&filter))? {
    -                        log::debug!("Downloading block {}", block_hash);
    -
    -                        let block = peer
    -                            .get_block(block_hash)?
    -                            .ok_or(CompactFiltersError::MissingBlock)?;
    -                        self.headers_store.save_full_block(&block, height)?;
    -                    }
    -                }
    -
    -                status = BundleStatus::Processed { cf_filters };
    -            }
    -            if let BundleStatus::Processed { cf_filters } = status {
    -                log::trace!("status: Processed");
    -
    -                if current_height - stop_height > 1000 {
    -                    status = self.cf_store.prune_filters(index, checkpoint)?;
    -                } else {
    -                    status = self.cf_store.mark_as_tip(index, cf_filters, checkpoint)?;
    -                }
    -
    -                completed_bundle(index)?;
    -            }
    -            if let BundleStatus::Pruned = status {
    -                log::trace!("status: Pruned");
    -            }
    -            if let BundleStatus::Tip { .. } = status {
    -                log::trace!("status: Tip");
    -            }
    -        }
    -
    -        Ok(())
    -    }
    -}
    -
    -pub fn sync_headers<F>(
    -    peer: Arc<Peer>,
    -    store: Arc<ChainStore<Full>>,
    -    sync_fn: F,
    -) -> Result<Option<ChainStore<Snapshot>>, CompactFiltersError>
    -where
    -    F: Fn(usize) -> Result<(), Error>,
    -{
    -    let locators = store.get_locators()?;
    -    let locators_vec = locators.iter().map(|(hash, _)| hash).cloned().collect();
    -    let locators_map: HashMap<_, _> = locators.into_iter().collect();
    -
    -    peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
    -        locators_vec,
    -        Default::default(),
    -    )))?;
    -    let (mut snapshot, mut last_hash) = if let NetworkMessage::Headers(headers) = peer
    -        .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -        .ok_or(CompactFiltersError::Timeout)?
    -    {
    -        if headers.is_empty() {
    -            return Ok(None);
    -        }
    -
    -        match locators_map.get(&headers[0].prev_blockhash) {
    -            None => return Err(CompactFiltersError::InvalidHeaders),
    -            Some(from) => (
    -                store.start_snapshot(*from)?,
    -                headers[0].prev_blockhash.clone(),
    -            ),
    -        }
    -    } else {
    -        return Err(CompactFiltersError::InvalidResponse);
    -    };
    -
    -    let mut sync_height = store.get_height()?;
    -    while sync_height < peer.get_version().start_height as usize {
    -        peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
    -            vec![last_hash],
    -            Default::default(),
    -        )))?;
    -        if let NetworkMessage::Headers(headers) = peer
    -            .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -            .ok_or(CompactFiltersError::Timeout)?
    -        {
    -            let batch_len = headers.len();
    -            last_hash = snapshot.apply(sync_height, headers)?;
    -
    -            sync_height += batch_len;
    -            sync_fn(sync_height)?;
    -        } else {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        }
    -    }
    -
    -    Ok(Some(snapshot))
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/electrum.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/electrum.rs.html deleted file mode 100644 index e40065bc4e..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/electrum.rs.html +++ /dev/null @@ -1,386 +0,0 @@ -electrum.rs - source - -
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Electrum
    -//!
    -//! This module defines a [`Blockchain`] struct that wraps an [`electrum_client::Client`]
    -//! and implements the logic required to populate the wallet's [database](crate::database::Database) by
    -//! querying the inner client.
    -//!
    -//! ## Example
    -//!
    -//! ```no_run
    -//! # use bdk::blockchain::electrum::ElectrumBlockchain;
    -//! let client = electrum_client::Client::new("ssl://electrum.blockstream.info:50002")?;
    -//! let blockchain = ElectrumBlockchain::from(client);
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use std::collections::HashSet;
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -use bitcoin::{BlockHeader, Script, Transaction, Txid};
    -
    -use electrum_client::{Client, ConfigBuilder, ElectrumApi, Socks5Config};
    -
    -use self::utils::{ELSGetHistoryRes, ElectrumLikeSync};
    -use super::*;
    -use crate::database::BatchDatabase;
    -use crate::error::Error;
    -use crate::FeeRate;
    -
    -/// Wrapper over an Electrum Client that implements the required blockchain traits
    -///
    -/// ## Example
    -/// See the [`blockchain::electrum`](crate::blockchain::electrum) module for a usage example.
    -pub struct ElectrumBlockchain(Client);
    -
    -#[cfg(test)]
    -#[cfg(feature = "test-electrum")]
    -#[bdk_blockchain_tests(crate)]
    -fn local_electrs() -> ElectrumBlockchain {
    -    ElectrumBlockchain::from(Client::new(&testutils::get_electrum_url()).unwrap())
    -}
    -
    -impl std::convert::From<Client> for ElectrumBlockchain {
    -    fn from(client: Client) -> Self {
    -        ElectrumBlockchain(client)
    -    }
    -}
    -
    -impl Blockchain for ElectrumBlockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        vec![
    -            Capability::FullHistory,
    -            Capability::GetAnyTx,
    -            Capability::AccurateFees,
    -        ]
    -        .into_iter()
    -        .collect()
    -    }
    -
    -    fn setup<D: BatchDatabase, P: Progress>(
    -        &self,
    -        stop_gap: Option<usize>,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        self.0
    -            .electrum_like_setup(stop_gap, database, progress_update)
    -    }
    -
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        Ok(self.0.transaction_get(txid).map(Option::Some)?)
    -    }
    -
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        Ok(self.0.transaction_broadcast(tx).map(|_| ())?)
    -    }
    -
    -    fn get_height(&self) -> Result<u32, Error> {
    -        // TODO: unsubscribe when added to the client, or is there a better call to use here?
    -
    -        Ok(self
    -            .0
    -            .block_headers_subscribe()
    -            .map(|data| data.height as u32)?)
    -    }
    -
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
    -        Ok(FeeRate::from_btc_per_kvb(
    -            self.0.estimate_fee(target)? as f32
    -        ))
    -    }
    -}
    -
    -impl ElectrumLikeSync for Client {
    -    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script> + Clone>(
    -        &self,
    -        scripts: I,
    -    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error> {
    -        self.batch_script_get_history(scripts)
    -            .map(|v| {
    -                v.into_iter()
    -                    .map(|v| {
    -                        v.into_iter()
    -                            .map(
    -                                |electrum_client::GetHistoryRes {
    -                                     height, tx_hash, ..
    -                                 }| ELSGetHistoryRes {
    -                                    height,
    -                                    tx_hash,
    -                                },
    -                            )
    -                            .collect()
    -                    })
    -                    .collect()
    -            })
    -            .map_err(Error::Electrum)
    -    }
    -
    -    fn els_batch_transaction_get<'s, I: IntoIterator<Item = &'s Txid> + Clone>(
    -        &self,
    -        txids: I,
    -    ) -> Result<Vec<Transaction>, Error> {
    -        self.batch_transaction_get(txids).map_err(Error::Electrum)
    -    }
    -
    -    fn els_batch_block_header<I: IntoIterator<Item = u32> + Clone>(
    -        &self,
    -        heights: I,
    -    ) -> Result<Vec<BlockHeader>, Error> {
    -        self.batch_block_header(heights).map_err(Error::Electrum)
    -    }
    -}
    -
    -/// Configuration for an [`ElectrumBlockchain`]
    -#[derive(Debug, serde::Deserialize, serde::Serialize)]
    -pub struct ElectrumBlockchainConfig {
    -    /// URL of the Electrum server (such as ElectrumX, Esplora, BWT) may start with `ssl://` or `tcp://` and include a port
    -    ///
    -    /// eg. `ssl://electrum.blockstream.info:60002`
    -    pub url: String,
    -    /// URL of the socks5 proxy server or a Tor service
    -    pub socks5: Option<String>,
    -    /// Request retry count
    -    pub retry: u8,
    -    /// Request timeout (seconds)
    -    pub timeout: u8,
    -}
    -
    -impl ConfigurableBlockchain for ElectrumBlockchain {
    -    type Config = ElectrumBlockchainConfig;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        let socks5 = config.socks5.as_ref().map(Socks5Config::new);
    -        let electrum_config = ConfigBuilder::new()
    -            .retry(config.retry)
    -            .socks5(socks5)?
    -            .timeout(config.timeout)?
    -            .build();
    -
    -        Ok(ElectrumBlockchain(Client::from_config(
    -            config.url.as_str(),
    -            electrum_config,
    -        )?))
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/esplora.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/esplora.rs.html deleted file mode 100644 index df6abccb0d..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/esplora.rs.html +++ /dev/null @@ -1,864 +0,0 @@ -esplora.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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Esplora
    -//!
    -//! This module defines a [`Blockchain`] struct that can query an Esplora backend
    -//! populate the wallet's [database](crate::database::Database) by
    -//!
    -//! ## Example
    -//!
    -//! ```no_run
    -//! # use bdk::blockchain::esplora::EsploraBlockchain;
    -//! let blockchain = EsploraBlockchain::new("https://blockstream.info/testnet/api", None);
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use std::collections::{HashMap, HashSet};
    -use std::fmt;
    -
    -use futures::stream::{self, FuturesOrdered, StreamExt, TryStreamExt};
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -use serde::Deserialize;
    -
    -use reqwest::{Client, StatusCode};
    -
    -use bitcoin::consensus::{self, deserialize, serialize};
    -use bitcoin::hashes::hex::{FromHex, ToHex};
    -use bitcoin::hashes::{sha256, Hash};
    -use bitcoin::{BlockHash, BlockHeader, Script, Transaction, Txid};
    -
    -use self::utils::{ELSGetHistoryRes, ElectrumLikeSync};
    -use super::*;
    -use crate::database::BatchDatabase;
    -use crate::error::Error;
    -use crate::wallet::utils::ChunksIterator;
    -use crate::FeeRate;
    -
    -const DEFAULT_CONCURRENT_REQUESTS: u8 = 4;
    -
    -#[derive(Debug)]
    -struct UrlClient {
    -    url: String,
    -    // We use the async client instead of the blocking one because it automatically uses `fetch`
    -    // when the target platform is wasm32.
    -    client: Client,
    -    concurrency: u8,
    -}
    -
    -/// Structure that implements the logic to sync with Esplora
    -///
    -/// ## Example
    -/// See the [`blockchain::esplora`](crate::blockchain::esplora) module for a usage example.
    -#[derive(Debug)]
    -pub struct EsploraBlockchain(UrlClient);
    -
    -impl std::convert::From<UrlClient> for EsploraBlockchain {
    -    fn from(url_client: UrlClient) -> Self {
    -        EsploraBlockchain(url_client)
    -    }
    -}
    -
    -impl EsploraBlockchain {
    -    /// Create a new instance of the client from a base URL
    -    pub fn new(base_url: &str, concurrency: Option<u8>) -> Self {
    -        EsploraBlockchain(UrlClient {
    -            url: base_url.to_string(),
    -            client: Client::new(),
    -            concurrency: concurrency.unwrap_or(DEFAULT_CONCURRENT_REQUESTS),
    -        })
    -    }
    -}
    -
    -#[maybe_async]
    -impl Blockchain for EsploraBlockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        vec![
    -            Capability::FullHistory,
    -            Capability::GetAnyTx,
    -            Capability::AccurateFees,
    -        ]
    -        .into_iter()
    -        .collect()
    -    }
    -
    -    fn setup<D: BatchDatabase, P: Progress>(
    -        &self,
    -        stop_gap: Option<usize>,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        maybe_await!(self
    -            .0
    -            .electrum_like_setup(stop_gap, database, progress_update))
    -    }
    -
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        Ok(await_or_block!(self.0._get_tx(txid))?)
    -    }
    -
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        Ok(await_or_block!(self.0._broadcast(tx))?)
    -    }
    -
    -    fn get_height(&self) -> Result<u32, Error> {
    -        Ok(await_or_block!(self.0._get_height())?)
    -    }
    -
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
    -        let estimates = await_or_block!(self.0._get_fee_estimates())?;
    -
    -        let fee_val = estimates
    -            .into_iter()
    -            .map(|(k, v)| Ok::<_, std::num::ParseIntError>((k.parse::<usize>()?, v)))
    -            .collect::<Result<Vec<_>, _>>()
    -            .map_err(|e| Error::Generic(e.to_string()))?
    -            .into_iter()
    -            .take_while(|(k, _)| k <= &target)
    -            .map(|(_, v)| v)
    -            .last()
    -            .unwrap_or(1.0);
    -
    -        Ok(FeeRate::from_sat_per_vb(fee_val as f32))
    -    }
    -}
    -
    -impl UrlClient {
    -    fn script_to_scripthash(script: &Script) -> String {
    -        sha256::Hash::hash(script.as_bytes()).into_inner().to_hex()
    -    }
    -
    -    async fn _get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, EsploraError> {
    -        let resp = self
    -            .client
    -            .get(&format!("{}/tx/{}/raw", self.url, txid))
    -            .send()
    -            .await?;
    -
    -        if let StatusCode::NOT_FOUND = resp.status() {
    -            return Ok(None);
    -        }
    -
    -        Ok(Some(deserialize(&resp.error_for_status()?.bytes().await?)?))
    -    }
    -
    -    async fn _get_tx_no_opt(&self, txid: &Txid) -> Result<Transaction, EsploraError> {
    -        match self._get_tx(txid).await {
    -            Ok(Some(tx)) => Ok(tx),
    -            Ok(None) => Err(EsploraError::TransactionNotFound(*txid)),
    -            Err(e) => Err(e),
    -        }
    -    }
    -
    -    async fn _get_header(&self, block_height: u32) -> Result<BlockHeader, EsploraError> {
    -        let resp = self
    -            .client
    -            .get(&format!("{}/block-height/{}", self.url, block_height))
    -            .send()
    -            .await?;
    -
    -        if let StatusCode::NOT_FOUND = resp.status() {
    -            return Err(EsploraError::HeaderHeightNotFound(block_height));
    -        }
    -        let bytes = resp.bytes().await?;
    -        let hash = std::str::from_utf8(&bytes)
    -            .map_err(|_| EsploraError::HeaderHeightNotFound(block_height))?;
    -
    -        let resp = self
    -            .client
    -            .get(&format!("{}/block/{}/header", self.url, hash))
    -            .send()
    -            .await?;
    -
    -        let header = deserialize(&Vec::from_hex(&resp.text().await?)?)?;
    -
    -        Ok(header)
    -    }
    -
    -    async fn _broadcast(&self, transaction: &Transaction) -> Result<(), EsploraError> {
    -        self.client
    -            .post(&format!("{}/tx", self.url))
    -            .body(serialize(transaction).to_hex())
    -            .send()
    -            .await?
    -            .error_for_status()?;
    -
    -        Ok(())
    -    }
    -
    -    async fn _get_height(&self) -> Result<u32, EsploraError> {
    -        let req = self
    -            .client
    -            .get(&format!("{}/blocks/tip/height", self.url))
    -            .send()
    -            .await?;
    -
    -        Ok(req.error_for_status()?.text().await?.parse()?)
    -    }
    -
    -    async fn _script_get_history(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Vec<ELSGetHistoryRes>, EsploraError> {
    -        let mut result = Vec::new();
    -        let scripthash = Self::script_to_scripthash(script);
    -
    -        // Add the unconfirmed transactions first
    -        result.extend(
    -            self.client
    -                .get(&format!(
    -                    "{}/scripthash/{}/txs/mempool",
    -                    self.url, scripthash
    -                ))
    -                .send()
    -                .await?
    -                .error_for_status()?
    -                .json::<Vec<EsploraGetHistory>>()
    -                .await?
    -                .into_iter()
    -                .map(|x| ELSGetHistoryRes {
    -                    tx_hash: x.txid,
    -                    height: x.status.block_height.unwrap_or(0) as i32,
    -                }),
    -        );
    -
    -        debug!(
    -            "Found {} mempool txs for {} - {:?}",
    -            result.len(),
    -            scripthash,
    -            script
    -        );
    -
    -        // Then go through all the pages of confirmed transactions
    -        let mut last_txid = String::new();
    -        loop {
    -            let response = self
    -                .client
    -                .get(&format!(
    -                    "{}/scripthash/{}/txs/chain/{}",
    -                    self.url, scripthash, last_txid
    -                ))
    -                .send()
    -                .await?
    -                .error_for_status()?
    -                .json::<Vec<EsploraGetHistory>>()
    -                .await?;
    -            let len = response.len();
    -            if let Some(elem) = response.last() {
    -                last_txid = elem.txid.to_hex();
    -            }
    -
    -            debug!("... adding {} confirmed transactions", len);
    -
    -            result.extend(response.into_iter().map(|x| ELSGetHistoryRes {
    -                tx_hash: x.txid,
    -                height: x.status.block_height.unwrap_or(0) as i32,
    -            }));
    -
    -            if len < 25 {
    -                break;
    -            }
    -        }
    -
    -        Ok(result)
    -    }
    -
    -    async fn _get_fee_estimates(&self) -> Result<HashMap<String, f64>, EsploraError> {
    -        Ok(self
    -            .client
    -            .get(&format!("{}/fee-estimates", self.url,))
    -            .send()
    -            .await?
    -            .error_for_status()?
    -            .json::<HashMap<String, f64>>()
    -            .await?)
    -    }
    -}
    -
    -#[maybe_async]
    -impl ElectrumLikeSync for UrlClient {
    -    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
    -        &self,
    -        scripts: I,
    -    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error> {
    -        let future = async {
    -            let mut results = vec![];
    -            for chunk in ChunksIterator::new(scripts.into_iter(), self.concurrency as usize) {
    -                let mut futs = FuturesOrdered::new();
    -                for script in chunk {
    -                    futs.push(self._script_get_history(&script));
    -                }
    -                let partial_results: Vec<Vec<ELSGetHistoryRes>> = futs.try_collect().await?;
    -                results.extend(partial_results);
    -            }
    -            Ok(stream::iter(results).collect().await)
    -        };
    -
    -        await_or_block!(future)
    -    }
    -
    -    fn els_batch_transaction_get<'s, I: IntoIterator<Item = &'s Txid>>(
    -        &self,
    -        txids: I,
    -    ) -> Result<Vec<Transaction>, Error> {
    -        let future = async {
    -            let mut results = vec![];
    -            for chunk in ChunksIterator::new(txids.into_iter(), self.concurrency as usize) {
    -                let mut futs = FuturesOrdered::new();
    -                for txid in chunk {
    -                    futs.push(self._get_tx_no_opt(&txid));
    -                }
    -                let partial_results: Vec<Transaction> = futs.try_collect().await?;
    -                results.extend(partial_results);
    -            }
    -            Ok(stream::iter(results).collect().await)
    -        };
    -
    -        await_or_block!(future)
    -    }
    -
    -    fn els_batch_block_header<I: IntoIterator<Item = u32>>(
    -        &self,
    -        heights: I,
    -    ) -> Result<Vec<BlockHeader>, Error> {
    -        let future = async {
    -            let mut results = vec![];
    -            for chunk in ChunksIterator::new(heights.into_iter(), self.concurrency as usize) {
    -                let mut futs = FuturesOrdered::new();
    -                for height in chunk {
    -                    futs.push(self._get_header(height));
    -                }
    -                let partial_results: Vec<BlockHeader> = futs.try_collect().await?;
    -                results.extend(partial_results);
    -            }
    -            Ok(stream::iter(results).collect().await)
    -        };
    -
    -        await_or_block!(future)
    -    }
    -}
    -
    -#[derive(Deserialize)]
    -struct EsploraGetHistoryStatus {
    -    block_height: Option<usize>,
    -}
    -
    -#[derive(Deserialize)]
    -struct EsploraGetHistory {
    -    txid: Txid,
    -    status: EsploraGetHistoryStatus,
    -}
    -
    -/// Configuration for an [`EsploraBlockchain`]
    -#[derive(Debug, serde::Deserialize, serde::Serialize)]
    -pub struct EsploraBlockchainConfig {
    -    /// Base URL of the esplora service
    -    ///
    -    /// eg. `https://blockstream.info/api/`
    -    pub base_url: String,
    -    /// Number of parallel requests sent to the esplora service (default: 4)
    -    pub concurrency: Option<u8>,
    -}
    -
    -impl ConfigurableBlockchain for EsploraBlockchain {
    -    type Config = EsploraBlockchainConfig;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        Ok(EsploraBlockchain::new(
    -            config.base_url.as_str(),
    -            config.concurrency,
    -        ))
    -    }
    -}
    -
    -/// Errors that can happen during a sync with [`EsploraBlockchain`]
    -#[derive(Debug)]
    -pub enum EsploraError {
    -    /// Error with the HTTP call
    -    Reqwest(reqwest::Error),
    -    /// Invalid number returned
    -    Parsing(std::num::ParseIntError),
    -    /// Invalid Bitcoin data returned
    -    BitcoinEncoding(bitcoin::consensus::encode::Error),
    -    /// Invalid Hex data returned
    -    Hex(bitcoin::hashes::hex::Error),
    -
    -    /// Transaction not found
    -    TransactionNotFound(Txid),
    -    /// Header height not found
    -    HeaderHeightNotFound(u32),
    -    /// Header hash not found
    -    HeaderHashNotFound(BlockHash),
    -}
    -
    -impl fmt::Display for EsploraError {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for EsploraError {}
    -
    -impl_error!(reqwest::Error, Reqwest, EsploraError);
    -impl_error!(std::num::ParseIntError, Parsing, EsploraError);
    -impl_error!(consensus::encode::Error, BitcoinEncoding, EsploraError);
    -impl_error!(bitcoin::hashes::hex::Error, Hex, EsploraError);
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/mod.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/mod.rs.html deleted file mode 100644 index 75931fe4bf..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/mod.rs.html +++ /dev/null @@ -1,554 +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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Blockchain backends
    -//!
    -//! This module provides the implementation of a few commonly-used backends like
    -//! [Electrum](crate::blockchain::electrum), [Esplora](crate::blockchain::esplora) and
    -//! [Compact Filters/Neutrino](crate::blockchain::compact_filters), along with a generalized trait
    -//! [`Blockchain`] that can be implemented to build customized backends.
    -
    -use std::collections::HashSet;
    -use std::ops::Deref;
    -use std::sync::mpsc::{channel, Receiver, Sender};
    -use std::sync::Arc;
    -
    -use bitcoin::{Transaction, Txid};
    -
    -use crate::database::BatchDatabase;
    -use crate::error::Error;
    -use crate::FeeRate;
    -
    -#[cfg(any(feature = "electrum", feature = "esplora"))]
    -pub(crate) mod utils;
    -
    -#[cfg(any(feature = "electrum", feature = "esplora", feature = "compact_filters"))]
    -pub mod any;
    -#[cfg(any(feature = "electrum", feature = "esplora", feature = "compact_filters"))]
    -pub use any::{AnyBlockchain, AnyBlockchainConfig};
    -
    -#[cfg(feature = "electrum")]
    -#[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
    -pub mod electrum;
    -#[cfg(feature = "electrum")]
    -pub use self::electrum::ElectrumBlockchain;
    -#[cfg(feature = "electrum")]
    -pub use self::electrum::ElectrumBlockchainConfig;
    -
    -#[cfg(feature = "esplora")]
    -#[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
    -pub mod esplora;
    -#[cfg(feature = "esplora")]
    -pub use self::esplora::EsploraBlockchain;
    -
    -#[cfg(feature = "compact_filters")]
    -#[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
    -pub mod compact_filters;
    -#[cfg(feature = "compact_filters")]
    -pub use self::compact_filters::CompactFiltersBlockchain;
    -
    -/// Capabilities that can be supported by a [`Blockchain`] backend
    -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
    -pub enum Capability {
    -    /// Can recover the full history of a wallet and not only the set of currently spendable UTXOs
    -    FullHistory,
    -    /// Can fetch any historical transaction given its txid
    -    GetAnyTx,
    -    /// Can compute accurate fees for the transactions found during sync
    -    AccurateFees,
    -}
    -
    -/// Marker trait for a blockchain backend
    -///
    -/// This is a marker trait for blockchain types. It is automatically implemented for types that
    -/// implement [`Blockchain`], so as a user of the library you won't have to implement this
    -/// manually.
    -///
    -/// Users of the library will probably never have to implement this trait manually, but they
    -/// could still need to import it to define types and structs with generics;
    -/// Implementing only the marker trait is pointless, since [`OfflineBlockchain`]
    -/// already does that, and whenever [`Blockchain`] is implemented, the marker trait is also
    -/// automatically implemented by the library.
    -pub trait BlockchainMarker {}
    -
    -/// The [`BlockchainMarker`] marker trait is automatically implemented for [`Blockchain`] types
    -impl<T: Blockchain> BlockchainMarker for T {}
    -
    -/// Type that only implements [`BlockchainMarker`] and is always "offline"
    -pub struct OfflineBlockchain;
    -impl BlockchainMarker for OfflineBlockchain {}
    -
    -/// Trait that defines the actions that must be supported by a blockchain backend
    -#[maybe_async]
    -pub trait Blockchain: BlockchainMarker {
    -    /// Return the set of [`Capability`] supported by this backend
    -    fn get_capabilities(&self) -> HashSet<Capability>;
    -
    -    /// Setup the backend and populate the internal database for the first time
    -    ///
    -    /// This method is the equivalent of [`Blockchain::sync`], but it's guaranteed to only be
    -    /// called once, at the first [`Wallet::sync`](crate::wallet::Wallet::sync).
    -    ///
    -    /// The rationale behind the distinction between `sync` and `setup` is that some custom backends
    -    /// might need to perform specific actions only the first time they are synced.
    -    ///
    -    /// For types that do not have that distinction, only this method can be implemented, since
    -    /// [`Blockchain::sync`] defaults to calling this internally if not overridden.
    -    fn setup<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        stop_gap: Option<usize>,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error>;
    -    /// Populate the internal database with transactions and UTXOs
    -    ///
    -    /// If not overridden, it defaults to calling [`Blockchain::setup`] internally.
    -    ///
    -    /// This method should implement the logic required to iterate over the list of the wallet's
    -    /// script_pubkeys using [`Database::iter_script_pubkeys`] and look for relevant transactions
    -    /// in the blockchain to populate the database with [`BatchOperations::set_tx`] and
    -    /// [`BatchOperations::set_utxo`].
    -    ///
    -    /// This method should also take care of removing UTXOs that are seen as spent in the
    -    /// blockchain, using [`BatchOperations::del_utxo`].
    -    ///
    -    /// The `progress_update` object can be used to give the caller updates about the progress by using
    -    /// [`Progress::update`].
    -    ///
    -    /// [`Database::iter_script_pubkeys`]: crate::database::Database::iter_script_pubkeys
    -    /// [`BatchOperations::set_tx`]: crate::database::BatchOperations::set_tx
    -    /// [`BatchOperations::set_utxo`]: crate::database::BatchOperations::set_utxo
    -    /// [`BatchOperations::del_utxo`]: crate::database::BatchOperations::del_utxo
    -    fn sync<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        stop_gap: Option<usize>,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        maybe_await!(self.setup(stop_gap, database, progress_update))
    -    }
    -
    -    /// Fetch a transaction from the blockchain given its txid
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
    -    /// Broadcast a transaction
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error>;
    -
    -    /// Return the current height
    -    fn get_height(&self) -> Result<u32, Error>;
    -    /// Estimate the fee rate required to confirm a transaction in a given `target` of blocks
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>;
    -}
    -
    -/// Trait for [`Blockchain`] types that can be created given a configuration
    -pub trait ConfigurableBlockchain: Blockchain + Sized {
    -    /// Type that contains the configuration
    -    type Config: std::fmt::Debug;
    -
    -    /// Create a new instance given a configuration
    -    fn from_config(config: &Self::Config) -> Result<Self, Error>;
    -}
    -
    -/// Data sent with a progress update over a [`channel`]
    -pub type ProgressData = (f32, Option<String>);
    -
    -/// Trait for types that can receive and process progress updates during [`Blockchain::sync`] and
    -/// [`Blockchain::setup`]
    -pub trait Progress: Send {
    -    /// Send a new progress update
    -    ///
    -    /// The `progress` value should be in the range 0.0 - 100.0, and the `message` value is an
    -    /// optional text message that can be displayed to the user.
    -    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error>;
    -}
    -
    -/// Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]
    -pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>) {
    -    channel()
    -}
    -
    -impl Progress for Sender<ProgressData> {
    -    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
    -        if progress < 0.0 || progress > 100.0 {
    -            return Err(Error::InvalidProgressValue(progress));
    -        }
    -
    -        self.send((progress, message))
    -            .map_err(|_| Error::ProgressUpdateError)
    -    }
    -}
    -
    -/// Type that implements [`Progress`] and drops every update received
    -#[derive(Clone)]
    -pub struct NoopProgress;
    -
    -/// Create a new instance of [`NoopProgress`]
    -pub fn noop_progress() -> NoopProgress {
    -    NoopProgress
    -}
    -
    -impl Progress for NoopProgress {
    -    fn update(&self, _progress: f32, _message: Option<String>) -> Result<(), Error> {
    -        Ok(())
    -    }
    -}
    -
    -/// Type that implements [`Progress`] and logs at level `INFO` every update received
    -#[derive(Clone)]
    -pub struct LogProgress;
    -
    -/// Create a nwe instance of [`LogProgress`]
    -pub fn log_progress() -> LogProgress {
    -    LogProgress
    -}
    -
    -impl Progress for LogProgress {
    -    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
    -        log::info!(
    -            "Sync {:.3}%: `{}`",
    -            progress,
    -            message.unwrap_or_else(|| "".into())
    -        );
    -
    -        Ok(())
    -    }
    -}
    -
    -#[maybe_async]
    -impl<T: Blockchain> Blockchain for Arc<T> {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        maybe_await!(self.deref().get_capabilities())
    -    }
    -
    -    fn setup<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        stop_gap: Option<usize>,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        maybe_await!(self.deref().setup(stop_gap, database, progress_update))
    -    }
    -
    -    fn sync<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        stop_gap: Option<usize>,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        maybe_await!(self.deref().sync(stop_gap, database, progress_update))
    -    }
    -
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        maybe_await!(self.deref().get_tx(txid))
    -    }
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        maybe_await!(self.deref().broadcast(tx))
    -    }
    -
    -    fn get_height(&self) -> Result<u32, Error> {
    -        maybe_await!(self.deref().get_height())
    -    }
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
    -        maybe_await!(self.deref().estimate_fee(target))
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/utils.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/utils.rs.html deleted file mode 100644 index 8cbfbf4840..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/blockchain/utils.rs.html +++ /dev/null @@ -1,800 +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
    -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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use std::collections::{HashMap, HashSet};
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -use rand::seq::SliceRandom;
    -use rand::thread_rng;
    -
    -use bitcoin::{BlockHeader, OutPoint, Script, Transaction, Txid};
    -
    -use super::*;
    -use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
    -use crate::error::Error;
    -use crate::types::{KeychainKind, TransactionDetails, UTXO};
    -use crate::wallet::time::Instant;
    -use crate::wallet::utils::ChunksIterator;
    -
    -#[derive(Debug)]
    -pub struct ELSGetHistoryRes {
    -    pub height: i32,
    -    pub tx_hash: Txid,
    -}
    -
    -/// Implements the synchronization logic for an Electrum-like client.
    -#[maybe_async]
    -pub trait ElectrumLikeSync {
    -    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script> + Clone>(
    -        &self,
    -        scripts: I,
    -    ) -> Result<Vec<Vec<ELSGetHistoryRes>>, Error>;
    -
    -    fn els_batch_transaction_get<'s, I: IntoIterator<Item = &'s Txid> + Clone>(
    -        &self,
    -        txids: I,
    -    ) -> Result<Vec<Transaction>, Error>;
    -
    -    fn els_batch_block_header<I: IntoIterator<Item = u32> + Clone>(
    -        &self,
    -        heights: I,
    -    ) -> Result<Vec<BlockHeader>, Error>;
    -
    -    // Provided methods down here...
    -
    -    fn electrum_like_setup<D: BatchDatabase, P: Progress>(
    -        &self,
    -        stop_gap: Option<usize>,
    -        db: &mut D,
    -        _progress_update: P,
    -    ) -> Result<(), Error> {
    -        // TODO: progress
    -        let start = Instant::new();
    -        debug!("start setup");
    -
    -        let stop_gap = stop_gap.unwrap_or(20);
    -        let chunk_size = stop_gap;
    -
    -        let mut history_txs_id = HashSet::new();
    -        let mut txid_height = HashMap::new();
    -        let mut max_indexes = HashMap::new();
    -
    -        let mut wallet_chains = vec![KeychainKind::Internal, KeychainKind::External];
    -        // shuffling improve privacy, the server doesn't know my first request is from my internal or external addresses
    -        wallet_chains.shuffle(&mut thread_rng());
    -        // download history of our internal and external script_pubkeys
    -        for keychain in wallet_chains.iter() {
    -            let script_iter = db.iter_script_pubkeys(Some(*keychain))?.into_iter();
    -
    -            for (i, chunk) in ChunksIterator::new(script_iter, stop_gap).enumerate() {
    -                // TODO if i == last, should create another chunk of addresses in db
    -                let call_result: Vec<Vec<ELSGetHistoryRes>> =
    -                    maybe_await!(self.els_batch_script_get_history(chunk.iter()))?;
    -                let max_index = call_result
    -                    .iter()
    -                    .enumerate()
    -                    .filter_map(|(i, v)| v.first().map(|_| i as u32))
    -                    .max();
    -                if let Some(max) = max_index {
    -                    max_indexes.insert(keychain, max + (i * chunk_size) as u32);
    -                }
    -                let flattened: Vec<ELSGetHistoryRes> = call_result.into_iter().flatten().collect();
    -                debug!("#{} of {:?} results:{}", i, keychain, flattened.len());
    -                if flattened.is_empty() {
    -                    // Didn't find anything in the last `stop_gap` script_pubkeys, breaking
    -                    break;
    -                }
    -
    -                for el in flattened {
    -                    // el.height = -1 means unconfirmed with unconfirmed parents
    -                    // el.height =  0 means unconfirmed with confirmed parents
    -                    // but we treat those tx the same
    -                    if el.height <= 0 {
    -                        txid_height.insert(el.tx_hash, None);
    -                    } else {
    -                        txid_height.insert(el.tx_hash, Some(el.height as u32));
    -                    }
    -                    history_txs_id.insert(el.tx_hash);
    -                }
    -            }
    -        }
    -
    -        // saving max indexes
    -        info!("max indexes are: {:?}", max_indexes);
    -        for keychain in wallet_chains.iter() {
    -            if let Some(index) = max_indexes.get(keychain) {
    -                db.set_last_index(*keychain, *index)?;
    -            }
    -        }
    -
    -        // get db status
    -        let txs_details_in_db: HashMap<Txid, TransactionDetails> = db
    -            .iter_txs(false)?
    -            .into_iter()
    -            .map(|tx| (tx.txid, tx))
    -            .collect();
    -        let txs_raw_in_db: HashMap<Txid, Transaction> = db
    -            .iter_raw_txs()?
    -            .into_iter()
    -            .map(|tx| (tx.txid(), tx))
    -            .collect();
    -        let utxos_deps = utxos_deps(db, &txs_raw_in_db)?;
    -
    -        // download new txs and headers
    -        let new_txs = maybe_await!(self.download_and_save_needed_raw_txs(
    -            &history_txs_id,
    -            &txs_raw_in_db,
    -            chunk_size,
    -            db
    -        ))?;
    -        let new_timestamps = maybe_await!(self.download_needed_headers(
    -            &txid_height,
    -            &txs_details_in_db,
    -            chunk_size
    -        ))?;
    -
    -        let mut batch = db.begin_batch();
    -
    -        // save any tx details not in db but in history_txs_id or with different height/timestamp
    -        for txid in history_txs_id.iter() {
    -            let height = txid_height.get(txid).cloned().flatten();
    -            let timestamp = *new_timestamps.get(txid).unwrap_or(&0u64);
    -            if let Some(tx_details) = txs_details_in_db.get(txid) {
    -                // check if height matches, otherwise updates it
    -                if tx_details.height != height {
    -                    let mut new_tx_details = tx_details.clone();
    -                    new_tx_details.height = height;
    -                    new_tx_details.timestamp = timestamp;
    -                    batch.set_tx(&new_tx_details)?;
    -                }
    -            } else {
    -                save_transaction_details_and_utxos(
    -                    &txid,
    -                    db,
    -                    timestamp,
    -                    height,
    -                    &mut batch,
    -                    &utxos_deps,
    -                )?;
    -            }
    -        }
    -
    -        // remove any tx details in db but not in history_txs_id
    -        for txid in txs_details_in_db.keys() {
    -            if !history_txs_id.contains(txid) {
    -                batch.del_tx(&txid, false)?;
    -            }
    -        }
    -
    -        // remove any spent utxo
    -        for new_tx in new_txs.iter() {
    -            for input in new_tx.input.iter() {
    -                batch.del_utxo(&input.previous_output)?;
    -            }
    -        }
    -
    -        db.commit_batch(batch)?;
    -        info!("finish setup, elapsed {:?}ms", start.elapsed().as_millis());
    -
    -        Ok(())
    -    }
    -
    -    /// download txs identified by `history_txs_id` and theirs previous outputs if not already present in db
    -    fn download_and_save_needed_raw_txs<D: BatchDatabase>(
    -        &self,
    -        history_txs_id: &HashSet<Txid>,
    -        txs_raw_in_db: &HashMap<Txid, Transaction>,
    -        chunk_size: usize,
    -        db: &mut D,
    -    ) -> Result<Vec<Transaction>, Error> {
    -        let mut txs_downloaded = vec![];
    -        let txids_raw_in_db: HashSet<Txid> = txs_raw_in_db.keys().cloned().collect();
    -        let txids_to_download: Vec<&Txid> = history_txs_id.difference(&txids_raw_in_db).collect();
    -        if !txids_to_download.is_empty() {
    -            info!("got {} txs to download", txids_to_download.len());
    -            txs_downloaded.extend(maybe_await!(self.download_and_save_in_chunks(
    -                txids_to_download,
    -                chunk_size,
    -                db,
    -            ))?);
    -            let mut prev_txids = HashSet::new();
    -            let mut txids_downloaded = HashSet::new();
    -            for tx in txs_downloaded.iter() {
    -                txids_downloaded.insert(tx.txid());
    -                // add every previous input tx, but skip coinbase
    -                for input in tx.input.iter().filter(|i| !i.previous_output.is_null()) {
    -                    prev_txids.insert(input.previous_output.txid);
    -                }
    -            }
    -            let already_present: HashSet<Txid> =
    -                txids_downloaded.union(&txids_raw_in_db).cloned().collect();
    -            let prev_txs_to_download: Vec<&Txid> =
    -                prev_txids.difference(&already_present).collect();
    -            info!("{} previous txs to download", prev_txs_to_download.len());
    -            txs_downloaded.extend(maybe_await!(self.download_and_save_in_chunks(
    -                prev_txs_to_download,
    -                chunk_size,
    -                db,
    -            ))?);
    -        }
    -
    -        Ok(txs_downloaded)
    -    }
    -
    -    /// download headers at heights in `txid_height` if tx details not already present, returns a map Txid -> timestamp
    -    fn download_needed_headers(
    -        &self,
    -        txid_height: &HashMap<Txid, Option<u32>>,
    -        txs_details_in_db: &HashMap<Txid, TransactionDetails>,
    -        chunk_size: usize,
    -    ) -> Result<HashMap<Txid, u64>, Error> {
    -        let mut txid_timestamp = HashMap::new();
    -        let needed_txid_height: HashMap<&Txid, u32> = txid_height
    -            .iter()
    -            .filter(|(t, _)| txs_details_in_db.get(*t).is_none())
    -            .filter_map(|(t, o)| o.map(|h| (t, h)))
    -            .collect();
    -        let needed_heights: HashSet<u32> = needed_txid_height.values().cloned().collect();
    -        if !needed_heights.is_empty() {
    -            info!("{} headers to download for timestamp", needed_heights.len());
    -            let mut height_timestamp: HashMap<u32, u64> = HashMap::new();
    -            for chunk in ChunksIterator::new(needed_heights.into_iter(), chunk_size) {
    -                let call_result: Vec<BlockHeader> =
    -                    maybe_await!(self.els_batch_block_header(chunk.clone()))?;
    -                height_timestamp.extend(
    -                    chunk
    -                        .into_iter()
    -                        .zip(call_result.iter().map(|h| h.time as u64)),
    -                );
    -            }
    -            for (txid, height) in needed_txid_height {
    -                let timestamp = height_timestamp
    -                    .get(&height)
    -                    .ok_or_else(|| Error::Generic("timestamp missing".to_string()))?;
    -                txid_timestamp.insert(*txid, *timestamp);
    -            }
    -        }
    -
    -        Ok(txid_timestamp)
    -    }
    -
    -    fn download_and_save_in_chunks<D: BatchDatabase>(
    -        &self,
    -        to_download: Vec<&Txid>,
    -        chunk_size: usize,
    -        db: &mut D,
    -    ) -> Result<Vec<Transaction>, Error> {
    -        let mut txs_downloaded = vec![];
    -        for chunk in ChunksIterator::new(to_download.into_iter(), chunk_size) {
    -            let call_result: Vec<Transaction> =
    -                maybe_await!(self.els_batch_transaction_get(chunk))?;
    -            let mut batch = db.begin_batch();
    -            for new_tx in call_result.iter() {
    -                batch.set_raw_tx(new_tx)?;
    -            }
    -            db.commit_batch(batch)?;
    -            txs_downloaded.extend(call_result);
    -        }
    -
    -        Ok(txs_downloaded)
    -    }
    -}
    -
    -fn save_transaction_details_and_utxos<D: BatchDatabase>(
    -    txid: &Txid,
    -    db: &mut D,
    -    timestamp: u64,
    -    height: Option<u32>,
    -    updates: &mut dyn BatchOperations,
    -    utxo_deps: &HashMap<OutPoint, OutPoint>,
    -) -> Result<(), Error> {
    -    let tx = db.get_raw_tx(txid)?.ok_or(Error::TransactionNotFound)?;
    -
    -    let mut incoming: u64 = 0;
    -    let mut outgoing: u64 = 0;
    -
    -    let mut inputs_sum: u64 = 0;
    -    let mut outputs_sum: u64 = 0;
    -
    -    // look for our own inputs
    -    for input in tx.input.iter() {
    -        // skip coinbase inputs
    -        if input.previous_output.is_null() {
    -            continue;
    -        }
    -
    -        // We already downloaded all previous output txs in the previous step
    -        if let Some(previous_output) = db.get_previous_output(&input.previous_output)? {
    -            inputs_sum += previous_output.value;
    -
    -            if db.is_mine(&previous_output.script_pubkey)? {
    -                outgoing += previous_output.value;
    -            }
    -        } else {
    -            // The input is not ours, but we still need to count it for the fees
    -            let tx = db
    -                .get_raw_tx(&input.previous_output.txid)?
    -                .ok_or(Error::TransactionNotFound)?;
    -            inputs_sum += tx.output[input.previous_output.vout as usize].value;
    -        }
    -
    -        // removes conflicting UTXO if any (generated from same inputs, like for example RBF)
    -        if let Some(outpoint) = utxo_deps.get(&input.previous_output) {
    -            updates.del_utxo(&outpoint)?;
    -        }
    -    }
    -
    -    for (i, output) in tx.output.iter().enumerate() {
    -        // to compute the fees later
    -        outputs_sum += output.value;
    -
    -        // this output is ours, we have a path to derive it
    -        if let Some((keychain, _child)) = db.get_path_from_script_pubkey(&output.script_pubkey)? {
    -            debug!("{} output #{} is mine, adding utxo", txid, i);
    -            updates.set_utxo(&UTXO {
    -                outpoint: OutPoint::new(tx.txid(), i as u32),
    -                txout: output.clone(),
    -                keychain,
    -            })?;
    -
    -            incoming += output.value;
    -        }
    -    }
    -
    -    let tx_details = TransactionDetails {
    -        txid: tx.txid(),
    -        transaction: Some(tx),
    -        received: incoming,
    -        sent: outgoing,
    -        height,
    -        timestamp,
    -        fees: inputs_sum.saturating_sub(outputs_sum), /* if the tx is a coinbase, fees would be negative */
    -    };
    -    updates.set_tx(&tx_details)?;
    -
    -    Ok(())
    -}
    -
    -/// returns utxo dependency as the inputs needed for the utxo to exist
    -/// `tx_raw_in_db` must contains utxo's generating txs or errors witt [crate::Error::TransactionNotFound]
    -fn utxos_deps<D: BatchDatabase>(
    -    db: &mut D,
    -    tx_raw_in_db: &HashMap<Txid, Transaction>,
    -) -> Result<HashMap<OutPoint, OutPoint>, Error> {
    -    let utxos = db.iter_utxos()?;
    -    let mut utxos_deps = HashMap::new();
    -    for utxo in utxos {
    -        let from_tx = tx_raw_in_db
    -            .get(&utxo.outpoint.txid)
    -            .ok_or(Error::TransactionNotFound)?;
    -        for input in from_tx.input.iter() {
    -            utxos_deps.insert(input.previous_output, utxo.outpoint);
    -        }
    -    }
    -    Ok(utxos_deps)
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/any.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/any.rs.html deleted file mode 100644 index 55b9fbcc5f..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/any.rs.html +++ /dev/null @@ -1,782 +0,0 @@ -any.rs - source - -
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Runtime-checked database types
    -//!
    -//! This module provides the implementation of [`AnyDatabase`] which allows switching the
    -//! inner [`Database`] type at runtime.
    -//!
    -//! ## Example
    -//!
    -//! In this example, `wallet_memory` and `wallet_sled` have the same type of `Wallet<OfflineBlockchain, AnyDatabase>`.
    -//!
    -//! ```no_run
    -//! # use bitcoin::Network;
    -//! # use bdk::database::{AnyDatabase, MemoryDatabase};
    -//! # use bdk::{Wallet, OfflineWallet};
    -//! let memory = MemoryDatabase::default().into();
    -//! let wallet_memory: OfflineWallet<AnyDatabase> =
    -//!     Wallet::new_offline("...", None, Network::Testnet, memory)?;
    -//!
    -//! # #[cfg(feature = "key-value-db")]
    -//! # {
    -//! let sled = sled::open("my-database")?.open_tree("default_tree")?.into();
    -//! let wallet_sled: OfflineWallet<AnyDatabase> =
    -//!     Wallet::new_offline("...", None, Network::Testnet, sled)?;
    -//! # }
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -//!
    -//! When paired with the use of [`ConfigurableDatabase`], it allows creating wallets with any
    -//! database supported using a single line of code:
    -//!
    -//! ```no_run
    -//! # use bitcoin::Network;
    -//! # use bdk::database::*;
    -//! # use bdk::{Wallet, OfflineWallet};
    -//! let config = serde_json::from_str("...")?;
    -//! let database = AnyDatabase::from_config(&config)?;
    -//! let wallet: OfflineWallet<_> = Wallet::new_offline("...", None, Network::Testnet, database)?;
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use super::*;
    -
    -macro_rules! impl_from {
    -    ( $from:ty, $to:ty, $variant:ident, $( $cfg:tt )* ) => {
    -        $( $cfg )*
    -        impl From<$from> for $to {
    -            fn from(inner: $from) -> Self {
    -                <$to>::$variant(inner)
    -            }
    -        }
    -    };
    -}
    -
    -macro_rules! impl_inner_method {
    -    ( $enum_name:ident, $self:expr, $name:ident $(, $args:expr)* ) => {
    -        match $self {
    -            $enum_name::Memory(inner) => inner.$name( $($args, )* ),
    -            #[cfg(feature = "key-value-db")]
    -            $enum_name::Sled(inner) => inner.$name( $($args, )* ),
    -        }
    -    }
    -}
    -
    -/// Type that can contain any of the [`Database`] types defined by the library
    -///
    -/// It allows switching database type at runtime.
    -///
    -/// See [this module](crate::database::any)'s documentation for a usage example.
    -#[derive(Debug)]
    -pub enum AnyDatabase {
    -    /// In-memory ephemeral database
    -    Memory(memory::MemoryDatabase),
    -    #[cfg(feature = "key-value-db")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
    -    /// Simple key-value embedded database based on [`sled`]
    -    Sled(sled::Tree),
    -}
    -
    -impl_from!(memory::MemoryDatabase, AnyDatabase, Memory,);
    -impl_from!(sled::Tree, AnyDatabase, Sled, #[cfg(feature = "key-value-db")]);
    -
    -/// Type that contains any of the [`BatchDatabase::Batch`] types defined by the library
    -pub enum AnyBatch {
    -    /// In-memory ephemeral database
    -    Memory(<memory::MemoryDatabase as BatchDatabase>::Batch),
    -    #[cfg(feature = "key-value-db")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
    -    /// Simple key-value embedded database based on [`sled`]
    -    Sled(<sled::Tree as BatchDatabase>::Batch),
    -}
    -
    -impl_from!(
    -    <memory::MemoryDatabase as BatchDatabase>::Batch,
    -    AnyBatch,
    -    Memory,
    -);
    -impl_from!(<sled::Tree as BatchDatabase>::Batch, AnyBatch, Sled, #[cfg(feature = "key-value-db")]);
    -
    -impl BatchOperations for AnyDatabase {
    -    fn set_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<(), Error> {
    -        impl_inner_method!(
    -            AnyDatabase,
    -            self,
    -            set_script_pubkey,
    -            script,
    -            keychain,
    -            child
    -        )
    -    }
    -    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
    -        impl_inner_method!(AnyDatabase, self, set_utxo, utxo)
    -    }
    -    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
    -        impl_inner_method!(AnyDatabase, self, set_raw_tx, transaction)
    -    }
    -    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
    -        impl_inner_method!(AnyDatabase, self, set_tx, transaction)
    -    }
    -    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
    -        impl_inner_method!(AnyDatabase, self, set_last_index, keychain, value)
    -    }
    -
    -    fn del_script_pubkey_from_path(
    -        &mut self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        impl_inner_method!(
    -            AnyDatabase,
    -            self,
    -            del_script_pubkey_from_path,
    -            keychain,
    -            child
    -        )
    -    }
    -    fn del_path_from_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        impl_inner_method!(AnyDatabase, self, del_path_from_script_pubkey, script)
    -    }
    -    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
    -        impl_inner_method!(AnyDatabase, self, del_utxo, outpoint)
    -    }
    -    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        impl_inner_method!(AnyDatabase, self, del_raw_tx, txid)
    -    }
    -    fn del_tx(
    -        &mut self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error> {
    -        impl_inner_method!(AnyDatabase, self, del_tx, txid, include_raw)
    -    }
    -    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        impl_inner_method!(AnyDatabase, self, del_last_index, keychain)
    -    }
    -}
    -
    -impl Database for AnyDatabase {
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        keychain: KeychainKind,
    -        bytes: B,
    -    ) -> Result<(), Error> {
    -        impl_inner_method!(
    -            AnyDatabase,
    -            self,
    -            check_descriptor_checksum,
    -            keychain,
    -            bytes
    -        )
    -    }
    -
    -    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
    -        impl_inner_method!(AnyDatabase, self, iter_script_pubkeys, keychain)
    -    }
    -    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error> {
    -        impl_inner_method!(AnyDatabase, self, iter_utxos)
    -    }
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
    -        impl_inner_method!(AnyDatabase, self, iter_raw_txs)
    -    }
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        impl_inner_method!(AnyDatabase, self, iter_txs, include_raw)
    -    }
    -
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        impl_inner_method!(
    -            AnyDatabase,
    -            self,
    -            get_script_pubkey_from_path,
    -            keychain,
    -            child
    -        )
    -    }
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        impl_inner_method!(AnyDatabase, self, get_path_from_script_pubkey, script)
    -    }
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
    -        impl_inner_method!(AnyDatabase, self, get_utxo, outpoint)
    -    }
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        impl_inner_method!(AnyDatabase, self, get_raw_tx, txid)
    -    }
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -        impl_inner_method!(AnyDatabase, self, get_tx, txid, include_raw)
    -    }
    -    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        impl_inner_method!(AnyDatabase, self, get_last_index, keychain)
    -    }
    -
    -    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
    -        impl_inner_method!(AnyDatabase, self, increment_last_index, keychain)
    -    }
    -}
    -
    -impl BatchOperations for AnyBatch {
    -    fn set_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<(), Error> {
    -        impl_inner_method!(AnyBatch, self, set_script_pubkey, script, keychain, child)
    -    }
    -    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
    -        impl_inner_method!(AnyBatch, self, set_utxo, utxo)
    -    }
    -    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
    -        impl_inner_method!(AnyBatch, self, set_raw_tx, transaction)
    -    }
    -    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
    -        impl_inner_method!(AnyBatch, self, set_tx, transaction)
    -    }
    -    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
    -        impl_inner_method!(AnyBatch, self, set_last_index, keychain, value)
    -    }
    -
    -    fn del_script_pubkey_from_path(
    -        &mut self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_script_pubkey_from_path, keychain, child)
    -    }
    -    fn del_path_from_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_path_from_script_pubkey, script)
    -    }
    -    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_utxo, outpoint)
    -    }
    -    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_raw_tx, txid)
    -    }
    -    fn del_tx(
    -        &mut self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_tx, txid, include_raw)
    -    }
    -    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_last_index, keychain)
    -    }
    -}
    -
    -impl BatchDatabase for AnyDatabase {
    -    type Batch = AnyBatch;
    -
    -    fn begin_batch(&self) -> Self::Batch {
    -        match self {
    -            AnyDatabase::Memory(inner) => inner.begin_batch().into(),
    -            #[cfg(feature = "key-value-db")]
    -            AnyDatabase::Sled(inner) => inner.begin_batch().into(),
    -        }
    -    }
    -    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
    -        // TODO: refactor once `move_ref_pattern` is stable
    -        #[allow(irrefutable_let_patterns)]
    -        match self {
    -            AnyDatabase::Memory(db) => {
    -                if let AnyBatch::Memory(batch) = batch {
    -                    db.commit_batch(batch)
    -                } else {
    -                    unimplemented!()
    -                }
    -            }
    -            #[cfg(feature = "key-value-db")]
    -            AnyDatabase::Sled(db) => {
    -                if let AnyBatch::Sled(batch) = batch {
    -                    db.commit_batch(batch)
    -                } else {
    -                    unimplemented!()
    -                }
    -            }
    -        }
    -    }
    -}
    -
    -/// Configuration type for a [`sled::Tree`] database
    -#[cfg(feature = "key-value-db")]
    -#[derive(Debug, serde::Serialize, serde::Deserialize)]
    -pub struct SledDbConfiguration {
    -    /// Main directory of the db
    -    pub path: String,
    -    /// Name of the database tree, a separated namespace for the data
    -    pub tree_name: String,
    -}
    -
    -#[cfg(feature = "key-value-db")]
    -impl ConfigurableDatabase for sled::Tree {
    -    type Config = SledDbConfiguration;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        Ok(sled::open(&config.path)?.open_tree(&config.tree_name)?)
    -    }
    -}
    -
    -/// Type that can contain any of the database configurations defined by the library
    -///
    -/// This allows storing a single configuration that can be loaded into an [`AnyDatabase`]
    -/// instance. Wallets that plan to offer users the ability to switch blockchain backend at runtime
    -/// will find this particularly useful.
    -#[derive(Debug, serde::Serialize, serde::Deserialize)]
    -pub enum AnyDatabaseConfig {
    -    /// Memory database has no config
    -    Memory(()),
    -    #[cfg(feature = "key-value-db")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
    -    /// Simple key-value embedded database based on [`sled`]
    -    Sled(SledDbConfiguration),
    -}
    -
    -impl ConfigurableDatabase for AnyDatabase {
    -    type Config = AnyDatabaseConfig;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        Ok(match config {
    -            AnyDatabaseConfig::Memory(inner) => {
    -                AnyDatabase::Memory(memory::MemoryDatabase::from_config(inner)?)
    -            }
    -            #[cfg(feature = "key-value-db")]
    -            AnyDatabaseConfig::Sled(inner) => AnyDatabase::Sled(sled::Tree::from_config(inner)?),
    -        })
    -    }
    -}
    -
    -impl_from!((), AnyDatabaseConfig, Memory,);
    -impl_from!(SledDbConfiguration, AnyDatabaseConfig, Sled, #[cfg(feature = "key-value-db")]);
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/keyvalue.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/keyvalue.rs.html deleted file mode 100644 index 200aeebca1..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/keyvalue.rs.html +++ /dev/null @@ -1,968 +0,0 @@ -keyvalue.rs - source - -
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use std::convert::TryInto;
    -
    -use sled::{Batch, Tree};
    -
    -use bitcoin::consensus::encode::{deserialize, serialize};
    -use bitcoin::hash_types::Txid;
    -use bitcoin::{OutPoint, Script, Transaction};
    -
    -use crate::database::memory::MapKey;
    -use crate::database::{BatchDatabase, BatchOperations, Database};
    -use crate::error::Error;
    -use crate::types::*;
    -
    -macro_rules! impl_batch_operations {
    -    ( { $($after_insert:tt)* }, $process_delete:ident ) => {
    -        fn set_script_pubkey(&mut self, script: &Script, keychain: KeychainKind, path: u32) -> Result<(), Error> {
    -            let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -            self.insert(key, serialize(script))$($after_insert)*;
    -
    -            let key = MapKey::Script(Some(script)).as_map_key();
    -            let value = json!({
    -                "t": keychain,
    -                "p": path,
    -            });
    -            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
    -            let key = MapKey::UTXO(Some(&utxo.outpoint)).as_map_key();
    -            let value = json!({
    -                "t": utxo.txout,
    -                "i": utxo.keychain,
    -            });
    -            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
    -            let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
    -            let value = serialize(transaction);
    -            self.insert(key, value)$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
    -            let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
    -
    -            // remove the raw tx from the serialized version
    -            let mut value = serde_json::to_value(transaction)?;
    -            value["transaction"] = serde_json::Value::Null;
    -            let value = serde_json::to_vec(&value)?;
    -
    -            self.insert(key, value)$($after_insert)*;
    -
    -            // insert the raw_tx if present
    -            if let Some(ref tx) = transaction.transaction {
    -                self.set_raw_tx(tx)?;
    -            }
    -
    -            Ok(())
    -        }
    -
    -        fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
    -            let key = MapKey::LastIndex(keychain).as_map_key();
    -            self.insert(key, &value.to_be_bytes())$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn del_script_pubkey_from_path(&mut self, keychain: KeychainKind, path: u32) -> Result<Option<Script>, Error> {
    -            let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
    -        }
    -
    -        fn del_path_from_script_pubkey(&mut self, script: &Script) -> Result<Option<(KeychainKind, u32)>, Error> {
    -            let key = MapKey::Script(Some(script)).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            match res {
    -                None => Ok(None),
    -                Some(b) => {
    -                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
    -                    let st = serde_json::from_value(val["t"].take())?;
    -                    let path = serde_json::from_value(val["p"].take())?;
    -
    -                    Ok(Some((st, path)))
    -                }
    -            }
    -        }
    -
    -        fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
    -            let key = MapKey::UTXO(Some(outpoint)).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            match res {
    -                None => Ok(None),
    -                Some(b) => {
    -                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
    -                    let txout = serde_json::from_value(val["t"].take())?;
    -                    let keychain = serde_json::from_value(val["i"].take())?;
    -
    -                    Ok(Some(UTXO { outpoint: outpoint.clone(), txout, keychain }))
    -                }
    -            }
    -        }
    -
    -        fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -            let key = MapKey::RawTx(Some(txid)).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
    -        }
    -
    -        fn del_tx(&mut self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -            let raw_tx = if include_raw {
    -                self.del_raw_tx(txid)?
    -            } else {
    -                None
    -            };
    -
    -            let key = MapKey::Transaction(Some(txid)).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            match res {
    -                None => Ok(None),
    -                Some(b) => {
    -                    let mut val: TransactionDetails = serde_json::from_slice(&b)?;
    -                    val.transaction = raw_tx;
    -
    -                    Ok(Some(val))
    -                }
    -            }
    -        }
    -
    -        fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -            let key = MapKey::LastIndex(keychain).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            match res {
    -                None => Ok(None),
    -                Some(b) => {
    -                    let array: [u8; 4] = b.as_ref().try_into().map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
    -                    let val = u32::from_be_bytes(array);
    -                    Ok(Some(val))
    -                }
    -            }
    -        }
    -    }
    -}
    -
    -macro_rules! process_delete_tree {
    -    ($res:expr) => {
    -        $res?
    -    };
    -}
    -impl BatchOperations for Tree {
    -    impl_batch_operations!({?}, process_delete_tree);
    -}
    -
    -macro_rules! process_delete_batch {
    -    ($res:expr) => {
    -        None as Option<sled::IVec>
    -    };
    -}
    -#[allow(unused_variables)]
    -impl BatchOperations for Batch {
    -    impl_batch_operations!({}, process_delete_batch);
    -}
    -
    -impl Database for Tree {
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        keychain: KeychainKind,
    -        bytes: B,
    -    ) -> Result<(), Error> {
    -        let key = MapKey::DescriptorChecksum(keychain).as_map_key();
    -
    -        let prev = self.get(&key)?.map(|x| x.to_vec());
    -        if let Some(val) = prev {
    -            if val == bytes.as_ref() {
    -                Ok(())
    -            } else {
    -                Err(Error::ChecksumMismatch)
    -            }
    -        } else {
    -            self.insert(&key, bytes.as_ref())?;
    -            Ok(())
    -        }
    -    }
    -
    -    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
    -        let key = MapKey::Path((keychain, None)).as_map_key();
    -        self.scan_prefix(key)
    -            .map(|x| -> Result<_, Error> {
    -                let (_, v) = x?;
    -                Ok(deserialize(&v)?)
    -            })
    -            .collect()
    -    }
    -
    -    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error> {
    -        let key = MapKey::UTXO(None).as_map_key();
    -        self.scan_prefix(key)
    -            .map(|x| -> Result<_, Error> {
    -                let (k, v) = x?;
    -                let outpoint = deserialize(&k[1..])?;
    -
    -                let mut val: serde_json::Value = serde_json::from_slice(&v)?;
    -                let txout = serde_json::from_value(val["t"].take())?;
    -                let keychain = serde_json::from_value(val["i"].take())?;
    -
    -                Ok(UTXO {
    -                    outpoint,
    -                    txout,
    -                    keychain,
    -                })
    -            })
    -            .collect()
    -    }
    -
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
    -        let key = MapKey::RawTx(None).as_map_key();
    -        self.scan_prefix(key)
    -            .map(|x| -> Result<_, Error> {
    -                let (_, v) = x?;
    -                Ok(deserialize(&v)?)
    -            })
    -            .collect()
    -    }
    -
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        let key = MapKey::Transaction(None).as_map_key();
    -        self.scan_prefix(key)
    -            .map(|x| -> Result<_, Error> {
    -                let (k, v) = x?;
    -                let mut txdetails: TransactionDetails = serde_json::from_slice(&v)?;
    -                if include_raw {
    -                    let txid = deserialize(&k[1..])?;
    -                    txdetails.transaction = self.get_raw_tx(&txid)?;
    -                }
    -
    -                Ok(txdetails)
    -            })
    -            .collect()
    -    }
    -
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        keychain: KeychainKind,
    -        path: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
    -    }
    -
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        let key = MapKey::Script(Some(script)).as_map_key();
    -        self.get(key)?
    -            .map(|b| -> Result<_, Error> {
    -                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
    -                let st = serde_json::from_value(val["t"].take())?;
    -                let path = serde_json::from_value(val["p"].take())?;
    -
    -                Ok((st, path))
    -            })
    -            .transpose()
    -    }
    -
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
    -        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
    -        self.get(key)?
    -            .map(|b| -> Result<_, Error> {
    -                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
    -                let txout = serde_json::from_value(val["t"].take())?;
    -                let keychain = serde_json::from_value(val["i"].take())?;
    -
    -                Ok(UTXO {
    -                    outpoint: *outpoint,
    -                    txout,
    -                    keychain,
    -                })
    -            })
    -            .transpose()
    -    }
    -
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        let key = MapKey::RawTx(Some(txid)).as_map_key();
    -        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
    -    }
    -
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -        let key = MapKey::Transaction(Some(txid)).as_map_key();
    -        self.get(key)?
    -            .map(|b| -> Result<_, Error> {
    -                let mut txdetails: TransactionDetails = serde_json::from_slice(&b)?;
    -                if include_raw {
    -                    txdetails.transaction = self.get_raw_tx(&txid)?;
    -                }
    -
    -                Ok(txdetails)
    -            })
    -            .transpose()
    -    }
    -
    -    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        self.get(key)?
    -            .map(|b| -> Result<_, Error> {
    -                let array: [u8; 4] = b
    -                    .as_ref()
    -                    .try_into()
    -                    .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
    -                let val = u32::from_be_bytes(array);
    -                Ok(val)
    -            })
    -            .transpose()
    -    }
    -
    -    // inserts 0 if not present
    -    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        self.update_and_fetch(key, |prev| {
    -            let new = match prev {
    -                Some(b) => {
    -                    let array: [u8; 4] = b.try_into().unwrap_or([0; 4]);
    -                    let val = u32::from_be_bytes(array);
    -
    -                    val + 1
    -                }
    -                None => 0,
    -            };
    -
    -            Some(new.to_be_bytes().to_vec())
    -        })?
    -        .map_or(Ok(0), |b| -> Result<_, Error> {
    -            let array: [u8; 4] = b
    -                .as_ref()
    -                .try_into()
    -                .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
    -            let val = u32::from_be_bytes(array);
    -            Ok(val)
    -        })
    -    }
    -}
    -
    -impl BatchDatabase for Tree {
    -    type Batch = sled::Batch;
    -
    -    fn begin_batch(&self) -> Self::Batch {
    -        sled::Batch::default()
    -    }
    -
    -    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
    -        Ok(self.apply_batch(batch)?)
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::sync::{Arc, Condvar, Mutex, Once};
    -    use std::time::{SystemTime, UNIX_EPOCH};
    -
    -    use sled::{Db, Tree};
    -
    -    static mut COUNT: usize = 0;
    -
    -    lazy_static! {
    -        static ref DB: Arc<(Mutex<Option<Db>>, Condvar)> =
    -            Arc::new((Mutex::new(None), Condvar::new()));
    -        static ref INIT: Once = Once::new();
    -    }
    -
    -    fn get_tree() -> Tree {
    -        unsafe {
    -            let cloned = DB.clone();
    -            let (mutex, cvar) = &*cloned;
    -
    -            INIT.call_once(|| {
    -                let mut db = mutex.lock().unwrap();
    -
    -                let time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
    -                let mut dir = std::env::temp_dir();
    -                dir.push(format!("mbw_{}", time.as_nanos()));
    -
    -                *db = Some(sled::open(dir).unwrap());
    -                cvar.notify_all();
    -            });
    -
    -            let mut db = mutex.lock().unwrap();
    -            while !db.is_some() {
    -                db = cvar.wait(db).unwrap();
    -            }
    -
    -            COUNT += 1;
    -
    -            db.as_ref()
    -                .unwrap()
    -                .open_tree(format!("tree_{}", COUNT))
    -                .unwrap()
    -        }
    -    }
    -
    -    #[test]
    -    fn test_script_pubkey() {
    -        crate::database::test::test_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_batch_script_pubkey() {
    -        crate::database::test::test_batch_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_iter_script_pubkey() {
    -        crate::database::test::test_iter_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_script_pubkey() {
    -        crate::database::test::test_del_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_utxo() {
    -        crate::database::test::test_utxo(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_raw_tx() {
    -        crate::database::test::test_raw_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_tx() {
    -        crate::database::test::test_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_last_index() {
    -        crate::database::test::test_last_index(get_tree());
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/memory.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/memory.rs.html deleted file mode 100644 index 350db935c6..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/memory.rs.html +++ /dev/null @@ -1,1138 +0,0 @@ -memory.rs - source - -
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -482
    -483
    -484
    -485
    -486
    -487
    -488
    -489
    -490
    -491
    -492
    -493
    -494
    -495
    -496
    -497
    -498
    -499
    -500
    -501
    -502
    -503
    -504
    -505
    -506
    -507
    -508
    -509
    -510
    -511
    -512
    -513
    -514
    -515
    -516
    -517
    -518
    -519
    -520
    -521
    -522
    -523
    -524
    -525
    -526
    -527
    -528
    -529
    -530
    -531
    -532
    -533
    -534
    -535
    -536
    -537
    -538
    -539
    -540
    -541
    -542
    -543
    -544
    -545
    -546
    -547
    -548
    -549
    -550
    -551
    -552
    -553
    -554
    -555
    -556
    -557
    -558
    -559
    -560
    -561
    -562
    -563
    -564
    -565
    -566
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! In-memory ephemeral database
    -//!
    -//! This module defines an in-memory database type called [`MemoryDatabase`] that is based on a
    -//! [`BTreeMap`].
    -
    -use std::collections::BTreeMap;
    -use std::ops::Bound::{Excluded, Included};
    -
    -use bitcoin::consensus::encode::{deserialize, serialize};
    -use bitcoin::hash_types::Txid;
    -use bitcoin::{OutPoint, Script, Transaction};
    -
    -use crate::database::{BatchDatabase, BatchOperations, ConfigurableDatabase, Database};
    -use crate::error::Error;
    -use crate::types::*;
    -
    -// path -> script       p{i,e}<path> -> script
    -// script -> path       s<script> -> {i,e}<path>
    -// outpoint             u<outpoint> -> txout
    -// rawtx                r<txid> -> tx
    -// transactions         t<txid> -> tx details
    -// deriv indexes        c{i,e} -> u32
    -// descriptor checksum  d{i,e} -> vec<u8>
    -
    -pub(crate) enum MapKey<'a> {
    -    Path((Option<KeychainKind>, Option<u32>)),
    -    Script(Option<&'a Script>),
    -    UTXO(Option<&'a OutPoint>),
    -    RawTx(Option<&'a Txid>),
    -    Transaction(Option<&'a Txid>),
    -    LastIndex(KeychainKind),
    -    DescriptorChecksum(KeychainKind),
    -}
    -
    -impl MapKey<'_> {
    -    fn as_prefix(&self) -> Vec<u8> {
    -        match self {
    -            MapKey::Path((st, _)) => {
    -                let mut v = b"p".to_vec();
    -                if let Some(st) = st {
    -                    v.push(st.as_byte());
    -                }
    -                v
    -            }
    -            MapKey::Script(_) => b"s".to_vec(),
    -            MapKey::UTXO(_) => b"u".to_vec(),
    -            MapKey::RawTx(_) => b"r".to_vec(),
    -            MapKey::Transaction(_) => b"t".to_vec(),
    -            MapKey::LastIndex(st) => [b"c", st.as_ref()].concat(),
    -            MapKey::DescriptorChecksum(st) => [b"d", st.as_ref()].concat(),
    -        }
    -    }
    -
    -    fn serialize_content(&self) -> Vec<u8> {
    -        match self {
    -            MapKey::Path((_, Some(child))) => child.to_be_bytes().to_vec(),
    -            MapKey::Script(Some(s)) => serialize(*s),
    -            MapKey::UTXO(Some(s)) => serialize(*s),
    -            MapKey::RawTx(Some(s)) => serialize(*s),
    -            MapKey::Transaction(Some(s)) => serialize(*s),
    -            _ => vec![],
    -        }
    -    }
    -
    -    pub fn as_map_key(&self) -> Vec<u8> {
    -        let mut v = self.as_prefix();
    -        v.extend_from_slice(&self.serialize_content());
    -
    -        v
    -    }
    -}
    -
    -fn after(key: &[u8]) -> Vec<u8> {
    -    let mut key = key.to_owned();
    -    let mut idx = key.len();
    -    while idx > 0 {
    -        if key[idx - 1] == 0xFF {
    -            idx -= 1;
    -            continue;
    -        } else {
    -            key[idx - 1] += 1;
    -            break;
    -        }
    -    }
    -
    -    key
    -}
    -
    -/// In-memory ephemeral database
    -///
    -/// This database can be used as a temporary storage for wallets that are not kept permanently on
    -/// a device, or on platforms that don't provide a filesystem, like `wasm32`.
    -///
    -/// Once it's dropped its content will be lost.
    -///
    -/// If you are looking for a permanent storage solution, you can try with the default key-value
    -/// database called [`sled`]. See the [`database`] module documentation for more defailts.
    -///
    -/// [`database`]: crate::database
    -#[derive(Debug, Default)]
    -pub struct MemoryDatabase {
    -    map: BTreeMap<Vec<u8>, Box<dyn std::any::Any>>,
    -    deleted_keys: Vec<Vec<u8>>,
    -}
    -
    -impl MemoryDatabase {
    -    /// Create a new empty database
    -    pub fn new() -> Self {
    -        MemoryDatabase {
    -            map: BTreeMap::new(),
    -            deleted_keys: Vec::new(),
    -        }
    -    }
    -}
    -
    -impl BatchOperations for MemoryDatabase {
    -    fn set_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -        keychain: KeychainKind,
    -        path: u32,
    -    ) -> Result<(), Error> {
    -        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -        self.map.insert(key, Box::new(script.clone()));
    -
    -        let key = MapKey::Script(Some(script)).as_map_key();
    -        let value = json!({
    -            "t": keychain,
    -            "p": path,
    -        });
    -        self.map.insert(key, Box::new(value));
    -
    -        Ok(())
    -    }
    -
    -    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error> {
    -        let key = MapKey::UTXO(Some(&utxo.outpoint)).as_map_key();
    -        self.map
    -            .insert(key, Box::new((utxo.txout.clone(), utxo.keychain)));
    -
    -        Ok(())
    -    }
    -    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
    -        let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
    -        self.map.insert(key, Box::new(transaction.clone()));
    -
    -        Ok(())
    -    }
    -    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
    -        let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
    -
    -        // insert the raw_tx if present
    -        if let Some(ref tx) = transaction.transaction {
    -            self.set_raw_tx(tx)?;
    -        }
    -
    -        // remove the raw tx from the serialized version
    -        let mut transaction = transaction.clone();
    -        transaction.transaction = None;
    -
    -        self.map.insert(key, Box::new(transaction));
    -
    -        Ok(())
    -    }
    -    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        self.map.insert(key, Box::new(value));
    -
    -        Ok(())
    -    }
    -
    -    fn del_script_pubkey_from_path(
    -        &mut self,
    -        keychain: KeychainKind,
    -        path: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
    -    }
    -    fn del_path_from_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        let key = MapKey::Script(Some(script)).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        match res {
    -            None => Ok(None),
    -            Some(b) => {
    -                let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
    -                let st = serde_json::from_value(val["t"].take())?;
    -                let path = serde_json::from_value(val["p"].take())?;
    -
    -                Ok(Some((st, path)))
    -            }
    -        }
    -    }
    -    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
    -        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        match res {
    -            None => Ok(None),
    -            Some(b) => {
    -                let (txout, keychain) = b.downcast_ref().cloned().unwrap();
    -                Ok(Some(UTXO {
    -                    outpoint: *outpoint,
    -                    txout,
    -                    keychain,
    -                }))
    -            }
    -        }
    -    }
    -    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        let key = MapKey::RawTx(Some(txid)).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
    -    }
    -    fn del_tx(
    -        &mut self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error> {
    -        let raw_tx = if include_raw {
    -            self.del_raw_tx(txid)?
    -        } else {
    -            None
    -        };
    -
    -        let key = MapKey::Transaction(Some(txid)).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        match res {
    -            None => Ok(None),
    -            Some(b) => {
    -                let mut val: TransactionDetails = b.downcast_ref().cloned().unwrap();
    -                val.transaction = raw_tx;
    -
    -                Ok(Some(val))
    -            }
    -        }
    -    }
    -    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        match res {
    -            None => Ok(None),
    -            Some(b) => Ok(Some(*b.downcast_ref().unwrap())),
    -        }
    -    }
    -}
    -
    -impl Database for MemoryDatabase {
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        keychain: KeychainKind,
    -        bytes: B,
    -    ) -> Result<(), Error> {
    -        let key = MapKey::DescriptorChecksum(keychain).as_map_key();
    -
    -        let prev = self
    -            .map
    -            .get(&key)
    -            .map(|x| x.downcast_ref::<Vec<u8>>().unwrap());
    -        if let Some(val) = prev {
    -            if val == &bytes.as_ref().to_vec() {
    -                Ok(())
    -            } else {
    -                Err(Error::ChecksumMismatch)
    -            }
    -        } else {
    -            self.map.insert(key, Box::new(bytes.as_ref().to_vec()));
    -            Ok(())
    -        }
    -    }
    -
    -    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
    -        let key = MapKey::Path((keychain, None)).as_map_key();
    -        self.map
    -            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
    -            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
    -            .collect()
    -    }
    -
    -    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error> {
    -        let key = MapKey::UTXO(None).as_map_key();
    -        self.map
    -            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
    -            .map(|(k, v)| {
    -                let outpoint = deserialize(&k[1..]).unwrap();
    -                let (txout, keychain) = v.downcast_ref().cloned().unwrap();
    -                Ok(UTXO {
    -                    outpoint,
    -                    txout,
    -                    keychain,
    -                })
    -            })
    -            .collect()
    -    }
    -
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
    -        let key = MapKey::RawTx(None).as_map_key();
    -        self.map
    -            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
    -            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
    -            .collect()
    -    }
    -
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        let key = MapKey::Transaction(None).as_map_key();
    -        self.map
    -            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
    -            .map(|(k, v)| {
    -                let mut txdetails: TransactionDetails = v.downcast_ref().cloned().unwrap();
    -                if include_raw {
    -                    let txid = deserialize(&k[1..])?;
    -                    txdetails.transaction = self.get_raw_tx(&txid)?;
    -                }
    -
    -                Ok(txdetails)
    -            })
    -            .collect()
    -    }
    -
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        keychain: KeychainKind,
    -        path: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -        Ok(self
    -            .map
    -            .get(&key)
    -            .map(|b| b.downcast_ref().cloned().unwrap()))
    -    }
    -
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        let key = MapKey::Script(Some(script)).as_map_key();
    -        Ok(self.map.get(&key).map(|b| {
    -            let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
    -            let st = serde_json::from_value(val["t"].take()).unwrap();
    -            let path = serde_json::from_value(val["p"].take()).unwrap();
    -
    -            (st, path)
    -        }))
    -    }
    -
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error> {
    -        let key = MapKey::UTXO(Some(outpoint)).as_map_key();
    -        Ok(self.map.get(&key).map(|b| {
    -            let (txout, keychain) = b.downcast_ref().cloned().unwrap();
    -            UTXO {
    -                outpoint: *outpoint,
    -                txout,
    -                keychain,
    -            }
    -        }))
    -    }
    -
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        let key = MapKey::RawTx(Some(txid)).as_map_key();
    -        Ok(self
    -            .map
    -            .get(&key)
    -            .map(|b| b.downcast_ref().cloned().unwrap()))
    -    }
    -
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -        let key = MapKey::Transaction(Some(txid)).as_map_key();
    -        Ok(self.map.get(&key).map(|b| {
    -            let mut txdetails: TransactionDetails = b.downcast_ref().cloned().unwrap();
    -            if include_raw {
    -                txdetails.transaction = self.get_raw_tx(&txid).unwrap();
    -            }
    -
    -            txdetails
    -        }))
    -    }
    -
    -    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        Ok(self.map.get(&key).map(|b| *b.downcast_ref().unwrap()))
    -    }
    -
    -    // inserts 0 if not present
    -    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        let value = self
    -            .map
    -            .entry(key)
    -            .and_modify(|x| *x.downcast_mut::<u32>().unwrap() += 1)
    -            .or_insert_with(|| Box::<u32>::new(0))
    -            .downcast_mut()
    -            .unwrap();
    -
    -        Ok(*value)
    -    }
    -}
    -
    -impl BatchDatabase for MemoryDatabase {
    -    type Batch = Self;
    -
    -    fn begin_batch(&self) -> Self::Batch {
    -        MemoryDatabase::new()
    -    }
    -
    -    fn commit_batch(&mut self, mut batch: Self::Batch) -> Result<(), Error> {
    -        for key in batch.deleted_keys {
    -            self.map.remove(&key);
    -        }
    -        self.map.append(&mut batch.map);
    -        Ok(())
    -    }
    -}
    -
    -impl ConfigurableDatabase for MemoryDatabase {
    -    type Config = ();
    -
    -    fn from_config(_config: &Self::Config) -> Result<Self, Error> {
    -        Ok(MemoryDatabase::default())
    -    }
    -}
    -
    -#[cfg(test)]
    -impl MemoryDatabase {
    -    // Artificially insert a tx in the database, as if we had found it with a `sync`
    -    pub fn received_tx(
    -        &mut self,
    -        tx_meta: testutils::TestIncomingTx,
    -        current_height: Option<u32>,
    -    ) -> bitcoin::Txid {
    -        use std::str::FromStr;
    -
    -        let tx = Transaction {
    -            version: 1,
    -            lock_time: 0,
    -            input: vec![],
    -            output: tx_meta
    -                .output
    -                .iter()
    -                .map(|out_meta| bitcoin::TxOut {
    -                    value: out_meta.value,
    -                    script_pubkey: bitcoin::Address::from_str(&out_meta.to_address)
    -                        .unwrap()
    -                        .script_pubkey(),
    -                })
    -                .collect(),
    -        };
    -
    -        let txid = tx.txid();
    -        let height = tx_meta
    -            .min_confirmations
    -            .map(|conf| current_height.unwrap().checked_sub(conf as u32).unwrap());
    -
    -        let tx_details = TransactionDetails {
    -            transaction: Some(tx.clone()),
    -            txid,
    -            timestamp: 0,
    -            height,
    -            received: 0,
    -            sent: 0,
    -            fees: 0,
    -        };
    -
    -        self.set_tx(&tx_details).unwrap();
    -        for (vout, out) in tx.output.iter().enumerate() {
    -            self.set_utxo(&UTXO {
    -                txout: out.clone(),
    -                outpoint: OutPoint {
    -                    txid,
    -                    vout: vout as u32,
    -                },
    -                keychain: KeychainKind::External,
    -            })
    -            .unwrap();
    -        }
    -
    -        txid
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use super::MemoryDatabase;
    -
    -    fn get_tree() -> MemoryDatabase {
    -        MemoryDatabase::new()
    -    }
    -
    -    #[test]
    -    fn test_script_pubkey() {
    -        crate::database::test::test_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_batch_script_pubkey() {
    -        crate::database::test::test_batch_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_iter_script_pubkey() {
    -        crate::database::test::test_iter_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_script_pubkey() {
    -        crate::database::test::test_del_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_utxo() {
    -        crate::database::test::test_utxo(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_raw_tx() {
    -        crate::database::test::test_raw_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_tx() {
    -        crate::database::test::test_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_last_index() {
    -        crate::database::test::test_last_index(get_tree());
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/mod.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/mod.rs.html deleted file mode 100644 index 864f1cb872..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/database/mod.rs.html +++ /dev/null @@ -1,772 +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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Database types
    -//!
    -//! This module provides the implementation of some defaults database types, along with traits that
    -//! can be implemented externally to let [`Wallet`]s use customized databases.
    -//!
    -//! It's important to note that the databases defined here only contains "blockchain-related" data.
    -//! They can be seen more as a cache than a critical piece of storage that contains secrets and
    -//! keys.
    -//!
    -//! The currently recommended database is [`sled`], which is a pretty simple key-value embedded
    -//! database written in Rust. If the `key-value-db` feature is enabled (which by default is),
    -//! this library automatically implements all the required traits for [`sled::Tree`].
    -//!
    -//! [`Wallet`]: crate::wallet::Wallet
    -
    -use bitcoin::hash_types::Txid;
    -use bitcoin::{OutPoint, Script, Transaction, TxOut};
    -
    -use crate::error::Error;
    -use crate::types::*;
    -
    -pub mod any;
    -pub use any::{AnyDatabase, AnyDatabaseConfig};
    -
    -#[cfg(feature = "key-value-db")]
    -pub(crate) mod keyvalue;
    -
    -pub mod memory;
    -pub use memory::MemoryDatabase;
    -
    -/// Trait for operations that can be batched
    -///
    -/// This trait defines the list of operations that must be implemented on the [`Database`] type and
    -/// the [`BatchDatabase::Batch`] type.
    -pub trait BatchOperations {
    -    /// Store a script_pubkey along with its keychain and child number.
    -    fn set_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<(), Error>;
    -    /// Store a [`UTXO`]
    -    fn set_utxo(&mut self, utxo: &UTXO) -> Result<(), Error>;
    -    /// Store a raw transaction
    -    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>;
    -    /// Store the metadata of a transaction
    -    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>;
    -    /// Store the last derivation index for a given keychain.
    -    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error>;
    -
    -    /// Delete a script_pubkey given the keychain and its child number.
    -    fn del_script_pubkey_from_path(
    -        &mut self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error>;
    -    /// Delete the data related to a specific script_pubkey, meaning the keychain and the child
    -    /// number.
    -    fn del_path_from_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error>;
    -    /// Delete a [`UTXO`] given its [`OutPoint`]
    -    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>;
    -    /// Delete a raw transaction given its [`Txid`]
    -    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>;
    -    /// Delete the metadata of a transaction and optionally the raw transaction itself
    -    fn del_tx(
    -        &mut self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error>;
    -    /// Delete the last derivation index for a keychain.
    -    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error>;
    -}
    -
    -/// Trait for reading data from a database
    -///
    -/// This traits defines the operations that can be used to read data out of a database
    -pub trait Database: BatchOperations {
    -    /// Read and checks the descriptor checksum for a given keychain.
    -    ///
    -    /// Should return [`Error::ChecksumMismatch`](crate::error::Error::ChecksumMismatch) if the
    -    /// checksum doesn't match. If there's no checksum in the database, simply store it for the
    -    /// next time.
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        keychain: KeychainKind,
    -        bytes: B,
    -    ) -> Result<(), Error>;
    -
    -    /// Return the list of script_pubkeys
    -    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error>;
    -    /// Return the list of [`UTXO`]s
    -    fn iter_utxos(&self) -> Result<Vec<UTXO>, Error>;
    -    /// Return the list of raw transactions
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>;
    -    /// Return the list of transactions metadata
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error>;
    -
    -    /// Fetch a script_pubkey given the child number of a keychain.
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error>;
    -    /// Fetch the keychain and child number of a given script_pubkey
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error>;
    -    /// Fetch a [`UTXO`] given its [`OutPoint`]
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<UTXO>, Error>;
    -    /// Fetch a raw transaction given its [`Txid`]
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
    -    /// Fetch the transaction metadata and optionally also the raw transaction
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error>;
    -    /// Return the last defivation index for a keychain.
    -    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error>;
    -
    -    /// Increment the last derivation index for a keychain and return it
    -    ///
    -    /// It should insert and return `0` if not present in the database
    -    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error>;
    -}
    -
    -/// Trait for a database that supports batch operations
    -///
    -/// This trait defines the methods to start and apply a batch of operations.
    -pub trait BatchDatabase: Database {
    -    /// Container for the operations
    -    type Batch: BatchOperations;
    -
    -    /// Create a new batch container
    -    fn begin_batch(&self) -> Self::Batch;
    -    /// Consume and apply a batch of operations
    -    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>;
    -}
    -
    -/// Trait for [`Database`] types that can be created given a configuration
    -pub trait ConfigurableDatabase: Database + Sized {
    -    /// Type that contains the configuration
    -    type Config: std::fmt::Debug;
    -
    -    /// Create a new instance given a configuration
    -    fn from_config(config: &Self::Config) -> Result<Self, Error>;
    -}
    -
    -pub(crate) trait DatabaseUtils: Database {
    -    fn is_mine(&self, script: &Script) -> Result<bool, Error> {
    -        self.get_path_from_script_pubkey(script)
    -            .map(|o| o.is_some())
    -    }
    -
    -    fn get_raw_tx_or<F>(&self, txid: &Txid, f: F) -> Result<Option<Transaction>, Error>
    -    where
    -        F: FnOnce() -> Result<Option<Transaction>, Error>,
    -    {
    -        self.get_tx(txid, true)?
    -            .map(|t| t.transaction)
    -            .flatten()
    -            .map_or_else(f, |t| Ok(Some(t)))
    -    }
    -
    -    fn get_previous_output(&self, outpoint: &OutPoint) -> Result<Option<TxOut>, Error> {
    -        self.get_raw_tx(&outpoint.txid)?
    -            .map(|previous_tx| {
    -                if outpoint.vout as usize >= previous_tx.output.len() {
    -                    Err(Error::InvalidOutpoint(*outpoint))
    -                } else {
    -                    Ok(previous_tx.output[outpoint.vout as usize].clone())
    -                }
    -            })
    -            .transpose()
    -    }
    -}
    -
    -impl<T: Database> DatabaseUtils for T {}
    -
    -#[cfg(test)]
    -pub mod test {
    -    use std::str::FromStr;
    -
    -    use bitcoin::consensus::encode::deserialize;
    -    use bitcoin::hashes::hex::*;
    -    use bitcoin::*;
    -
    -    use super::*;
    -
    -    pub fn test_script_pubkey<D: Database>(mut tree: D) {
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let keychain = KeychainKind::External;
    -
    -        tree.set_script_pubkey(&script, keychain, path).unwrap();
    -
    -        assert_eq!(
    -            tree.get_script_pubkey_from_path(keychain, path).unwrap(),
    -            Some(script.clone())
    -        );
    -        assert_eq!(
    -            tree.get_path_from_script_pubkey(&script).unwrap(),
    -            Some((keychain, path.clone()))
    -        );
    -    }
    -
    -    pub fn test_batch_script_pubkey<D: BatchDatabase>(mut tree: D) {
    -        let mut batch = tree.begin_batch();
    -
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let keychain = KeychainKind::External;
    -
    -        batch.set_script_pubkey(&script, keychain, path).unwrap();
    -
    -        assert_eq!(
    -            tree.get_script_pubkey_from_path(keychain, path).unwrap(),
    -            None
    -        );
    -        assert_eq!(tree.get_path_from_script_pubkey(&script).unwrap(), None);
    -
    -        tree.commit_batch(batch).unwrap();
    -
    -        assert_eq!(
    -            tree.get_script_pubkey_from_path(keychain, path).unwrap(),
    -            Some(script.clone())
    -        );
    -        assert_eq!(
    -            tree.get_path_from_script_pubkey(&script).unwrap(),
    -            Some((keychain, path.clone()))
    -        );
    -    }
    -
    -    pub fn test_iter_script_pubkey<D: Database>(mut tree: D) {
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let keychain = KeychainKind::External;
    -
    -        tree.set_script_pubkey(&script, keychain, path).unwrap();
    -
    -        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 1);
    -    }
    -
    -    pub fn test_del_script_pubkey<D: Database>(mut tree: D) {
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let keychain = KeychainKind::External;
    -
    -        tree.set_script_pubkey(&script, keychain, path).unwrap();
    -        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 1);
    -
    -        tree.del_script_pubkey_from_path(keychain, path).unwrap();
    -        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 0);
    -    }
    -
    -    pub fn test_utxo<D: Database>(mut tree: D) {
    -        let outpoint = OutPoint::from_str(
    -            "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0",
    -        )
    -        .unwrap();
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let txout = TxOut {
    -            value: 133742,
    -            script_pubkey: script,
    -        };
    -        let utxo = UTXO {
    -            txout,
    -            outpoint,
    -            keychain: KeychainKind::External,
    -        };
    -
    -        tree.set_utxo(&utxo).unwrap();
    -
    -        assert_eq!(tree.get_utxo(&outpoint).unwrap(), Some(utxo));
    -    }
    -
    -    pub fn test_raw_tx<D: Database>(mut tree: D) {
    -        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
    -        let tx: Transaction = deserialize(&hex_tx).unwrap();
    -
    -        tree.set_raw_tx(&tx).unwrap();
    -
    -        let txid = tx.txid();
    -
    -        assert_eq!(tree.get_raw_tx(&txid).unwrap(), Some(tx));
    -    }
    -
    -    pub fn test_tx<D: Database>(mut tree: D) {
    -        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
    -        let tx: Transaction = deserialize(&hex_tx).unwrap();
    -        let txid = tx.txid();
    -        let mut tx_details = TransactionDetails {
    -            transaction: Some(tx),
    -            txid,
    -            timestamp: 123456,
    -            received: 1337,
    -            sent: 420420,
    -            fees: 140,
    -            height: Some(1000),
    -        };
    -
    -        tree.set_tx(&tx_details).unwrap();
    -
    -        // get with raw tx too
    -        assert_eq!(
    -            tree.get_tx(&tx_details.txid, true).unwrap(),
    -            Some(tx_details.clone())
    -        );
    -        // get only raw_tx
    -        assert_eq!(
    -            tree.get_raw_tx(&tx_details.txid).unwrap(),
    -            tx_details.transaction
    -        );
    -
    -        // now get without raw_tx
    -        tx_details.transaction = None;
    -        assert_eq!(
    -            tree.get_tx(&tx_details.txid, false).unwrap(),
    -            Some(tx_details)
    -        );
    -    }
    -
    -    pub fn test_last_index<D: Database>(mut tree: D) {
    -        tree.set_last_index(KeychainKind::External, 1337).unwrap();
    -
    -        assert_eq!(
    -            tree.get_last_index(KeychainKind::External).unwrap(),
    -            Some(1337)
    -        );
    -        assert_eq!(tree.get_last_index(KeychainKind::Internal).unwrap(), None);
    -
    -        let res = tree.increment_last_index(KeychainKind::External).unwrap();
    -        assert_eq!(res, 1338);
    -        let res = tree.increment_last_index(KeychainKind::Internal).unwrap();
    -        assert_eq!(res, 0);
    -
    -        assert_eq!(
    -            tree.get_last_index(KeychainKind::External).unwrap(),
    -            Some(1338)
    -        );
    -        assert_eq!(
    -            tree.get_last_index(KeychainKind::Internal).unwrap(),
    -            Some(0)
    -        );
    -    }
    -
    -    // TODO: more tests...
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/checksum.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/checksum.rs.html deleted file mode 100644 index d1a56388f4..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/checksum.rs.html +++ /dev/null @@ -1,258 +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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Descriptor checksum
    -//!
    -//! This module contains a re-implementation of the function used by Bitcoin Core to calculate the
    -//! checksum of a descriptor
    -
    -use std::iter::FromIterator;
    -
    -use crate::descriptor::Error;
    -
    -const INPUT_CHARSET: &str =  "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
    -const CHECKSUM_CHARSET: &str = "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 of a descriptor
    -pub fn get_checksum(desc: &str) -> Result<String, Error> {
    -    let mut c = 1;
    -    let mut cls = 0;
    -    let mut clscount = 0;
    -    for ch in desc.chars() {
    -        let pos = INPUT_CHARSET
    -            .find(ch)
    -            .ok_or(Error::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 chars = Vec::with_capacity(8);
    -    for j in 0..8 {
    -        chars.push(
    -            CHECKSUM_CHARSET
    -                .chars()
    -                .nth(((c >> (5 * (7 - j))) & 31) as usize)
    -                .unwrap(),
    -        );
    -    }
    -
    -    Ok(String::from_iter(chars))
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use super::*;
    -    use crate::descriptor::get_checksum;
    -
    -    // test get_checksum() function; it should return the same value as Bitcoin Core
    -    #[test]
    -    fn test_get_checksum() {
    -        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)";
    -        assert_eq!(get_checksum(desc).unwrap(), "tqz0nc62");
    -
    -        let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)";
    -        assert_eq!(get_checksum(desc).unwrap(), "lasegmfs");
    -    }
    -
    -    #[test]
    -    fn test_get_checksum_invalid_character() {
    -        let sparkle_heart = vec![240, 159, 146, 150];
    -        let sparkle_heart = std::str::from_utf8(&sparkle_heart)
    -            .unwrap()
    -            .chars()
    -            .next()
    -            .unwrap();
    -        let invalid_desc = format!("wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcL{}fjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)", sparkle_heart);
    -
    -        assert!(matches!(
    -            get_checksum(&invalid_desc).err(),
    -            Some(Error::InvalidDescriptorCharacter(invalid_char)) if invalid_char == sparkle_heart
    -        ));
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/dsl.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/dsl.rs.html deleted file mode 100644 index 418ef8e3ab..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/dsl.rs.html +++ /dev/null @@ -1,1630 +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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Descriptors DSL
    -
    -#[doc(hidden)]
    -#[macro_export]
    -macro_rules! impl_top_level_sh {
    -    // disallow `sortedmulti` in `bare()`
    -    ( Bare, Bare, sortedmulti $( $inner:tt )* ) => {
    -        compile_error!("`bare()` descriptors can't contain any `sortedmulti` operands");
    -    };
    -    ( Bare, Bare, sortedmulti_vec $( $inner:tt )* ) => {
    -        compile_error!("`bare()` descriptors can't contain any `sortedmulti_vec` operands");
    -    };
    -
    -    ( $descriptor_variant:ident, $sortedmulti_variant:ident, sortedmulti $( $inner:tt )* ) => {
    -        $crate::impl_sortedmulti!(sortedmulti $( $inner )*)
    -            .and_then(|(inner, key_map, valid_networks)| Ok(($crate::miniscript::Descriptor::$sortedmulti_variant(inner), key_map, valid_networks)))
    -    };
    -    ( $descriptor_variant:ident, $sortedmulti_variant:ident, sortedmulti_vec $( $inner:tt )* ) => {
    -        $crate::impl_sortedmulti!(sortedmulti_vec $( $inner )*)
    -            .and_then(|(inner, key_map, valid_networks)| Ok(($crate::miniscript::Descriptor::$sortedmulti_variant(inner), key_map, valid_networks)))
    -    };
    -
    -    ( $descriptor_variant:ident, $sortedmulti_variant:ident, $( $minisc:tt )* ) => {
    -        $crate::fragment!($( $minisc )*)
    -            .map(|(minisc, keymap, networks)|($crate::miniscript::Descriptor::<$crate::miniscript::descriptor::DescriptorPublicKey>::$descriptor_variant(minisc), keymap, networks))
    -    };
    -}
    -
    -#[doc(hidden)]
    -#[macro_export]
    -macro_rules! impl_top_level_pk {
    -    ( $descriptor_variant:ident, $ctx:ty, $key:expr ) => {{
    -        #[allow(unused_imports)]
    -        use $crate::keys::{DescriptorKey, ToDescriptorKey};
    -        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
    -
    -        $key.to_descriptor_key()
    -            .and_then(|key: DescriptorKey<$ctx>| key.extract(&secp))
    -            .map(|(pk, key_map, valid_networks)| {
    -                (
    -                    $crate::miniscript::Descriptor::<
    -                        $crate::miniscript::descriptor::DescriptorPublicKey,
    -                    >::$descriptor_variant(pk),
    -                    key_map,
    -                    valid_networks,
    -                )
    -            })
    -    }};
    -}
    -
    -#[doc(hidden)]
    -#[macro_export]
    -macro_rules! impl_modifier {
    -    ( $terminal_variant:ident, $( $inner:tt )* ) => {
    -        $crate::fragment!($( $inner )*)
    -            .map_err(|e| -> $crate::Error { e.into() })
    -            .and_then(|(minisc, keymap, networks)| Ok(($crate::miniscript::Miniscript::from_ast($crate::miniscript::miniscript::decode::Terminal::$terminal_variant(std::sync::Arc::new(minisc)))?, keymap, networks)))
    -    };
    -}
    -
    -#[doc(hidden)]
    -#[macro_export]
    -macro_rules! impl_leaf_opcode {
    -    ( $terminal_variant:ident ) => {
    -        $crate::miniscript::Miniscript::from_ast(
    -            $crate::miniscript::miniscript::decode::Terminal::$terminal_variant,
    -        )
    -        .map_err($crate::Error::Miniscript)
    -        .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 ) => {
    -        $crate::miniscript::Miniscript::from_ast(
    -            $crate::miniscript::miniscript::decode::Terminal::$terminal_variant($value),
    -        )
    -        .map_err($crate::Error::Miniscript)
    -        .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 ) => {
    -        $crate::miniscript::Miniscript::from_ast(
    -            $crate::miniscript::miniscript::decode::Terminal::$terminal_variant($one, $two),
    -        )
    -        .map_err($crate::Error::Miniscript)
    -        .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, ( $( $a:tt )* ), ( $( $b:tt )* ) ) => {
    -        $crate::fragment!($( $a )*)
    -            .and_then(|a| Ok((a, $crate::fragment!($( $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());
    -
    -                Ok(($crate::miniscript::Miniscript::from_ast($crate::miniscript::miniscript::decode::Terminal::$terminal_variant(
    -                    std::sync::Arc::new(a_minisc),
    -                    std::sync::Arc::new(b_minisc),
    -                ))?, a_keymap, $crate::keys::merge_networks(&a_networks, &b_networks)))
    -            })
    -    };
    -}
    -
    -#[doc(hidden)]
    -#[macro_export]
    -macro_rules! impl_node_opcode_three {
    -    ( $terminal_variant:ident, ( $( $a:tt )* ), ( $( $b:tt )* ), ( $( $c:tt )* ) ) => {
    -        $crate::fragment!($( $a )*)
    -            .and_then(|a| Ok((a, $crate::fragment!($( $b )*)?, $crate::fragment!($( $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);
    -
    -                Ok(($crate::miniscript::Miniscript::from_ast($crate::miniscript::miniscript::decode::Terminal::$terminal_variant(
    -                    std::sync::Arc::new(a_minisc),
    -                    std::sync::Arc::new(b_minisc),
    -                    std::sync::Arc::new(c_minisc),
    -                ))?, a_keymap, networks))
    -            })
    -    };
    -}
    -
    -#[doc(hidden)]
    -#[macro_export]
    -macro_rules! impl_sortedmulti {
    -    ( sortedmulti_vec $thresh:expr, $keys:expr ) => ({
    -        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
    -        $crate::keys::make_sortedmulti_inner($thresh, $keys, &secp)
    -    });
    -    ( sortedmulti $thresh:expr $(, $key:expr )+ ) => ({
    -        use $crate::keys::ToDescriptorKey;
    -        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
    -
    -        let mut keys = vec![];
    -        $(
    -            keys.push($key.to_descriptor_key());
    -        )*
    -
    -        keys.into_iter().collect::<Result<Vec<_>, _>>()
    -            .and_then(|keys| $crate::keys::make_sortedmulti_inner($thresh, keys, &secp))
    -    });
    -
    -}
    -
    -/// Macro to write full descriptors with code
    -///
    -/// This macro expands to a `Result` of
    -/// [`DescriptorTemplateOut`](super::template::DescriptorTemplateOut) and [`Error`](crate::Error)
    -///
    -/// ## Example
    -///
    -/// Signature plus timelock, equivalent to: `sh(wsh(and_v(v:pk(...), older(...))))`
    -///
    -/// ```
    -/// # use std::str::FromStr;
    -/// let my_key = bitcoin::PublicKey::from_str("02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c")?;
    -/// let my_timelock = 50;
    -/// let (my_descriptor, my_keys_map, networks) = bdk::descriptor!(sh ( wsh ( and_v (+v pk my_key), ( older my_timelock ))))?;
    -/// # 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(...),sdv: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+d+v older my_timelock)
    -///     )
    -/// }?;
    -///
    -/// let b_items = vec![
    -///     bdk::fragment!(pk my_key_1)?,
    -///     bdk::fragment!(+s pk my_key_2)?,
    -///     bdk::fragment!(+s+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>>(())
    -/// ```
    -#[macro_export]
    -macro_rules! descriptor {
    -    ( bare ( $( $minisc:tt )* ) ) => ({
    -        $crate::impl_top_level_sh!(Bare, Bare, $( $minisc )*)
    -    });
    -    ( sh ( wsh ( $( $minisc:tt )* ) ) ) => ({
    -        $crate::descriptor!(shwsh ($( $minisc )*))
    -    });
    -    ( shwsh ( $( $minisc:tt )* ) ) => ({
    -        $crate::impl_top_level_sh!(ShWsh, ShWshSortedMulti, $( $minisc )*)
    -    });
    -    ( pk $key:expr ) => ({
    -        $crate::impl_top_level_pk!(Pk, $crate::miniscript::Legacy, $key)
    -    });
    -    ( pkh $key:expr ) => ({
    -        $crate::impl_top_level_pk!(Pkh,$crate::miniscript::Legacy, $key)
    -    });
    -    ( wpkh $key:expr ) => ({
    -        $crate::impl_top_level_pk!(Wpkh, $crate::miniscript::Segwitv0, $key)
    -    });
    -    ( sh ( wpkh ( $key:expr ) ) ) => ({
    -        $crate::descriptor!(shwpkh ( $key ))
    -    });
    -    ( shwpkh ( $key:expr ) ) => ({
    -        $crate::impl_top_level_pk!(ShWpkh, $crate::miniscript::Segwitv0, $key)
    -    });
    -    ( sh ( $( $minisc:tt )* ) ) => ({
    -        $crate::impl_top_level_sh!(Sh, ShSortedMulti, $( $minisc )*)
    -    });
    -    ( wsh ( $( $minisc:tt )* ) ) => ({
    -        $crate::impl_top_level_sh!(Wsh, WshSortedMulti, $( $minisc )*)
    -    });
    -}
    -
    -/// Macro to write descriptor fragments with code
    -///
    -/// This macro will be expanded to an object of type `Result<(Miniscript<DescriptorPublicKey, _>, KeyMap, ValidNetworks), Error>`. It allows writing
    -/// fragments of larger descriptors that can be pieced together using `fragment!(thresh_vec ...)`.
    -#[macro_export]
    -macro_rules! fragment {
    -    // Modifiers
    -    ( +a $( $inner:tt )* ) => ({
    -        $crate::impl_modifier!(Alt, $( $inner )*)
    -    });
    -    ( +s $( $inner:tt )* ) => ({
    -        $crate::impl_modifier!(Swap, $( $inner )*)
    -    });
    -    ( +c $( $inner:tt )* ) => ({
    -        $crate::impl_modifier!(Check, $( $inner )*)
    -    });
    -    ( +d $( $inner:tt )* ) => ({
    -        $crate::impl_modifier!(DupIf, $( $inner )*)
    -    });
    -    ( +v $( $inner:tt )* ) => ({
    -        $crate::impl_modifier!(Verify, $( $inner )*)
    -    });
    -    ( +j $( $inner:tt )* ) => ({
    -        $crate::impl_modifier!(NonZero, $( $inner )*)
    -    });
    -    ( +n $( $inner:tt )* ) => ({
    -        $crate::impl_modifier!(ZeroNotEqual, $( $inner )*)
    -    });
    -    ( +t $( $inner:tt )* ) => ({
    -        $crate::fragment!(and_v ( $( $inner )* ), ( true ) )
    -    });
    -    ( +l $( $inner:tt )* ) => ({
    -        $crate::fragment!(or_i ( false ), ( $( $inner )* ) )
    -    });
    -    ( +u $( $inner:tt )* ) => ({
    -        $crate::fragment!(or_i ( $( $inner )* ), ( false ) )
    -    });
    -
    -    // 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_hash:expr ) => ({
    -        $crate::impl_leaf_opcode_value!(PkH, $key_hash)
    -    });
    -    ( after $value:expr ) => ({
    -        $crate::impl_leaf_opcode_value!(After, $value)
    -    });
    -    ( older $value:expr ) => ({
    -        $crate::impl_leaf_opcode_value!(Older, $value)
    -    });
    -    ( 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 ( $( $a:tt )* ), ( $( $b:tt )* ) ) => ({
    -        $crate::impl_node_opcode_two!(AndV, ( $( $a )* ), ( $( $b )* ))
    -    });
    -    ( and_b ( $( $a:tt )* ), ( $( $b:tt )* ) ) => ({
    -        $crate::impl_node_opcode_two!(AndB, ( $( $a )* ), ( $( $b )* ))
    -    });
    -    ( and_or ( $( $a:tt )* ), ( $( $b:tt )* ), ( $( $c:tt )* ) ) => ({
    -        $crate::impl_node_opcode_three!(AndOr, ( $( $a )* ), ( $( $b )* ), ( $( $c )* ))
    -    });
    -    ( or_b ( $( $a:tt )* ), ( $( $b:tt )* ) ) => ({
    -        $crate::impl_node_opcode_two!(OrB, ( $( $a )* ), ( $( $b )* ))
    -    });
    -    ( or_d ( $( $a:tt )* ), ( $( $b:tt )* ) ) => ({
    -        $crate::impl_node_opcode_two!(OrD, ( $( $a )* ), ( $( $b )* ))
    -    });
    -    ( or_c ( $( $a:tt )* ), ( $( $b:tt )* ) ) => ({
    -        $crate::impl_node_opcode_two!(OrC, ( $( $a )* ), ( $( $b )* ))
    -    });
    -    ( or_i ( $( $a:tt )* ), ( $( $b:tt )* ) ) => ({
    -        $crate::impl_node_opcode_two!(OrI, ( $( $a )* ), ( $( $b )* ))
    -    });
    -    ( thresh_vec $thresh:expr, $items:expr ) => ({
    -        use $crate::miniscript::descriptor::KeyMap;
    -
    -        let (items, key_maps_networks): (Vec<_>, Vec<_>) = $items.into_iter().map(|(a, b, c)| (a, (b, c))).unzip();
    -        let items = items.into_iter().map(std::sync::Arc::new).collect();
    -
    -        let (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 $(, ( $( $item:tt )* ) )+ ) => ({
    -        let mut items = vec![];
    -        $(
    -            items.push($crate::fragment!($( $item )*));
    -        )*
    -
    -        items.into_iter().collect::<Result<Vec<_>, _>>()
    -            .and_then(|items| $crate::fragment!(thresh_vec $thresh, items))
    -    });
    -    ( multi_vec $thresh:expr, $keys:expr ) => ({
    -        $crate::keys::make_multi($thresh, $keys)
    -    });
    -    ( multi $thresh:expr $(, $key:expr )+ ) => ({
    -        use $crate::keys::ToDescriptorKey;
    -        let secp = $crate::bitcoin::secp256k1::Secp256k1::new();
    -
    -        let mut keys = vec![];
    -        $(
    -            keys.push($key.to_descriptor_key());
    -        )*
    -
    -        keys.into_iter().collect::<Result<Vec<_>, _>>()
    -            .and_then(|keys| $crate::keys::make_multi($thresh, keys, &secp))
    -    });
    -
    -    // `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 bitcoin::hashes::hex::ToHex;
    -    use bitcoin::secp256k1::Secp256k1;
    -    use miniscript::descriptor::{DescriptorPublicKey, DescriptorPublicKeyCtx, KeyMap};
    -    use miniscript::{Descriptor, Legacy, Segwitv0};
    -
    -    use std::str::FromStr;
    -
    -    use crate::descriptor::DescriptorMeta;
    -    use crate::keys::{DescriptorKey, KeyError, ToDescriptorKey, ValidNetworks};
    -    use bitcoin::network::constants::Network::{Bitcoin, Regtest, Testnet};
    -    use bitcoin::util::bip32;
    -    use bitcoin::util::bip32::ChildNumber;
    -
    -    // 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), KeyError>,
    -        is_witness: bool,
    -        is_fixed: bool,
    -        expected: &[&str],
    -    ) {
    -        let secp = Secp256k1::new();
    -        let deriv_ctx = DescriptorPublicKeyCtx::new(&secp, ChildNumber::Normal { index: 0 });
    -
    -        let (desc, _key_map, _networks) = desc.unwrap();
    -        assert_eq!(desc.is_witness(), is_witness);
    -        assert_eq!(desc.is_fixed(), is_fixed);
    -        for i in 0..expected.len() {
    -            let index = i as u32;
    -            let child_desc = if desc.is_fixed() {
    -                desc.clone()
    -            } else {
    -                desc.derive(ChildNumber::from_normal_idx(index).unwrap())
    -            };
    -            let address = child_desc.address(Regtest, deriv_ctx);
    -            if let Some(address) = address {
    -                assert_eq!(address.to_string(), *expected.get(i).unwrap());
    -            } else {
    -                let script = child_desc.script_pubkey(deriv_ctx);
    -                assert_eq!(script.to_hex().as_str(), *expected.get(i).unwrap());
    -            }
    -        }
    -    }
    -
    -    // - at least one of each "type" of operator; ie. one modifier, one leaf_opcode, one leaf_opcode_value, etc.
    -    // - mixing up key types that implement ToDescriptorKey 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_bip32_legacy_descriptors() {
    -        let xprv = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
    -
    -        let path = bip32::DerivationPath::from_str("m/0").unwrap();
    -        let desc_key = (xprv, path.clone()).to_descriptor_key().unwrap();
    -        check(
    -            descriptor!(pk(desc_key)),
    -            false,
    -            false,
    -            &[
    -                "2102363ad03c10024e1b597a5b01b9982807fb638e00b06f3b2d4a89707de3b93c37ac",
    -                "2102063a21fd780df370ed2fc8c4b86aa5ea642630609c203009df631feb7b480dd2ac",
    -                "2102ba2685ad1fa5891cb100f1656b2ce3801822ccb9bac0336734a6f8c1b93ebbc0ac",
    -            ],
    -        );
    -
    -        let desc_key = (xprv, path.clone()).to_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).to_descriptor_key().unwrap();
    -        let desc_key2 = (xprv, path2).to_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::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
    -
    -        let path = bip32::DerivationPath::from_str("m/0").unwrap();
    -        let desc_key = (xprv, path.clone()).to_descriptor_key().unwrap();
    -        check(
    -            descriptor!(wpkh(desc_key)),
    -            true,
    -            false,
    -            &[
    -                "bcrt1qnhm8w9fhc8cxzgqsmqdf9fyjccyvc0gltnymu0",
    -                "bcrt1qhylfd55rn75w9fj06zspctad5w4hz33rf0ttad",
    -                "bcrt1qq5sq3a6k9av9d8cne0k9wcldy4nqey5yt6889r",
    -            ],
    -        );
    -
    -        let desc_key = (xprv, path.clone()).to_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()).to_descriptor_key().unwrap();
    -        let desc_key2 = (xprv, path2.clone()).to_descriptor_key().unwrap();
    -        check(
    -            descriptor!(wsh(multi 1,desc_key1,desc_key2)),
    -            true,
    -            false,
    -            &[
    -                "bcrt1qfxv8mxmlv5sz8q2mnuyaqdfe9jr4vvmx0csjhn092p6f4qfygfkq2hng49",
    -                "bcrt1qerj85g243e6jlcdxpmn9spk0gefcwvu7nw7ee059d5ydzpdhkm2qwfkf5k",
    -                "bcrt1qxkl2qss3k58q9ktc8e89pwr4gnptfpw4hju4xstxcjc0hkcae3jstluty7",
    -            ],
    -        );
    -
    -        let desc_key1 = (xprv, path).to_descriptor_key().unwrap();
    -        let desc_key2 = (xprv, path2).to_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::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
    -        let path_1 = bip32::DerivationPath::from_str("m/0").unwrap();
    -
    -        let key_2 = bip32::ExtendedPrivKey::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::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
    -        let path = bip32::DerivationPath::from_str("m/0").unwrap();
    -        let desc_key = (xprv, path.clone()).to_descriptor_key().unwrap();
    -
    -        let (_desc, _key_map, valid_networks) = descriptor!(pkh(desc_key)).unwrap();
    -        assert_eq!(valid_networks, [Testnet, Regtest].iter().cloned().collect());
    -
    -        let xprv = bip32::ExtendedPrivKey::from_str("xprv9s21ZrQH143K3QTDL4LXw2F7HEK3wJUD2nW2nRk4stbPy6cq3jPPqjiChkVvvNKmPGJxWUtg6LnF5kejMRNNU3TGtRBeJgk33yuGBxrMPHi").unwrap();
    -        let path = bip32::DerivationPath::from_str("m/10/20/30/40").unwrap();
    -        let desc_key = (xprv, path.clone()).to_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::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
    -        let path1 = bip32::DerivationPath::from_str("m/0").unwrap();
    -        let desc_key1 = (xprv1, path1.clone()).to_descriptor_key().unwrap();
    -
    -        let xprv2 = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPegBHHnq7YEgM815dG24M2Jk5RVqipgDxF1HJ1tsnT815X5Fd5FRfMVUs8NZs9XCb6y9an8hRPThnhfwfXJ36intaekySHGF").unwrap();
    -        let path2 = bip32::DerivationPath::from_str("m/2147483647'/0").unwrap();
    -        let desc_key2 = (xprv2, path2.clone()).to_descriptor_key().unwrap();
    -
    -        let xprv3 = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPdZXrcHNLf5JAJWFAoJ2TrstMRdSKtEggz6PddbuSkvHKM9oKJyFgZV1B7rw8oChspxyYbtmEXYyg1AjfWbL3ho3XHDpHRZf").unwrap();
    -        let path3 = bip32::DerivationPath::from_str("m/10/20/30/40").unwrap();
    -        let desc_key3 = (xprv3, path3.clone()).to_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.clone()).to_descriptor_key().unwrap();
    -        let desc_key2: DescriptorKey<Segwitv0> =
    -            (xprv2, path2.clone()).to_descriptor_key().unwrap();
    -        let desc_key3: DescriptorKey<Segwitv0> =
    -            (xprv3, path3.clone()).to_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 ToDescriptorKey<Segwitv0> to a pkh() descriptor should throw a compilation error
    -    #[test]
    -    fn test_script_context_validation() {
    -        // this compiles
    -        let xprv = bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
    -        let path = bip32::DerivationPath::from_str("m/0").unwrap();
    -        let desc_key: DescriptorKey<Legacy> = (xprv, path.clone()).to_descriptor_key().unwrap();
    -
    -        let (desc, _key_map, _valid_networks) = descriptor!(pkh(desc_key)).unwrap();
    -        assert_eq!(desc.to_string(), "pkh(tpubD6NzVbkrYhZ4WR7a4vY1VT3khMJMeAxVsfq9TBJyJWrNk247zCJtV7AWf6UJP7rAVsn8NNKdJi3gFyKPTmWZS9iukb91xbn2HbFSMQm2igY/0/*)");
    -
    -        // as expected this does not compile due to invalid context
    -        //let desc_key:DescriptorKey<Segwitv0> = (xprv, path.clone()).to_descriptor_key().unwrap();
    -        //let (desc, _key_map, _valid_networks) = descriptor!(pkh(desc_key)).unwrap();
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/error.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/error.rs.html deleted file mode 100644 index 2472440c46..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/error.rs.html +++ /dev/null @@ -1,176 +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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Descriptor errors
    -
    -/// Errors related to the parsing and usage of descriptors
    -#[derive(Debug)]
    -pub enum Error {
    -    //InternalError,
    -    //InvalidPrefix(Vec<u8>),
    -    //HardenedDerivationOnXpub,
    -    //MalformedInput,
    -    /// Invalid HD Key path, such as having a wildcard but a length != 1
    -    InvalidHDKeyPath,
    -
    -    //KeyParsingError(String),
    -    /// Error thrown while working with [`keys`](crate::keys)
    -    Key(crate::keys::KeyError),
    -    /// Error while extracting and manipulating policies
    -    Policy(crate::descriptor::policy::PolicyError),
    -
    -    //InputIndexDoesntExist,
    -    //MissingPublicKey,
    -    //MissingDetails,
    -    /// Invalid character found in the descriptor checksum
    -    InvalidDescriptorCharacter(char),
    -
    -    //CantDeriveWithMiniscript,
    -    /// BIP32 error
    -    BIP32(bitcoin::util::bip32::Error),
    -    /// Error during base58 decoding
    -    Base58(bitcoin::util::base58::Error),
    -    /// Key-related error
    -    PK(bitcoin::util::key::Error),
    -    /// Miniscript error
    -    Miniscript(miniscript::Error),
    -    /// Hex decoding error
    -    Hex(bitcoin::hashes::hex::Error),
    -}
    -
    -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 std::fmt::Display for Error {
    -    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for Error {}
    -
    -impl_error!(bitcoin::util::bip32::Error, BIP32);
    -impl_error!(bitcoin::util::base58::Error, Base58);
    -impl_error!(bitcoin::util::key::Error, PK);
    -impl_error!(miniscript::Error, Miniscript);
    -impl_error!(bitcoin::hashes::hex::Error, Hex);
    -impl_error!(crate::descriptor::policy::PolicyError, Policy);
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/mod.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/mod.rs.html deleted file mode 100644 index 22803d1c76..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/mod.rs.html +++ /dev/null @@ -1,1560 +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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Descriptors
    -//!
    -//! This module contains generic utilities to work with descriptors, plus some re-exported types
    -//! from [`miniscript`].
    -
    -use std::collections::{BTreeMap, HashMap};
    -use std::fmt;
    -
    -use bitcoin::secp256k1::Secp256k1;
    -use bitcoin::util::bip32::{ChildNumber, DerivationPath, ExtendedPubKey, Fingerprint, KeySource};
    -use bitcoin::util::psbt;
    -use bitcoin::{Network, PublicKey, Script, TxOut};
    -
    -use miniscript::descriptor::{DescriptorPublicKey, DescriptorXKey, InnerXKey};
    -pub use miniscript::{
    -    descriptor::KeyMap, Descriptor, Legacy, Miniscript, MiniscriptKey, ScriptContext, Segwitv0,
    -    Terminal, ToPublicKey,
    -};
    -
    -pub mod checksum;
    -mod dsl;
    -pub mod error;
    -pub mod policy;
    -pub mod template;
    -
    -pub use self::checksum::get_checksum;
    -use self::error::Error;
    -pub use self::policy::Policy;
    -use self::template::DescriptorTemplateOut;
    -use crate::keys::{KeyError, ToDescriptorKey};
    -use crate::wallet::signer::SignersContainer;
    -use crate::wallet::utils::{descriptor_to_pk_ctx, SecpCtx};
    -
    -/// Alias for a [`Descriptor`] that can contain extended keys using [`DescriptorPublicKey`]
    -pub type ExtendedDescriptor = Descriptor<DescriptorPublicKey>;
    -
    -/// Alias for the type of maps that represent derivation paths in a [`psbt::Input`] or
    -/// [`psbt::Output`]
    -///
    -/// [`psbt::Input`]: bitcoin::util::psbt::Input
    -/// [`psbt::Output`]: bitcoin::util::psbt::Output
    -pub type HDKeyPaths = BTreeMap<PublicKey, KeySource>;
    -
    -/// Trait for types which can be converted into an [`ExtendedDescriptor`] and a [`KeyMap`] usable by a wallet in a specific [`Network`]
    -pub trait ToWalletDescriptor {
    -    /// Convert to wallet descriptor
    -    fn to_wallet_descriptor(
    -        self,
    -        network: Network,
    -    ) -> Result<(ExtendedDescriptor, KeyMap), KeyError>;
    -}
    -
    -impl ToWalletDescriptor for &str {
    -    fn to_wallet_descriptor(
    -        self,
    -        network: Network,
    -    ) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
    -        let descriptor = if self.contains('#') {
    -            let parts: Vec<&str> = self.splitn(2, '#').collect();
    -            if !get_checksum(parts[0])
    -                .ok()
    -                .map(|computed| computed == parts[1])
    -                .unwrap_or(false)
    -            {
    -                return Err(KeyError::InvalidChecksum);
    -            }
    -
    -            parts[0]
    -        } else {
    -            self
    -        };
    -
    -        ExtendedDescriptor::parse_descriptor(descriptor)?.to_wallet_descriptor(network)
    -    }
    -}
    -
    -impl ToWalletDescriptor for &String {
    -    fn to_wallet_descriptor(
    -        self,
    -        network: Network,
    -    ) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
    -        self.as_str().to_wallet_descriptor(network)
    -    }
    -}
    -
    -impl ToWalletDescriptor for ExtendedDescriptor {
    -    fn to_wallet_descriptor(
    -        self,
    -        network: Network,
    -    ) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
    -        (self, KeyMap::default()).to_wallet_descriptor(network)
    -    }
    -}
    -
    -impl ToWalletDescriptor for (ExtendedDescriptor, KeyMap) {
    -    fn to_wallet_descriptor(
    -        self,
    -        network: Network,
    -    ) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
    -        use crate::keys::DescriptorKey;
    -
    -        let secp = Secp256k1::new();
    -
    -        let check_key = |pk: &DescriptorPublicKey| {
    -            let (pk, _, networks) = if self.0.is_witness() {
    -                let desciptor_key: DescriptorKey<miniscript::Segwitv0> =
    -                    pk.clone().to_descriptor_key()?;
    -                desciptor_key.extract(&secp)?
    -            } else {
    -                let desciptor_key: DescriptorKey<miniscript::Legacy> =
    -                    pk.clone().to_descriptor_key()?;
    -                desciptor_key.extract(&secp)?
    -            };
    -
    -            if networks.contains(&network) {
    -                Ok(pk)
    -            } else {
    -                Err(KeyError::InvalidNetwork)
    -            }
    -        };
    -
    -        // check the network for the keys
    -        let translated = self.0.translate_pk(check_key, check_key)?;
    -
    -        Ok((translated, self.1))
    -    }
    -}
    -
    -impl ToWalletDescriptor for DescriptorTemplateOut {
    -    fn to_wallet_descriptor(
    -        self,
    -        network: Network,
    -    ) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
    -        let valid_networks = &self.2;
    -
    -        let fix_key = |pk: &DescriptorPublicKey| {
    -            if valid_networks.contains(&network) {
    -                // 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 = network;
    -
    -                        DescriptorPublicKey::XPub(xpub)
    -                    }
    -                    other => other.clone(),
    -                };
    -
    -                Ok(pk)
    -            } else {
    -                Err(KeyError::InvalidNetwork)
    -            }
    -        };
    -
    -        // fixup the network for keys that need it
    -        let translated = self.0.translate_pk(fix_key, fix_key)?;
    -
    -        Ok((translated, self.1))
    -    }
    -}
    -
    -/// 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,
    -        secp: &SecpCtx,
    -    ) -> Result<Option<Policy>, Error>;
    -}
    -
    -pub(crate) trait XKeyUtils {
    -    fn full_path(&self, append: &[ChildNumber]) -> DerivationPath;
    -    fn root_fingerprint(&self, secp: &SecpCtx) -> Fingerprint;
    -}
    -
    -impl<K: InnerXKey> XKeyUtils for DescriptorXKey<K> {
    -    fn full_path(&self, append: &[ChildNumber]) -> DerivationPath {
    -        let full_path = match self.origin {
    -            Some((_, ref path)) => path
    -                .into_iter()
    -                .chain(self.derivation_path.into_iter())
    -                .cloned()
    -                .collect(),
    -            None => self.derivation_path.clone(),
    -        };
    -
    -        if self.is_wildcard {
    -            full_path
    -                .into_iter()
    -                .chain(append.iter())
    -                .cloned()
    -                .collect()
    -        } else {
    -            full_path
    -        }
    -    }
    -
    -    fn root_fingerprint(&self, secp: &SecpCtx) -> Fingerprint {
    -        match self.origin {
    -            Some((fingerprint, _)) => fingerprint,
    -            None => self.xkey.xkey_fingerprint(secp),
    -        }
    -    }
    -}
    -
    -pub(crate) trait DescriptorMeta: Sized {
    -    fn is_witness(&self) -> bool;
    -    fn get_hd_keypaths(&self, index: u32, secp: &SecpCtx) -> Result<HDKeyPaths, Error>;
    -    fn get_extended_keys(&self) -> Result<Vec<DescriptorXKey<ExtendedPubKey>>, Error>;
    -    fn is_fixed(&self) -> bool;
    -    fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths, secp: &SecpCtx) -> Option<Self>;
    -    fn derive_from_psbt_input(
    -        &self,
    -        psbt_input: &psbt::Input,
    -        utxo: Option<TxOut>,
    -        secp: &SecpCtx,
    -    ) -> Option<Self>;
    -}
    -
    -pub(crate) trait DescriptorScripts {
    -    fn psbt_redeem_script(&self, secp: &SecpCtx) -> Option<Script>;
    -    fn psbt_witness_script(&self, secp: &SecpCtx) -> Option<Script>;
    -}
    -
    -impl DescriptorScripts for Descriptor<DescriptorPublicKey> {
    -    fn psbt_redeem_script(&self, secp: &SecpCtx) -> Option<Script> {
    -        let deriv_ctx = descriptor_to_pk_ctx(secp);
    -
    -        match self {
    -            Descriptor::ShWpkh(_) => Some(self.witness_script(deriv_ctx)),
    -            Descriptor::ShWsh(ref script) => Some(script.encode(deriv_ctx).to_v0_p2wsh()),
    -            Descriptor::Sh(ref script) => Some(script.encode(deriv_ctx)),
    -            Descriptor::Bare(ref script) => Some(script.encode(deriv_ctx)),
    -            Descriptor::ShSortedMulti(ref keys) => Some(keys.encode(deriv_ctx)),
    -            _ => None,
    -        }
    -    }
    -
    -    fn psbt_witness_script(&self, secp: &SecpCtx) -> Option<Script> {
    -        let deriv_ctx = descriptor_to_pk_ctx(secp);
    -
    -        match self {
    -            Descriptor::Wsh(ref script) => Some(script.encode(deriv_ctx)),
    -            Descriptor::ShWsh(ref script) => Some(script.encode(deriv_ctx)),
    -            Descriptor::WshSortedMulti(ref keys) | Descriptor::ShWshSortedMulti(ref keys) => {
    -                Some(keys.encode(deriv_ctx))
    -            }
    -            _ => None,
    -        }
    -    }
    -}
    -
    -impl DescriptorMeta for Descriptor<DescriptorPublicKey> {
    -    fn is_witness(&self) -> bool {
    -        match self {
    -            Descriptor::Bare(_)
    -            | Descriptor::Pk(_)
    -            | Descriptor::Pkh(_)
    -            | Descriptor::Sh(_)
    -            | Descriptor::ShSortedMulti(_) => false,
    -            Descriptor::Wpkh(_)
    -            | Descriptor::ShWpkh(_)
    -            | Descriptor::Wsh(_)
    -            | Descriptor::ShWsh(_)
    -            | Descriptor::ShWshSortedMulti(_)
    -            | Descriptor::WshSortedMulti(_) => true,
    -        }
    -    }
    -
    -    fn get_hd_keypaths(&self, index: u32, secp: &SecpCtx) -> Result<HDKeyPaths, Error> {
    -        let translate_key = |key: &DescriptorPublicKey,
    -                             index: u32,
    -                             paths: &mut HDKeyPaths|
    -         -> Result<DummyKey, Error> {
    -            match key {
    -                DescriptorPublicKey::SinglePub(_) => {}
    -                DescriptorPublicKey::XPub(xpub) => {
    -                    let derive_path = if xpub.is_wildcard {
    -                        xpub.derivation_path
    -                            .into_iter()
    -                            .chain([ChildNumber::from_normal_idx(index)?].iter())
    -                            .cloned()
    -                            .collect()
    -                    } else {
    -                        xpub.derivation_path.clone()
    -                    };
    -                    let derived_pubkey = xpub
    -                        .xkey
    -                        .derive_pub(&Secp256k1::verification_only(), &derive_path)?;
    -
    -                    paths.insert(
    -                        derived_pubkey.public_key,
    -                        (
    -                            xpub.root_fingerprint(secp),
    -                            xpub.full_path(&[ChildNumber::from_normal_idx(index)?]),
    -                        ),
    -                    );
    -                }
    -            }
    -
    -            Ok(DummyKey::default())
    -        };
    -
    -        let mut answer_pk = BTreeMap::new();
    -        let mut answer_pkh = BTreeMap::new();
    -
    -        self.translate_pk(
    -            |pk| translate_key(pk, index, &mut answer_pk),
    -            |pkh| translate_key(pkh, index, &mut answer_pkh),
    -        )?;
    -
    -        answer_pk.append(&mut answer_pkh);
    -
    -        Ok(answer_pk)
    -    }
    -
    -    fn get_extended_keys(&self) -> Result<Vec<DescriptorXKey<ExtendedPubKey>>, Error> {
    -        let get_key = |key: &DescriptorPublicKey,
    -                       keys: &mut Vec<DescriptorXKey<ExtendedPubKey>>|
    -         -> Result<DummyKey, Error> {
    -            if let DescriptorPublicKey::XPub(xpub) = key {
    -                keys.push(xpub.clone())
    -            }
    -
    -            Ok(DummyKey::default())
    -        };
    -
    -        let mut answer_pk = Vec::new();
    -        let mut answer_pkh = Vec::new();
    -
    -        self.translate_pk(
    -            |pk| get_key(pk, &mut answer_pk),
    -            |pkh| get_key(pkh, &mut answer_pkh),
    -        )?;
    -
    -        answer_pk.append(&mut answer_pkh);
    -
    -        Ok(answer_pk)
    -    }
    -
    -    fn is_fixed(&self) -> bool {
    -        fn check_key(key: &DescriptorPublicKey, flag: &mut bool) -> Result<DummyKey, Error> {
    -            match key {
    -                DescriptorPublicKey::SinglePub(_) => {}
    -                DescriptorPublicKey::XPub(xpub) => {
    -                    if xpub.is_wildcard {
    -                        *flag = true;
    -                    }
    -                }
    -            }
    -
    -            Ok(DummyKey::default())
    -        }
    -
    -        let mut found_wildcard_pk = false;
    -        let mut found_wildcard_pkh = false;
    -
    -        self.translate_pk(
    -            |pk| check_key(pk, &mut found_wildcard_pk),
    -            |pkh| check_key(pkh, &mut found_wildcard_pkh),
    -        )
    -        .unwrap();
    -
    -        !found_wildcard_pk && !found_wildcard_pkh
    -    }
    -
    -    fn derive_from_hd_keypaths(&self, hd_keypaths: &HDKeyPaths, secp: &SecpCtx) -> Option<Self> {
    -        let try_key = |key: &DescriptorPublicKey,
    -                       index: &HashMap<Fingerprint, DerivationPath>,
    -                       found_path: &mut Option<ChildNumber>|
    -         -> Result<DummyKey, Error> {
    -            if found_path.is_some() {
    -                // already found a matching path, we are done
    -                return Ok(DummyKey::default());
    -            }
    -
    -            if let DescriptorPublicKey::XPub(xpub) = key {
    -                // Check if the key matches one entry in our `index`. If it does, `matches()` will
    -                // return the "prefix" that matched, so we remove that prefix from the full path
    -                // found in `index` 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 derivation_path: Option<Vec<ChildNumber>> = index
    -                    .get_key_value(&root_fingerprint)
    -                    .and_then(|(fingerprint, path)| {
    -                        xpub.matches(&(*fingerprint, path.clone()), secp)
    -                    })
    -                    .map(|prefix| {
    -                        index
    -                            .get(&xpub.root_fingerprint(secp))
    -                            .unwrap()
    -                            .into_iter()
    -                            .skip(prefix.into_iter().count())
    -                            .cloned()
    -                            .collect()
    -                    });
    -
    -                match derivation_path {
    -                    Some(path) if xpub.is_wildcard && path.len() == 1 => {
    -                        *found_path = Some(path[0])
    -                    }
    -                    Some(path) if !xpub.is_wildcard && path.is_empty() => {
    -                        *found_path = Some(ChildNumber::Normal { index: 0 })
    -                    }
    -                    Some(_) => return Err(Error::InvalidHDKeyPath),
    -                    _ => {}
    -                }
    -            }
    -
    -            Ok(DummyKey::default())
    -        };
    -
    -        let index: HashMap<_, _> = hd_keypaths.values().cloned().collect();
    -
    -        let mut found_path_pk = None;
    -        let mut found_path_pkh = None;
    -
    -        if self
    -            .translate_pk(
    -                |pk| try_key(pk, &index, &mut found_path_pk),
    -                |pkh| try_key(pkh, &index, &mut found_path_pkh),
    -            )
    -            .is_err()
    -        {
    -            return None;
    -        }
    -
    -        // if we have found a path for both `found_path_pk` and `found_path_pkh` but they are
    -        // different we consider this an error and return None. we only return a path either if
    -        // they are equal or if only one of them is Some(_)
    -        let merged_path = match (found_path_pk, found_path_pkh) {
    -            (Some(a), Some(b)) if a != b => return None,
    -            (a, b) => a.or(b),
    -        };
    -
    -        merged_path.map(|path| self.derive(path))
    -    }
    -
    -    fn derive_from_psbt_input(
    -        &self,
    -        psbt_input: &psbt::Input,
    -        utxo: Option<TxOut>,
    -        secp: &SecpCtx,
    -    ) -> Option<Self> {
    -        if let Some(derived) = self.derive_from_hd_keypaths(&psbt_input.hd_keypaths, secp) {
    -            return Some(derived);
    -        } else if !self.is_fixed() {
    -            // If the descriptor is not fixed we can't brute-force the derivation address, so just
    -            // exit here
    -            return None;
    -        }
    -
    -        let deriv_ctx = descriptor_to_pk_ctx(secp);
    -        match self {
    -            Descriptor::Pk(_)
    -            | Descriptor::Pkh(_)
    -            | Descriptor::Wpkh(_)
    -            | Descriptor::ShWpkh(_)
    -                if utxo.is_some()
    -                    && self.script_pubkey(deriv_ctx) == utxo.as_ref().unwrap().script_pubkey =>
    -            {
    -                Some(self.clone())
    -            }
    -            Descriptor::Bare(ms)
    -                if psbt_input.redeem_script.is_some()
    -                    && &ms.encode(deriv_ctx) == psbt_input.redeem_script.as_ref().unwrap() =>
    -            {
    -                Some(self.clone())
    -            }
    -            Descriptor::Sh(ms)
    -                if psbt_input.redeem_script.is_some()
    -                    && &ms.encode(deriv_ctx) == psbt_input.redeem_script.as_ref().unwrap() =>
    -            {
    -                Some(self.clone())
    -            }
    -            Descriptor::Wsh(ms) | Descriptor::ShWsh(ms)
    -                if psbt_input.witness_script.is_some()
    -                    && &ms.encode(deriv_ctx) == psbt_input.witness_script.as_ref().unwrap() =>
    -            {
    -                Some(self.clone())
    -            }
    -            Descriptor::ShSortedMulti(keys)
    -                if psbt_input.redeem_script.is_some()
    -                    && &keys.encode(deriv_ctx) == psbt_input.redeem_script.as_ref().unwrap() =>
    -            {
    -                Some(self.clone())
    -            }
    -            Descriptor::WshSortedMulti(keys) | Descriptor::ShWshSortedMulti(keys)
    -                if psbt_input.witness_script.is_some()
    -                    && &keys.encode(deriv_ctx) == psbt_input.witness_script.as_ref().unwrap() =>
    -            {
    -                Some(self.clone())
    -            }
    -            _ => None,
    -        }
    -    }
    -}
    -
    -#[derive(Debug, Clone, Hash, PartialEq, PartialOrd, Eq, Ord, Default)]
    -struct DummyKey();
    -
    -impl fmt::Display for DummyKey {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "DummyKey")
    -    }
    -}
    -
    -impl std::str::FromStr for DummyKey {
    -    type Err = ();
    -
    -    fn from_str(_: &str) -> Result<Self, Self::Err> {
    -        Ok(DummyKey::default())
    -    }
    -}
    -
    -impl miniscript::MiniscriptKey for DummyKey {
    -    type Hash = DummyKey;
    -
    -    fn to_pubkeyhash(&self) -> DummyKey {
    -        DummyKey::default()
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::str::FromStr;
    -
    -    use bitcoin::consensus::encode::deserialize;
    -    use bitcoin::hashes::hex::FromHex;
    -    use bitcoin::secp256k1::Secp256k1;
    -    use bitcoin::util::{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::PartiallySignedTransaction = 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::PartiallySignedTransaction = 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::PartiallySignedTransaction = 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::PartiallySignedTransaction = 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, ToDescriptorKey};
    -
    -        let xpub = bip32::ExtendedPubKey::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").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 = (xpub, path).to_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 conver the key that supports "any_network" to the right network (testnet)
    -        let (wallet_desc, _) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
    -
    -        assert_eq!(wallet_desc.to_string(), "wpkh(tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)");
    -    }
    -
    -    // test ToWalletDescriptor trait from &str with and without checksum appended
    -    #[test]
    -    fn test_descriptor_from_str_with_checksum() {
    -        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#tqz0nc62"
    -            .to_wallet_descriptor(Network::Testnet);
    -        assert!(desc.is_ok());
    -
    -        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
    -            .to_wallet_descriptor(Network::Testnet);
    -        assert!(desc.is_ok());
    -
    -        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)#67ju93jw"
    -            .to_wallet_descriptor(Network::Testnet);
    -        assert!(desc.is_ok());
    -
    -        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
    -            .to_wallet_descriptor(Network::Testnet);
    -        assert!(desc.is_ok());
    -
    -        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#67ju93jw"
    -            .to_wallet_descriptor(Network::Testnet);
    -        assert!(matches!(desc.err(), Some(KeyError::InvalidChecksum)));
    -
    -        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#67ju93jw"
    -            .to_wallet_descriptor(Network::Testnet);
    -        assert!(matches!(desc.err(), Some(KeyError::InvalidChecksum)));
    -    }
    -
    -    // test ToWalletDescriptor trait from &str with keys from right and wrong network
    -    #[test]
    -    fn test_descriptor_from_str_with_keys_network() {
    -        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
    -            .to_wallet_descriptor(Network::Testnet);
    -        assert!(desc.is_ok());
    -
    -        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
    -            .to_wallet_descriptor(Network::Regtest);
    -        assert!(desc.is_ok());
    -
    -        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
    -            .to_wallet_descriptor(Network::Testnet);
    -        assert!(desc.is_ok());
    -
    -        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
    -            .to_wallet_descriptor(Network::Regtest);
    -        assert!(desc.is_ok());
    -
    -        let desc = "sh(wpkh(02864bb4ad00cefa806098a69e192bbda937494e69eb452b87bb3f20f6283baedb))"
    -            .to_wallet_descriptor(Network::Testnet);
    -        assert!(desc.is_ok());
    -
    -        let desc = "sh(wpkh(02864bb4ad00cefa806098a69e192bbda937494e69eb452b87bb3f20f6283baedb))"
    -            .to_wallet_descriptor(Network::Bitcoin);
    -        assert!(desc.is_ok());
    -
    -        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)"
    -            .to_wallet_descriptor(Network::Bitcoin);
    -        assert!(matches!(desc.err(), Some(KeyError::InvalidNetwork)));
    -
    -        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
    -            .to_wallet_descriptor(Network::Bitcoin);
    -        assert!(matches!(desc.err(), Some(KeyError::InvalidNetwork)));
    -    }
    -
    -    // test ToWalletDescriptor trait from the output of the descriptor!() macro
    -    #[test]
    -    fn test_descriptor_from_str_from_output_of_macro() {
    -        let tpub = bip32::ExtendedPubKey::from_str("tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK").unwrap();
    -        let path = bip32::DerivationPath::from_str("m/1/2").unwrap();
    -        let key = (tpub, path).to_descriptor_key().unwrap();
    -
    -        // make a descriptor out of it
    -        let desc = crate::descriptor!(wpkh(key)).unwrap();
    -
    -        let (wallet_desc, _) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
    -        let wallet_desc_str = wallet_desc.to_string();
    -        assert_eq!(wallet_desc_str, "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)");
    -
    -        let (wallet_desc2, _) = wallet_desc_str
    -            .to_wallet_descriptor(Network::Testnet)
    -            .unwrap();
    -        assert_eq!(wallet_desc, wallet_desc2)
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/policy.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/policy.rs.html deleted file mode 100644 index ea8a2c70d1..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/policy.rs.html +++ /dev/null @@ -1,2462 +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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! 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::bitcoin::secp256k1::Secp256k1;
    -//! 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(desc)?;
    -//! println!("{:?}", extended_desc);
    -//!
    -//! let signers = Arc::new(key_map.into());
    -//! let policy = extended_desc.extract_policy(&signers, &secp)?;
    -//! println!("policy: {}", serde_json::to_string(&policy)?);
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use std::cmp::{max, Ordering};
    -use std::collections::{BTreeMap, HashSet, VecDeque};
    -use std::fmt;
    -
    -use serde::ser::SerializeMap;
    -use serde::{Serialize, Serializer};
    -
    -use bitcoin::hashes::*;
    -use bitcoin::util::bip32::Fingerprint;
    -use bitcoin::PublicKey;
    -
    -use miniscript::descriptor::{DescriptorPublicKey, SortedMultiVec};
    -use miniscript::{Descriptor, Miniscript, MiniscriptKey, ScriptContext, Terminal, ToPublicKey};
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -use crate::descriptor::ExtractPolicy;
    -use crate::wallet::signer::{SignerId, SignersContainer};
    -use crate::wallet::utils::{self, descriptor_to_pk_ctx, SecpCtx};
    -
    -use super::checksum::get_checksum;
    -use super::error::Error;
    -use super::XKeyUtils;
    -
    -/// Raw public key or extended key fingerprint
    -#[derive(Debug, Clone, Default, Serialize)]
    -pub struct PKOrF {
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    pubkey: Option<PublicKey>,
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    pubkey_hash: Option<hash160::Hash>,
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    fingerprint: Option<Fingerprint>,
    -}
    -
    -impl PKOrF {
    -    fn from_key(k: &DescriptorPublicKey, secp: &SecpCtx) -> Self {
    -        match k {
    -            DescriptorPublicKey::SinglePub(pubkey) => PKOrF {
    -                pubkey: Some(pubkey.key),
    -                ..Default::default()
    -            },
    -            DescriptorPublicKey::XPub(xpub) => PKOrF {
    -                fingerprint: Some(xpub.root_fingerprint(secp)),
    -                ..Default::default()
    -            },
    -        }
    -    }
    -
    -    fn from_key_hash(k: hash160::Hash) -> Self {
    -        PKOrF {
    -            pubkey_hash: Some(k),
    -            ..Default::default()
    -        }
    -    }
    -}
    -
    -/// An item that needs to be satisfied
    -#[derive(Debug, Clone, Serialize)]
    -#[serde(tag = "type", rename_all = "UPPERCASE")]
    -pub enum SatisfiableItem {
    -    // Leaves
    -    /// Signature for a raw public key
    -    Signature(PKOrF),
    -    /// Signature for an extended key fingerprint
    -    SignatureKey(PKOrF),
    -    /// SHA256 preimage hash
    -    SHA256Preimage {
    -        /// The digest value
    -        hash: sha256::Hash,
    -    },
    -    /// Double SHA256 preimage hash
    -    HASH256Preimage {
    -        /// The digest value
    -        hash: sha256d::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 timestamp value
    -        value: u32,
    -    },
    -    /// Relative timelock locktime
    -    RelativeTimelock {
    -        /// The locktime value
    -        value: u32,
    -    },
    -    /// 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 {
    -        get_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, 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
    -        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) -> Result<(), PolicyError> {
    -        // 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 ([choosen 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 possibile options and check whether or not they are compatible.
    -                    .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: &Vec<(Vec<usize>, Vec<Condition>)>| println!("fetch {:?}", x))
    -                    // since the previous step can turn one item of the iterator into multiple ones, we call flatten to expand them out
    -                    .flatten()
    -                    // .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,
    -                };
    -            }
    -        }
    -
    -        Ok(())
    -    }
    -}
    -
    -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, Serialize)]
    -pub struct Policy {
    -    /// Identifier for this policy node
    -    pub id: String,
    -
    -    /// Type of this policy node
    -    #[serde(flatten)]
    -    pub item: SatisfiableItem,
    -    /// How a much given PSBT already satisfies this polcy node **(currently unused)**
    -    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
    -#[derive(Hash, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default, Serialize)]
    -pub struct Condition {
    -    /// Optional CheckSequenceVerify condition
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    pub csv: Option<u32>,
    -    /// Optional timelock condition
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    pub timelock: Option<u32>,
    -}
    -
    -impl Condition {
    -    fn merge_nlocktime(a: u32, b: u32) -> Result<u32, PolicyError> {
    -        if (a < utils::BLOCKS_TIMELOCK_THRESHOLD) != (b < utils::BLOCKS_TIMELOCK_THRESHOLD) {
    -            Err(PolicyError::MixedTimelockUnits)
    -        } else {
    -            Ok(max(a, b))
    -        }
    -    }
    -
    -    fn merge_nsequence(a: u32, b: u32) -> Result<u32, PolicyError> {
    -        let mask = utils::SEQUENCE_LOCKTIME_TYPE_FLAG | utils::SEQUENCE_LOCKTIME_MASK;
    -
    -        let a = a & mask;
    -        let b = b & mask;
    -
    -        if (a < utils::SEQUENCE_LOCKTIME_TYPE_FLAG) != (b < utils::SEQUENCE_LOCKTIME_TYPE_FLAG) {
    -            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)]
    -pub enum PolicyError {
    -    /// Not enough items are selected to satisfy a [`SatisfiableItem::Thresh`]
    -    NotEnoughItemsSelected(String),
    -    /// Too many items are selected to satisfy a [`SatisfiableItem::Thresh`]
    -    TooManyItemsSelected(String),
    -    /// Index out of range for an item to satisfy a [`SatisfiableItem::Thresh`]
    -    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 {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -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,
    -        };
    -        for (index, item) in items.iter().enumerate() {
    -            contribution.add(&item.contribution, index)?;
    -        }
    -        contribution.finalize()?;
    -
    -        let mut policy: Policy = SatisfiableItem::Thresh { items, threshold }.into();
    -        policy.contribution = contribution;
    -
    -        Ok(Some(policy))
    -    }
    -
    -    fn make_multisig(
    -        keys: &[DescriptorPublicKey],
    -        signers: &SignersContainer,
    -        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),
    -        };
    -        for (index, key) in keys.iter().enumerate() {
    -            if signers.find(signer_id(key, secp)).is_some() {
    -                contribution.add(
    -                    &Satisfaction::Complete {
    -                        condition: Default::default(),
    -                    },
    -                    index,
    -                )?;
    -            }
    -        }
    -        contribution.finalize()?;
    -
    -        let mut policy: Policy = SatisfiableItem::Multisig {
    -            keys: parsed_keys,
    -            threshold,
    -        }
    -        .into();
    -        policy.contribution = contribution;
    -
    -        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()
    -            }
    -            _ => vec![],
    -        };
    -        let selected = match path.get(&self.id) {
    -            _ if !default.is_empty() => &default,
    -            Some(arr) => arr,
    -            _ => &default,
    -        };
    -
    -        match &self.item {
    -            SatisfiableItem::Thresh { items, threshold } => {
    -                let mapped_req = items
    -                    .iter()
    -                    .map(|i| i.get_condition(path))
    -                    .collect::<Result<Vec<_>, _>>()?;
    -
    -                // if all the requirements are null we don't care about `selected` because there
    -                // are no requirements
    -                if mapped_req.iter().all(Condition::is_null) {
    -                    return Ok(Condition::default());
    -                }
    -
    -                // 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
    -                match selected.len().cmp(threshold) {
    -                    Ordering::Less => {
    -                        return Err(PolicyError::NotEnoughItemsSelected(self.id.clone()))
    -                    }
    -                    Ordering::Greater => {
    -                        return Err(PolicyError::TooManyItemsSelected(self.id.clone()))
    -                    }
    -                    Ordering::Equal => (),
    -                }
    -
    -                // check the selected items, see if there are conflicting requirements
    -                let mut requirements = Condition::default();
    -                for item_index in selected {
    -                    requirements = requirements.merge(
    -                        mapped_req
    -                            .get(*item_index)
    -                            .ok_or(PolicyError::IndexOutOfRange(*item_index))?,
    -                    )?;
    -                }
    -
    -                Ok(requirements)
    -            }
    -            _ if !selected.is_empty() => Err(PolicyError::TooManyItemsSelected(self.id.clone())),
    -            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 {
    -    match key {
    -        DescriptorPublicKey::SinglePub(pubkey) => pubkey.key.to_pubkeyhash().into(),
    -        DescriptorPublicKey::XPub(xpub) => xpub.root_fingerprint(secp).into(),
    -    }
    -}
    -
    -fn signature(key: &DescriptorPublicKey, signers: &SignersContainer, secp: &SecpCtx) -> Policy {
    -    let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key(key, secp)).into();
    -
    -    policy.contribution = if signers.find(signer_id(key, secp)).is_some() {
    -        Satisfaction::Complete {
    -            condition: Default::default(),
    -        }
    -    } else {
    -        Satisfaction::None
    -    };
    -
    -    policy
    -}
    -
    -fn signature_key(
    -    key: &<DescriptorPublicKey as MiniscriptKey>::Hash,
    -    signers: &SignersContainer,
    -    secp: &SecpCtx,
    -) -> Policy {
    -    let deriv_ctx = descriptor_to_pk_ctx(secp);
    -    let key_hash = key.to_public_key(deriv_ctx).to_pubkeyhash();
    -    let mut policy: Policy = SatisfiableItem::Signature(PKOrF::from_key_hash(key_hash)).into();
    -
    -    if signers.find(SignerId::PkHash(key_hash)).is_some() {
    -        policy.contribution = Satisfaction::Complete {
    -            condition: Default::default(),
    -        }
    -    }
    -
    -    policy
    -}
    -
    -impl<Ctx: ScriptContext> ExtractPolicy for Miniscript<DescriptorPublicKey, Ctx> {
    -    fn extract_policy(
    -        &self,
    -        signers: &SignersContainer,
    -        secp: &SecpCtx,
    -    ) -> Result<Option<Policy>, Error> {
    -        Ok(match &self.node {
    -            // Leaves
    -            Terminal::True | Terminal::False => None,
    -            Terminal::PkK(pubkey) => Some(signature(pubkey, signers, secp)),
    -            Terminal::PkH(pubkey_hash) => Some(signature_key(pubkey_hash, signers, secp)),
    -            Terminal::After(value) => {
    -                let mut policy: Policy = SatisfiableItem::AbsoluteTimelock { value: *value }.into();
    -                policy.contribution = Satisfaction::Complete {
    -                    condition: Condition {
    -                        timelock: Some(*value),
    -                        csv: None,
    -                    },
    -                };
    -
    -                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),
    -                    },
    -                };
    -
    -                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) => Policy::make_multisig(pks, signers, *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, secp)?,
    -            // Complex policies
    -            Terminal::AndV(a, b) | Terminal::AndB(a, b) => Policy::make_and(
    -                a.extract_policy(signers, secp)?,
    -                b.extract_policy(signers, secp)?,
    -            )?,
    -            Terminal::AndOr(x, y, z) => Policy::make_or(
    -                Policy::make_and(
    -                    x.extract_policy(signers, secp)?,
    -                    y.extract_policy(signers, secp)?,
    -                )?,
    -                z.extract_policy(signers, secp)?,
    -            )?,
    -            Terminal::OrB(a, b)
    -            | Terminal::OrD(a, b)
    -            | Terminal::OrC(a, b)
    -            | Terminal::OrI(a, b) => Policy::make_or(
    -                a.extract_policy(signers, secp)?,
    -                b.extract_policy(signers, secp)?,
    -            )?,
    -            Terminal::Thresh(k, nodes) => {
    -                let mut threshold = *k;
    -                let mapped: Vec<_> = nodes
    -                    .iter()
    -                    .map(|n| n.extract_policy(signers, secp))
    -                    .collect::<Result<Vec<_>, _>>()?
    -                    .into_iter()
    -                    .filter_map(|x| x)
    -                    .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)?
    -            }
    -        })
    -    }
    -}
    -
    -impl ExtractPolicy for Descriptor<DescriptorPublicKey> {
    -    fn extract_policy(
    -        &self,
    -        signers: &SignersContainer,
    -        secp: &SecpCtx,
    -    ) -> Result<Option<Policy>, Error> {
    -        fn make_sortedmulti<Ctx: ScriptContext>(
    -            keys: &SortedMultiVec<DescriptorPublicKey, Ctx>,
    -            signers: &SignersContainer,
    -            secp: &SecpCtx,
    -        ) -> Result<Option<Policy>, Error> {
    -            Ok(Policy::make_multisig(
    -                keys.pks.as_ref(),
    -                signers,
    -                keys.k,
    -                true,
    -                secp,
    -            )?)
    -        }
    -
    -        match self {
    -            Descriptor::Pk(pubkey)
    -            | Descriptor::Pkh(pubkey)
    -            | Descriptor::Wpkh(pubkey)
    -            | Descriptor::ShWpkh(pubkey) => Ok(Some(signature(pubkey, signers, secp))),
    -            Descriptor::Bare(inner) => Ok(inner.extract_policy(signers, secp)?),
    -            Descriptor::Sh(inner) => Ok(inner.extract_policy(signers, secp)?),
    -            Descriptor::Wsh(inner) | Descriptor::ShWsh(inner) => {
    -                Ok(inner.extract_policy(signers, secp)?)
    -            }
    -
    -            // `sortedmulti()` is handled separately
    -            Descriptor::ShSortedMulti(keys) => make_sortedmulti(&keys, signers, secp),
    -            Descriptor::ShWshSortedMulti(keys) | Descriptor::WshSortedMulti(keys) => {
    -                make_sortedmulti(&keys, signers, secp)
    -            }
    -        }
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -
    -    use crate::descriptor;
    -    use crate::descriptor::{ExtractPolicy, ToWalletDescriptor};
    -
    -    use super::*;
    -    use crate::descriptor::policy::SatisfiableItem::{Multisig, Signature, Thresh};
    -    use crate::keys::{DescriptorKey, ToDescriptorKey};
    -    use crate::wallet::signer::SignersContainer;
    -    use bitcoin::secp256k1::{All, Secp256k1};
    -    use bitcoin::util::bip32;
    -    use bitcoin::util::bip32::ChildNumber;
    -    use bitcoin::Network;
    -    use std::str::FromStr;
    -    use std::sync::Arc;
    -
    -    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::ExtendedPrivKey::from_str(tprv).unwrap();
    -        let tpub = bip32::ExtendedPubKey::from_private(&secp, &tprv);
    -        let fingerprint = tprv.fingerprint(&secp);
    -        let prvkey = (tprv, path.clone()).to_descriptor_key().unwrap();
    -        let pubkey = (tpub, path).to_descriptor_key().unwrap();
    -
    -        (prvkey, pubkey, fingerprint)
    -    }
    -
    -    // test ExtractPolicy trait for simple descriptors; wpkh(), sh(multi())
    -
    -    #[test]
    -    fn test_extract_policy_for_wpkh() {
    -        let (prvkey, pubkey, fingerprint) = setup_keys(TPRV0_STR);
    -        let desc = descriptor!(wpkh(pubkey)).unwrap();
    -        let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
    -        let signers_container = Arc::new(SignersContainer::from(keymap));
    -        let policy = wallet_desc
    -            .extract_policy(&signers_container, &Secp256k1::new())
    -            .unwrap()
    -            .unwrap();
    -
    -        assert!(
    -            matches!(&policy.item, Signature(pk_or_f) if &pk_or_f.fingerprint.unwrap() == &fingerprint)
    -        );
    -        assert!(matches!(&policy.contribution, Satisfaction::None));
    -
    -        let desc = descriptor!(wpkh(prvkey)).unwrap();
    -        let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
    -        let signers_container = Arc::new(SignersContainer::from(keymap));
    -        let policy = wallet_desc
    -            .extract_policy(&signers_container, &Secp256k1::new())
    -            .unwrap()
    -            .unwrap();
    -
    -        assert!(
    -            matches!(&policy.item, Signature(pk_or_f) if &pk_or_f.fingerprint.unwrap() == &fingerprint)
    -        );
    -        assert!(
    -            matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == None)
    -        );
    -    }
    -
    -    // 2 pub keys descriptor, required 2 prv keys
    -    // #[test]
    -    // fn test_extract_policy_for_sh_multi_partial_0of2() {
    -    //     let (_prvkey0, pubkey0, fingerprint0) = setup_keys(TPRV0_STR);
    -    //     let (_prvkey1, pubkey1, fingerprint1) = setup_keys(TPRV1_STR);
    -    //     let desc = descriptor!(sh(multi 2, pubkey0, pubkey1)).unwrap();
    -    //     let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
    -    //     let signers_container = Arc::new(SignersContainer::from(keymap));
    -    //     let policy = wallet_desc
    -    //         .extract_policy(signers_container)
    -    //         .unwrap()
    -    //         .unwrap();
    -    //
    -    //     assert!(
    -    //         matches!(&policy.item, Multisig { keys, threshold } if threshold == &2
    -    //         && &keys[0].fingerprint.unwrap() == &fingerprint0
    -    //         && &keys[1].fingerprint.unwrap() == &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 == &2
    -    //         && m == &2
    -    //         && 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 (prvkey0, _pubkey0, fingerprint0) = setup_keys(TPRV0_STR);
    -    //     let (_prvkey1, pubkey1, fingerprint1) = setup_keys(TPRV1_STR);
    -    //     let desc = descriptor!(sh(multi 2, prvkey0, pubkey1)).unwrap();
    -    //     let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
    -    //     let signers_container = Arc::new(SignersContainer::from(keymap));
    -    //     let policy = wallet_desc
    -    //         .extract_policy(signers_container)
    -    //         .unwrap()
    -    //         .unwrap();
    -    //
    -    //     assert!(
    -    //         matches!(&policy.item, Multisig { keys, threshold } if threshold == &2
    -    //         && &keys[0].fingerprint.unwrap() == &fingerprint0
    -    //         && &keys[1].fingerprint.unwrap() == &fingerprint1)
    -    //     );
    -    //
    -    //     // TODO should this be "Satisfaction::Partial" since we have only one of two prv keys?
    -    //     assert!(
    -    //         matches!(&policy.contribution, Satisfaction::PartialComplete { n, m, items, conditions} if n == &2
    -    //          && m == &2
    -    //          && items.len() == 2
    -    //          && conditions.contains_key(&vec![0,1])
    -    //         )
    -    //     );
    -    // }
    -
    -    // 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 (_prvkey0, pubkey0, fingerprint0) = setup_keys(TPRV0_STR);
    -        let (prvkey1, _pubkey1, fingerprint1) = setup_keys(TPRV1_STR);
    -        let desc = descriptor!(sh(multi 1, pubkey0, prvkey1)).unwrap();
    -        let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
    -        let signers_container = Arc::new(SignersContainer::from(keymap));
    -        let policy = wallet_desc
    -            .extract_policy(&signers_container, &Secp256k1::new())
    -            .unwrap()
    -            .unwrap();
    -
    -        assert!(
    -            matches!(&policy.item, Multisig { keys, threshold } if threshold == &1
    -            && &keys[0].fingerprint.unwrap() == &fingerprint0
    -            && &keys[1].fingerprint.unwrap() == &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 (prvkey0, _pubkey0, fingerprint0) = setup_keys(TPRV0_STR);
    -        let (prvkey1, _pubkey1, fingerprint1) = setup_keys(TPRV1_STR);
    -        let desc = descriptor!(sh(multi 2, prvkey0, prvkey1)).unwrap();
    -        let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
    -        let signers_container = Arc::new(SignersContainer::from(keymap));
    -        let policy = wallet_desc
    -            .extract_policy(&signers_container, &Secp256k1::new())
    -            .unwrap()
    -            .unwrap();
    -
    -        assert!(
    -            matches!(&policy.item, Multisig { keys, threshold } if threshold == &2
    -            && &keys[0].fingerprint.unwrap() == &fingerprint0
    -            && &keys[1].fingerprint.unwrap() == &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 (prvkey, pubkey, fingerprint) = setup_keys(TPRV0_STR);
    -        let desc = descriptor!(wpkh(pubkey)).unwrap();
    -        let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
    -        let single_key = wallet_desc.derive(ChildNumber::from_normal_idx(0).unwrap());
    -        let signers_container = Arc::new(SignersContainer::from(keymap));
    -        let policy = single_key
    -            .extract_policy(&signers_container, &Secp256k1::new())
    -            .unwrap()
    -            .unwrap();
    -
    -        assert!(
    -            matches!(&policy.item, Signature(pk_or_f) if &pk_or_f.fingerprint.unwrap() == &fingerprint)
    -        );
    -        assert!(matches!(&policy.contribution, Satisfaction::None));
    -
    -        let desc = descriptor!(wpkh(prvkey)).unwrap();
    -        let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
    -        let single_key = wallet_desc.derive(ChildNumber::from_normal_idx(0).unwrap());
    -        let signers_container = Arc::new(SignersContainer::from(keymap));
    -        let policy = single_key
    -            .extract_policy(&signers_container, &Secp256k1::new())
    -            .unwrap()
    -            .unwrap();
    -
    -        assert!(
    -            matches!(&policy.item, Signature(pk_or_f) if &pk_or_f.fingerprint.unwrap() == &fingerprint)
    -        );
    -        assert!(
    -            matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == 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 (_prvkey0, pubkey0, fingerprint0) = setup_keys(TPRV0_STR);
    -        let (prvkey1, _pubkey1, fingerprint1) = setup_keys(TPRV1_STR);
    -        let desc = descriptor!(sh(multi 1, pubkey0, prvkey1)).unwrap();
    -        let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
    -        let single_key = wallet_desc.derive(ChildNumber::from_normal_idx(0).unwrap());
    -        let signers_container = Arc::new(SignersContainer::from(keymap));
    -        let policy = single_key
    -            .extract_policy(&signers_container, &Secp256k1::new())
    -            .unwrap()
    -            .unwrap();
    -
    -        assert!(
    -            matches!(&policy.item, Multisig { keys, threshold } if threshold == &1
    -            && &keys[0].fingerprint.unwrap() == &fingerprint0
    -            && &keys[1].fingerprint.unwrap() == &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 (prvkey0, _pubkey0, _fingerprint0) = setup_keys(TPRV0_STR);
    -        let (_prvkey1, pubkey1, _fingerprint1) = setup_keys(TPRV1_STR);
    -        let sequence = 50;
    -        let desc = descriptor!(wsh (
    -            thresh 2, (pk prvkey0), (+s pk pubkey1), (+s+d+v older sequence)
    -        ))
    -        .unwrap();
    -
    -        let (wallet_desc, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
    -        let signers_container = Arc::new(SignersContainer::from(keymap));
    -        let policy = wallet_desc
    -            .extract_policy(&signers_container, &Secp256k1::new())
    -            .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)
    -             && conditions.get(&vec![1,2]).unwrap().iter().next().unwrap().csv == Some(sequence)
    -            )
    -        );
    -    }
    -
    -    // - mixed timelocks should fail
    -
    -    // #[test]
    -    // fn test_extract_policy_for_wsh_mixed_timelocks() {
    -    //     let (prvkey0, _pubkey0, _fingerprint0) = setup_keys(TPRV0_STR);
    -    //     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.to_wallet_descriptor(Network::Testnet).unwrap();
    -    //     let signers_container = Arc::new(SignersContainer::from(keymap));
    -    //     let policy = wallet_desc
    -    //         .extract_policy(signers_container)
    -    //         .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]
    -    // fn test_extract_policy_for_multiple_same_timelocks() {
    -    //     let (prvkey0, _pubkey0, _fingerprint0) = setup_keys(TPRV0_STR);
    -    //     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.to_wallet_descriptor(Network::Testnet).unwrap();
    -    //     let signers_container = Arc::new(SignersContainer::from(keymap));
    -    //     let policy = wallet_desc
    -    //         .extract_policy(signers_container)
    -    //         .unwrap()
    -    //         .unwrap();
    -    //
    -    //     println!("desc policy = {:?}", policy); // TODO remove
    -    //
    -    //     // TODO how should this merge timelocks?
    -    //
    -    //     let (prvkey1, _pubkey1, _fingerprint1) = setup_keys(TPRV0_STR);
    -    //     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.to_wallet_descriptor(Network::Testnet).unwrap();
    -    //     let signers_container = Arc::new(SignersContainer::from(keymap));
    -    //     let policy = wallet_desc
    -    //         .extract_policy(signers_container)
    -    //         .unwrap()
    -    //         .unwrap();
    -    //
    -    //     println!("desc policy = {:?}", policy); // TODO remove
    -    //
    -    //     // TODO how should this merge timelocks?
    -    // }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/template.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/template.rs.html deleted file mode 100644 index 751445aba5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/descriptor/template.rs.html +++ /dev/null @@ -1,1460 +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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! 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::util::bip32;
    -use bitcoin::Network;
    -
    -use miniscript::{Legacy, Segwitv0};
    -
    -use super::{ExtendedDescriptor, KeyMap, ToWalletDescriptor};
    -use crate::keys::{DerivableKey, KeyError, ToDescriptorKey, ValidNetworks};
    -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 [`ToWalletDescriptor`] is implemented for any [`DescriptorTemplate`], they can also be
    -/// passed directly to the [`Wallet`](crate::Wallet) constructor.
    -///
    -/// ## Example
    -///
    -/// ```
    -/// use bdk::keys::{KeyError, ToDescriptorKey};
    -/// use bdk::miniscript::Legacy;
    -/// use bdk::template::{DescriptorTemplate, DescriptorTemplateOut};
    -///
    -/// struct MyP2PKH<K: ToDescriptorKey<Legacy>>(K);
    -///
    -/// impl<K: ToDescriptorKey<Legacy>> DescriptorTemplate for MyP2PKH<K> {
    -///     fn build(self) -> Result<DescriptorTemplateOut, KeyError> {
    -///         Ok(bdk::descriptor!(pkh(self.0))?)
    -///     }
    -/// }
    -/// ```
    -pub trait DescriptorTemplate {
    -    /// Build the complete descriptor
    -    fn build(self) -> Result<DescriptorTemplateOut, KeyError>;
    -}
    -
    -/// Turns a [`DescriptorTemplate`] into a valid wallet descriptor by calling its
    -/// [`build`](DescriptorTemplate::build) method
    -impl<T: DescriptorTemplate> ToWalletDescriptor for T {
    -    fn to_wallet_descriptor(
    -        self,
    -        network: Network,
    -    ) -> Result<(ExtendedDescriptor, KeyMap), KeyError> {
    -        Ok(self.build()?.to_wallet_descriptor(network)?)
    -    }
    -}
    -
    -/// P2PKH template. Expands to a descriptor `pkh(key)`
    -///
    -/// ## Example
    -///
    -/// ```
    -/// # use bdk::bitcoin::{PrivateKey, Network};
    -/// # use bdk::{Wallet, OfflineWallet};
    -/// # use bdk::database::MemoryDatabase;
    -/// use bdk::template::P2PKH;
    -///
    -/// let key =
    -///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
    -/// let wallet: OfflineWallet<_> = Wallet::new_offline(
    -///     P2PKH(key),
    -///     None,
    -///     Network::Testnet,
    -///     MemoryDatabase::default(),
    -/// )?;
    -///
    -/// assert_eq!(
    -///     wallet.get_new_address()?.to_string(),
    -///     "mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"
    -/// );
    -/// # Ok::<_, Box<dyn std::error::Error>>(())
    -/// ```
    -pub struct P2PKH<K: ToDescriptorKey<Legacy>>(pub K);
    -
    -impl<K: ToDescriptorKey<Legacy>> DescriptorTemplate for P2PKH<K> {
    -    fn build(self) -> Result<DescriptorTemplateOut, KeyError> {
    -        Ok(descriptor!(pkh(self.0))?)
    -    }
    -}
    -
    -/// P2WPKH-P2SH template. Expands to a descriptor `sh(wpkh(key))`
    -///
    -/// ## Example
    -///
    -/// ```
    -/// # use bdk::bitcoin::{PrivateKey, Network};
    -/// # use bdk::{Wallet, OfflineWallet};
    -/// # use bdk::database::MemoryDatabase;
    -/// use bdk::template::P2WPKH_P2SH;
    -///
    -/// let key =
    -///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
    -/// let wallet: OfflineWallet<_> = Wallet::new_offline(
    -///     P2WPKH_P2SH(key),
    -///     None,
    -///     Network::Testnet,
    -///     MemoryDatabase::default(),
    -/// )?;
    -///
    -/// assert_eq!(
    -///     wallet.get_new_address()?.to_string(),
    -///     "2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"
    -/// );
    -/// # Ok::<_, Box<dyn std::error::Error>>(())
    -/// ```
    -#[allow(non_camel_case_types)]
    -pub struct P2WPKH_P2SH<K: ToDescriptorKey<Segwitv0>>(pub K);
    -
    -impl<K: ToDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH_P2SH<K> {
    -    fn build(self) -> Result<DescriptorTemplateOut, KeyError> {
    -        Ok(descriptor!(sh(wpkh(self.0)))?)
    -    }
    -}
    -
    -/// P2WPKH template. Expands to a descriptor `wpkh(key)`
    -///
    -/// ## Example
    -///
    -/// ```
    -/// # use bdk::bitcoin::{PrivateKey, Network};
    -/// # use bdk::{Wallet, OfflineWallet};
    -/// # use bdk::database::MemoryDatabase;
    -/// use bdk::template::P2WPKH;
    -///
    -/// let key =
    -///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
    -/// let wallet: OfflineWallet<_> = Wallet::new_offline(
    -///     P2WPKH(key),
    -///     None,
    -///     Network::Testnet,
    -///     MemoryDatabase::default(),
    -/// )?;
    -///
    -/// assert_eq!(
    -///     wallet.get_new_address()?.to_string(),
    -///     "tb1q4525hmgw265tl3drrl8jjta7ayffu6jf68ltjd"
    -/// );
    -/// # Ok::<_, Box<dyn std::error::Error>>(())
    -/// ```
    -pub struct P2WPKH<K: ToDescriptorKey<Segwitv0>>(pub K);
    -
    -impl<K: ToDescriptorKey<Segwitv0>> DescriptorTemplate for P2WPKH<K> {
    -    fn build(self) -> Result<DescriptorTemplateOut, KeyError> {
    -        Ok(descriptor!(wpkh(self.0))?)
    -    }
    -}
    -
    -/// BIP44 template. Expands to `pkh(key/44'/0'/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, OfflineWallet, KeychainKind};
    -/// # use bdk::database::MemoryDatabase;
    -/// use bdk::template::BIP44;
    -///
    -/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -/// let wallet: OfflineWallet<_> = Wallet::new_offline(
    -///     BIP44(key.clone(), KeychainKind::External),
    -///     Some(BIP44(key, KeychainKind::Internal)),
    -///     Network::Testnet,
    -///     MemoryDatabase::default()
    -/// )?;
    -///
    -/// assert_eq!(wallet.get_new_address()?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)");
    -/// # 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) -> Result<DescriptorTemplateOut, KeyError> {
    -        Ok(P2PKH(legacy::make_bipxx_private(44, self.0, self.1)?).build()?)
    -    }
    -}
    -
    -/// BIP44 public template. Expands to `pkh(key/{0,1}/*)`
    -///
    -/// This assumes that the key used has already been derived with `m/44'/0'/0'`.
    -///
    -/// 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, OfflineWallet, KeychainKind};
    -/// # use bdk::database::MemoryDatabase;
    -/// use bdk::template::BIP44Public;
    -///
    -/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
    -/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
    -/// let wallet: OfflineWallet<_> = Wallet::new_offline(
    -///     BIP44Public(key.clone(), fingerprint, KeychainKind::External),
    -///     Some(BIP44Public(key, fingerprint, KeychainKind::Internal)),
    -///     Network::Testnet,
    -///     MemoryDatabase::default()
    -/// )?;
    -///
    -/// assert_eq!(wallet.get_new_address()?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)");
    -/// # 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) -> Result<DescriptorTemplateOut, KeyError> {
    -        Ok(P2PKH(legacy::make_bipxx_public(44, self.0, self.1, self.2)?).build()?)
    -    }
    -}
    -
    -/// BIP49 template. Expands to `sh(wpkh(key/49'/0'/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, OfflineWallet, KeychainKind};
    -/// # use bdk::database::MemoryDatabase;
    -/// use bdk::template::BIP49;
    -///
    -/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -/// let wallet: OfflineWallet<_> = Wallet::new_offline(
    -///     BIP49(key.clone(), KeychainKind::External),
    -///     Some(BIP49(key, KeychainKind::Internal)),
    -///     Network::Testnet,
    -///     MemoryDatabase::default()
    -/// )?;
    -///
    -/// assert_eq!(wallet.get_new_address()?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))");
    -/// # 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) -> Result<DescriptorTemplateOut, KeyError> {
    -        Ok(P2WPKH_P2SH(segwit_v0::make_bipxx_private(49, self.0, self.1)?).build()?)
    -    }
    -}
    -
    -/// 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'`.
    -///
    -/// 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, OfflineWallet, KeychainKind};
    -/// # use bdk::database::MemoryDatabase;
    -/// use bdk::template::BIP49Public;
    -///
    -/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
    -/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
    -/// let wallet: OfflineWallet<_> = Wallet::new_offline(
    -///     BIP49Public(key.clone(), fingerprint, KeychainKind::External),
    -///     Some(BIP49Public(key, fingerprint, KeychainKind::Internal)),
    -///     Network::Testnet,
    -///     MemoryDatabase::default()
    -/// )?;
    -///
    -/// assert_eq!(wallet.get_new_address()?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))");
    -/// # 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) -> Result<DescriptorTemplateOut, KeyError> {
    -        Ok(P2WPKH_P2SH(segwit_v0::make_bipxx_public(49, self.0, self.1, self.2)?).build()?)
    -    }
    -}
    -
    -/// BIP84 template. Expands to `wpkh(key/84'/0'/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, OfflineWallet, KeychainKind};
    -/// # use bdk::database::MemoryDatabase;
    -/// use bdk::template::BIP84;
    -///
    -/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -/// let wallet: OfflineWallet<_> = Wallet::new_offline(
    -///     BIP84(key.clone(), KeychainKind::External),
    -///     Some(BIP84(key, KeychainKind::Internal)),
    -///     Network::Testnet,
    -///     MemoryDatabase::default()
    -/// )?;
    -///
    -/// assert_eq!(wallet.get_new_address()?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)");
    -/// # 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) -> Result<DescriptorTemplateOut, KeyError> {
    -        Ok(P2WPKH(segwit_v0::make_bipxx_private(84, self.0, self.1)?).build()?)
    -    }
    -}
    -
    -/// BIP84 public template. Expands to `wpkh(key/{0,1}/*)`
    -///
    -/// This assumes that the key used has already been derived with `m/84'/0'/0'`.
    -///
    -/// 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, OfflineWallet, KeychainKind};
    -/// # use bdk::database::MemoryDatabase;
    -/// use bdk::template::BIP84Public;
    -///
    -/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
    -/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
    -/// let wallet: OfflineWallet<_> = Wallet::new_offline(
    -///     BIP84Public(key.clone(), fingerprint, KeychainKind::External),
    -///     Some(BIP84Public(key, fingerprint, KeychainKind::Internal)),
    -///     Network::Testnet,
    -///     MemoryDatabase::default()
    -/// )?;
    -///
    -/// assert_eq!(wallet.get_new_address()?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)");
    -/// # 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) -> Result<DescriptorTemplateOut, KeyError> {
    -        Ok(P2WPKH(segwit_v0::make_bipxx_public(84, self.0, self.1, self.2)?).build()?)
    -    }
    -}
    -
    -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,
    -            ) -> Result<impl ToDescriptorKey<$ctx>, KeyError> {
    -                let mut derivation_path = Vec::with_capacity(4);
    -                derivation_path.push(bip32::ChildNumber::from_hardened_idx(bip)?);
    -                derivation_path.push(bip32::ChildNumber::from_hardened_idx(0)?);
    -                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,
    -            ) -> Result<impl ToDescriptorKey<$ctx>, KeyError> {
    -                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 mut source_path = Vec::with_capacity(3);
    -                source_path.push(bip32::ChildNumber::from_hardened_idx(bip)?);
    -                source_path.push(bip32::ChildNumber::from_hardened_idx(0)?);
    -                source_path.push(bip32::ChildNumber::from_hardened_idx(0)?);
    -                let source_path: bip32::DerivationPath = source_path.into();
    -
    -                Ok((key, (parent_fingerprint, source_path), derivation_path))
    -            }
    -        }
    -    };
    -}
    -
    -expand_make_bipxx!(legacy, Legacy);
    -expand_make_bipxx!(segwit_v0, Segwitv0);
    -
    -#[cfg(test)]
    -mod test {
    -    // test existing descriptor templates, make sure they are expanded to the right descriptors
    -
    -    use super::*;
    -    use crate::descriptor::DescriptorMeta;
    -    use crate::keys::{KeyError, ValidNetworks};
    -    use bitcoin::hashes::core::str::FromStr;
    -    use bitcoin::network::constants::Network::Regtest;
    -    use bitcoin::secp256k1::Secp256k1;
    -    use bitcoin::util::bip32::ChildNumber;
    -    use miniscript::descriptor::{DescriptorPublicKey, DescriptorPublicKeyCtx, KeyMap};
    -    use miniscript::Descriptor;
    -
    -    // verify template descriptor generates expected address(es)
    -    fn check(
    -        desc: Result<(Descriptor<DescriptorPublicKey>, KeyMap, ValidNetworks), KeyError>,
    -        is_witness: bool,
    -        is_fixed: bool,
    -        expected: &[&str],
    -    ) {
    -        let secp = Secp256k1::new();
    -        let deriv_ctx =
    -            DescriptorPublicKeyCtx::new(&secp, ChildNumber::from_normal_idx(0).unwrap());
    -
    -        let (desc, _key_map, _networks) = desc.unwrap();
    -        assert_eq!(desc.is_witness(), is_witness);
    -        assert_eq!(desc.is_fixed(), is_fixed);
    -        for i in 0..expected.len() {
    -            let index = i as u32;
    -            let child_desc = if desc.is_fixed() {
    -                desc.clone()
    -            } else {
    -                desc.derive(ChildNumber::from_normal_idx(index).unwrap())
    -            };
    -            let address = child_desc.address(Regtest, deriv_ctx).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(),
    -            false,
    -            true,
    -            &["mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"],
    -        );
    -
    -        let pubkey = bitcoin::PublicKey::from_str(
    -            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
    -        )
    -        .unwrap();
    -        check(
    -            P2PKH(pubkey).build(),
    -            false,
    -            true,
    -            &["muZpTpBYhxmRFuCjLc7C6BBDF32C8XVJUi"],
    -        );
    -    }
    -
    -    // P2WPKH-P2SH `sh(wpkh(key))`
    -    #[test]
    -    fn test_p2wphp2sh_template() {
    -        let prvkey =
    -            bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
    -                .unwrap();
    -        check(
    -            P2WPKH_P2SH(prvkey).build(),
    -            true,
    -            true,
    -            &["2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"],
    -        );
    -
    -        let pubkey = bitcoin::PublicKey::from_str(
    -            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
    -        )
    -        .unwrap();
    -        check(
    -            P2WPKH_P2SH(pubkey).build(),
    -            true,
    -            true,
    -            &["2N5LiC3CqzxDamRTPG1kiNv1FpNJQ7x28sb"],
    -        );
    -    }
    -
    -    // P2WPKH `wpkh(key)`
    -    #[test]
    -    fn test_p2wph_template() {
    -        let prvkey =
    -            bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
    -                .unwrap();
    -        check(
    -            P2WPKH(prvkey).build(),
    -            true,
    -            true,
    -            &["bcrt1q4525hmgw265tl3drrl8jjta7ayffu6jfcwxx9y"],
    -        );
    -
    -        let pubkey = bitcoin::PublicKey::from_str(
    -            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
    -        )
    -        .unwrap();
    -        check(
    -            P2WPKH(pubkey).build(),
    -            true,
    -            true,
    -            &["bcrt1qngw83fg8dz0k749cg7k3emc7v98wy0c7azaa6h"],
    -        );
    -    }
    -
    -    // BIP44 `pkh(key/44'/0'/0'/{0,1}/*)`
    -    #[test]
    -    fn test_bip44_template() {
    -        let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
    -        check(
    -            BIP44(prvkey, KeychainKind::External).build(),
    -            false,
    -            false,
    -            &[
    -                "n453VtnjDHPyDt2fDstKSu7A3YCJoHZ5g5",
    -                "mvfrrumXgTtwFPWDNUecBBgzuMXhYM7KRP",
    -                "mzYvhRAuQqbdSKMVVzXNYyqihgNdRadAUQ",
    -            ],
    -        );
    -        check(
    -            BIP44(prvkey, KeychainKind::Internal).build(),
    -            false,
    -            false,
    -            &[
    -                "muHF98X9KxEzdKrnFAX85KeHv96eXopaip",
    -                "n4hpyLJE5ub6B5Bymv4eqFxS5KjrewSmYR",
    -                "mgvkdv1ffmsXd2B1sRKQ5dByK3SzpG42rA",
    -            ],
    -        );
    -    }
    -
    -    // BIP44 public `pkh(key/{0,1}/*)`
    -    #[test]
    -    fn test_bip44_public_template() {
    -        let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU").unwrap();
    -        let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
    -        check(
    -            BIP44Public(pubkey, fingerprint, KeychainKind::External).build(),
    -            false,
    -            false,
    -            &[
    -                "miNG7dJTzJqNbFS19svRdTCisC65dsubtR",
    -                "n2UqaDbCjWSFJvpC84m3FjUk5UaeibCzYg",
    -                "muCPpS6Ue7nkzeJMWDViw7Lkwr92Yc4K8g",
    -            ],
    -        );
    -        check(
    -            BIP44Public(pubkey, fingerprint, KeychainKind::Internal).build(),
    -            false,
    -            false,
    -            &[
    -                "moDr3vJ8wpt5nNxSK55MPq797nXJb2Ru9H",
    -                "ms7A1Yt4uTezT2XkefW12AvLoko8WfNJMG",
    -                "mhYiyat2rtEnV77cFfQsW32y1m2ceCGHPo",
    -            ],
    -        );
    -    }
    -
    -    // BIP49 `sh(wpkh(key/49'/0'/0'/{0,1}/*))`
    -    #[test]
    -    fn test_bip49_template() {
    -        let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
    -        check(
    -            BIP49(prvkey, KeychainKind::External).build(),
    -            true,
    -            false,
    -            &[
    -                "2N9bCAJXGm168MjVwpkBdNt6ucka3PKVoUV",
    -                "2NDckYkqrYyDMtttEav5hB3Bfw9EGAW5HtS",
    -                "2NAFTVtksF9T4a97M7nyCjwUBD24QevZ5Z4",
    -            ],
    -        );
    -        check(
    -            BIP49(prvkey, KeychainKind::Internal).build(),
    -            true,
    -            false,
    -            &[
    -                "2NB3pA8PnzJLGV8YEKNDFpbViZv3Bm1K6CG",
    -                "2NBiX2Wzxngb5rPiWpUiJQ2uLVB4HBjFD4p",
    -                "2NA8ek4CdQ6aMkveYF6AYuEYNrftB47QGTn",
    -            ],
    -        );
    -    }
    -
    -    // BIP49 public `sh(wpkh(key/{0,1}/*))`
    -    #[test]
    -    fn test_bip49_public_template() {
    -        let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L").unwrap();
    -        let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
    -        check(
    -            BIP49Public(pubkey, fingerprint, KeychainKind::External).build(),
    -            true,
    -            false,
    -            &[
    -                "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt",
    -                "2NCTQfJ1sZa3wQ3pPseYRHbaNEpC3AquEfX",
    -                "2MveFxAuC8BYPzTybx7FxSzW8HSd8ATT4z7",
    -            ],
    -        );
    -        check(
    -            BIP49Public(pubkey, fingerprint, KeychainKind::Internal).build(),
    -            true,
    -            false,
    -            &[
    -                "2NF2vttKibwyxigxtx95Zw8K7JhDbo5zPVJ",
    -                "2Mtmyd8taksxNVWCJ4wVvaiss7QPZGcAJuH",
    -                "2NBs3CTVYPr1HCzjB4YFsnWCPCtNg8uMEfp",
    -            ],
    -        );
    -    }
    -
    -    // BIP84 `wpkh(key/84'/0'/0'/{0,1}/*)`
    -    #[test]
    -    fn test_bip84_template() {
    -        let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
    -        check(
    -            BIP84(prvkey, KeychainKind::External).build(),
    -            true,
    -            false,
    -            &[
    -                "bcrt1qkmvk2nadgplmd57ztld8nf8v2yxkzmdvwtjf8s",
    -                "bcrt1qx0v6zgfwe50m4kqc58cqzcyem7ay2sfl3gvqhp",
    -                "bcrt1q4h7fq9zhxst6e69p3n882nfj649l7w9g3zccfp",
    -            ],
    -        );
    -        check(
    -            BIP84(prvkey, KeychainKind::Internal).build(),
    -            true,
    -            false,
    -            &[
    -                "bcrt1qtrwtz00wxl69e5xex7amy4xzlxkaefg3gfdkxa",
    -                "bcrt1qqqasfhxpkkf7zrxqnkr2sfhn74dgsrc3e3ky45",
    -                "bcrt1qpks7n0gq74hsgsz3phn5vuazjjq0f5eqhsgyce",
    -            ],
    -        );
    -    }
    -
    -    // BIP84 public `wpkh(key/{0,1}/*)`
    -    #[test]
    -    fn test_bip84_public_template() {
    -        let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q").unwrap();
    -        let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
    -        check(
    -            BIP84Public(pubkey, fingerprint, KeychainKind::External).build(),
    -            true,
    -            false,
    -            &[
    -                "bcrt1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2prcdvd0h",
    -                "bcrt1q3lncdlwq3lgcaaeyruynjnlccr0ve0kakh6ana",
    -                "bcrt1qt9800y6xl3922jy3uyl0z33jh5wfpycyhcylr9",
    -            ],
    -        );
    -        check(
    -            BIP84Public(pubkey, fingerprint, KeychainKind::Internal).build(),
    -            true,
    -            false,
    -            &[
    -                "bcrt1qm6wqukenh7guu792lj2njgw9n78cmwsy8xy3z2",
    -                "bcrt1q694twxtjn4nnrvnyvra769j0a23rllj5c6cgwp",
    -                "bcrt1qhlac3c5ranv5w5emlnqs7wxhkxt8maelylcarp",
    -            ],
    -        );
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/error.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/error.rs.html deleted file mode 100644 index cd048a7951..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/error.rs.html +++ /dev/null @@ -1,414 +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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use std::fmt;
    -
    -use crate::{descriptor, wallet, wallet::address_validator};
    -use bitcoin::OutPoint;
    -
    -/// Errors that can be thrown by the [`Wallet`](crate::wallet::Wallet)
    -#[derive(Debug)]
    -pub enum Error {
    -    /// Wrong number of bytes found when trying to convert to u32
    -    InvalidU32Bytes(Vec<u8>),
    -    /// Generic error
    -    Generic(String),
    -    /// This error is thrown when trying to convert Bare and Public key script to address
    -    ScriptDoesntHaveAddressForm,
    -    /// Found multiple outputs when `single_recipient` option has been specified
    -    SingleRecipientMultipleOutputs,
    -    /// `single_recipient` option is selected but neither `drain_wallet` nor `manually_selected_only` are
    -    SingleRecipientNoInputs,
    -    /// Cannot build a tx without recipients
    -    NoRecipients,
    -    /// `manually_selected_only` option is selected but no utxo has been passed
    -    NoUtxosSelected,
    -    /// Output created is under the dust limit, 546 satoshis
    -    OutputBelowDustLimit(usize),
    -    /// Wallet's UTXO set is not enough to cover recipient's requested plus fee
    -    InsufficientFunds,
    -    /// 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,
    -    /// 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,
    -    /// Happens when trying to spend an UTXO that is not in the internal database
    -    UnknownUTXO,
    -    /// Thrown when a tx is not found in the internal database
    -    TransactionNotFound,
    -    /// Happens when trying to bump a transaction that is already confirmed
    -    TransactionConfirmed,
    -    /// Trying to replace a tx that has a sequence >= `0xFFFFFFFE`
    -    IrreplaceableTransaction,
    -    /// When bumping a tx the fee rate requested is lower than required
    -    FeeRateTooLow {
    -        /// Required fee rate (satoshi/vbyte)
    -        required: crate::types::FeeRate,
    -    },
    -    /// When bumping a tx the absolute fee requested is lower than replaced tx absolute fee
    -    FeeTooLow {
    -        /// Required fee absolute value (satoshi)
    -        required: u64,
    -    },
    -    /// 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),
    -    /// Error while working with [`keys`](crate::keys)
    -    Key(crate::keys::KeyError),
    -    /// Descriptor checksum mismatch
    -    ChecksumMismatch,
    -    /// Spending policy is not compatible with this [`KeychainKind`](crate::types::KeychainKind)
    -    SpendingPolicyRequired(crate::types::KeychainKind),
    -    /// Error while extracting and manipulating policies
    -    InvalidPolicyPathError(crate::descriptor::policy::PolicyError),
    -    /// Signing error
    -    Signer(crate::wallet::signer::SignerError),
    -
    -    // Blockchain interface errors
    -    /// Thrown when trying to call a method that requires a network connection, [`Wallet::sync`](crate::Wallet::sync) and [`Wallet::broadcast`](crate::Wallet::broadcast)
    -    /// This error is thrown when creating the Client for the first time, while recovery attempts are tried
    -    /// during the sync
    -    OfflineClient,
    -    /// Progress value must be between `0.0` (included) and `100.0` (included)
    -    InvalidProgressValue(f32),
    -    /// Progress update error (maybe the channel has been closed)
    -    ProgressUpdateError,
    -    /// Requested outpoint doesn't exist in the tx (vout greater than available outputs)
    -    InvalidOutpoint(OutPoint),
    -
    -    /// Error related to the parsing and usage of descriptors
    -    Descriptor(crate::descriptor::error::Error),
    -    /// Error that can be returned to fail the validation of an address
    -    AddressValidator(crate::wallet::address_validator::AddressValidatorError),
    -    /// Encoding error
    -    Encode(bitcoin::consensus::encode::Error),
    -    /// Miniscript error
    -    Miniscript(miniscript::Error),
    -    /// BIP32 error
    -    BIP32(bitcoin::util::bip32::Error),
    -    /// An ECDSA error
    -    Secp256k1(bitcoin::secp256k1::Error),
    -    /// Error serializing or deserializing JSON data
    -    JSON(serde_json::Error),
    -    /// Hex decoding error
    -    Hex(bitcoin::hashes::hex::Error),
    -    /// Partially signed bitcoin transaction error
    -    PSBT(bitcoin::util::psbt::Error),
    -
    -    //KeyMismatch(bitcoin::secp256k1::PublicKey, bitcoin::secp256k1::PublicKey),
    -    //MissingInputUTXO(usize),
    -    //InvalidAddressNetwork(Address),
    -    //DifferentTransactions,
    -    //DifferentDescriptorStructure,
    -    //Uncapable(crate::blockchain::Capability),
    -    //MissingCachedAddresses,
    -    #[cfg(feature = "electrum")]
    -    /// Electrum client error
    -    Electrum(electrum_client::Error),
    -    #[cfg(feature = "esplora")]
    -    /// Esplora client error
    -    Esplora(crate::blockchain::esplora::EsploraError),
    -    #[cfg(feature = "compact_filters")]
    -    /// Compact filters client error)
    -    CompactFilters(crate::blockchain::compact_filters::CompactFiltersError),
    -    #[cfg(feature = "key-value-db")]
    -    /// Sled database error
    -    Sled(sled::Error),
    -}
    -
    -impl fmt::Display for Error {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for Error {}
    -
    -macro_rules! impl_error {
    -    ( $from:ty, $to:ident ) => {
    -        impl_error!($from, $to, Error);
    -    };
    -    ( $from:ty, $to:ident, $impl_for:ty ) => {
    -        impl std::convert::From<$from> for $impl_for {
    -            fn from(err: $from) -> Self {
    -                <$impl_for>::$to(err)
    -            }
    -        }
    -    };
    -}
    -
    -impl_error!(descriptor::error::Error, Descriptor);
    -impl_error!(address_validator::AddressValidatorError, AddressValidator);
    -impl_error!(descriptor::policy::PolicyError, InvalidPolicyPathError);
    -impl_error!(wallet::signer::SignerError, Signer);
    -
    -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),
    -            crate::keys::KeyError::InvalidChecksum => Error::ChecksumMismatch,
    -            e => Error::Key(e),
    -        }
    -    }
    -}
    -
    -impl_error!(bitcoin::consensus::encode::Error, Encode);
    -impl_error!(miniscript::Error, Miniscript);
    -impl_error!(bitcoin::util::bip32::Error, BIP32);
    -impl_error!(bitcoin::secp256k1::Error, Secp256k1);
    -impl_error!(serde_json::Error, JSON);
    -impl_error!(bitcoin::hashes::hex::Error, Hex);
    -impl_error!(bitcoin::util::psbt::Error, PSBT);
    -
    -#[cfg(feature = "electrum")]
    -impl_error!(electrum_client::Error, Electrum);
    -#[cfg(feature = "esplora")]
    -impl_error!(crate::blockchain::esplora::EsploraError, Esplora);
    -#[cfg(feature = "key-value-db")]
    -impl_error!(sled::Error, Sled);
    -
    -#[cfg(feature = "compact_filters")]
    -impl From<crate::blockchain::compact_filters::CompactFiltersError> for Error {
    -    fn from(other: crate::blockchain::compact_filters::CompactFiltersError) -> Self {
    -        match other {
    -            crate::blockchain::compact_filters::CompactFiltersError::Global(e) => *e,
    -            err @ _ => Error::CompactFilters(err),
    -        }
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/keys/bip39.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/keys/bip39.rs.html deleted file mode 100644 index b7bd41a2f9..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/keys/bip39.rs.html +++ /dev/null @@ -1,352 +0,0 @@ -bip39.rs - source - -
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! BIP-0039
    -
    -// TODO: maybe write our own implementation of bip39? Seems stupid to have an extra dependency for
    -// something that should be fairly simple to re-implement.
    -
    -use bitcoin::util::bip32;
    -use bitcoin::Network;
    -
    -use miniscript::ScriptContext;
    -
    -use bip39::{Language, Mnemonic, MnemonicType, Seed};
    -
    -use super::{any_network, DerivableKey, DescriptorKey, GeneratableKey, GeneratedKey, KeyError};
    -
    -/// Type for a BIP39 mnemonic with an optional passphrase
    -pub type MnemonicWithPassphrase = (Mnemonic, Option<String>);
    -
    -#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
    -impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed {
    -    fn add_metadata(
    -        self,
    -        source: Option<bip32::KeySource>,
    -        derivation_path: bip32::DerivationPath,
    -    ) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        let xprv = bip32::ExtendedPrivKey::new_master(Network::Bitcoin, &self.as_bytes())?;
    -        let descriptor_key = xprv.add_metadata(source, derivation_path)?;
    -
    -        // here we must choose one network to build the xpub, but since the bip39 standard doesn't
    -        // encode the network, the xpub we create is actually valid everywhere. so we override the
    -        // valid networks with `any_network()`.
    -        Ok(descriptor_key.override_valid_networks(any_network()))
    -    }
    -}
    -
    -#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
    -impl<Ctx: ScriptContext> DerivableKey<Ctx> for MnemonicWithPassphrase {
    -    fn add_metadata(
    -        self,
    -        source: Option<bip32::KeySource>,
    -        derivation_path: bip32::DerivationPath,
    -    ) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        let (mnemonic, passphrase) = self;
    -        let seed = Seed::new(&mnemonic, passphrase.as_deref().unwrap_or(""));
    -        seed.add_metadata(source, derivation_path)
    -    }
    -}
    -
    -#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
    -impl<Ctx: ScriptContext> DerivableKey<Ctx> for Mnemonic {
    -    fn add_metadata(
    -        self,
    -        source: Option<bip32::KeySource>,
    -        derivation_path: bip32::DerivationPath,
    -    ) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        (self, None).add_metadata(source, derivation_path)
    -    }
    -}
    -
    -#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
    -impl<Ctx: ScriptContext> GeneratableKey<Ctx> for Mnemonic {
    -    type Entropy = [u8; 32];
    -
    -    type Options = (MnemonicType, Language);
    -    type Error = Option<bip39::ErrorKind>;
    -
    -    fn generate_with_entropy(
    -        (mnemonic_type, language): Self::Options,
    -        entropy: Self::Entropy,
    -    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
    -        let entropy = &entropy.as_ref()[..(mnemonic_type.entropy_bits() / 8)];
    -        let mnemonic = Mnemonic::from_entropy(entropy, language).map_err(|e| e.downcast().ok())?;
    -
    -        Ok(GeneratedKey::new(mnemonic, any_network()))
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::str::FromStr;
    -
    -    use bitcoin::util::bip32;
    -
    -    use bip39::{Language, Mnemonic, MnemonicType};
    -
    -    use crate::keys::{any_network, GeneratableKey, GeneratedKey};
    -
    -    #[test]
    -    fn test_keys_bip39_mnemonic() {
    -        let mnemonic =
    -            "aim bunker wash balance finish force paper analyst cabin spoon stable organ";
    -        let mnemonic = Mnemonic::from_phrase(mnemonic, Language::English).unwrap();
    -        let path = bip32::DerivationPath::from_str("m/44'/0'/0'/0").unwrap();
    -
    -        let key = (mnemonic, path);
    -        let (desc, keys, networks) = crate::descriptor!(wpkh(key)).unwrap();
    -        assert_eq!(desc.to_string(), "wpkh([be83839f/44'/0'/0']xpub6DCQ1YcqvZtSwGWMrwHELPehjWV3f2MGZ69yBADTxFEUAoLwb5Mp5GniQK6tTp3AgbngVz9zEFbBJUPVnkG7LFYt8QMTfbrNqs6FNEwAPKA/0/*)");
    -        assert_eq!(keys.len(), 1);
    -        assert_eq!(networks.len(), 3);
    -    }
    -
    -    #[test]
    -    fn test_keys_bip39_mnemonic_passphrase() {
    -        let mnemonic =
    -            "aim bunker wash balance finish force paper analyst cabin spoon stable organ";
    -        let mnemonic = Mnemonic::from_phrase(mnemonic, Language::English).unwrap();
    -        let path = bip32::DerivationPath::from_str("m/44'/0'/0'/0").unwrap();
    -
    -        let key = ((mnemonic, Some("passphrase".into())), path);
    -        let (desc, keys, networks) = crate::descriptor!(wpkh(key)).unwrap();
    -        assert_eq!(desc.to_string(), "wpkh([8f6cb80c/44'/0'/0']xpub6DWYS8bbihFevy29M4cbw4ZR3P5E12jB8R88gBDWCTCNpYiDHhYWNywrCF9VZQYagzPmsZpxXpytzSoxynyeFr4ZyzheVjnpLKuse4fiwZw/0/*)");
    -        assert_eq!(keys.len(), 1);
    -        assert_eq!(networks.len(), 3);
    -    }
    -
    -    #[test]
    -    fn test_keys_generate_bip39() {
    -        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
    -            Mnemonic::generate_with_entropy(
    -                (MnemonicType::Words12, Language::English),
    -                crate::keys::test::TEST_ENTROPY,
    -            )
    -            .unwrap();
    -        assert_eq!(generated_mnemonic.valid_networks, any_network());
    -        assert_eq!(
    -            generated_mnemonic.to_string(),
    -            "primary fetch primary fetch primary fetch primary fetch primary fetch primary fever"
    -        );
    -
    -        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
    -            Mnemonic::generate_with_entropy(
    -                (MnemonicType::Words24, Language::English),
    -                crate::keys::test::TEST_ENTROPY,
    -            )
    -            .unwrap();
    -        assert_eq!(generated_mnemonic.valid_networks, any_network());
    -        assert_eq!(generated_mnemonic.to_string(), "primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary foster");
    -    }
    -
    -    #[test]
    -    fn test_keys_generate_bip39_random() {
    -        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
    -            Mnemonic::generate((MnemonicType::Words12, Language::English)).unwrap();
    -        assert_eq!(generated_mnemonic.valid_networks, any_network());
    -
    -        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
    -            Mnemonic::generate((MnemonicType::Words24, Language::English)).unwrap();
    -        assert_eq!(generated_mnemonic.valid_networks, any_network());
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/keys/mod.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/keys/mod.rs.html deleted file mode 100644 index a18ef6494a..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/keys/mod.rs.html +++ /dev/null @@ -1,1482 +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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Key formats
    -
    -use std::any::TypeId;
    -use std::collections::HashSet;
    -use std::marker::PhantomData;
    -use std::ops::Deref;
    -
    -use bitcoin::secp256k1;
    -
    -use bitcoin::util::bip32;
    -use bitcoin::{Network, PrivateKey, PublicKey};
    -
    -pub use miniscript::descriptor::{
    -    DescriptorPublicKey, DescriptorSecretKey, DescriptorSinglePriv, DescriptorSinglePub,
    -    SortedMultiVec,
    -};
    -use miniscript::descriptor::{DescriptorXKey, KeyMap};
    -pub use miniscript::ScriptContext;
    -use miniscript::{Miniscript, Terminal};
    -
    -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 and regtest
    -pub fn any_network() -> ValidNetworks {
    -    vec![Network::Bitcoin, Network::Testnet, Network::Regtest]
    -        .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]
    -        .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::with_capacity(1);
    -
    -                let public = secret
    -                    .as_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,
    -}
    -
    -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
    -    }
    -}
    -
    -/// 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()
    -    }
    -}
    -
    -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,
    -            _ => 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, KeyError, ScriptContext, ToDescriptorKey};
    -///
    -/// pub struct MyKeyType {
    -///     pubkey: PublicKey,
    -/// }
    -///
    -/// impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for MyKeyType {
    -///     fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
    -///         self.pubkey.to_descriptor_key()
    -///     }
    -/// }
    -/// ```
    -///
    -/// Key type that is only valid on mainnet:
    -///
    -/// ```
    -/// use bdk::bitcoin::PublicKey;
    -///
    -/// use bdk::keys::{
    -///     mainnet_network, DescriptorKey, DescriptorPublicKey, DescriptorSinglePub, KeyError,
    -///     ScriptContext, ToDescriptorKey,
    -/// };
    -///
    -/// pub struct MyKeyType {
    -///     pubkey: PublicKey,
    -/// }
    -///
    -/// impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for MyKeyType {
    -///     fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
    -///         Ok(DescriptorKey::from_public(
    -///             DescriptorPublicKey::SinglePub(DescriptorSinglePub {
    -///                 origin: None,
    -///                 key: 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, KeyError, ScriptContext, ToDescriptorKey};
    -///
    -/// pub struct MyKeyType {
    -///     is_legacy: bool,
    -///     pubkey: PublicKey,
    -/// }
    -///
    -/// impl<Ctx: ScriptContext + 'static> ToDescriptorKey<Ctx> for MyKeyType {
    -///     fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
    -///         if Ctx::is_legacy() == self.is_legacy {
    -///             self.pubkey.to_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 std::str::FromStr;
    -///
    -/// use bdk::keys::{DescriptorKey, KeyError, ToDescriptorKey};
    -///
    -/// pub struct MySegwitOnlyKeyType {
    -///     pubkey: PublicKey,
    -/// }
    -///
    -/// impl ToDescriptorKey<bdk::miniscript::Segwitv0> for MySegwitOnlyKeyType {
    -///     fn to_descriptor_key(self) -> Result<DescriptorKey<bdk::miniscript::Segwitv0>, KeyError> {
    -///         self.pubkey.to_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 ToDescriptorKey<Ctx: ScriptContext>: Sized {
    -    /// Turn the key into a [`DescriptorKey`] within the requested [`ScriptContext`]
    -    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError>;
    -}
    -
    -/// Trait for keys that can be derived.
    -///
    -/// When extra metadata are provided, a [`DerivableKey`] can be transofrmed into a
    -/// [`DescriptorKey`]: the trait [`ToDescriptorKey`] 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 implemented this trait instead of [`ToDescriptorKey`]. The same
    -/// rules regarding script context and valid networks apply.
    -///
    -/// [`DerivationPath`]: (bip32::DerivationPath)
    -pub trait DerivableKey<Ctx: ScriptContext> {
    -    /// Add a extra metadata, consume `self` and turn it into a [`DescriptorKey`]
    -    fn add_metadata(
    -        self,
    -        origin: Option<bip32::KeySource>,
    -        derivation_path: bip32::DerivationPath,
    -    ) -> Result<DescriptorKey<Ctx>, KeyError>;
    -}
    -
    -impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPubKey {
    -    fn add_metadata(
    -        self,
    -        origin: Option<bip32::KeySource>,
    -        derivation_path: bip32::DerivationPath,
    -    ) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        DescriptorPublicKey::XPub(DescriptorXKey {
    -            origin,
    -            xkey: self,
    -            derivation_path,
    -            is_wildcard: true,
    -        })
    -        .to_descriptor_key()
    -    }
    -}
    -
    -impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPrivKey {
    -    fn add_metadata(
    -        self,
    -        origin: Option<bip32::KeySource>,
    -        derivation_path: bip32::DerivationPath,
    -    ) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        DescriptorSecretKey::XPrv(DescriptorXKey {
    -            origin,
    -            xkey: self,
    -            derivation_path,
    -            is_wildcard: true,
    -        })
    -        .to_descriptor_key()
    -    }
    -}
    -
    -/// 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
    -    }
    -}
    -
    -// 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 add_metadata(
    -        self,
    -        origin: Option<bip32::KeySource>,
    -        derivation_path: bip32::DerivationPath,
    -    ) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        let descriptor_key = self.key.add_metadata(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> ToDescriptorKey<Ctx> for GeneratedKey<K, Ctx>
    -where
    -    Ctx: ScriptContext,
    -    K: ToDescriptorKey<Ctx>,
    -{
    -    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        let desc_key = self.key.to_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 [`ToDescriptorKey`] 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
    -/// [`ToDescriptorKey`]: the generated keys can be directly used in descriptors if `Self` is also
    -/// [`ToDescriptorKey`].
    -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: std::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::ExtendedPrivKey {
    -    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::ExtendedPrivKey::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 key = secp256k1::SecretKey::from_slice(&entropy)?;
    -        let private_key = PrivateKey {
    -            compressed: options.compressed,
    -            network: Network::Bitcoin,
    -            key,
    -        };
    -
    -        Ok(GeneratedKey::new(private_key, any_network()))
    -    }
    -}
    -
    -impl<Ctx: ScriptContext, T: DerivableKey<Ctx>> ToDescriptorKey<Ctx> for (T, bip32::DerivationPath) {
    -    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        self.0.add_metadata(None, self.1)
    -    }
    -}
    -
    -impl<Ctx: ScriptContext, T: DerivableKey<Ctx>> ToDescriptorKey<Ctx>
    -    for (T, bip32::KeySource, bip32::DerivationPath)
    -{
    -    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        self.0.add_metadata(Some(self.1), self.2)
    -    }
    -}
    -
    -fn expand_multi_keys<Pk: ToDescriptorKey<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| Ok::<_, KeyError>(key.to_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.into_iter());
    -            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: ToDescriptorKey<Ctx>, Ctx: ScriptContext>(
    -    descriptor_key: Pk,
    -    secp: &SecpCtx,
    -) -> Result<(Miniscript<DescriptorPublicKey, Ctx>, KeyMap, ValidNetworks), KeyError> {
    -    let (key, key_map, valid_networks) = descriptor_key.to_descriptor_key()?.extract(secp)?;
    -
    -    Ok((
    -        Miniscript::from_ast(Terminal::PkK(key))?,
    -        key_map,
    -        valid_networks,
    -    ))
    -}
    -
    -// Used internally by `bdk::fragment!` to build `multi()` fragments
    -#[doc(hidden)]
    -pub fn make_multi<Pk: ToDescriptorKey<Ctx>, Ctx: ScriptContext>(
    -    thresh: usize,
    -    pks: Vec<Pk>,
    -    secp: &SecpCtx,
    -) -> Result<(Miniscript<DescriptorPublicKey, Ctx>, KeyMap, ValidNetworks), KeyError> {
    -    let (pks, key_map, valid_networks) = expand_multi_keys(pks, secp)?;
    -
    -    Ok((
    -        Miniscript::from_ast(Terminal::Multi(thresh, pks))?,
    -        key_map,
    -        valid_networks,
    -    ))
    -}
    -
    -// Used internally by `bdk::descriptor!` to build `sortedmulti()` fragments
    -#[doc(hidden)]
    -pub fn make_sortedmulti_inner<Pk: ToDescriptorKey<Ctx>, Ctx: ScriptContext>(
    -    thresh: usize,
    -    pks: Vec<Pk>,
    -    secp: &SecpCtx,
    -) -> Result<
    -    (
    -        SortedMultiVec<DescriptorPublicKey, Ctx>,
    -        KeyMap,
    -        ValidNetworks,
    -    ),
    -    KeyError,
    -> {
    -    let (pks, key_map, valid_networks) = expand_multi_keys(pks, secp)?;
    -
    -    Ok((SortedMultiVec::new(thresh, pks)?, key_map, valid_networks))
    -}
    -
    -/// The "identity" conversion is used internally by some `bdk::fragment`s
    -impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorKey<Ctx> {
    -    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        Ok(self)
    -    }
    -}
    -
    -impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorPublicKey {
    -    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        let networks = match self {
    -            DescriptorPublicKey::SinglePub(_) => any_network(),
    -            DescriptorPublicKey::XPub(DescriptorXKey { xkey, .. })
    -                if xkey.network == Network::Bitcoin =>
    -            {
    -                mainnet_network()
    -            }
    -            _ => test_networks(),
    -        };
    -
    -        Ok(DescriptorKey::from_public(self, networks))
    -    }
    -}
    -
    -impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for PublicKey {
    -    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        DescriptorPublicKey::SinglePub(DescriptorSinglePub {
    -            key: self,
    -            origin: None,
    -        })
    -        .to_descriptor_key()
    -    }
    -}
    -
    -impl<Ctx: ScriptContext> ToDescriptorKey<Ctx> for DescriptorSecretKey {
    -    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        let networks = match &self {
    -            DescriptorSecretKey::SinglePriv(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> ToDescriptorKey<Ctx> for PrivateKey {
    -    fn to_descriptor_key(self) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        DescriptorSecretKey::SinglePriv(DescriptorSinglePriv {
    -            key: self,
    -            origin: None,
    -        })
    -        .to_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::util::bip32::Error),
    -    /// Miniscript error
    -    Miniscript(miniscript::Error),
    -}
    -
    -impl_error!(miniscript::Error, Miniscript, KeyError);
    -impl_error!(bitcoin::util::bip32::Error, BIP32, KeyError);
    -
    -impl std::fmt::Display for KeyError {
    -    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for KeyError {}
    -
    -#[cfg(test)]
    -pub mod test {
    -    use bitcoin::util::bip32;
    -
    -    use super::*;
    -
    -    pub const TEST_ENTROPY: [u8; 32] = [0xAA; 32];
    -
    -    #[test]
    -    fn test_keys_generate_xprv() {
    -        let generated_xprv: GeneratedKey<_, miniscript::Segwitv0> =
    -            bip32::ExtendedPrivKey::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"
    -        );
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/lib.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/lib.rs.html deleted file mode 100644 index 41b65ad153..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/lib.rs.html +++ /dev/null @@ -1,548 +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
    - 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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -// rustdoc will warn if there are missing docs
    -#![warn(missing_docs)]
    -// only enables the `doc_cfg` feature when
    -// the `docsrs` configuration attribute is defined
    -#![cfg_attr(docsrs, feature(doc_cfg))]
    -// only enables the nightly `external_doc` feature when
    -// `test-md-docs` is enabled
    -#![cfg_attr(feature = "test-md-docs", feature(external_doc))]
    -
    -//! A modern, lightweight, descriptor-based wallet library written in Rust.
    -//!
    -//! # About
    -//!
    -//! The BDK library aims to be the core building block for Bitcoin wallets of any kind.
    -//!
    -//! * It uses [Miniscript](https://github.com/rust-bitcoin/rust-miniscript) to support descriptors with generalized conditions. This exact same library can be used to build
    -//!   single-sig wallets, multisigs, timelocked contracts and more.
    -//! * It supports multiple blockchain backends and databases, allowing developers to choose exactly what's right for their projects.
    -//! * It is built to be cross-platform: the core logic works on desktop, mobile, and even WebAssembly.
    -//! * It is very easy to extend: developers can implement customized logic for blockchain backends, databases, signers, coin selection, and more, without having to fork and modify this library.
    -//!
    -//! # A Tour of BDK
    -//!
    -//! BDK consists of a number of modules that provide a range of functionality
    -//! essential for implementing descriptor based Bitcoin wallet applications in Rust. In this
    -//! section, we will take a brief tour of BDK, summarizing the major APIs and
    -//! their uses.
    -//!
    -//! The easiest way to get started is to add bdk to your dependencies with the default features.
    -//! The default features include a simple key-value database ([`sled`](sled)) to cache
    -//! blockchain data and an [electrum](https://docs.rs/electrum-client/) blockchain client to
    -//! interact with the bitcoin P2P network.
    -//!
    -//! ```toml
    -//! bdk = "0.2.0"
    -//! ```
    -//!
    -//! ## Sync the balance of a descriptor
    -//!
    -//! ### Example
    -//! ```ignore
    -//! use bdk::Wallet;
    -//! use bdk::database::MemoryDatabase;
    -//! use bdk::blockchain::{noop_progress, ElectrumBlockchain};
    -//!
    -//! use bdk::electrum_client::Client;
    -//!
    -//! fn main() -> Result<(), bdk::Error> {
    -//!     let client = Client::new("ssl://electrum.blockstream.info:60002")?;
    -//!     let wallet = Wallet::new(
    -//!         "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
    -//!         Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
    -//!         bitcoin::Network::Testnet,
    -//!         MemoryDatabase::default(),
    -//!         ElectrumBlockchain::from(client)
    -//!     )?;
    -//!
    -//!     wallet.sync(noop_progress(), None)?;
    -//!
    -//!     println!("Descriptor balance: {} SAT", wallet.get_balance()?);
    -//!
    -//!     Ok(())
    -//! }
    -//! ```
    -//!
    -//! ## Generate a few addresses
    -//!
    -//! ### Example
    -//! ```
    -//! use bdk::{Wallet, OfflineWallet};
    -//! use bdk::database::MemoryDatabase;
    -//!
    -//! fn main() -> Result<(), bdk::Error> {
    -//!     let wallet: OfflineWallet<_> = Wallet::new_offline(
    -//!         "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
    -//!         Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
    -//!         bitcoin::Network::Testnet,
    -//!         MemoryDatabase::default(),
    -//!     )?;
    -//!
    -//!     println!("Address #0: {}", wallet.get_new_address()?);
    -//!     println!("Address #1: {}", wallet.get_new_address()?);
    -//!     println!("Address #2: {}", wallet.get_new_address()?);
    -//!
    -//!     Ok(())
    -//! }
    -//! ```
    -//!
    -//! ## Create a transaction
    -//!
    -//! ### Example
    -//! ```ignore
    -//! use base64::decode;
    -//! use bdk::{FeeRate, TxBuilder, Wallet};
    -//! use bdk::database::MemoryDatabase;
    -//! use bdk::blockchain::{noop_progress, ElectrumBlockchain};
    -//!
    -//! use bdk::electrum_client::Client;
    -//!
    -//! use bitcoin::consensus::serialize;
    -//!
    -//! fn main() -> Result<(), bdk::Error> {
    -//!     let client = Client::new("ssl://electrum.blockstream.info:60002")?;
    -//!     let wallet = Wallet::new(
    -//!         "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
    -//!         Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
    -//!         bitcoin::Network::Testnet,
    -//!         MemoryDatabase::default(),
    -//!         ElectrumBlockchain::from(client)
    -//!     )?;
    -//!
    -//!     wallet.sync(noop_progress(), None)?;
    -//!
    -//!     let send_to = wallet.get_new_address()?;
    -//!     let (psbt, details) = wallet.create_tx(
    -//!         TxBuilder::with_recipients(vec![(send_to.script_pubkey(), 50_000)])
    -//!             .enable_rbf()
    -//!             .do_not_spend_change()
    -//!             .fee_rate(FeeRate::from_sat_per_vb(5.0))
    -//!     )?;
    -//!
    -//!     println!("Transaction details: {:#?}", details);
    -//!     println!("Unsigned PSBT: {}", base64::encode(&serialize(&psbt)));
    -//!
    -//!     Ok(())
    -//! }
    -//! ```
    -//!
    -//! ## Sign a transaction
    -//!
    -//! ### Example
    -//! ```ignore
    -//! use base64::decode;
    -//! use bdk::{Wallet, OfflineWallet};
    -//! use bdk::database::MemoryDatabase;
    -//!
    -//! use bitcoin::consensus::deserialize;
    -//!
    -//! fn main() -> Result<(), bdk::Error> {
    -//!     let wallet: OfflineWallet<_> = Wallet::new_offline(
    -//!         "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
    -//!         Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
    -//!         bitcoin::Network::Testnet,
    -//!         MemoryDatabase::default(),
    -//!     )?;
    -//!
    -//!     let psbt = "...";
    -//!     let psbt = deserialize(&base64::decode(psbt).unwrap())?;
    -//!
    -//!     let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
    -//!
    -//!     Ok(())
    -//! }
    -//! ```
    -//!
    -//! # Feature flags
    -//!
    -//! BDK uses a set of [feature flags](https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section)
    -//! to reduce the amount of compiled code by allowing projects to only enable the features they need.
    -//! By default, BDK enables two internal features, `key-value-db` and `electrum`.
    -//!
    -//! If you are new to BDK we recommended that you use the default features which will enable
    -//! basic descriptor wallet functionality. More advanced users can disable the `default` features
    -//! (`--no-default-features`) and build the BDK library with only the features you need.
    -
    -//! Below is a list of the available feature flags and the additional functionality they provide.
    -//!
    -//! * `all-keys`: all features for working with bitcoin keys
    -//! * `async-interface`: async functions in bdk traits
    -//! * `cli-utils`: utilities for creating a command line interface wallet
    -//! * `keys-bip39`: [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) mnemonic codes for generating deterministic keys
    -//!
    -//! ## Internal features
    -//!
    -//! These features do not expose any new API, but influence internal implementation aspects of
    -//! BDK.
    -//!
    -//! * `compact_filters`: [`compact_filters`](crate::blockchain::compact_filters) client protocol for interacting with the bitcoin P2P network
    -//! * `electrum`: [`electrum`](crate::blockchain::electrum) client protocol for interacting with electrum servers
    -//! * `esplora`: [`esplora`](crate::blockchain::esplora) client protocol for interacting with blockstream [electrs](https://github.com/Blockstream/electrs) servers
    -//! * `key-value-db`: key value [`database`](crate::database) based on [`sled`](crate::sled) for caching blockchain data
    -
    -pub extern crate bitcoin;
    -extern crate log;
    -pub extern crate miniscript;
    -extern crate serde;
    -#[macro_use]
    -extern crate serde_json;
    -
    -#[cfg(feature = "keys-bip39")]
    -extern crate bip39;
    -
    -#[cfg(any(target_arch = "wasm32", feature = "async-interface"))]
    -#[macro_use]
    -extern crate async_trait;
    -#[macro_use]
    -extern crate bdk_macros;
    -
    -#[cfg(feature = "compact_filters")]
    -#[macro_use]
    -extern crate lazy_static;
    -
    -#[cfg(feature = "electrum")]
    -pub extern crate electrum_client;
    -
    -#[cfg(feature = "esplora")]
    -pub extern crate reqwest;
    -
    -#[cfg(feature = "key-value-db")]
    -pub extern crate sled;
    -
    -#[cfg(feature = "cli-utils")]
    -pub mod cli;
    -
    -#[allow(unused_imports)]
    -#[cfg(test)]
    -#[macro_use]
    -extern crate testutils;
    -#[allow(unused_imports)]
    -#[cfg(test)]
    -#[macro_use]
    -extern crate testutils_macros;
    -#[allow(unused_imports)]
    -#[cfg(test)]
    -#[macro_use]
    -extern crate serial_test;
    -
    -#[macro_use]
    -pub(crate) mod error;
    -pub mod blockchain;
    -pub mod database;
    -pub mod descriptor;
    -#[cfg(feature = "test-md-docs")]
    -mod doctest;
    -pub mod keys;
    -pub(crate) mod psbt;
    -pub(crate) mod types;
    -pub mod wallet;
    -
    -pub use descriptor::template;
    -pub use descriptor::HDKeyPaths;
    -pub use error::Error;
    -pub use types::*;
    -pub use wallet::address_validator;
    -pub use wallet::signer;
    -pub use wallet::tx_builder::TxBuilder;
    -pub use wallet::{OfflineWallet, Wallet};
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/psbt/mod.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/psbt/mod.rs.html deleted file mode 100644 index 27b1f86e57..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/psbt/mod.rs.html +++ /dev/null @@ -1,110 +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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
    -use bitcoin::TxOut;
    -
    -pub trait PSBTUtils {
    -    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut>;
    -}
    -
    -impl PSBTUtils for PSBT {
    -    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut> {
    -        let tx = &self.global.unsigned_tx;
    -
    -        if input_index >= tx.input.len() {
    -            return None;
    -        }
    -
    -        if let Some(input) = self.inputs.get(input_index) {
    -            if let Some(wit_utxo) = &input.witness_utxo {
    -                Some(wit_utxo.clone())
    -            } else if let Some(in_tx) = &input.non_witness_utxo {
    -                Some(in_tx.output[tx.input[input_index].previous_output.vout as usize].clone())
    -            } else {
    -                None
    -            }
    -        } else {
    -            None
    -        }
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/types.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/types.rs.html deleted file mode 100644 index 4f731ccfd6..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/types.rs.html +++ /dev/null @@ -1,248 +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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use std::convert::AsRef;
    -
    -use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxOut};
    -use bitcoin::hash_types::Txid;
    -
    -use serde::{Deserialize, Serialize};
    -
    -/// Types of keychains
    -#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
    -pub enum KeychainKind {
    -    /// External
    -    External = 0,
    -    /// Internal, usually used for change outputs
    -    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",
    -        }
    -    }
    -}
    -
    -/// Fee rate
    -#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
    -// Internally stored as satoshi/vbyte
    -pub struct FeeRate(f32);
    -
    -impl FeeRate {
    -    /// Create a new instance of [`FeeRate`] given a float fee rate in btc/kvbytes
    -    pub fn from_btc_per_kvb(btc_per_kvb: f32) -> Self {
    -        FeeRate(btc_per_kvb * 1e5)
    -    }
    -
    -    /// Create a new instance of [`FeeRate`] given a float fee rate in satoshi/vbyte
    -    pub fn from_sat_per_vb(sat_per_vb: f32) -> Self {
    -        FeeRate(sat_per_vb)
    -    }
    -
    -    /// Create a new [`FeeRate`] with the default min relay fee value
    -    pub fn default_min_relay_fee() -> Self {
    -        FeeRate(1.0)
    -    }
    -
    -    /// Return the value as satoshi/vbyte
    -    pub fn as_sat_vb(&self) -> f32 {
    -        self.0
    -    }
    -}
    -
    -impl std::default::Default for FeeRate {
    -    fn default() -> Self {
    -        FeeRate::default_min_relay_fee()
    -    }
    -}
    -
    -/// A wallet unspent output
    -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
    -pub struct UTXO {
    -    /// Reference to a transaction output
    -    pub outpoint: OutPoint,
    -    /// Transaction output
    -    pub txout: TxOut,
    -    /// Type of keychain
    -    pub keychain: KeychainKind,
    -}
    -
    -/// A wallet transaction
    -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
    -pub struct TransactionDetails {
    -    /// Optional transaction
    -    pub transaction: Option<Transaction>,
    -    /// Transaction id
    -    pub txid: Txid,
    -    /// Timestamp
    -    pub timestamp: u64,
    -    /// Received value (sats)
    -    pub received: u64,
    -    /// Sent value (sats)
    -    pub sent: u64,
    -    /// Fee value (sats)
    -    pub fees: u64,
    -    /// Confirmed in block height, `None` means unconfirmed
    -    pub height: Option<u32>,
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/address_validator.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/address_validator.rs.html deleted file mode 100644 index de52fb046b..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/address_validator.rs.html +++ /dev/null @@ -1,340 +0,0 @@ -address_validator.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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Address validation callbacks
    -//!
    -//! The typical usage of those callbacks is for displaying the newly-generated address on a
    -//! hardware wallet, so that the user can cross-check its correctness.
    -//!
    -//! More generally speaking though, these callbacks can also be used to "do something" every time
    -//! an address is generated, without necessarily checking or validating it.
    -//!
    -//! An address validator can be attached to a [`Wallet`](super::Wallet) by using the
    -//! [`Wallet::add_address_validator`](super::Wallet::add_address_validator) method, and
    -//! whenever a new address is generated (either explicitly by the user with
    -//! [`Wallet::get_new_address`](super::Wallet::get_new_address) or internally to create a change
    -//! address) all the attached validators will be polled, in sequence. All of them must complete
    -//! successfully to continue.
    -//!
    -//! ## Example
    -//!
    -//! ```
    -//! # use std::sync::Arc;
    -//! # use bitcoin::*;
    -//! # use bdk::address_validator::*;
    -//! # use bdk::database::*;
    -//! # use bdk::*;
    -//! struct PrintAddressAndContinue;
    -//!
    -//! impl AddressValidator for PrintAddressAndContinue {
    -//!     fn validate(
    -//!         &self,
    -//!         keychain: KeychainKind,
    -//!         hd_keypaths: &HDKeyPaths,
    -//!         script: &Script
    -//!     ) -> Result<(), AddressValidatorError> {
    -//!         let address = Address::from_script(script, Network::Testnet)
    -//!             .as_ref()
    -//!             .map(Address::to_string)
    -//!             .unwrap_or(script.to_string());
    -//!         println!("New address of type {:?}: {}", keychain, address);
    -//!         println!("HD keypaths: {:#?}", hd_keypaths);
    -//!
    -//!         Ok(())
    -//!     }
    -//! }
    -//!
    -//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -//! let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -//! wallet.add_address_validator(Arc::new(PrintAddressAndContinue));
    -//!
    -//! let address = wallet.get_new_address()?;
    -//! println!("Address: {}", address);
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use std::fmt;
    -
    -use bitcoin::Script;
    -
    -use crate::descriptor::HDKeyPaths;
    -use crate::types::KeychainKind;
    -
    -/// Errors that can be returned to fail the validation of an address
    -#[derive(Debug, Clone, PartialEq, Eq)]
    -pub enum AddressValidatorError {
    -    /// User rejected the address
    -    UserRejected,
    -    /// Network connection error
    -    ConnectionError,
    -    /// Network request timeout error
    -    TimeoutError,
    -    /// Invalid script
    -    InvalidScript,
    -    /// A custom error message
    -    Message(String),
    -}
    -
    -impl fmt::Display for AddressValidatorError {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for AddressValidatorError {}
    -
    -/// Trait to build address validators
    -///
    -/// All the address validators attached to a wallet with [`Wallet::add_address_validator`](super::Wallet::add_address_validator) will be polled
    -/// every time an address (external or internal) is generated by the wallet. Errors returned in the
    -/// validator will be propagated up to the original caller that triggered the address generation.
    -///
    -/// For a usage example see [this module](crate::address_validator)'s documentation.
    -pub trait AddressValidator: Send + Sync {
    -    /// Validate or inspect an address
    -    fn validate(
    -        &self,
    -        keychain: KeychainKind,
    -        hd_keypaths: &HDKeyPaths,
    -        script: &Script,
    -    ) -> Result<(), AddressValidatorError>;
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::sync::Arc;
    -
    -    use super::*;
    -    use crate::wallet::test::{get_funded_wallet, get_test_wpkh};
    -    use crate::wallet::TxBuilder;
    -
    -    struct TestValidator;
    -    impl AddressValidator for TestValidator {
    -        fn validate(
    -            &self,
    -            _keychain: KeychainKind,
    -            _hd_keypaths: &HDKeyPaths,
    -            _script: &bitcoin::Script,
    -        ) -> Result<(), AddressValidatorError> {
    -            Err(AddressValidatorError::InvalidScript)
    -        }
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InvalidScript")]
    -    fn test_address_validator_external() {
    -        let (mut wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        wallet.add_address_validator(Arc::new(TestValidator));
    -
    -        wallet.get_new_address().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InvalidScript")]
    -    fn test_address_validator_internal() {
    -        let (mut wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        wallet.add_address_validator(Arc::new(TestValidator));
    -
    -        let addr = testutils!(@external descriptors, 10);
    -        wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/coin_selection.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/coin_selection.rs.html deleted file mode 100644 index f52a1c8b9a..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/coin_selection.rs.html +++ /dev/null @@ -1,2000 +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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Coin selection
    -//!
    -//! This module provides the trait [`CoinSelectionAlgorithm`] that can be implemented to
    -//! define custom coin selection algorithms.
    -//!
    -//! The coin selection algorithm is not globally part of a [`Wallet`](super::Wallet), instead it
    -//! is selected whenever a [`Wallet::create_tx`](super::Wallet::create_tx) call is made, through
    -//! the use of the [`TxBuilder`] structure, specifically with
    -//! [`TxBuilder::coin_selection`](super::tx_builder::TxBuilder::coin_selection) method.
    -//!
    -//! The [`DefaultCoinSelectionAlgorithm`] selects the default coin selection algorithm that
    -//! [`TxBuilder`] uses, if it's not explicitly overridden.
    -//!
    -//! [`TxBuilder`]: super::tx_builder::TxBuilder
    -//!
    -//! ## Example
    -//!
    -//! ```no_run
    -//! # use std::str::FromStr;
    -//! # use bitcoin::*;
    -//! # use bdk::wallet::coin_selection::*;
    -//! # use bdk::database::Database;
    -//! # use bdk::*;
    -//! # const TXIN_BASE_WEIGHT: usize = (32 + 4 + 4 + 1) * 4;
    -//! #[derive(Debug)]
    -//! struct AlwaysSpendEverything;
    -//!
    -//! impl<D: Database> CoinSelectionAlgorithm<D> for AlwaysSpendEverything {
    -//!     fn coin_select(
    -//!         &self,
    -//!         database: &D,
    -//!         required_utxos: Vec<(UTXO, usize)>,
    -//!         optional_utxos: Vec<(UTXO, usize)>,
    -//!         fee_rate: FeeRate,
    -//!         amount_needed: u64,
    -//!         fee_amount: f32,
    -//!     ) -> Result<CoinSelectionResult, bdk::Error> {
    -//!         let mut selected_amount = 0;
    -//!         let mut additional_weight = 0;
    -//!         let all_utxos_selected = required_utxos
    -//!             .into_iter().chain(optional_utxos)
    -//!             .scan((&mut selected_amount, &mut additional_weight), |(selected_amount, additional_weight), (utxo, weight)| {
    -//!                 **selected_amount += utxo.txout.value;
    -//!                 **additional_weight += TXIN_BASE_WEIGHT + weight;
    -//!
    -//!                 Some(utxo)
    -//!             })
    -//!             .collect::<Vec<_>>();
    -//!         let additional_fees = additional_weight as f32 * fee_rate.as_sat_vb() / 4.0;
    -//!
    -//!         if (fee_amount + additional_fees).ceil() as u64 + amount_needed > selected_amount {
    -//!             return Err(bdk::Error::InsufficientFunds);
    -//!         }
    -//!
    -//!         Ok(CoinSelectionResult {
    -//!             selected: all_utxos_selected,
    -//!             selected_amount,
    -//!             fee_amount: fee_amount + additional_fees,
    -//!         })
    -//!     }
    -//! }
    -//!
    -//! # let wallet: OfflineWallet<_> = Wallet::new_offline("", None, Network::Testnet, bdk::database::MemoryDatabase::default())?;
    -//! // create wallet, sync, ...
    -//!
    -//! let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -//! let (psbt, details) = wallet.create_tx(
    -//!     TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
    -//!         .coin_selection(AlwaysSpendEverything),
    -//! )?;
    -//!
    -//! // inspect, sign, broadcast, ...
    -//!
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use crate::database::Database;
    -use crate::error::Error;
    -use crate::types::{FeeRate, UTXO};
    -
    -use rand::seq::SliceRandom;
    -#[cfg(not(test))]
    -use rand::thread_rng;
    -#[cfg(test)]
    -use rand::{rngs::StdRng, SeedableRng};
    -
    -/// Default coin selection algorithm used by [`TxBuilder`](super::tx_builder::TxBuilder) if not
    -/// overridden
    -#[cfg(not(test))]
    -pub type DefaultCoinSelectionAlgorithm = BranchAndBoundCoinSelection;
    -#[cfg(test)]
    -pub type DefaultCoinSelectionAlgorithm = LargestFirstCoinSelection; // make the tests more predictable
    -
    -// Base weight of a Txin, not counting the weight needed for satisfying it.
    -// prev_txid (32 bytes) + prev_vout (4 bytes) + sequence (4 bytes) + script_len (1 bytes)
    -pub(crate) const TXIN_BASE_WEIGHT: usize = (32 + 4 + 4 + 1) * 4;
    -
    -/// Result of a successful coin selection
    -#[derive(Debug)]
    -pub struct CoinSelectionResult {
    -    /// List of outputs selected for use as inputs
    -    pub selected: Vec<UTXO>,
    -    /// Sum of the selected inputs' value
    -    pub selected_amount: u64,
    -    /// Total fee amount in satoshi
    -    pub fee_amount: f32,
    -}
    -
    -/// 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<D: Database>: std::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 `amount_needed` with their
    -    ///                     weight cost
    -    /// - `optional_utxos`: the remaining available utxos to satisfy `amount_needed` with their
    -    ///                     weight cost
    -    /// - `fee_rate`: fee rate to use
    -    /// - `amount_needed`: the amount in satoshi to select
    -    /// - `fee_amount`: the amount of fees in satoshi already accumulated from adding outputs and
    -    ///                 the transaction's header
    -    fn coin_select(
    -        &self,
    -        database: &D,
    -        required_utxos: Vec<(UTXO, usize)>,
    -        optional_utxos: Vec<(UTXO, usize)>,
    -        fee_rate: FeeRate,
    -        amount_needed: u64,
    -        fee_amount: f32,
    -    ) -> 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)]
    -pub struct LargestFirstCoinSelection;
    -
    -impl<D: Database> CoinSelectionAlgorithm<D> for LargestFirstCoinSelection {
    -    fn coin_select(
    -        &self,
    -        _database: &D,
    -        required_utxos: Vec<(UTXO, usize)>,
    -        mut optional_utxos: Vec<(UTXO, usize)>,
    -        fee_rate: FeeRate,
    -        amount_needed: u64,
    -        mut fee_amount: f32,
    -    ) -> Result<CoinSelectionResult, Error> {
    -        let calc_fee_bytes = |wu| (wu as f32) * fee_rate.as_sat_vb() / 4.0;
    -
    -        log::debug!(
    -            "amount_needed = `{}`, fee_amount = `{}`, fee_rate = `{:?}`",
    -            amount_needed,
    -            fee_amount,
    -            fee_rate
    -        );
    -
    -        // 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(|(utxo, _)| utxo.txout.value);
    -            required_utxos
    -                .into_iter()
    -                .map(|utxo| (true, utxo))
    -                .chain(optional_utxos.into_iter().rev().map(|utxo| (false, utxo)))
    -        };
    -
    -        // Keep including inputs until we've got enough.
    -        // Store the total input value in selected_amount and the total fee being paid in fee_amount
    -        let mut selected_amount = 0;
    -        let selected = utxos
    -            .scan(
    -                (&mut selected_amount, &mut fee_amount),
    -                |(selected_amount, fee_amount), (must_use, (utxo, weight))| {
    -                    if must_use || **selected_amount < amount_needed + (fee_amount.ceil() as u64) {
    -                        **fee_amount += calc_fee_bytes(TXIN_BASE_WEIGHT + weight);
    -                        **selected_amount += utxo.txout.value;
    -
    -                        log::debug!(
    -                            "Selected {}, updated fee_amount = `{}`",
    -                            utxo.outpoint,
    -                            fee_amount
    -                        );
    -
    -                        Some(utxo)
    -                    } else {
    -                        None
    -                    }
    -                },
    -            )
    -            .collect::<Vec<_>>();
    -
    -        if selected_amount < amount_needed + (fee_amount.ceil() as u64) {
    -            return Err(Error::InsufficientFunds);
    -        }
    -
    -        Ok(CoinSelectionResult {
    -            selected,
    -            fee_amount,
    -            selected_amount,
    -        })
    -    }
    -}
    -
    -#[derive(Debug, Clone)]
    -// Adds fee information to an UTXO.
    -struct OutputGroup {
    -    utxo: UTXO,
    -    // weight needed to satisfy the UTXO, as described in `Descriptor::max_satisfaction_weight`
    -    satisfaction_weight: usize,
    -    // Amount of fees for spending a certain utxo, calculated using a certain FeeRate
    -    fee: f32,
    -    // The effective value of the UTXO, i.e., the utxo value minus the fee for spending it
    -    effective_value: i64,
    -}
    -
    -impl OutputGroup {
    -    fn new(utxo: UTXO, satisfaction_weight: usize, fee_rate: FeeRate) -> Self {
    -        let fee = (TXIN_BASE_WEIGHT + satisfaction_weight) as f32 / 4.0 * fee_rate.as_sat_vb();
    -        let effective_value = utxo.txout.value as i64 - fee.ceil() as i64;
    -        OutputGroup {
    -            utxo,
    -            satisfaction_weight,
    -            effective_value,
    -            fee,
    -        }
    -    }
    -}
    -
    -/// 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)]
    -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<D: Database> CoinSelectionAlgorithm<D> for BranchAndBoundCoinSelection {
    -    fn coin_select(
    -        &self,
    -        _database: &D,
    -        required_utxos: Vec<(UTXO, usize)>,
    -        optional_utxos: Vec<(UTXO, usize)>,
    -        fee_rate: FeeRate,
    -        amount_needed: u64,
    -        fee_amount: f32,
    -    ) -> 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.0, u.1, fee_rate))
    -            .collect();
    -
    -        // Mapping every (UTXO, usize) to an output group.
    -        // Filtering UTXOs with an effective_value < 0, as the fee paid for
    -        // adding them is more than their value
    -        let optional_utxos: Vec<OutputGroup> = optional_utxos
    -            .into_iter()
    -            .map(|u| OutputGroup::new(u.0, u.1, fee_rate))
    -            .filter(|u| u.effective_value > 0)
    -            .collect();
    -
    -        let curr_value = required_utxos
    -            .iter()
    -            .fold(0, |acc, x| acc + x.effective_value as u64);
    -
    -        let curr_available_value = optional_utxos
    -            .iter()
    -            .fold(0, |acc, x| acc + x.effective_value as u64);
    -
    -        let actual_target = fee_amount.ceil() as u64 + amount_needed;
    -        let cost_of_change = self.size_of_change as f32 * fee_rate.as_sat_vb();
    -
    -        if curr_available_value + curr_value < actual_target {
    -            return Err(Error::InsufficientFunds);
    -        }
    -
    -        Ok(self
    -            .bnb(
    -                required_utxos.clone(),
    -                optional_utxos.clone(),
    -                curr_value,
    -                curr_available_value,
    -                actual_target,
    -                fee_amount,
    -                cost_of_change,
    -            )
    -            .unwrap_or_else(|_| {
    -                self.single_random_draw(
    -                    required_utxos,
    -                    optional_utxos,
    -                    curr_value,
    -                    actual_target,
    -                    fee_amount,
    -                )
    -            }))
    -    }
    -}
    -
    -impl BranchAndBoundCoinSelection {
    -    // TODO: make this more Rust-onic :)
    -    // (And perhpaps refactor with less arguments?)
    -    #[allow(clippy::too_many_arguments)]
    -    fn bnb(
    -        &self,
    -        required_utxos: Vec<OutputGroup>,
    -        mut optional_utxos: Vec<OutputGroup>,
    -        mut curr_value: u64,
    -        mut curr_available_value: u64,
    -        actual_target: u64,
    -        fee_amount: f32,
    -        cost_of_change: f32,
    -    ) -> 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 < actual_target
    -                || curr_value > actual_target + cost_of_change as u64
    -            {
    -                backtrack = true;
    -            } else if curr_value >= actual_target {
    -                // 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 = current_selection.clone();
    -                    best_selection_value = Some(curr_value);
    -                }
    -
    -                // If we found a perfect match, break here
    -                if curr_value == actual_target {
    -                    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 as u64;
    -                }
    -
    -                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 as u64;
    -            } 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 as u64;
    -
    -                // Inclusion branch first (Largest First Exploration)
    -                current_selection.push(true);
    -                curr_value += utxo.effective_value as u64;
    -            }
    -        }
    -
    -        // 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();
    -
    -        Ok(BranchAndBoundCoinSelection::calculate_cs_result(
    -            selected_utxos,
    -            required_utxos,
    -            fee_amount,
    -        ))
    -    }
    -
    -    fn single_random_draw(
    -        &self,
    -        required_utxos: Vec<OutputGroup>,
    -        mut optional_utxos: Vec<OutputGroup>,
    -        curr_value: u64,
    -        actual_target: u64,
    -        fee_amount: f32,
    -    ) -> CoinSelectionResult {
    -        #[cfg(not(test))]
    -        optional_utxos.shuffle(&mut thread_rng());
    -        #[cfg(test)]
    -        {
    -            let seed = [0; 32];
    -            let mut rng: StdRng = SeedableRng::from_seed(seed);
    -            optional_utxos.shuffle(&mut rng);
    -        }
    -
    -        let selected_utxos = optional_utxos
    -            .into_iter()
    -            .scan(curr_value, |curr_value, utxo| {
    -                if *curr_value >= actual_target {
    -                    None
    -                } else {
    -                    *curr_value += utxo.effective_value as u64;
    -                    Some(utxo)
    -                }
    -            })
    -            .collect::<Vec<_>>();
    -
    -        BranchAndBoundCoinSelection::calculate_cs_result(selected_utxos, required_utxos, fee_amount)
    -    }
    -
    -    fn calculate_cs_result(
    -        mut selected_utxos: Vec<OutputGroup>,
    -        mut required_utxos: Vec<OutputGroup>,
    -        mut fee_amount: f32,
    -    ) -> CoinSelectionResult {
    -        selected_utxos.append(&mut required_utxos);
    -        fee_amount += selected_utxos.iter().map(|u| u.fee).sum::<f32>();
    -        let selected = selected_utxos
    -            .into_iter()
    -            .map(|u| u.utxo)
    -            .collect::<Vec<_>>();
    -        let selected_amount = selected.iter().map(|u| u.txout.value).sum();
    -
    -        CoinSelectionResult {
    -            selected,
    -            fee_amount,
    -            selected_amount,
    -        }
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::str::FromStr;
    -
    -    use bitcoin::{OutPoint, Script, TxOut};
    -
    -    use super::*;
    -    use crate::database::MemoryDatabase;
    -    use crate::types::*;
    -
    -    use rand::rngs::StdRng;
    -    use rand::seq::SliceRandom;
    -    use rand::{Rng, SeedableRng};
    -
    -    const P2WPKH_WITNESS_SIZE: usize = 73 + 33 + 2;
    -
    -    fn get_test_utxos() -> Vec<(UTXO, usize)> {
    -        vec![
    -            (
    -                UTXO {
    -                    outpoint: OutPoint::from_str(
    -                        "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:0",
    -                    )
    -                    .unwrap(),
    -                    txout: TxOut {
    -                        value: 100_000,
    -                        script_pubkey: Script::new(),
    -                    },
    -                    keychain: KeychainKind::External,
    -                },
    -                P2WPKH_WITNESS_SIZE,
    -            ),
    -            (
    -                UTXO {
    -                    outpoint: OutPoint::from_str(
    -                        "65d92ddff6b6dc72c89624a6491997714b90f6004f928d875bc0fd53f264fa85:0",
    -                    )
    -                    .unwrap(),
    -                    txout: TxOut {
    -                        value: 200_000,
    -                        script_pubkey: Script::new(),
    -                    },
    -                    keychain: KeychainKind::Internal,
    -                },
    -                P2WPKH_WITNESS_SIZE,
    -            ),
    -        ]
    -    }
    -
    -    fn generate_random_utxos(rng: &mut StdRng, utxos_number: usize) -> Vec<(UTXO, usize)> {
    -        let mut res = Vec::new();
    -        for _ in 0..utxos_number {
    -            res.push((
    -                UTXO {
    -                    outpoint: OutPoint::from_str(
    -                        "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:0",
    -                    )
    -                    .unwrap(),
    -                    txout: TxOut {
    -                        value: rng.gen_range(0, 200000000),
    -                        script_pubkey: Script::new(),
    -                    },
    -                    keychain: KeychainKind::External,
    -                },
    -                P2WPKH_WITNESS_SIZE,
    -            ));
    -        }
    -        res
    -    }
    -
    -    fn generate_same_value_utxos(utxos_value: u64, utxos_number: usize) -> Vec<(UTXO, usize)> {
    -        let utxo = (
    -            UTXO {
    -                outpoint: OutPoint::from_str(
    -                    "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:0",
    -                )
    -                .unwrap(),
    -                txout: TxOut {
    -                    value: utxos_value,
    -                    script_pubkey: Script::new(),
    -                },
    -                keychain: KeychainKind::External,
    -            },
    -            P2WPKH_WITNESS_SIZE,
    -        );
    -        vec![utxo; utxos_number]
    -    }
    -
    -    fn sum_random_utxos(mut rng: &mut StdRng, utxos: &mut Vec<(UTXO, usize)>) -> u64 {
    -        let utxos_picked_len = rng.gen_range(2, utxos.len() / 2);
    -        utxos.shuffle(&mut rng);
    -        utxos[..utxos_picked_len]
    -            .iter()
    -            .fold(0, |acc, x| acc + x.0.txout.value)
    -    }
    -
    -    #[test]
    -    fn test_largest_first_coin_selection_success() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        let result = LargestFirstCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                utxos,
    -                vec![],
    -                FeeRate::from_sat_per_vb(1.0),
    -                250_000,
    -                50.0,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.selected.len(), 2);
    -        assert_eq!(result.selected_amount, 300_000);
    -        assert_eq!(result.fee_amount, 186.0);
    -    }
    -
    -    #[test]
    -    fn test_largest_first_coin_selection_use_all() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        let result = LargestFirstCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                utxos,
    -                vec![],
    -                FeeRate::from_sat_per_vb(1.0),
    -                20_000,
    -                50.0,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.selected.len(), 2);
    -        assert_eq!(result.selected_amount, 300_000);
    -        assert_eq!(result.fee_amount, 186.0);
    -    }
    -
    -    #[test]
    -    fn test_largest_first_coin_selection_use_only_necessary() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        let result = LargestFirstCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                vec![],
    -                utxos,
    -                FeeRate::from_sat_per_vb(1.0),
    -                20_000,
    -                50.0,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.selected.len(), 1);
    -        assert_eq!(result.selected_amount, 200_000);
    -        assert_eq!(result.fee_amount, 118.0);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_largest_first_coin_selection_insufficient_funds() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        LargestFirstCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                vec![],
    -                utxos,
    -                FeeRate::from_sat_per_vb(1.0),
    -                500_000,
    -                50.0,
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_largest_first_coin_selection_insufficient_funds_high_fees() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        LargestFirstCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                vec![],
    -                utxos,
    -                FeeRate::from_sat_per_vb(1000.0),
    -                250_000,
    -                50.0,
    -            )
    -            .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 database = MemoryDatabase::default();
    -
    -        let result = BranchAndBoundCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                vec![],
    -                utxos,
    -                FeeRate::from_sat_per_vb(1.0),
    -                250_000,
    -                50.0,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.selected.len(), 3);
    -        assert_eq!(result.selected_amount, 300_000);
    -        assert_eq!(result.fee_amount, 254.0);
    -    }
    -
    -    #[test]
    -    fn test_bnb_coin_selection_required_are_enough() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        let result = BranchAndBoundCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                utxos.clone(),
    -                utxos,
    -                FeeRate::from_sat_per_vb(1.0),
    -                20_000,
    -                50.0,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.selected.len(), 2);
    -        assert_eq!(result.selected_amount, 300_000);
    -        assert_eq!(result.fee_amount, 186.0);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_bnb_coin_selection_insufficient_funds() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        BranchAndBoundCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                vec![],
    -                utxos,
    -                FeeRate::from_sat_per_vb(1.0),
    -                500_000,
    -                50.0,
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_bnb_coin_selection_insufficient_funds_high_fees() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        BranchAndBoundCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                vec![],
    -                utxos,
    -                FeeRate::from_sat_per_vb(1000.0),
    -                250_000,
    -                50.0,
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_bnb_coin_selection_check_fee_rate() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        let result = BranchAndBoundCoinSelection::new(0)
    -            .coin_select(
    -                &database,
    -                vec![],
    -                utxos.clone(),
    -                FeeRate::from_sat_per_vb(1.0),
    -                99932, // first utxo's effective value
    -                0.0,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.selected.len(), 1);
    -        assert_eq!(result.selected_amount, 100_000);
    -        let input_size = (TXIN_BASE_WEIGHT as f32) / 4.0 + P2WPKH_WITNESS_SIZE as f32 / 4.0;
    -        let epsilon = 0.5;
    -        assert!((1.0 - (result.fee_amount / input_size)).abs() < epsilon);
    -    }
    -
    -    #[test]
    -    fn test_bnb_coin_selection_exact_match() {
    -        let seed = [0; 32];
    -        let mut rng: StdRng = SeedableRng::from_seed(seed);
    -        let database = MemoryDatabase::default();
    -
    -        for _i in 0..200 {
    -            let mut optional_utxos = generate_random_utxos(&mut rng, 16);
    -            let target_amount = sum_random_utxos(&mut rng, &mut optional_utxos);
    -            let result = BranchAndBoundCoinSelection::new(0)
    -                .coin_select(
    -                    &database,
    -                    vec![],
    -                    optional_utxos,
    -                    FeeRate::from_sat_per_vb(0.0),
    -                    target_amount,
    -                    0.0,
    -                )
    -                .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(10.0);
    -        let utxos: Vec<OutputGroup> = get_test_utxos()
    -            .into_iter()
    -            .map(|u| OutputGroup::new(u.0, u.1, fee_rate))
    -            .collect();
    -
    -        let curr_available_value = utxos
    -            .iter()
    -            .fold(0, |acc, x| acc + x.effective_value as u64);
    -
    -        let size_of_change = 31;
    -        let cost_of_change = size_of_change as f32 * fee_rate.as_sat_vb();
    -        BranchAndBoundCoinSelection::new(size_of_change)
    -            .bnb(
    -                vec![],
    -                utxos,
    -                0,
    -                curr_available_value,
    -                20_000,
    -                50.0,
    -                cost_of_change,
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "BnBTotalTriesExceeded")]
    -    fn test_bnb_function_tries_exceeded() {
    -        let fee_rate = FeeRate::from_sat_per_vb(10.0);
    -        let utxos: Vec<OutputGroup> = generate_same_value_utxos(100_000, 100_000)
    -            .into_iter()
    -            .map(|u| OutputGroup::new(u.0, u.1, fee_rate))
    -            .collect();
    -
    -        let curr_available_value = utxos
    -            .iter()
    -            .fold(0, |acc, x| acc + x.effective_value as u64);
    -
    -        let size_of_change = 31;
    -        let cost_of_change = size_of_change as f32 * fee_rate.as_sat_vb();
    -
    -        BranchAndBoundCoinSelection::new(size_of_change)
    -            .bnb(
    -                vec![],
    -                utxos,
    -                0,
    -                curr_available_value,
    -                20_000,
    -                50.0,
    -                cost_of_change,
    -            )
    -            .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(1.0);
    -        let size_of_change = 31;
    -        let cost_of_change = size_of_change as f32 * fee_rate.as_sat_vb();
    -        let fee_amount = 50.0;
    -
    -        let utxos: Vec<_> = generate_same_value_utxos(50_000, 10)
    -            .into_iter()
    -            .map(|u| OutputGroup::new(u.0, u.1, fee_rate))
    -            .collect();
    -
    -        let curr_value = 0;
    -
    -        let curr_available_value = utxos
    -            .iter()
    -            .fold(0, |acc, x| acc + x.effective_value as u64);
    -
    -        // 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.ceil() as u64 + 5;
    -
    -        let result = BranchAndBoundCoinSelection::new(size_of_change)
    -            .bnb(
    -                vec![],
    -                utxos,
    -                curr_value,
    -                curr_available_value,
    -                target_amount,
    -                fee_amount,
    -                cost_of_change,
    -            )
    -            .unwrap();
    -        assert_eq!(result.fee_amount, 186.0);
    -        assert_eq!(result.selected_amount, 100_000);
    -    }
    -
    -    // 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::from_sat_per_vb(0.0);
    -
    -        for _ in 0..200 {
    -            let optional_utxos: Vec<_> = generate_random_utxos(&mut rng, 40)
    -                .into_iter()
    -                .map(|u| OutputGroup::new(u.0, u.1, fee_rate))
    -                .collect();
    -
    -            let curr_value = 0;
    -
    -            let curr_available_value = optional_utxos
    -                .iter()
    -                .fold(0, |acc, x| acc + x.effective_value as u64);
    -
    -            let target_amount = optional_utxos[3].effective_value as u64
    -                + optional_utxos[23].effective_value as u64;
    -
    -            let result = BranchAndBoundCoinSelection::new(0)
    -                .bnb(
    -                    vec![],
    -                    optional_utxos,
    -                    curr_value,
    -                    curr_available_value,
    -                    target_amount,
    -                    0.0,
    -                    0.0,
    -                )
    -                .unwrap();
    -            assert_eq!(result.selected_amount, target_amount);
    -        }
    -    }
    -
    -    #[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);
    -
    -        let fee_rate = FeeRate::from_sat_per_vb(1.0);
    -        let utxos: Vec<OutputGroup> = utxos
    -            .into_iter()
    -            .map(|u| OutputGroup::new(u.0, u.1, fee_rate))
    -            .collect();
    -
    -        let result = BranchAndBoundCoinSelection::default().single_random_draw(
    -            vec![],
    -            utxos,
    -            0,
    -            target_amount,
    -            50.0,
    -        );
    -
    -        assert!(result.selected_amount > target_amount);
    -        assert_eq!(
    -            result.fee_amount,
    -            50.0 + result.selected.len() as f32 * 68.0
    -        );
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/export.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/export.rs.html deleted file mode 100644 index 1f0ffc2e91..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/export.rs.html +++ /dev/null @@ -1,692 +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
    -342
    -343
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! 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::database::*;
    -//! # use bdk::wallet::export::*;
    -//! # use bdk::*;
    -//! let import = r#"{
    -//!     "descriptor": "wpkh([c258d2e4\/84h\/1h\/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe\/0\/*)",
    -//!     "blockheight":1782088,
    -//!     "label":"testnet"
    -//! }"#;
    -//!
    -//! let import = WalletExport::from_str(import)?;
    -//! let wallet: OfflineWallet<_> = Wallet::new_offline(
    -//!     &import.descriptor(),
    -//!     import.change_descriptor().as_ref(),
    -//!     Network::Testnet,
    -//!     MemoryDatabase::default(),
    -//! )?;
    -//! # Ok::<_, bdk::Error>(())
    -//! ```
    -//!
    -//! ### Export a `Wallet`
    -//! ```
    -//! # use bitcoin::*;
    -//! # use bdk::database::*;
    -//! # use bdk::wallet::export::*;
    -//! # use bdk::*;
    -//! let wallet: OfflineWallet<_> = Wallet::new_offline(
    -//!     "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
    -//!     Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
    -//!     Network::Testnet,
    -//!     MemoryDatabase::default()
    -//! )?;
    -//! let export = WalletExport::export_wallet(&wallet, "exported wallet", true)
    -//!     .map_err(ToString::to_string)
    -//!     .map_err(bdk::Error::Generic)?;
    -//!
    -//! println!("Exported: {}", export.to_string());
    -//! # Ok::<_, bdk::Error>(())
    -//! ```
    -
    -use std::str::FromStr;
    -
    -use serde::{Deserialize, Serialize};
    -
    -use miniscript::{Descriptor, DescriptorPublicKey, ScriptContext, Terminal};
    -
    -use crate::blockchain::BlockchainMarker;
    -use crate::database::BatchDatabase;
    -use crate::wallet::Wallet;
    -
    -/// 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 WalletExport {
    -    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 ToString for WalletExport {
    -    fn to_string(&self) -> String {
    -        serde_json::to_string(self).unwrap()
    -    }
    -}
    -
    -impl FromStr for WalletExport {
    -    type Err = serde_json::Error;
    -
    -    fn from_str(s: &str) -> Result<Self, Self::Err> {
    -        serde_json::from_str(s)
    -    }
    -}
    -
    -impl WalletExport {
    -    /// 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<B: BlockchainMarker, D: BatchDatabase>(
    -        wallet: &Wallet<B, D>,
    -        label: &str,
    -        include_blockheight: bool,
    -    ) -> Result<Self, &'static str> {
    -        let descriptor = wallet
    -            .descriptor
    -            .to_string_with_secret(&wallet.signers.as_key_map(wallet.secp_ctx()));
    -        Self::is_compatible_with_core(&descriptor)?;
    -
    -        let blockheight = match wallet.database.borrow().iter_txs(false) {
    -            _ if !include_blockheight => 0,
    -            Err(_) => 0,
    -            Ok(txs) => {
    -                let mut heights = txs
    -                    .into_iter()
    -                    .map(|tx| tx.height.unwrap_or(0))
    -                    .collect::<Vec<_>>();
    -                heights.sort_unstable();
    -
    -                *heights.last().unwrap_or(&0)
    -            }
    -        };
    -
    -        let export = WalletExport {
    -            descriptor,
    -            label: label.into(),
    -            blockheight,
    -        };
    -
    -        let desc_to_string = |d: &Descriptor<DescriptorPublicKey>| {
    -            d.to_string_with_secret(&wallet.change_signers.as_key_map(wallet.secp_ctx()))
    -        };
    -        if export.change_descriptor() != wallet.change_descriptor.as_ref().map(desc_to_string) {
    -            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")
    -            }
    -        }
    -
    -        match Descriptor::<String>::from_str(descriptor).map_err(|_| "Invalid descriptor")? {
    -            Descriptor::Pk(_)
    -            | Descriptor::Pkh(_)
    -            | Descriptor::Wpkh(_)
    -            | Descriptor::ShWpkh(_) => Ok(()),
    -            Descriptor::Sh(ms) => check_ms(ms.node),
    -            Descriptor::Wsh(ms) | Descriptor::ShWsh(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 std::str::FromStr;
    -
    -    use bitcoin::{Network, Txid};
    -
    -    use super::*;
    -    use crate::database::{memory::MemoryDatabase, BatchOperations};
    -    use crate::types::TransactionDetails;
    -    use crate::wallet::{OfflineWallet, Wallet};
    -
    -    fn get_test_db() -> MemoryDatabase {
    -        let mut db = MemoryDatabase::new();
    -        db.set_tx(&TransactionDetails {
    -            transaction: None,
    -            txid: Txid::from_str(
    -                "4ddff1fa33af17f377f62b72357b43107c19110a8009b36fb832af505efed98a",
    -            )
    -            .unwrap(),
    -            timestamp: 12345678,
    -            received: 100_000,
    -            sent: 0,
    -            fees: 500,
    -            height: Some(5000),
    -        })
    -        .unwrap();
    -
    -        db
    -    }
    -
    -    #[test]
    -    fn test_export_bip44() {
    -        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
    -        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
    -
    -        let wallet: OfflineWallet<_> = Wallet::new_offline(
    -            descriptor,
    -            Some(change_descriptor),
    -            Network::Bitcoin,
    -            get_test_db(),
    -        )
    -        .unwrap();
    -        let export = WalletExport::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: OfflineWallet<_> =
    -            Wallet::new_offline(descriptor, None, Network::Bitcoin, get_test_db()).unwrap();
    -        WalletExport::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: OfflineWallet<_> = Wallet::new_offline(
    -            descriptor,
    -            Some(change_descriptor),
    -            Network::Bitcoin,
    -            get_test_db(),
    -        )
    -        .unwrap();
    -        WalletExport::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: OfflineWallet<_> = Wallet::new_offline(
    -            descriptor,
    -            Some(change_descriptor),
    -            Network::Testnet,
    -            get_test_db(),
    -        )
    -        .unwrap();
    -        let export = WalletExport::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: OfflineWallet<_> = Wallet::new_offline(
    -            descriptor,
    -            Some(change_descriptor),
    -            Network::Bitcoin,
    -            get_test_db(),
    -        )
    -        .unwrap();
    -        let export = WalletExport::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 = WalletExport::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/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/mod.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/mod.rs.html deleted file mode 100644 index a6ebcf5de5..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/mod.rs.html +++ /dev/null @@ -1,6828 +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
    -2709
    -2710
    -2711
    -2712
    -2713
    -2714
    -2715
    -2716
    -2717
    -2718
    -2719
    -2720
    -2721
    -2722
    -2723
    -2724
    -2725
    -2726
    -2727
    -2728
    -2729
    -2730
    -2731
    -2732
    -2733
    -2734
    -2735
    -2736
    -2737
    -2738
    -2739
    -2740
    -2741
    -2742
    -2743
    -2744
    -2745
    -2746
    -2747
    -2748
    -2749
    -2750
    -2751
    -2752
    -2753
    -2754
    -2755
    -2756
    -2757
    -2758
    -2759
    -2760
    -2761
    -2762
    -2763
    -2764
    -2765
    -2766
    -2767
    -2768
    -2769
    -2770
    -2771
    -2772
    -2773
    -2774
    -2775
    -2776
    -2777
    -2778
    -2779
    -2780
    -2781
    -2782
    -2783
    -2784
    -2785
    -2786
    -2787
    -2788
    -2789
    -2790
    -2791
    -2792
    -2793
    -2794
    -2795
    -2796
    -2797
    -2798
    -2799
    -2800
    -2801
    -2802
    -2803
    -2804
    -2805
    -2806
    -2807
    -2808
    -2809
    -2810
    -2811
    -2812
    -2813
    -2814
    -2815
    -2816
    -2817
    -2818
    -2819
    -2820
    -2821
    -2822
    -2823
    -2824
    -2825
    -2826
    -2827
    -2828
    -2829
    -2830
    -2831
    -2832
    -2833
    -2834
    -2835
    -2836
    -2837
    -2838
    -2839
    -2840
    -2841
    -2842
    -2843
    -2844
    -2845
    -2846
    -2847
    -2848
    -2849
    -2850
    -2851
    -2852
    -2853
    -2854
    -2855
    -2856
    -2857
    -2858
    -2859
    -2860
    -2861
    -2862
    -2863
    -2864
    -2865
    -2866
    -2867
    -2868
    -2869
    -2870
    -2871
    -2872
    -2873
    -2874
    -2875
    -2876
    -2877
    -2878
    -2879
    -2880
    -2881
    -2882
    -2883
    -2884
    -2885
    -2886
    -2887
    -2888
    -2889
    -2890
    -2891
    -2892
    -2893
    -2894
    -2895
    -2896
    -2897
    -2898
    -2899
    -2900
    -2901
    -2902
    -2903
    -2904
    -2905
    -2906
    -2907
    -2908
    -2909
    -2910
    -2911
    -2912
    -2913
    -2914
    -2915
    -2916
    -2917
    -2918
    -2919
    -2920
    -2921
    -2922
    -2923
    -2924
    -2925
    -2926
    -2927
    -2928
    -2929
    -2930
    -2931
    -2932
    -2933
    -2934
    -2935
    -2936
    -2937
    -2938
    -2939
    -2940
    -2941
    -2942
    -2943
    -2944
    -2945
    -2946
    -2947
    -2948
    -2949
    -2950
    -2951
    -2952
    -2953
    -2954
    -2955
    -2956
    -2957
    -2958
    -2959
    -2960
    -2961
    -2962
    -2963
    -2964
    -2965
    -2966
    -2967
    -2968
    -2969
    -2970
    -2971
    -2972
    -2973
    -2974
    -2975
    -2976
    -2977
    -2978
    -2979
    -2980
    -2981
    -2982
    -2983
    -2984
    -2985
    -2986
    -2987
    -2988
    -2989
    -2990
    -2991
    -2992
    -2993
    -2994
    -2995
    -2996
    -2997
    -2998
    -2999
    -3000
    -3001
    -3002
    -3003
    -3004
    -3005
    -3006
    -3007
    -3008
    -3009
    -3010
    -3011
    -3012
    -3013
    -3014
    -3015
    -3016
    -3017
    -3018
    -3019
    -3020
    -3021
    -3022
    -3023
    -3024
    -3025
    -3026
    -3027
    -3028
    -3029
    -3030
    -3031
    -3032
    -3033
    -3034
    -3035
    -3036
    -3037
    -3038
    -3039
    -3040
    -3041
    -3042
    -3043
    -3044
    -3045
    -3046
    -3047
    -3048
    -3049
    -3050
    -3051
    -3052
    -3053
    -3054
    -3055
    -3056
    -3057
    -3058
    -3059
    -3060
    -3061
    -3062
    -3063
    -3064
    -3065
    -3066
    -3067
    -3068
    -3069
    -3070
    -3071
    -3072
    -3073
    -3074
    -3075
    -3076
    -3077
    -3078
    -3079
    -3080
    -3081
    -3082
    -3083
    -3084
    -3085
    -3086
    -3087
    -3088
    -3089
    -3090
    -3091
    -3092
    -3093
    -3094
    -3095
    -3096
    -3097
    -3098
    -3099
    -3100
    -3101
    -3102
    -3103
    -3104
    -3105
    -3106
    -3107
    -3108
    -3109
    -3110
    -3111
    -3112
    -3113
    -3114
    -3115
    -3116
    -3117
    -3118
    -3119
    -3120
    -3121
    -3122
    -3123
    -3124
    -3125
    -3126
    -3127
    -3128
    -3129
    -3130
    -3131
    -3132
    -3133
    -3134
    -3135
    -3136
    -3137
    -3138
    -3139
    -3140
    -3141
    -3142
    -3143
    -3144
    -3145
    -3146
    -3147
    -3148
    -3149
    -3150
    -3151
    -3152
    -3153
    -3154
    -3155
    -3156
    -3157
    -3158
    -3159
    -3160
    -3161
    -3162
    -3163
    -3164
    -3165
    -3166
    -3167
    -3168
    -3169
    -3170
    -3171
    -3172
    -3173
    -3174
    -3175
    -3176
    -3177
    -3178
    -3179
    -3180
    -3181
    -3182
    -3183
    -3184
    -3185
    -3186
    -3187
    -3188
    -3189
    -3190
    -3191
    -3192
    -3193
    -3194
    -3195
    -3196
    -3197
    -3198
    -3199
    -3200
    -3201
    -3202
    -3203
    -3204
    -3205
    -3206
    -3207
    -3208
    -3209
    -3210
    -3211
    -3212
    -3213
    -3214
    -3215
    -3216
    -3217
    -3218
    -3219
    -3220
    -3221
    -3222
    -3223
    -3224
    -3225
    -3226
    -3227
    -3228
    -3229
    -3230
    -3231
    -3232
    -3233
    -3234
    -3235
    -3236
    -3237
    -3238
    -3239
    -3240
    -3241
    -3242
    -3243
    -3244
    -3245
    -3246
    -3247
    -3248
    -3249
    -3250
    -3251
    -3252
    -3253
    -3254
    -3255
    -3256
    -3257
    -3258
    -3259
    -3260
    -3261
    -3262
    -3263
    -3264
    -3265
    -3266
    -3267
    -3268
    -3269
    -3270
    -3271
    -3272
    -3273
    -3274
    -3275
    -3276
    -3277
    -3278
    -3279
    -3280
    -3281
    -3282
    -3283
    -3284
    -3285
    -3286
    -3287
    -3288
    -3289
    -3290
    -3291
    -3292
    -3293
    -3294
    -3295
    -3296
    -3297
    -3298
    -3299
    -3300
    -3301
    -3302
    -3303
    -3304
    -3305
    -3306
    -3307
    -3308
    -3309
    -3310
    -3311
    -3312
    -3313
    -3314
    -3315
    -3316
    -3317
    -3318
    -3319
    -3320
    -3321
    -3322
    -3323
    -3324
    -3325
    -3326
    -3327
    -3328
    -3329
    -3330
    -3331
    -3332
    -3333
    -3334
    -3335
    -3336
    -3337
    -3338
    -3339
    -3340
    -3341
    -3342
    -3343
    -3344
    -3345
    -3346
    -3347
    -3348
    -3349
    -3350
    -3351
    -3352
    -3353
    -3354
    -3355
    -3356
    -3357
    -3358
    -3359
    -3360
    -3361
    -3362
    -3363
    -3364
    -3365
    -3366
    -3367
    -3368
    -3369
    -3370
    -3371
    -3372
    -3373
    -3374
    -3375
    -3376
    -3377
    -3378
    -3379
    -3380
    -3381
    -3382
    -3383
    -3384
    -3385
    -3386
    -3387
    -3388
    -3389
    -3390
    -3391
    -3392
    -3393
    -3394
    -3395
    -3396
    -3397
    -3398
    -3399
    -3400
    -3401
    -3402
    -3403
    -3404
    -3405
    -3406
    -3407
    -3408
    -3409
    -3410
    -3411
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Wallet
    -//!
    -//! This module defines the [`Wallet`] structure.
    -
    -use std::cell::RefCell;
    -use std::collections::HashMap;
    -use std::collections::{BTreeMap, HashSet};
    -use std::ops::{Deref, DerefMut};
    -use std::sync::Arc;
    -
    -use bitcoin::secp256k1::Secp256k1;
    -
    -use bitcoin::consensus::encode::serialize;
    -use bitcoin::util::base58;
    -use bitcoin::util::bip32::ChildNumber;
    -use bitcoin::util::psbt::raw::Key as PSBTKey;
    -use bitcoin::util::psbt::PartiallySignedTransaction as PSBT;
    -use bitcoin::{Address, Network, OutPoint, Script, Transaction, TxOut, Txid};
    -
    -use miniscript::psbt::PsbtInputSatisfier;
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -pub mod address_validator;
    -pub mod coin_selection;
    -pub mod export;
    -pub mod signer;
    -pub mod time;
    -pub mod tx_builder;
    -pub(crate) mod utils;
    -
    -pub use utils::IsDust;
    -
    -use address_validator::AddressValidator;
    -use signer::{Signer, SignerId, SignerOrdering, SignersContainer};
    -use tx_builder::{BumpFee, CreateTx, FeePolicy, TxBuilder, TxBuilderContext};
    -use utils::{check_nlocktime, check_nsequence_rbf, descriptor_to_pk_ctx, After, Older, SecpCtx};
    -
    -use crate::blockchain::{Blockchain, BlockchainMarker, OfflineBlockchain, Progress};
    -use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
    -use crate::descriptor::{
    -    get_checksum, DescriptorMeta, DescriptorScripts, ExtendedDescriptor, ExtractPolicy, Policy,
    -    ToWalletDescriptor, XKeyUtils,
    -};
    -use crate::error::Error;
    -use crate::psbt::PSBTUtils;
    -use crate::types::*;
    -
    -const CACHE_ADDR_BATCH_SIZE: u32 = 100;
    -
    -/// Type alias for a [`Wallet`] that uses [`OfflineBlockchain`]
    -pub type OfflineWallet<D> = Wallet<OfflineBlockchain, D>;
    -
    -/// A Bitcoin wallet
    -///
    -/// A wallet takes descriptors, a [`database`](trait@crate::database::Database) and a
    -/// [`blockchain`](trait@crate::blockchain::Blockchain) and implements the basic functions that a Bitcoin wallets
    -/// needs to operate, like [generating addresses](Wallet::get_new_address), [returning the balance](Wallet::get_balance),
    -/// [creating transactions](Wallet::create_tx), etc.
    -///
    -/// A wallet can be either "online" if the [`blockchain`](crate::blockchain) type provided
    -/// implements [`Blockchain`], or "offline" [`OfflineBlockchain`] is used. Offline wallets only expose
    -/// methods that don't need any interaction with the blockchain to work.
    -pub struct Wallet<B, D> {
    -    descriptor: ExtendedDescriptor,
    -    change_descriptor: Option<ExtendedDescriptor>,
    -
    -    signers: Arc<SignersContainer>,
    -    change_signers: Arc<SignersContainer>,
    -
    -    address_validators: Vec<Arc<dyn AddressValidator>>,
    -
    -    network: Network,
    -
    -    current_height: Option<u32>,
    -
    -    client: Option<B>,
    -    database: RefCell<D>,
    -
    -    secp: SecpCtx,
    -}
    -
    -// offline actions, always available
    -impl<B, D> Wallet<B, D>
    -where
    -    B: BlockchainMarker,
    -    D: BatchDatabase,
    -{
    -    /// Create a new "offline" wallet
    -    pub fn new_offline<E: ToWalletDescriptor>(
    -        descriptor: E,
    -        change_descriptor: Option<E>,
    -        network: Network,
    -        mut database: D,
    -    ) -> Result<Self, Error> {
    -        let (descriptor, keymap) = descriptor.to_wallet_descriptor(network)?;
    -        database.check_descriptor_checksum(
    -            KeychainKind::External,
    -            get_checksum(&descriptor.to_string())?.as_bytes(),
    -        )?;
    -        let signers = Arc::new(SignersContainer::from(keymap));
    -        let (change_descriptor, change_signers) = match change_descriptor {
    -            Some(desc) => {
    -                let (change_descriptor, change_keymap) = desc.to_wallet_descriptor(network)?;
    -                database.check_descriptor_checksum(
    -                    KeychainKind::Internal,
    -                    get_checksum(&change_descriptor.to_string())?.as_bytes(),
    -                )?;
    -
    -                let change_signers = Arc::new(SignersContainer::from(change_keymap));
    -                // if !parsed.same_structure(descriptor.as_ref()) {
    -                //     return Err(Error::DifferentDescriptorStructure);
    -                // }
    -
    -                (Some(change_descriptor), change_signers)
    -            }
    -            None => (None, Arc::new(SignersContainer::new())),
    -        };
    -
    -        Ok(Wallet {
    -            descriptor,
    -            change_descriptor,
    -            signers,
    -            change_signers,
    -            address_validators: Vec::new(),
    -
    -            network,
    -
    -            current_height: None,
    -
    -            client: None,
    -            database: RefCell::new(database),
    -
    -            secp: Secp256k1::new(),
    -        })
    -    }
    -
    -    /// Return a newly generated address using the external descriptor
    -    pub fn get_new_address(&self) -> Result<Address, Error> {
    -        let index = self.fetch_and_increment_index(KeychainKind::External)?;
    -        let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
    -
    -        self.descriptor
    -            .derive(ChildNumber::from_normal_idx(index)?)
    -            .address(self.network, deriv_ctx)
    -            .ok_or(Error::ScriptDoesntHaveAddressForm)
    -    }
    -
    -    /// Return whether or not a `script` is part of this wallet (either internal or external)
    -    pub fn is_mine(&self, script: &Script) -> Result<bool, Error> {
    -        self.database.borrow().is_mine(script)
    -    }
    -
    -    /// Return the list of unspent outputs of this wallet
    -    ///
    -    /// Note that this methods only operate on the internal database, which first needs to be
    -    /// [`Wallet::sync`] manually.
    -    pub fn list_unspent(&self) -> Result<Vec<UTXO>, Error> {
    -        self.database.borrow().iter_utxos()
    -    }
    -
    -    /// Return the list of transactions made and received by the wallet
    -    ///
    -    /// Optionally fill the [`TransactionDetails::transaction`] field with the raw transaction if
    -    /// `include_raw` is `true`.
    -    ///
    -    /// Note that this methods only operate on the internal database, which first needs to be
    -    /// [`Wallet::sync`] manually.
    -    pub fn list_transactions(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        self.database.borrow().iter_txs(include_raw)
    -    }
    -
    -    /// Return the balance, meaning the sum of this wallet's unspent outputs' values
    -    ///
    -    /// Note that this methods only operate on the internal database, which first needs to be
    -    /// [`Wallet::sync`] manually.
    -    pub fn get_balance(&self) -> Result<u64, Error> {
    -        Ok(self
    -            .list_unspent()?
    -            .iter()
    -            .fold(0, |sum, i| sum + i.txout.value))
    -    }
    -
    -    /// Add an external signer
    -    ///
    -    /// See [the `signer` module](signer) for an example.
    -    pub fn add_signer(
    -        &mut self,
    -        keychain: KeychainKind,
    -        id: SignerId,
    -        ordering: SignerOrdering,
    -        signer: Arc<dyn Signer>,
    -    ) {
    -        let signers = match keychain {
    -            KeychainKind::External => Arc::make_mut(&mut self.signers),
    -            KeychainKind::Internal => Arc::make_mut(&mut self.change_signers),
    -        };
    -
    -        signers.add_external(id, ordering, signer);
    -    }
    -
    -    /// Add an address validator
    -    ///
    -    /// See [the `address_validator` module](address_validator) for an example.
    -    pub fn add_address_validator(&mut self, validator: Arc<dyn AddressValidator>) {
    -        self.address_validators.push(validator);
    -    }
    -
    -    /// Create a new transaction following the options specified in the `builder`
    -    ///
    -    /// ## Example
    -    ///
    -    /// ```no_run
    -    /// # use std::str::FromStr;
    -    /// # use bitcoin::*;
    -    /// # use bdk::*;
    -    /// # use bdk::database::*;
    -    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -    /// let (psbt, details) = wallet.create_tx(
    -    ///     TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
    -    /// )?;
    -    /// // sign and broadcast ...
    -    /// # Ok::<(), bdk::Error>(())
    -    /// ```
    -    pub fn create_tx<Cs: coin_selection::CoinSelectionAlgorithm<D>>(
    -        &self,
    -        builder: TxBuilder<D, Cs, CreateTx>,
    -    ) -> Result<(PSBT, TransactionDetails), Error> {
    -        let external_policy = self
    -            .descriptor
    -            .extract_policy(&self.signers, &self.secp)?
    -            .unwrap();
    -        let internal_policy = self
    -            .change_descriptor
    -            .as_ref()
    -            .map(|desc| {
    -                Ok::<_, Error>(
    -                    desc.extract_policy(&self.change_signers, &self.secp)?
    -                        .unwrap(),
    -                )
    -            })
    -            .transpose()?;
    -
    -        // The policy allows spending external outputs, but it requires a policy path that hasn't been
    -        // provided
    -        if builder.change_policy != tx_builder::ChangeSpendPolicy::OnlyChange
    -            && external_policy.requires_path()
    -            && builder.external_policy_path.is_none()
    -        {
    -            return Err(Error::SpendingPolicyRequired(KeychainKind::External));
    -        };
    -        // Same for the internal_policy path, if present
    -        if let Some(internal_policy) = &internal_policy {
    -            if builder.change_policy != tx_builder::ChangeSpendPolicy::ChangeForbidden
    -                && internal_policy.requires_path()
    -                && builder.internal_policy_path.is_none()
    -            {
    -                return Err(Error::SpendingPolicyRequired(KeychainKind::Internal));
    -            };
    -        }
    -
    -        let external_requirements = external_policy.get_condition(
    -            builder
    -                .external_policy_path
    -                .as_ref()
    -                .unwrap_or(&BTreeMap::new()),
    -        )?;
    -        let internal_requirements = internal_policy
    -            .map(|policy| {
    -                Ok::<_, Error>(
    -                    policy.get_condition(
    -                        builder
    -                            .internal_policy_path
    -                            .as_ref()
    -                            .unwrap_or(&BTreeMap::new()),
    -                    )?,
    -                )
    -            })
    -            .transpose()?;
    -
    -        let requirements = external_requirements
    -            .clone()
    -            .merge(&internal_requirements.unwrap_or_default())?;
    -        debug!("Policy requirements: {:?}", requirements);
    -
    -        let version = match builder.version {
    -            Some(tx_builder::Version(0)) => {
    -                return Err(Error::Generic("Invalid version `0`".into()))
    -            }
    -            Some(tx_builder::Version(1)) if requirements.csv.is_some() => {
    -                return Err(Error::Generic(
    -                    "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
    -                        .into(),
    -                ))
    -            }
    -            Some(tx_builder::Version(x)) => x,
    -            None if requirements.csv.is_some() => 2,
    -            _ => 1,
    -        };
    -
    -        let lock_time = match builder.locktime {
    -            // No nLockTime, default to 0
    -            None => requirements.timelock.unwrap_or(0),
    -            // 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 check_nlocktime(x, requirements.timelock.unwrap()) => x,
    -            // Invalid nLockTime required
    -            Some(x) => return Err(Error::Generic(format!("TxBuilder requested timelock of `{}`, but at least `{}` is required to spend from this script", x, requirements.timelock.unwrap())))
    -        };
    -
    -        let n_sequence = match (builder.rbf, requirements.csv) {
    -            // No RBF or CSV but there's an nLockTime, so the nSequence cannot be final
    -            (None, None) if lock_time != 0 => 0xFFFFFFFE,
    -            // No RBF, CSV or nLockTime, make the transaction final
    -            (None, None) => 0xFFFFFFFF,
    -
    -            // 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 >= 0xFFFFFFFE => {
    -                return Err(Error::Generic(
    -                    "Cannot enable RBF with a nSequence >= 0xFFFFFFFE".into(),
    -                ))
    -            }
    -            // 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(Error::Generic(format!(
    -                    "Cannot enable RBF with nSequence `{}` given a required OP_CSV of `{}`",
    -                    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 mut tx = Transaction {
    -            version,
    -            lock_time,
    -            input: vec![],
    -            output: vec![],
    -        };
    -
    -        let (fee_rate, mut fee_amount) = match builder
    -            .fee_policy
    -            .as_ref()
    -            .unwrap_or(&FeePolicy::FeeRate(FeeRate::default()))
    -        {
    -            FeePolicy::FeeAmount(amount) => (FeeRate::from_sat_per_vb(0.0), *amount as f32),
    -            FeePolicy::FeeRate(rate) => (*rate, 0.0),
    -        };
    -
    -        // try not to move from `builder` because we still need to use it later.
    -        let recipients = match &builder.single_recipient {
    -            Some(recipient) => vec![(recipient, 0)],
    -            None => builder.recipients.iter().map(|(r, v)| (r, *v)).collect(),
    -        };
    -        if builder.single_recipient.is_some()
    -            && !builder.manually_selected_only
    -            && !builder.drain_wallet
    -        {
    -            return Err(Error::SingleRecipientNoInputs);
    -        }
    -        if recipients.is_empty() {
    -            return Err(Error::NoRecipients);
    -        }
    -
    -        if builder.manually_selected_only && builder.utxos.is_empty() {
    -            return Err(Error::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 calc_fee_bytes = |wu| (wu as f32) * fee_rate.as_sat_vb() / 4.0;
    -        fee_amount += calc_fee_bytes(tx.get_weight());
    -
    -        for (index, (script_pubkey, satoshi)) in recipients.into_iter().enumerate() {
    -            let value = match builder.single_recipient {
    -                Some(_) => 0,
    -                None if satoshi.is_dust() => return Err(Error::OutputBelowDustLimit(index)),
    -                None => satoshi,
    -            };
    -
    -            if self.is_mine(script_pubkey)? {
    -                received += value;
    -            }
    -
    -            let new_out = TxOut {
    -                script_pubkey: script_pubkey.clone(),
    -                value,
    -            };
    -            fee_amount += calc_fee_bytes(serialize(&new_out).len() * 4);
    -
    -            tx.output.push(new_out);
    -
    -            outgoing += value;
    -        }
    -
    -        if builder.change_policy != tx_builder::ChangeSpendPolicy::ChangeAllowed
    -            && self.change_descriptor.is_none()
    -        {
    -            return Err(Error::Generic(
    -                "The `change_policy` can be set only if the wallet has a change_descriptor".into(),
    -            ));
    -        }
    -
    -        let (required_utxos, optional_utxos) = self.preselect_utxos(
    -            builder.change_policy,
    -            &builder.unspendable,
    -            &builder.utxos,
    -            builder.drain_wallet,
    -            builder.manually_selected_only,
    -            false, // we don't mind using unconfirmed outputs here, hopefully coin selection will sort this out?
    -        )?;
    -
    -        let coin_selection::CoinSelectionResult {
    -            selected,
    -            selected_amount,
    -            mut fee_amount,
    -        } = builder.coin_selection.coin_select(
    -            self.database.borrow().deref(),
    -            required_utxos,
    -            optional_utxos,
    -            fee_rate,
    -            outgoing,
    -            fee_amount,
    -        )?;
    -        tx.input = selected
    -            .iter()
    -            .map(|u| bitcoin::TxIn {
    -                previous_output: u.outpoint,
    -                script_sig: Script::default(),
    -                sequence: n_sequence,
    -                witness: vec![],
    -            })
    -            .collect();
    -
    -        // prepare the change output
    -        let change_output = match builder.single_recipient {
    -            Some(_) => None,
    -            None => {
    -                let change_script = self.get_change_address()?;
    -                let change_output = TxOut {
    -                    script_pubkey: change_script,
    -                    value: 0,
    -                };
    -
    -                // take the change into account for fees
    -                fee_amount += calc_fee_bytes(serialize(&change_output).len() * 4);
    -                Some(change_output)
    -            }
    -        };
    -
    -        let mut fee_amount = fee_amount.ceil() as u64;
    -        let change_val = (selected_amount - outgoing).saturating_sub(fee_amount);
    -
    -        match change_output {
    -            None if change_val.is_dust() => {
    -                // single recipient, but the only output would be below dust limit
    -                return Err(Error::InsufficientFunds); // TODO: or OutputBelowDustLimit?
    -            }
    -            Some(_) if change_val.is_dust() => {
    -                // skip the change output because it's dust, this adds up to the fees
    -                fee_amount += selected_amount - outgoing;
    -            }
    -            Some(mut change_output) => {
    -                change_output.value = change_val;
    -                received += change_val;
    -
    -                tx.output.push(change_output);
    -            }
    -            None => {
    -                // there's only one output, send everything to it
    -                tx.output[0].value = change_val;
    -
    -                // the single recipient is our address
    -                if self.is_mine(&tx.output[0].script_pubkey)? {
    -                    received = change_val;
    -                }
    -            }
    -        }
    -
    -        // sort input/outputs according to the chosen algorithm
    -        builder.ordering.sort_tx(&mut tx);
    -
    -        let txid = tx.txid();
    -        let psbt = self.complete_transaction(tx, selected, builder)?;
    -
    -        let transaction_details = TransactionDetails {
    -            transaction: None,
    -            txid,
    -            timestamp: time::get_timestamp(),
    -            received,
    -            sent: selected_amount,
    -            fees: fee_amount,
    -            height: None,
    -        };
    -
    -        Ok((psbt, transaction_details))
    -    }
    -
    -    /// Bump the fee of a transaction following the options specified in the `builder`
    -    ///
    -    /// Return an error if the transaction is already confirmed or doesn't explicitly signal RBF.
    -    ///
    -    /// **NOTE**: if the original transaction was made with [`TxBuilder::set_single_recipient`],
    -    /// the [`TxBuilder::maintain_single_recipient`] flag should be enabled to correctly reduce the
    -    /// only output's value in order to increase the fees.
    -    ///
    -    /// If the `builder` specifies some `utxos` that must be spent, they will be added to the
    -    /// transaction regardless of whether they are necessary or not to cover additional fees.
    -    ///
    -    /// ## Example
    -    ///
    -    /// ```no_run
    -    /// # use std::str::FromStr;
    -    /// # use bitcoin::*;
    -    /// # use bdk::*;
    -    /// # use bdk::database::*;
    -    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -    /// let txid = Txid::from_str("faff0a466b70f5d5f92bd757a92c1371d4838bdd5bc53a06764e2488e51ce8f8").unwrap();
    -    /// let (psbt, details) = wallet.bump_fee(
    -    ///     &txid,
    -    ///     TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(5.0)),
    -    /// )?;
    -    /// // sign and broadcast ...
    -    /// # Ok::<(), bdk::Error>(())
    -    /// ```
    -    // TODO: support for merging multiple transactions while bumping the fees
    -    // TODO: option to force addition of an extra output? seems bad for privacy to update the
    -    // change
    -    pub fn bump_fee<Cs: coin_selection::CoinSelectionAlgorithm<D>>(
    -        &self,
    -        txid: &Txid,
    -        builder: TxBuilder<D, Cs, BumpFee>,
    -    ) -> Result<(PSBT, TransactionDetails), Error> {
    -        let mut details = match self.database.borrow().get_tx(&txid, true)? {
    -            None => return Err(Error::TransactionNotFound),
    -            Some(tx) if tx.transaction.is_none() => return Err(Error::TransactionNotFound),
    -            Some(tx) if tx.height.is_some() => return Err(Error::TransactionConfirmed),
    -            Some(tx) => tx,
    -        };
    -        let mut tx = details.transaction.take().unwrap();
    -        if !tx.input.iter().any(|txin| txin.sequence <= 0xFFFFFFFD) {
    -            return Err(Error::IrreplaceableTransaction);
    -        }
    -
    -        // the new tx must "pay for its bandwidth"
    -        let vbytes = tx.get_weight() as f32 / 4.0;
    -        let required_feerate = FeeRate::from_sat_per_vb(details.fees as f32 / vbytes + 1.0);
    -
    -        // find the index of the output that we can update. either the change or the only one if
    -        // it's `single_recipient`
    -        let updatable_output = match builder.single_recipient {
    -            Some(_) if tx.output.len() != 1 => return Err(Error::SingleRecipientMultipleOutputs),
    -            Some(_) => Some(0),
    -            None => {
    -                let mut change_output = None;
    -                for (index, txout) in tx.output.iter().enumerate() {
    -                    // look for an output that we know and that has the right KeychainKind. We use
    -                    // `get_descriptor_for` to find what's the KeychainKind for `Internal`
    -                    // addresses really is, because if there's no change_descriptor it's actually equal
    -                    // to "External"
    -                    let (_, change_type) = self.get_descriptor_for_keychain(KeychainKind::Internal);
    -                    match self
    -                        .database
    -                        .borrow()
    -                        .get_path_from_script_pubkey(&txout.script_pubkey)?
    -                    {
    -                        Some((keychain, _)) if keychain == change_type => {
    -                            change_output = Some(index);
    -                            break;
    -                        }
    -                        _ => {}
    -                    }
    -                }
    -
    -                change_output
    -            }
    -        };
    -        let updatable_output = match updatable_output {
    -            Some(updatable_output) => updatable_output,
    -            None => {
    -                // we need a change output, add one here and take into account the extra fees for it
    -                let change_script = self.get_change_address()?;
    -                let change_txout = TxOut {
    -                    script_pubkey: change_script,
    -                    value: 0,
    -                };
    -                tx.output.push(change_txout);
    -
    -                tx.output.len() - 1
    -            }
    -        };
    -
    -        // initially always remove the output we can change
    -        let mut removed_updatable_output = tx.output.remove(updatable_output);
    -        if self.is_mine(&removed_updatable_output.script_pubkey)? {
    -            details.received -= removed_updatable_output.value;
    -        }
    -
    -        let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
    -        let original_sequence = tx.input[0].sequence;
    -
    -        // remove the inputs from the tx and process them
    -        let original_txin = tx.input.drain(..).collect::<Vec<_>>();
    -        let mut original_utxos = original_txin
    -            .iter()
    -            .map(|txin| -> Result<(UTXO, usize), Error> {
    -                let txout = self
    -                    .database
    -                    .borrow()
    -                    .get_previous_output(&txin.previous_output)?
    -                    .ok_or(Error::UnknownUTXO)?;
    -
    -                let (weight, keychain) = match self
    -                    .database
    -                    .borrow()
    -                    .get_path_from_script_pubkey(&txout.script_pubkey)?
    -                {
    -                    Some((keychain, _)) => (
    -                        self.get_descriptor_for_keychain(keychain)
    -                            .0
    -                            .max_satisfaction_weight(deriv_ctx)
    -                            .unwrap(),
    -                        keychain,
    -                    ),
    -                    None => {
    -                        // estimate the weight based on the scriptsig/witness size present in the
    -                        // original transaction
    -                        let weight =
    -                            serialize(&txin.script_sig).len() * 4 + serialize(&txin.witness).len();
    -                        (weight, KeychainKind::External)
    -                    }
    -                };
    -
    -                let utxo = UTXO {
    -                    outpoint: txin.previous_output,
    -                    txout,
    -                    keychain,
    -                };
    -
    -                Ok((utxo, weight))
    -            })
    -            .collect::<Result<Vec<_>, _>>()?;
    -
    -        if builder.manually_selected_only && builder.utxos.is_empty() {
    -            return Err(Error::NoUtxosSelected);
    -        }
    -
    -        let builder_extra_utxos = builder
    -            .utxos
    -            .iter()
    -            .filter(|utxo| {
    -                !original_txin
    -                    .iter()
    -                    .any(|txin| &&txin.previous_output == utxo)
    -            })
    -            .cloned()
    -            .collect::<Vec<_>>();
    -
    -        let (mut required_utxos, optional_utxos) = self.preselect_utxos(
    -            builder.change_policy,
    -            &builder.unspendable,
    -            &builder_extra_utxos[..],
    -            builder.drain_wallet,
    -            builder.manually_selected_only,
    -            true, // we only want confirmed transactions for RBF
    -        )?;
    -
    -        required_utxos.append(&mut original_utxos);
    -
    -        let amount_needed = tx.output.iter().fold(0, |acc, out| acc + out.value);
    -        let (new_feerate, initial_fee) = match builder
    -            .fee_policy
    -            .as_ref()
    -            .unwrap_or(&FeePolicy::FeeRate(FeeRate::default()))
    -        {
    -            FeePolicy::FeeAmount(amount) => {
    -                if *amount < details.fees {
    -                    return Err(Error::FeeTooLow {
    -                        required: details.fees,
    -                    });
    -                }
    -                (FeeRate::from_sat_per_vb(0.0), *amount as f32)
    -            }
    -            FeePolicy::FeeRate(rate) => {
    -                if *rate < required_feerate {
    -                    return Err(Error::FeeRateTooLow {
    -                        required: required_feerate,
    -                    });
    -                }
    -                (*rate, tx.get_weight() as f32 / 4.0 * rate.as_sat_vb())
    -            }
    -        };
    -
    -        let coin_selection::CoinSelectionResult {
    -            selected,
    -            selected_amount,
    -            fee_amount,
    -        } = builder.coin_selection.coin_select(
    -            self.database.borrow().deref(),
    -            required_utxos,
    -            optional_utxos,
    -            new_feerate,
    -            amount_needed,
    -            initial_fee,
    -        )?;
    -
    -        tx.input = selected
    -            .iter()
    -            .map(|u| bitcoin::TxIn {
    -                previous_output: u.outpoint,
    -                script_sig: Script::default(),
    -                // TODO: use builder.n_sequence??
    -                sequence: original_sequence,
    -                witness: vec![],
    -            })
    -            .collect();
    -
    -        details.sent = selected_amount;
    -
    -        let mut fee_amount = fee_amount.ceil() as u64;
    -        let removed_output_fee_cost = (serialize(&removed_updatable_output).len() as f32
    -            * new_feerate.as_sat_vb())
    -        .ceil() as u64;
    -
    -        let change_val = selected_amount - amount_needed - fee_amount;
    -        let change_val_after_add = change_val.saturating_sub(removed_output_fee_cost);
    -        match builder.single_recipient {
    -            None if change_val_after_add.is_dust() => {
    -                // skip the change output because it's dust, this adds up to the fees
    -                fee_amount += change_val;
    -            }
    -            Some(_) if change_val_after_add.is_dust() => {
    -                // single_recipient but the only output would be below dust limit
    -                return Err(Error::InsufficientFunds); // TODO: or OutputBelowDustLimit?
    -            }
    -            None => {
    -                removed_updatable_output.value = change_val_after_add;
    -                fee_amount += removed_output_fee_cost;
    -                details.received += change_val_after_add;
    -
    -                tx.output.push(removed_updatable_output);
    -            }
    -            Some(_) => {
    -                removed_updatable_output.value = change_val_after_add;
    -                fee_amount += removed_output_fee_cost;
    -
    -                // single recipient and it's our address
    -                if self.is_mine(&removed_updatable_output.script_pubkey)? {
    -                    details.received = change_val_after_add;
    -                }
    -
    -                tx.output.push(removed_updatable_output);
    -            }
    -        }
    -
    -        // sort input/outputs according to the chosen algorithm
    -        builder.ordering.sort_tx(&mut tx);
    -
    -        // TODO: check that we are not replacing more than 100 txs from mempool
    -
    -        details.txid = tx.txid();
    -        details.fees = fee_amount;
    -        details.timestamp = time::get_timestamp();
    -
    -        let psbt = self.complete_transaction(tx, selected, builder)?;
    -
    -        Ok((psbt, details))
    -    }
    -
    -    /// Sign a transaction with all the wallet's signers, in the order specified by every signer's
    -    /// [`SignerOrdering`]
    -    ///
    -    /// ## Example
    -    ///
    -    /// ```no_run
    -    /// # use std::str::FromStr;
    -    /// # use bitcoin::*;
    -    /// # use bdk::*;
    -    /// # use bdk::database::*;
    -    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -    /// # let wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -    /// # let (psbt, _) = wallet.create_tx(TxBuilder::new())?;
    -    /// let (signed_psbt, finalized) = wallet.sign(psbt, None)?;
    -    /// # Ok::<(), bdk::Error>(())
    -    pub fn sign(&self, mut psbt: PSBT, assume_height: Option<u32>) -> Result<(PSBT, bool), Error> {
    -        // this helps us doing our job later
    -        self.add_input_hd_keypaths(&mut psbt)?;
    -
    -        for signer in self
    -            .signers
    -            .signers()
    -            .iter()
    -            .chain(self.change_signers.signers().iter())
    -        {
    -            if signer.sign_whole_tx() {
    -                signer.sign(&mut psbt, None, &self.secp)?;
    -            } else {
    -                for index in 0..psbt.inputs.len() {
    -                    signer.sign(&mut psbt, Some(index), &self.secp)?;
    -                }
    -            }
    -        }
    -
    -        // attempt to finalize
    -        self.finalize_psbt(psbt, assume_height)
    -    }
    -
    -    /// Return the spending policies for the wallet's descriptor
    -    pub fn policies(&self, keychain: KeychainKind) -> Result<Option<Policy>, Error> {
    -        match (keychain, self.change_descriptor.as_ref()) {
    -            (KeychainKind::External, _) => {
    -                Ok(self.descriptor.extract_policy(&self.signers, &self.secp)?)
    -            }
    -            (KeychainKind::Internal, None) => Ok(None),
    -            (KeychainKind::Internal, Some(desc)) => {
    -                Ok(desc.extract_policy(&self.change_signers, &self.secp)?)
    -            }
    -        }
    -    }
    -
    -    /// 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,
    -    ) -> Result<Option<ExtendedDescriptor>, Error> {
    -        match (keychain, self.change_descriptor.as_ref()) {
    -            (KeychainKind::External, _) => Ok(Some(self.descriptor.clone())),
    -            (KeychainKind::Internal, None) => Ok(None),
    -            (KeychainKind::Internal, Some(desc)) => Ok(Some(desc.clone())),
    -        }
    -    }
    -
    -    /// Try to finalize a PSBT
    -    pub fn finalize_psbt(
    -        &self,
    -        mut psbt: PSBT,
    -        assume_height: Option<u32>,
    -    ) -> Result<(PSBT, bool), Error> {
    -        let tx = &psbt.global.unsigned_tx;
    -        let mut finished = true;
    -
    -        for (n, input) in tx.input.iter().enumerate() {
    -            let psbt_input = &psbt.inputs[n];
    -            if psbt_input.final_script_sig.is_some() || psbt_input.final_script_witness.is_some() {
    -                continue;
    -            }
    -            // if the height is None in the database it means it's still unconfirmed, so consider
    -            // that as a very high value
    -            let create_height = self
    -                .database
    -                .borrow()
    -                .get_tx(&input.previous_output.txid, false)?
    -                .map(|tx| tx.height.unwrap_or(std::u32::MAX));
    -            let current_height = assume_height.or(self.current_height);
    -
    -            debug!(
    -                "Input #{} - {}, using `create_height` = {:?}, `current_height` = {:?}",
    -                n, input.previous_output, create_height, current_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 `hd_keypaths`,
    -            //   `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)
    -                .map(|txout| self.get_descriptor_for_txout(&txout))
    -                .transpose()?
    -                .flatten()
    -                .or_else(|| {
    -                    self.descriptor.derive_from_psbt_input(
    -                        psbt_input,
    -                        psbt.get_utxo_for(n),
    -                        &self.secp,
    -                    )
    -                })
    -                .or_else(|| {
    -                    self.change_descriptor.as_ref().and_then(|desc| {
    -                        desc.derive_from_psbt_input(psbt_input, psbt.get_utxo_for(n), &self.secp)
    -                    })
    -                });
    -
    -            match desc {
    -                Some(desc) => {
    -                    let mut tmp_input = bitcoin::TxIn::default();
    -                    let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
    -                    match desc.satisfy(
    -                        &mut tmp_input,
    -                        (
    -                            PsbtInputSatisfier::new(&psbt, n),
    -                            After::new(current_height, false),
    -                            Older::new(current_height, create_height, false),
    -                        ),
    -                        deriv_ctx,
    -                    ) {
    -                        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);
    -                        }
    -                        Err(e) => {
    -                            debug!("satisfy error {:?} for input {}", e, n);
    -                            finished = false
    -                        }
    -                    }
    -                }
    -                None => finished = false,
    -            }
    -        }
    -
    -        Ok((psbt, finished))
    -    }
    -
    -    /// Return the secp256k1 context used for all signing operations
    -    pub fn secp_ctx(&self) -> &SecpCtx {
    -        &self.secp
    -    }
    -
    -    // Internals
    -
    -    fn get_descriptor_for_keychain(
    -        &self,
    -        keychain: KeychainKind,
    -    ) -> (&ExtendedDescriptor, KeychainKind) {
    -        match keychain {
    -            KeychainKind::Internal if self.change_descriptor.is_some() => (
    -                self.change_descriptor.as_ref().unwrap(),
    -                KeychainKind::Internal,
    -            ),
    -            _ => (&self.descriptor, KeychainKind::External),
    -        }
    -    }
    -
    -    fn get_descriptor_for_txout(&self, txout: &TxOut) -> Result<Option<ExtendedDescriptor>, Error> {
    -        Ok(self
    -            .database
    -            .borrow()
    -            .get_path_from_script_pubkey(&txout.script_pubkey)?
    -            .map(|(keychain, child)| (self.get_descriptor_for_keychain(keychain).0, child))
    -            .map(|(desc, child)| desc.derive(ChildNumber::from_normal_idx(child).unwrap())))
    -    }
    -
    -    fn get_change_address(&self) -> Result<Script, Error> {
    -        let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
    -
    -        let (desc, keychain) = self.get_descriptor_for_keychain(KeychainKind::Internal);
    -        let index = self.fetch_and_increment_index(keychain)?;
    -
    -        Ok(desc
    -            .derive(ChildNumber::from_normal_idx(index)?)
    -            .script_pubkey(deriv_ctx))
    -    }
    -
    -    fn fetch_and_increment_index(&self, keychain: KeychainKind) -> Result<u32, Error> {
    -        let (descriptor, keychain) = self.get_descriptor_for_keychain(keychain);
    -        let index = match descriptor.is_fixed() {
    -            true => 0,
    -            false => self.database.borrow_mut().increment_last_index(keychain)?,
    -        };
    -
    -        if self
    -            .database
    -            .borrow()
    -            .get_script_pubkey_from_path(keychain, index)?
    -            .is_none()
    -        {
    -            self.cache_addresses(keychain, index, CACHE_ADDR_BATCH_SIZE)?;
    -        }
    -
    -        let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
    -
    -        let hd_keypaths = descriptor.get_hd_keypaths(index, &self.secp)?;
    -        let script = descriptor
    -            .derive(ChildNumber::from_normal_idx(index)?)
    -            .script_pubkey(deriv_ctx);
    -        for validator in &self.address_validators {
    -            validator.validate(keychain, &hd_keypaths, &script)?;
    -        }
    -
    -        Ok(index)
    -    }
    -
    -    fn cache_addresses(
    -        &self,
    -        keychain: KeychainKind,
    -        from: u32,
    -        mut count: u32,
    -    ) -> Result<(), Error> {
    -        let (descriptor, keychain) = self.get_descriptor_for_keychain(keychain);
    -        if descriptor.is_fixed() {
    -            if from > 0 {
    -                return Ok(());
    -            }
    -
    -            count = 1;
    -        }
    -
    -        let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
    -
    -        let mut address_batch = self.database.borrow().begin_batch();
    -
    -        let start_time = time::Instant::new();
    -        for i in from..(from + count) {
    -            address_batch.set_script_pubkey(
    -                &descriptor
    -                    .derive(ChildNumber::from_normal_idx(i)?)
    -                    .script_pubkey(deriv_ctx),
    -                keychain,
    -                i,
    -            )?;
    -        }
    -
    -        info!(
    -            "Derivation of {} addresses from {} took {} ms",
    -            count,
    -            from,
    -            start_time.elapsed().as_millis()
    -        );
    -
    -        self.database.borrow_mut().commit_batch(address_batch)?;
    -
    -        Ok(())
    -    }
    -
    -    fn get_available_utxos(&self) -> Result<Vec<(UTXO, usize)>, Error> {
    -        let deriv_ctx = descriptor_to_pk_ctx(&self.secp);
    -        Ok(self
    -            .list_unspent()?
    -            .into_iter()
    -            .map(|utxo| {
    -                let keychain = utxo.keychain;
    -                (
    -                    utxo,
    -                    self.get_descriptor_for_keychain(keychain)
    -                        .0
    -                        .max_satisfaction_weight(deriv_ctx)
    -                        .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.
    -    #[allow(clippy::type_complexity)]
    -    fn preselect_utxos(
    -        &self,
    -        change_policy: tx_builder::ChangeSpendPolicy,
    -        unspendable: &HashSet<OutPoint>,
    -        manually_selected: &[OutPoint],
    -        must_use_all_available: bool,
    -        manual_only: bool,
    -        must_only_use_confirmed_tx: bool,
    -    ) -> Result<(Vec<(UTXO, usize)>, Vec<(UTXO, usize)>), Error> {
    -        //    must_spend <- manually selected utxos
    -        //    may_spend  <- all other available utxos
    -        let mut may_spend = self.get_available_utxos()?;
    -        let mut must_spend = {
    -            let must_spend_idx = manually_selected
    -                .iter()
    -                .map(|manually_selected| {
    -                    may_spend
    -                        .iter()
    -                        .position(|available| available.0.outpoint == *manually_selected)
    -                        .ok_or(Error::UnknownUTXO)
    -                })
    -                .collect::<Result<Vec<_>, _>>()?;
    -
    -            must_spend_idx
    -                .into_iter()
    -                .map(|i| may_spend.remove(i))
    -                .collect()
    -        };
    -
    -        // NOTE: we are intentionally ignoring `unspendable` here. i.e manual
    -        // selection overrides unspendable.
    -        if manual_only {
    -            return Ok((must_spend, vec![]));
    -        }
    -
    -        let satisfies_confirmed = match must_only_use_confirmed_tx {
    -            true => {
    -                let database = self.database.borrow_mut();
    -                may_spend
    -                    .iter()
    -                    .map(|u| {
    -                        database
    -                            .get_tx(&u.0.outpoint.txid, true)
    -                            .map(|tx| match tx {
    -                                None => false,
    -                                Some(tx) => tx.height.is_some(),
    -                            })
    -                    })
    -                    .collect::<Result<Vec<_>, _>>()?
    -            }
    -            false => vec![true; may_spend.len()],
    -        };
    -
    -        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
    -        });
    -
    -        if must_use_all_available {
    -            must_spend.append(&mut may_spend);
    -        }
    -
    -        Ok((must_spend, may_spend))
    -    }
    -
    -    fn complete_transaction<
    -        Cs: coin_selection::CoinSelectionAlgorithm<D>,
    -        Ctx: TxBuilderContext,
    -    >(
    -        &self,
    -        tx: Transaction,
    -        selected: Vec<UTXO>,
    -        builder: TxBuilder<D, Cs, Ctx>,
    -    ) -> Result<PSBT, Error> {
    -        use bitcoin::util::psbt::serialize::Serialize;
    -
    -        let mut psbt = PSBT::from_unsigned_tx(tx)?;
    -
    -        if builder.add_global_xpubs {
    -            let mut all_xpubs = self.descriptor.get_extended_keys()?;
    -            if let Some(change_descriptor) = &self.change_descriptor {
    -                all_xpubs.extend(change_descriptor.get_extended_keys()?);
    -            }
    -
    -            for xpub in all_xpubs {
    -                let serialized_xpub = base58::from_check(&xpub.xkey.to_string())
    -                    .expect("Internal serialization error");
    -                let key = PSBTKey {
    -                    type_value: 0x01,
    -                    key: serialized_xpub,
    -                };
    -
    -                let origin = match xpub.origin {
    -                    Some(origin) => origin,
    -                    None if xpub.xkey.depth == 0 => {
    -                        (xpub.root_fingerprint(&self.secp), vec![].into())
    -                    }
    -                    _ => return Err(Error::MissingKeyOrigin(xpub.xkey.to_string())),
    -                };
    -
    -                psbt.global.unknown.insert(key, origin.serialize());
    -            }
    -        }
    -
    -        let 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.global.unsigned_tx.input.iter())
    -        {
    -            let utxo = match lookup_output.get(&input.previous_output) {
    -                Some(utxo) => utxo,
    -                None => continue,
    -            };
    -
    -            // Only set it if the builder has a custom one, otherwise leave blank which defaults to
    -            // SIGHASH_ALL
    -            if let Some(sighash_type) = builder.sighash {
    -                psbt_input.sighash_type = Some(sighash_type);
    -            }
    -
    -            // 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) = match self
    -                .database
    -                .borrow()
    -                .get_path_from_script_pubkey(&utxo.txout.script_pubkey)?
    -            {
    -                Some(x) => x,
    -                None => continue,
    -            };
    -
    -            let (desc, _) = self.get_descriptor_for_keychain(keychain);
    -            psbt_input.hd_keypaths = desc.get_hd_keypaths(child, &self.secp)?;
    -            let derived_descriptor = desc.derive(ChildNumber::from_normal_idx(child)?);
    -
    -            psbt_input.redeem_script = derived_descriptor.psbt_redeem_script(&self.secp);
    -            psbt_input.witness_script = derived_descriptor.psbt_witness_script(&self.secp);
    -
    -            let prev_output = input.previous_output;
    -            if let Some(prev_tx) = self.database.borrow().get_raw_tx(&prev_output.txid)? {
    -                if derived_descriptor.is_witness() {
    -                    psbt_input.witness_utxo =
    -                        Some(prev_tx.output[prev_output.vout as usize].clone());
    -                }
    -                if !derived_descriptor.is_witness() || builder.force_non_witness_utxo {
    -                    psbt_input.non_witness_utxo = Some(prev_tx);
    -                }
    -            }
    -        }
    -
    -        // probably redundant but it doesn't hurt...
    -        self.add_input_hd_keypaths(&mut psbt)?;
    -
    -        // add metadata for the outputs
    -        for (psbt_output, tx_output) in psbt
    -            .outputs
    -            .iter_mut()
    -            .zip(psbt.global.unsigned_tx.output.iter())
    -        {
    -            if let Some((keychain, child)) = self
    -                .database
    -                .borrow()
    -                .get_path_from_script_pubkey(&tx_output.script_pubkey)?
    -            {
    -                let (desc, _) = self.get_descriptor_for_keychain(keychain);
    -                psbt_output.hd_keypaths = desc.get_hd_keypaths(child, &self.secp)?;
    -                if builder.include_output_redeem_witness_script {
    -                    let derived_descriptor = desc.derive(ChildNumber::from_normal_idx(child)?);
    -                    psbt_output.witness_script = derived_descriptor.psbt_witness_script(&self.secp);
    -                    psbt_output.redeem_script = derived_descriptor.psbt_redeem_script(&self.secp);
    -                };
    -            }
    -        }
    -
    -        Ok(psbt)
    -    }
    -
    -    fn add_input_hd_keypaths(&self, psbt: &mut PSBT) -> Result<(), Error> {
    -        let mut input_utxos = Vec::with_capacity(psbt.inputs.len());
    -        for n in 0..psbt.inputs.len() {
    -            input_utxos.push(psbt.get_utxo_for(n).clone());
    -        }
    -
    -        // try to add hd_keypaths if we've already seen the output
    -        for (psbt_input, out) in psbt.inputs.iter_mut().zip(input_utxos.iter()) {
    -            if let Some(out) = out {
    -                if let Some((keychain, child)) = self
    -                    .database
    -                    .borrow()
    -                    .get_path_from_script_pubkey(&out.script_pubkey)?
    -                {
    -                    debug!("Found descriptor {:?}/{}", keychain, child);
    -
    -                    // merge hd_keypaths
    -                    let (desc, _) = self.get_descriptor_for_keychain(keychain);
    -                    let mut hd_keypaths = desc.get_hd_keypaths(child, &self.secp)?;
    -                    psbt_input.hd_keypaths.append(&mut hd_keypaths);
    -                }
    -            }
    -        }
    -
    -        Ok(())
    -    }
    -}
    -
    -impl<B, D> Wallet<B, D>
    -where
    -    B: Blockchain,
    -    D: BatchDatabase,
    -{
    -    /// Create a new "online" wallet
    -    #[maybe_async]
    -    pub fn new<E: ToWalletDescriptor>(
    -        descriptor: E,
    -        change_descriptor: Option<E>,
    -        network: Network,
    -        database: D,
    -        client: B,
    -    ) -> Result<Self, Error> {
    -        let mut wallet = Self::new_offline(descriptor, change_descriptor, network, database)?;
    -
    -        wallet.current_height = Some(maybe_await!(client.get_height())? as u32);
    -        wallet.client = Some(client);
    -
    -        Ok(wallet)
    -    }
    -
    -    /// Sync the internal database with the blockchain
    -    #[maybe_async]
    -    pub fn sync<P: 'static + Progress>(
    -        &self,
    -        progress_update: P,
    -        max_address_param: Option<u32>,
    -    ) -> Result<(), Error> {
    -        debug!("Begin sync...");
    -
    -        let mut run_setup = false;
    -
    -        let max_address = match self.descriptor.is_fixed() {
    -            true => 0,
    -            false => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
    -        };
    -        if self
    -            .database
    -            .borrow()
    -            .get_script_pubkey_from_path(KeychainKind::External, max_address.saturating_sub(1))?
    -            .is_none()
    -        {
    -            run_setup = true;
    -            self.cache_addresses(KeychainKind::External, 0, max_address)?;
    -        }
    -
    -        if let Some(change_descriptor) = &self.change_descriptor {
    -            let max_address = match change_descriptor.is_fixed() {
    -                true => 0,
    -                false => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
    -            };
    -
    -            if self
    -                .database
    -                .borrow()
    -                .get_script_pubkey_from_path(KeychainKind::Internal, max_address.saturating_sub(1))?
    -                .is_none()
    -            {
    -                run_setup = true;
    -                self.cache_addresses(KeychainKind::Internal, 0, max_address)?;
    -            }
    -        }
    -
    -        // TODO: what if i generate an address first and cache some addresses?
    -        // TODO: we should sync if generating an address triggers a new batch to be stored
    -        if run_setup {
    -            maybe_await!(self.client.as_ref().ok_or(Error::OfflineClient)?.setup(
    -                None,
    -                self.database.borrow_mut().deref_mut(),
    -                progress_update,
    -            ))
    -        } else {
    -            maybe_await!(self.client.as_ref().ok_or(Error::OfflineClient)?.sync(
    -                None,
    -                self.database.borrow_mut().deref_mut(),
    -                progress_update,
    -            ))
    -        }
    -    }
    -
    -    /// Return a reference to the internal blockchain client
    -    pub fn client(&self) -> Option<&B> {
    -        self.client.as_ref()
    -    }
    -
    -    /// Get the Bitcoin network the wallet is using.
    -    pub fn network(&self) -> Network {
    -        self.network
    -    }
    -
    -    /// Broadcast a transaction to the network
    -    #[maybe_async]
    -    pub fn broadcast(&self, tx: Transaction) -> Result<Txid, Error> {
    -        maybe_await!(self
    -            .client
    -            .as_ref()
    -            .ok_or(Error::OfflineClient)?
    -            .broadcast(&tx))?;
    -
    -        Ok(tx.txid())
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::str::FromStr;
    -
    -    use bitcoin::Network;
    -
    -    use crate::database::memory::MemoryDatabase;
    -    use crate::database::Database;
    -    use crate::types::KeychainKind;
    -
    -    use super::*;
    -
    -    #[test]
    -    fn test_cache_addresses_fixed() {
    -        let db = MemoryDatabase::new();
    -        let wallet: OfflineWallet<_> = Wallet::new_offline(
    -            "wpkh(L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6)",
    -            None,
    -            Network::Testnet,
    -            db,
    -        )
    -        .unwrap();
    -
    -        assert_eq!(
    -            wallet.get_new_address().unwrap().to_string(),
    -            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
    -        );
    -        assert_eq!(
    -            wallet.get_new_address().unwrap().to_string(),
    -            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
    -        );
    -
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::External, 0)
    -            .unwrap()
    -            .is_some());
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::Internal, 0)
    -            .unwrap()
    -            .is_none());
    -    }
    -
    -    #[test]
    -    fn test_cache_addresses() {
    -        let db = MemoryDatabase::new();
    -        let wallet: OfflineWallet<_> = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
    -
    -        assert_eq!(
    -            wallet.get_new_address().unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -        assert_eq!(
    -            wallet.get_new_address().unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE - 1)
    -            .unwrap()
    -            .is_some());
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE)
    -            .unwrap()
    -            .is_none());
    -    }
    -
    -    #[test]
    -    fn test_cache_addresses_refill() {
    -        let db = MemoryDatabase::new();
    -        let wallet: OfflineWallet<_> = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
    -
    -        assert_eq!(
    -            wallet.get_new_address().unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE - 1)
    -            .unwrap()
    -            .is_some());
    -
    -        for _ in 0..CACHE_ADDR_BATCH_SIZE {
    -            wallet.get_new_address().unwrap();
    -        }
    -
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE * 2 - 1)
    -            .unwrap()
    -            .is_some());
    -    }
    -
    -    pub(crate) fn get_test_wpkh() -> &'static str {
    -        "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)"
    -    }
    -
    -    pub(crate) fn get_test_single_sig_csv() -> &'static str {
    -        // and(pk(Alice),older(6))
    -        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),older(6)))"
    -    }
    -
    -    pub(crate) fn get_test_a_or_b_plus_csv() -> &'static str {
    -        // or(pk(Alice),and(pk(Bob),older(144)))
    -        "wsh(or_d(pk(cRjo6jqfVNP33HhSS76UhXETZsGTZYx8FMFvR9kpbtCSV1PmdZdu),and_v(v:pk(cMnkdebixpXMPfkcNEjjGin7s94hiehAH4mLbYkZoh9KSiNNmqC8),older(144))))"
    -    }
    -
    -    pub(crate) fn get_test_single_sig_cltv() -> &'static str {
    -        // and(pk(Alice),after(100000))
    -        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(100000)))"
    -    }
    -
    -    pub(crate) fn get_funded_wallet(
    -        descriptor: &str,
    -    ) -> (
    -        OfflineWallet<MemoryDatabase>,
    -        (String, Option<String>),
    -        bitcoin::Txid,
    -    ) {
    -        let descriptors = testutils!(@descriptors (descriptor));
    -        let wallet: OfflineWallet<_> = Wallet::new_offline(
    -            &descriptors.0,
    -            None,
    -            Network::Regtest,
    -            MemoryDatabase::new(),
    -        )
    -        .unwrap();
    -
    -        let txid = wallet.database.borrow_mut().received_tx(
    -            testutils! {
    -                @tx ( (@external descriptors, 0) => 50_000 ) (@confirmations 1)
    -            },
    -            Some(100),
    -        );
    -
    -        (wallet, descriptors, txid)
    -    }
    -
    -    macro_rules! assert_fee_rate {
    -        ($tx:expr, $fees:expr, $fee_rate:expr $( ,@dust_change $( $dust_change:expr )* )* $( ,@add_signature $( $add_signature:expr )* )* ) => ({
    -            let mut tx = $tx.clone();
    -            $(
    -                $( $add_signature )*
    -                for txin in &mut tx.input {
    -                    txin.witness.push([0x00; 108].to_vec()); // fake signature
    -                }
    -            )*
    -
    -            #[allow(unused_mut)]
    -            #[allow(unused_assignments)]
    -            let mut dust_change = false;
    -            $(
    -                $( $dust_change )*
    -                dust_change = true;
    -            )*
    -
    -            let tx_fee_rate = $fees as f32 / (tx.get_weight() as f32 / 4.0);
    -            let fee_rate = $fee_rate.as_sat_vb();
    -
    -            if !dust_change {
    -                assert!((tx_fee_rate - fee_rate).abs() < 0.5, format!("Expected fee rate of {}, the tx has {}", fee_rate, tx_fee_rate));
    -            } else {
    -                assert!(tx_fee_rate >= fee_rate, format!("Expected fee rate of at least {}, the tx has {}", fee_rate, tx_fee_rate));
    -            }
    -        });
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "NoRecipients")]
    -    fn test_create_tx_empty_recipients() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        wallet
    -            .create_tx(TxBuilder::with_recipients(vec![]))
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "NoUtxosSelected")]
    -    fn test_create_tx_manually_selected_empty_utxos() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
    -                    .manually_selected_only()
    -                    .utxos(vec![]),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "Invalid version `0`")]
    -    fn test_create_tx_version_0() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(0))
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
    -    )]
    -    fn test_create_tx_version_1_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
    -        let addr = wallet.get_new_address().unwrap();
    -        wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(1))
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_version() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).version(42))
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.version, 42);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_locktime() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.lock_time, 0);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_locktime_cltv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.lock_time, 100_000);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_locktime() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(630_000),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_locktime_compatible_with_cltv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(630_000),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "TxBuilder requested timelock of `50000`, but at least `100000` is required to spend from this script"
    -    )]
    -    fn test_create_tx_custom_locktime_incompatible_with_cltv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -        let addr = wallet.get_new_address().unwrap();
    -        wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).nlocktime(50000),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_no_rbf_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 6);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_with_default_rbf_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -
    -        // When CSV is enabled it takes precedence over the rbf value (unless forced by the user).
    -        // It will be set to the OP_CSV value, in this case 6
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 6);
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "Cannot enable RBF with nSequence `3` given a required OP_CSV of `6`"
    -    )]
    -    fn test_create_tx_with_custom_rbf_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
    -        let addr = wallet.get_new_address().unwrap();
    -        wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
    -                    .enable_rbf_with_sequence(3),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_no_rbf_cltv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFE);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "Cannot enable RBF with a nSequence >= 0xFFFFFFFE")]
    -    fn test_create_tx_invalid_rbf_sequence() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
    -                    .enable_rbf_with_sequence(0xFFFFFFFE),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_rbf_sequence() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
    -                    .enable_rbf_with_sequence(0xDEADBEEF),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xDEADBEEF);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_sequence() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFF);
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "The `change_policy` can be set only if the wallet has a change_descriptor"
    -    )]
    -    fn test_create_tx_change_policy_no_internal() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
    -                    .do_not_spend_change(),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_single_recipient_drain_wallet() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, details) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet(),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
    -        assert_eq!(
    -            psbt.global.unsigned_tx.output[0].value,
    -            50_000 - details.fees
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_fee_rate() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, details) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::default(), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_fee_rate() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
    -                    .fee_rate(FeeRate::from_sat_per_vb(5.0)),
    -            )
    -            .unwrap();
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(5.0), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_absolute_fee() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, details) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet()
    -                    .fee_absolute(100),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(details.fees, 100);
    -        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
    -        assert_eq!(
    -            psbt.global.unsigned_tx.output[0].value,
    -            50_000 - details.fees
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_absolute_zero_fee() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, details) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet()
    -                    .fee_absolute(0),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(details.fees, 0);
    -        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
    -        assert_eq!(
    -            psbt.global.unsigned_tx.output[0].value,
    -            50_000 - details.fees
    -        );
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_create_tx_absolute_high_fee() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (_psbt, _details) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet()
    -                    .fee_absolute(60_000),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_add_change() {
    -        use super::tx_builder::TxOrdering;
    -
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)])
    -                    .ordering(TxOrdering::Untouched),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.output.len(), 2);
    -        assert_eq!(psbt.global.unsigned_tx.output[0].value, 25_000);
    -        assert_eq!(
    -            psbt.global.unsigned_tx.output[1].value,
    -            25_000 - details.fees
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_skip_change_dust() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                49_800,
    -            )]))
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
    -        assert_eq!(psbt.global.unsigned_tx.output[0].value, 49_800);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_create_tx_single_recipient_dust_amount() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        // very high fee rate, so that the only output would be below dust
    -        wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet()
    -                    .fee_rate(FeeRate::from_sat_per_vb(453.0)),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_ordering_respected() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![
    -                    (addr.script_pubkey(), 30_000),
    -                    (addr.script_pubkey(), 10_000),
    -                ])
    -                .ordering(super::tx_builder::TxOrdering::BIP69Lexicographic),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.output.len(), 3);
    -        assert_eq!(
    -            psbt.global.unsigned_tx.output[0].value,
    -            10_000 - details.fees
    -        );
    -        assert_eq!(psbt.global.unsigned_tx.output[1].value, 10_000);
    -        assert_eq!(psbt.global.unsigned_tx.output[2].value, 30_000);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_sighash() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                30_000,
    -            )]))
    -            .unwrap();
    -
    -        assert_eq!(psbt.inputs[0].sighash_type, None);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_sighash() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 30_000)])
    -                    .sighash(bitcoin::SigHashType::Single),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(
    -            psbt.inputs[0].sighash_type,
    -            Some(bitcoin::SigHashType::Single)
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_input_hd_keypaths() {
    -        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
    -        use std::str::FromStr;
    -
    -        let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet(),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.inputs[0].hd_keypaths.len(), 1);
    -        assert_eq!(
    -            psbt.inputs[0].hd_keypaths.values().nth(0).unwrap(),
    -            &(
    -                Fingerprint::from_str("d34db33f").unwrap(),
    -                DerivationPath::from_str("m/44'/0'/0'/0/0").unwrap()
    -            )
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_output_hd_keypaths() {
    -        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
    -        use std::str::FromStr;
    -
    -        let (wallet, descriptors, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)");
    -        // cache some addresses
    -        wallet.get_new_address().unwrap();
    -
    -        let addr = testutils!(@external descriptors, 5);
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet(),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.outputs[0].hd_keypaths.len(), 1);
    -        assert_eq!(
    -            psbt.outputs[0].hd_keypaths.values().nth(0).unwrap(),
    -            &(
    -                Fingerprint::from_str("d34db33f").unwrap(),
    -                DerivationPath::from_str("m/44'/0'/0'/0/5").unwrap()
    -            )
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_set_redeem_script_p2sh() {
    -        use bitcoin::hashes::hex::FromHex;
    -
    -        let (wallet, _, _) =
    -            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet(),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(
    -            psbt.inputs[0].redeem_script,
    -            Some(Script::from(
    -                Vec::<u8>::from_hex(
    -                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
    -                )
    -                .unwrap()
    -            ))
    -        );
    -        assert_eq!(psbt.inputs[0].witness_script, None);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_set_witness_script_p2wsh() {
    -        use bitcoin::hashes::hex::FromHex;
    -
    -        let (wallet, _, _) =
    -            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet(),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.inputs[0].redeem_script, None);
    -        assert_eq!(
    -            psbt.inputs[0].witness_script,
    -            Some(Script::from(
    -                Vec::<u8>::from_hex(
    -                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
    -                )
    -                .unwrap()
    -            ))
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_set_redeem_witness_script_p2wsh_p2sh() {
    -        use bitcoin::hashes::hex::FromHex;
    -
    -        let (wallet, _, _) =
    -            get_funded_wallet("sh(wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)))");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet(),
    -            )
    -            .unwrap();
    -
    -        let script = Script::from(
    -            Vec::<u8>::from_hex(
    -                "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac",
    -            )
    -            .unwrap(),
    -        );
    -
    -        assert_eq!(psbt.inputs[0].redeem_script, Some(script.to_v0_p2wsh()));
    -        assert_eq!(psbt.inputs[0].witness_script, Some(script));
    -    }
    -
    -    #[test]
    -    fn test_create_tx_non_witness_utxo() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet(),
    -            )
    -            .unwrap();
    -
    -        assert!(psbt.inputs[0].non_witness_utxo.is_some());
    -        assert!(psbt.inputs[0].witness_utxo.is_none());
    -    }
    -
    -    #[test]
    -    fn test_create_tx_only_witness_utxo() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet(),
    -            )
    -            .unwrap();
    -
    -        assert!(psbt.inputs[0].non_witness_utxo.is_none());
    -        assert!(psbt.inputs[0].witness_utxo.is_some());
    -    }
    -
    -    #[test]
    -    fn test_create_tx_shwpkh_has_witness_utxo() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("sh(wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet(),
    -            )
    -            .unwrap();
    -
    -        assert!(psbt.inputs[0].non_witness_utxo.is_none());
    -        assert!(psbt.inputs[0].witness_utxo.is_some());
    -    }
    -
    -    #[test]
    -    fn test_create_tx_both_non_witness_utxo_and_witness_utxo() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet()
    -                    .force_non_witness_utxo(),
    -            )
    -            .unwrap();
    -
    -        assert!(psbt.inputs[0].non_witness_utxo.is_some());
    -        assert!(psbt.inputs[0].witness_utxo.is_some());
    -    }
    -
    -    #[test]
    -    fn test_create_tx_add_utxo() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let small_output_txid = wallet.database.borrow_mut().received_tx(
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 30_000)]).add_utxo(
    -                    OutPoint {
    -                        txid: small_output_txid,
    -                        vout: 0,
    -                    },
    -                ),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(
    -            psbt.global.unsigned_tx.input.len(),
    -            2,
    -            "should add an additional input since 25_000 < 30_000"
    -        );
    -        assert_eq!(details.sent, 75_000, "total should be sum of both inputs");
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_create_tx_manually_selected_insufficient() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let small_output_txid = wallet.database.borrow_mut().received_tx(
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 30_000)])
    -                    .add_utxo(OutPoint {
    -                        txid: small_output_txid,
    -                        vout: 0,
    -                    })
    -                    .manually_selected_only(),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "SpendingPolicyRequired(External)")]
    -    fn test_create_tx_policy_path_required() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_a_or_b_plus_csv());
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                30_000,
    -            )]))
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_policy_path_no_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_a_or_b_plus_csv());
    -
    -        let external_policy = wallet.policies(KeychainKind::External).unwrap().unwrap();
    -        let root_id = external_policy.id;
    -        // child #0 is just the key "A"
    -        let path = vec![(root_id, vec![0])].into_iter().collect();
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 30_000)])
    -                    .policy_path(path, KeychainKind::External),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFF);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_policy_path_use_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_a_or_b_plus_csv());
    -
    -        let external_policy = wallet.policies(KeychainKind::External).unwrap().unwrap();
    -        let root_id = external_policy.id;
    -        // child #1 is or(pk(B),older(144))
    -        let path = vec![(root_id, vec![1])].into_iter().collect();
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 30_000)])
    -                    .policy_path(path, KeychainKind::External),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 144);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_global_xpubs_with_origin() {
    -        use bitcoin::hashes::hex::FromHex;
    -        use bitcoin::util::base58;
    -        use bitcoin::util::psbt::raw::Key;
    -
    -        let (wallet, _, _) = get_funded_wallet("wpkh([73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*)");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).add_global_xpubs(),
    -            )
    -            .unwrap();
    -
    -        let type_value = 0x01;
    -        let key = base58::from_check("tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3").unwrap();
    -
    -        let psbt_key = Key { type_value, key };
    -
    -        // This key has an explicit origin, so it will be encoded here
    -        let value_bytes = Vec::<u8>::from_hex("73756c7f30000080000000800000008002000080").unwrap();
    -
    -        assert_eq!(psbt.global.unknown.len(), 1);
    -        assert_eq!(psbt.global.unknown.get(&psbt_key), Some(&value_bytes));
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "MissingKeyOrigin(\"tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3\")"
    -    )]
    -    fn test_create_tx_global_xpubs_origin_missing() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*)");
    -        let addr = wallet.get_new_address().unwrap();
    -        wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).add_global_xpubs(),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_global_xpubs_master_without_origin() {
    -        use bitcoin::hashes::hex::FromHex;
    -        use bitcoin::util::base58;
    -        use bitcoin::util::psbt::raw::Key;
    -
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL/0/*)");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).add_global_xpubs(),
    -            )
    -            .unwrap();
    -
    -        let type_value = 0x01;
    -        let key = base58::from_check("tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL").unwrap();
    -
    -        let psbt_key = Key { type_value, key };
    -
    -        // This key doesn't have an explicit origin, but it's a master key (depth = 0). So we encode
    -        // its fingerprint directly and an empty path
    -        let value_bytes = Vec::<u8>::from_hex("997a323b").unwrap();
    -
    -        assert_eq!(psbt.global.unknown.len(), 1);
    -        assert_eq!(psbt.global.unknown.get(&psbt_key), Some(&value_bytes));
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "IrreplaceableTransaction")]
    -    fn test_bump_fee_irreplaceable_tx() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, mut details) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        wallet.bump_fee(&txid, TxBuilder::new()).unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "TransactionConfirmed")]
    -    fn test_bump_fee_confirmed_tx() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, mut details) = wallet
    -            .create_tx(TxBuilder::with_recipients(vec![(
    -                addr.script_pubkey(),
    -                25_000,
    -            )]))
    -            .unwrap();
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        details.height = Some(42);
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        wallet.bump_fee(&txid, TxBuilder::new()).unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "FeeRateTooLow")]
    -    fn test_bump_fee_low_fee_rate() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, mut details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(1.0)),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "FeeTooLow")]
    -    fn test_bump_fee_low_abs() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, mut details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        wallet
    -            .bump_fee(&txid, TxBuilder::new().fee_absolute(10))
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "FeeTooLow")]
    -    fn test_bump_fee_zero_abs() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, mut details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        wallet
    -            .bump_fee(&txid, TxBuilder::new().fee_absolute(0))
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_reduce_change() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let (psbt, details) = wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(2.5)),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent);
    -        assert_eq!(
    -            details.received + details.fees,
    -            original_details.received + original_details.fees
    -        );
    -        assert!(details.fees > original_details.fees);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            25_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(2.5), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_absolute_reduce_change() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 25_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let (psbt, details) = wallet
    -            .bump_fee(&txid, TxBuilder::new().fee_absolute(200))
    -            .unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent);
    -        assert_eq!(
    -            details.received + details.fees,
    -            original_details.received + original_details.fees
    -        );
    -        assert!(
    -            details.fees > original_details.fees,
    -            "{} > {}",
    -            details.fees,
    -            original_details.fees
    -        );
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            25_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_eq!(details.fees, 200);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_reduce_single_recipient() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet()
    -                    .enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let (psbt, details) = wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new()
    -                    .maintain_single_recipient()
    -                    .fee_rate(FeeRate::from_sat_per_vb(2.5)),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent);
    -        assert!(details.fees > original_details.fees);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.output.len(), 1);
    -        assert_eq!(tx.output[0].value + details.fees, details.sent);
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(2.5), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_absolute_reduce_single_recipient() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet()
    -                    .enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let (psbt, details) = wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new()
    -                    .maintain_single_recipient()
    -                    .fee_absolute(300),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent);
    -        assert!(details.fees > original_details.fees);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.output.len(), 1);
    -        assert_eq!(tx.output[0].value + details.fees, details.sent);
    -
    -        assert_eq!(details.fees, 300);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_drain_wallet() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        // receive an extra tx so that our wallet has two utxos.
    -        let incoming_txid = wallet.database.borrow_mut().received_tx(
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -        let outpoint = OutPoint {
    -            txid: incoming_txid,
    -            vout: 0,
    -        };
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .utxos(vec![outpoint])
    -                    .manually_selected_only()
    -                    .enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -        assert_eq!(original_details.sent, 25_000);
    -
    -        // for the new feerate, it should be enough to reduce the output, but since we specify
    -        // `drain_wallet` we expect to spend everything
    -        let (_, details) = wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new()
    -                    .drain_wallet()
    -                    .maintain_single_recipient()
    -                    .fee_rate(FeeRate::from_sat_per_vb(5.0)),
    -            )
    -            .unwrap();
    -        assert_eq!(details.sent, 75_000);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_bump_fee_remove_output_manually_selected_only() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        // receive an extra tx so that our wallet has two utxos. then we manually pick only one of
    -        // them, and make sure that `bump_fee` doesn't try to add more. eventually, it should fail
    -        // because the fee rate is too high and the single utxo isn't enough to create a non-dust
    -        // output
    -        let incoming_txid = wallet.database.borrow_mut().received_tx(
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -        let outpoint = OutPoint {
    -            txid: incoming_txid,
    -            vout: 0,
    -        };
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .utxos(vec![outpoint])
    -                    .manually_selected_only()
    -                    .enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -        assert_eq!(original_details.sent, 25_000);
    -
    -        wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new()
    -                    .utxos(vec![outpoint])
    -                    .manually_selected_only()
    -                    .fee_rate(FeeRate::from_sat_per_vb(225.0)),
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_add_input() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        wallet.database.borrow_mut().received_tx(
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let (psbt, details) = wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(50.0)),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fees + details.received, 30_000);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(50.0), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_absolute_add_input() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        wallet.database.borrow_mut().received_tx(
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let (psbt, details) = wallet
    -            .bump_fee(&txid, TxBuilder::new().fee_absolute(6_000))
    -            .unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fees + details.received, 30_000);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_eq!(details.fees, 6_000);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_no_change_add_input_and_change() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let incoming_txid = wallet.database.borrow_mut().received_tx(
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        // initially make a tx without change by using `set_single_recipient`
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .add_utxo(OutPoint {
    -                        txid: incoming_txid,
    -                        vout: 0,
    -                    })
    -                    .manually_selected_only()
    -                    .enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        // now bump the fees without using `maintain_single_recipient`. the wallet should add an
    -        // extra input and a change output, and leave the original output untouched
    -        let (psbt, details) = wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(50.0)),
    -            )
    -            .unwrap();
    -
    -        let original_send_all_amount = original_details.sent - original_details.fees;
    -        assert_eq!(details.sent, original_details.sent + 50_000);
    -        assert_eq!(
    -            details.received,
    -            75_000 - original_send_all_amount - details.fees
    -        );
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            original_send_all_amount
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            75_000 - original_send_all_amount - details.fees
    -        );
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(50.0), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_add_input_change_dust() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        wallet.database.borrow_mut().received_tx(
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        assert_eq!(tx.input.len(), 1);
    -        assert_eq!(tx.output.len(), 2);
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let (psbt, details) = wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new().fee_rate(FeeRate::from_sat_per_vb(140.0)),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(original_details.received, 5_000 - original_details.fees);
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fees, 30_000);
    -        assert_eq!(details.received, 0);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 1);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(140.0), @dust_change, @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_force_add_input() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let incoming_txid = wallet.database.borrow_mut().received_tx(
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        // the new fee_rate is low enough that just reducing the change would be fine, but we force
    -        // the addition of an extra input with `add_utxo()`
    -        let (psbt, details) = wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new()
    -                    .add_utxo(OutPoint {
    -                        txid: incoming_txid,
    -                        vout: 0,
    -                    })
    -                    .fee_rate(FeeRate::from_sat_per_vb(5.0)),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fees + details.received, 30_000);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fees, FeeRate::from_sat_per_vb(5.0), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_absolute_force_add_input() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let incoming_txid = wallet.database.borrow_mut().received_tx(
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, mut original_details) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)]).enable_rbf(),
    -            )
    -            .unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        // the new fee_rate is low enough that just reducing the change would be fine, but we force
    -        // the addition of an extra input with `add_utxo()`
    -        let (psbt, details) = wallet
    -            .bump_fee(
    -                &txid,
    -                TxBuilder::new()
    -                    .add_utxo(OutPoint {
    -                        txid: incoming_txid,
    -                        vout: 0,
    -                    })
    -                    .fee_absolute(250),
    -            )
    -            .unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fees + details.received, 30_000);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_eq!(details.fees, 250);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_xprv() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet(),
    -            )
    -            .unwrap();
    -
    -        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
    -        assert_eq!(finalized, true);
    -
    -        let extracted = signed_psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_xprv_bip44_path() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/44'/0'/0'/0/*)");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet(),
    -            )
    -            .unwrap();
    -
    -        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
    -        assert_eq!(finalized, true);
    -
    -        let extracted = signed_psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_xprv_sh_wpkh() {
    -        let (wallet, _, _) = get_funded_wallet("sh(wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*))");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet(),
    -            )
    -            .unwrap();
    -
    -        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
    -        assert_eq!(finalized, true);
    -
    -        let extracted = signed_psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_wif() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet(),
    -            )
    -            .unwrap();
    -
    -        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
    -        assert_eq!(finalized, true);
    -
    -        let extracted = signed_psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_xprv_no_hd_keypaths() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wallet.get_new_address().unwrap();
    -        let (mut psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::new()
    -                    .set_single_recipient(addr.script_pubkey())
    -                    .drain_wallet(),
    -            )
    -            .unwrap();
    -
    -        psbt.inputs[0].hd_keypaths.clear();
    -        assert_eq!(psbt.inputs[0].hd_keypaths.len(), 0);
    -
    -        let (signed_psbt, finalized) = wallet.sign(psbt, None).unwrap();
    -        assert_eq!(finalized, true);
    -
    -        let extracted = signed_psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_include_output_redeem_witness_script() {
    -        let (wallet, _, _) = get_funded_wallet("sh(wsh(multi(1,cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW,cRjo6jqfVNP33HhSS76UhXETZsGTZYx8FMFvR9kpbtCSV1PmdZdu)))");
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)])
    -                    .include_output_redeem_witness_script(),
    -            )
    -            .unwrap();
    -
    -        // p2sh-p2wsh transaction should contain both witness and redeem scripts
    -        assert!(psbt
    -            .outputs
    -            .iter()
    -            .any(|output| output.redeem_script.is_some() && output.witness_script.is_some()));
    -    }
    -
    -    #[test]
    -    fn test_signing_only_one_of_multiple_inputs() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let (mut psbt, _) = wallet
    -            .create_tx(
    -                TxBuilder::with_recipients(vec![(addr.script_pubkey(), 45_000)])
    -                    .include_output_redeem_witness_script(),
    -            )
    -            .unwrap();
    -
    -        // add another input to the psbt that is at least passable.
    -        let mut dud_input = bitcoin::util::psbt::Input::default();
    -        dud_input.witness_utxo = Some(TxOut {
    -            value: 100_000,
    -            script_pubkey: miniscript::Descriptor::<bitcoin::PublicKey>::from_str(
    -                "wpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)",
    -            )
    -            .unwrap()
    -            .script_pubkey(miniscript::NullCtx),
    -        });
    -        psbt.inputs.push(dud_input);
    -        psbt.global.unsigned_tx.input.push(bitcoin::TxIn::default());
    -        let (psbt, is_final) = wallet.sign(psbt, None).unwrap();
    -        assert!(
    -            !is_final,
    -            "shouldn't be final since we can't sign one of the inputs"
    -        );
    -        assert!(
    -            psbt.inputs[0].final_script_witness.is_some(),
    -            "should finalized input it signed"
    -        )
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/signer.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/signer.rs.html deleted file mode 100644 index 76c505864f..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/signer.rs.html +++ /dev/null @@ -1,1358 +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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! 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 std::sync::Arc;
    -//! # use std::str::FromStr;
    -//! # use bitcoin::secp256k1::{Secp256k1, All};
    -//! # use bitcoin::*;
    -//! # use bitcoin::util::psbt;
    -//! # use bitcoin::util::bip32::Fingerprint;
    -//! # use bdk::signer::*;
    -//! # use bdk::database::*;
    -//! # use bdk::*;
    -//! # #[derive(Debug)]
    -//! # struct CustomHSM;
    -//! # impl CustomHSM {
    -//! #     fn sign_input(&self, _psbt: &mut psbt::PartiallySignedTransaction, _input: usize) -> Result<(), SignerError> {
    -//! #         Ok(())
    -//! #     }
    -//! #     fn connect() -> Self {
    -//! #         CustomHSM
    -//! #     }
    -//! # }
    -//! #[derive(Debug)]
    -//! struct CustomSigner {
    -//!     device: CustomHSM,
    -//! }
    -//!
    -//! impl CustomSigner {
    -//!     fn connect() -> Self {
    -//!         CustomSigner { device: CustomHSM::connect() }
    -//!     }
    -//! }
    -//!
    -//! impl Signer for CustomSigner {
    -//!     fn sign(
    -//!         &self,
    -//!         psbt: &mut psbt::PartiallySignedTransaction,
    -//!         input_index: Option<usize>,
    -//!         _secp: &Secp256k1<All>,
    -//!     ) -> Result<(), SignerError> {
    -//!         let input_index = input_index.ok_or(SignerError::InputIndexOutOfRange)?;
    -//!         self.device.sign_input(psbt, input_index)?;
    -//!
    -//!         Ok(())
    -//!     }
    -//!
    -//!     fn sign_whole_tx(&self) -> bool {
    -//!         false
    -//!     }
    -//! }
    -//!
    -//! let custom_signer = CustomSigner::connect();
    -//!
    -//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -//! let mut wallet: OfflineWallet<_> = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -//! wallet.add_signer(
    -//!     KeychainKind::External,
    -//!     Fingerprint::from_str("e30f11b8").unwrap().into(),
    -//!     SignerOrdering(200),
    -//!     Arc::new(custom_signer)
    -//! );
    -//!
    -//! # Ok::<_, bdk::Error>(())
    -//! ```
    -
    -use std::cmp::Ordering;
    -use std::collections::BTreeMap;
    -use std::fmt;
    -use std::ops::Bound::Included;
    -use std::sync::Arc;
    -
    -use bitcoin::blockdata::opcodes;
    -use bitcoin::blockdata::script::Builder as ScriptBuilder;
    -use bitcoin::hashes::{hash160, Hash};
    -use bitcoin::secp256k1::{Message, Secp256k1};
    -use bitcoin::util::bip32::{ExtendedPrivKey, Fingerprint};
    -use bitcoin::util::{bip143, psbt};
    -use bitcoin::{PrivateKey, Script, SigHash, SigHashType};
    -
    -use miniscript::descriptor::{DescriptorSecretKey, DescriptorSinglePriv, DescriptorXKey, KeyMap};
    -use miniscript::{Legacy, MiniscriptKey, Segwitv0};
    -
    -use super::utils::SecpCtx;
    -use crate::descriptor::XKeyUtils;
    -
    -/// 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),
    -}
    -
    -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, PartialEq, Eq, Clone)]
    -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 requied to sign this input
    -    MissingWitnessScript,
    -    /// The fingerprint and derivation path are missing from the psbt input
    -    MissingHDKeypath,
    -}
    -
    -impl fmt::Display for SignerError {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for SignerError {}
    -
    -/// Trait for signers
    -///
    -/// This trait can be implemented to provide customized signers to the wallet. For an example see
    -/// [`this module`](crate::wallet::signer)'s documentation.
    -pub trait Signer: fmt::Debug + Send + Sync {
    -    /// Sign a PSBT
    -    ///
    -    /// The `input_index` argument is only provided if the wallet doesn't declare to sign the whole
    -    /// transaction in one go (see [`Signer::sign_whole_tx`]). Otherwise its value is `None` and
    -    /// can be ignored.
    -    fn sign(
    -        &self,
    -        psbt: &mut psbt::PartiallySignedTransaction,
    -        input_index: Option<usize>,
    -        secp: &SecpCtx,
    -    ) -> Result<(), SignerError>;
    -
    -    /// Return whether or not the signer signs the whole transaction in one go instead of every
    -    /// input individually
    -    fn sign_whole_tx(&self) -> bool;
    -
    -    /// 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
    -    }
    -}
    -
    -impl Signer for DescriptorXKey<ExtendedPrivKey> {
    -    fn sign(
    -        &self,
    -        psbt: &mut psbt::PartiallySignedTransaction,
    -        input_index: Option<usize>,
    -        secp: &SecpCtx,
    -    ) -> Result<(), SignerError> {
    -        let input_index = input_index.unwrap();
    -        if input_index >= psbt.inputs.len() {
    -            return Err(SignerError::InputIndexOutOfRange);
    -        }
    -
    -        let (public_key, deriv_path) = match psbt.inputs[input_index]
    -            .hd_keypaths
    -            .iter()
    -            .filter_map(|(pk, &(fingerprint, ref path))| {
    -                if self.matches(&(fingerprint, path.clone()), &secp).is_some() {
    -                    Some((pk, path))
    -                } else {
    -                    None
    -                }
    -            })
    -            .next()
    -        {
    -            Some((pk, full_path)) => (pk, full_path.clone()),
    -            None => return Ok(()),
    -        };
    -
    -        let derived_key = self.xkey.derive_priv(&secp, &deriv_path).unwrap();
    -        if &derived_key.private_key.public_key(&secp) != public_key {
    -            Err(SignerError::InvalidKey)
    -        } else {
    -            derived_key.private_key.sign(psbt, Some(input_index), secp)
    -        }
    -    }
    -
    -    fn sign_whole_tx(&self) -> bool {
    -        false
    -    }
    -
    -    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
    -        Some(DescriptorSecretKey::XPrv(self.clone()))
    -    }
    -}
    -
    -impl Signer for PrivateKey {
    -    fn sign(
    -        &self,
    -        psbt: &mut psbt::PartiallySignedTransaction,
    -        input_index: Option<usize>,
    -        secp: &SecpCtx,
    -    ) -> Result<(), SignerError> {
    -        let input_index = input_index.unwrap();
    -        if input_index >= psbt.inputs.len() {
    -            return Err(SignerError::InputIndexOutOfRange);
    -        }
    -
    -        let pubkey = self.public_key(&secp);
    -        if psbt.inputs[input_index].partial_sigs.contains_key(&pubkey) {
    -            return Ok(());
    -        }
    -
    -        // FIXME: use the presence of `witness_utxo` as an indication that we should make a bip143
    -        // sig. Does this make sense? Should we add an extra argument to explicitly swith between
    -        // these? The original idea was to declare sign() as sign<Ctx: ScriptContex>() and use Ctx,
    -        // but that violates the rules for trait-objects, so we can't do it.
    -        let (hash, sighash) = match psbt.inputs[input_index].witness_utxo {
    -            Some(_) => Segwitv0::sighash(psbt, input_index)?,
    -            None => Legacy::sighash(psbt, input_index)?,
    -        };
    -
    -        let signature = secp.sign(
    -            &Message::from_slice(&hash.into_inner()[..]).unwrap(),
    -            &self.key,
    -        );
    -
    -        let mut final_signature = Vec::with_capacity(75);
    -        final_signature.extend_from_slice(&signature.serialize_der());
    -        final_signature.push(sighash.as_u32() as u8);
    -
    -        psbt.inputs[input_index]
    -            .partial_sigs
    -            .insert(pubkey, final_signature);
    -
    -        Ok(())
    -    }
    -
    -    fn sign_whole_tx(&self) -> bool {
    -        false
    -    }
    -
    -    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
    -        Some(DescriptorSecretKey::SinglePriv(DescriptorSinglePriv {
    -            key: *self,
    -            origin: None,
    -        }))
    -    }
    -}
    -
    -/// 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 std::default::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 Signer>>);
    -
    -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.as_public(secp).ok().map(|public| (public, secret)))
    -            .collect()
    -    }
    -}
    -
    -impl From<KeyMap> for SignersContainer {
    -    fn from(keymap: KeyMap) -> SignersContainer {
    -        let secp = Secp256k1::new();
    -        let mut container = SignersContainer::new();
    -
    -        for (_, secret) in keymap {
    -            match secret {
    -                DescriptorSecretKey::SinglePriv(private_key) => container.add_external(
    -                    SignerId::from(
    -                        private_key
    -                            .key
    -                            .public_key(&Secp256k1::signing_only())
    -                            .to_pubkeyhash(),
    -                    ),
    -                    SignerOrdering::default(),
    -                    Arc::new(private_key.key),
    -                ),
    -                DescriptorSecretKey::XPrv(xprv) => container.add_external(
    -                    SignerId::from(xprv.root_fingerprint(&secp)),
    -                    SignerOrdering::default(),
    -                    Arc::new(xprv),
    -                ),
    -            };
    -        }
    -
    -        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 Signer>,
    -    ) -> Option<Arc<dyn Signer>> {
    -        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 Signer>> {
    -        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 Signer>> {
    -        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 Signer>> {
    -        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()
    -    }
    -}
    -
    -pub(crate) trait ComputeSighash {
    -    fn sighash(
    -        psbt: &psbt::PartiallySignedTransaction,
    -        input_index: usize,
    -    ) -> Result<(SigHash, SigHashType), SignerError>;
    -}
    -
    -impl ComputeSighash for Legacy {
    -    fn sighash(
    -        psbt: &psbt::PartiallySignedTransaction,
    -        input_index: usize,
    -    ) -> Result<(SigHash, SigHashType), SignerError> {
    -        if input_index >= psbt.inputs.len() {
    -            return Err(SignerError::InputIndexOutOfRange);
    -        }
    -
    -        let psbt_input = &psbt.inputs[input_index];
    -        let tx_input = &psbt.global.unsigned_tx.input[input_index];
    -
    -        let sighash = psbt_input.sighash_type.unwrap_or(SigHashType::All);
    -        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((
    -            psbt.global
    -                .unsigned_tx
    -                .signature_hash(input_index, &script, sighash.as_u32()),
    -            sighash,
    -        ))
    -    }
    -}
    -
    -fn p2wpkh_script_code(script: &Script) -> Script {
    -    ScriptBuilder::new()
    -        .push_opcode(opcodes::all::OP_DUP)
    -        .push_opcode(opcodes::all::OP_HASH160)
    -        .push_slice(&script[2..])
    -        .push_opcode(opcodes::all::OP_EQUALVERIFY)
    -        .push_opcode(opcodes::all::OP_CHECKSIG)
    -        .into_script()
    -}
    -
    -impl ComputeSighash for Segwitv0 {
    -    fn sighash(
    -        psbt: &psbt::PartiallySignedTransaction,
    -        input_index: usize,
    -    ) -> Result<(SigHash, SigHashType), SignerError> {
    -        if input_index >= psbt.inputs.len() {
    -            return Err(SignerError::InputIndexOutOfRange);
    -        }
    -
    -        let psbt_input = &psbt.inputs[input_index];
    -
    -        let sighash = psbt_input.sighash_type.unwrap_or(SigHashType::All);
    -
    -        let witness_utxo = psbt_input
    -            .witness_utxo
    -            .as_ref()
    -            .ok_or(SignerError::MissingNonWitnessUtxo)?;
    -        let value = witness_utxo.value;
    -
    -        let script = match psbt_input.witness_script {
    -            Some(ref witness_script) => witness_script.clone(),
    -            None => {
    -                if witness_utxo.script_pubkey.is_v0_p2wpkh() {
    -                    p2wpkh_script_code(&witness_utxo.script_pubkey)
    -                } else if psbt_input
    -                    .redeem_script
    -                    .as_ref()
    -                    .map(Script::is_v0_p2wpkh)
    -                    .unwrap_or(false)
    -                {
    -                    p2wpkh_script_code(&psbt_input.redeem_script.as_ref().unwrap())
    -                } else {
    -                    return Err(SignerError::MissingWitnessScript);
    -                }
    -            }
    -        };
    -
    -        Ok((
    -            bip143::SigHashCache::new(&psbt.global.unsigned_tx).signature_hash(
    -                input_index,
    -                &script,
    -                value,
    -                sighash,
    -            ),
    -            sighash,
    -        ))
    -    }
    -}
    -
    -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::ToWalletDescriptor;
    -    use crate::keys::{DescriptorKey, ToDescriptorKey};
    -    use bitcoin::secp256k1::All;
    -    use bitcoin::util::bip32;
    -    use bitcoin::util::psbt::PartiallySignedTransaction;
    -    use bitcoin::Network;
    -    use miniscript::ScriptContext;
    -    use std::str::FromStr;
    -
    -    // 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 (prvkey1, _, _) = setup_keys(TPRV0_STR);
    -        let (prvkey2, _, _) = setup_keys(TPRV1_STR);
    -        let desc = descriptor!(sh(multi 2, prvkey1, prvkey2)).unwrap();
    -        let (_, keymap) = desc.to_wallet_descriptor(Network::Testnet).unwrap();
    -
    -        let signers = SignersContainer::from(keymap);
    -        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);
    -        let signer2 = Arc::new(DummySigner);
    -        let signer3 = Arc::new(DummySigner);
    -
    -        signers.add_external(
    -            SignerId::Fingerprint(b"cafe"[..].into()),
    -            SignerOrdering(1),
    -            signer1.clone(),
    -        );
    -        signers.add_external(
    -            SignerId::Fingerprint(b"babe"[..].into()),
    -            SignerOrdering(2),
    -            signer2.clone(),
    -        );
    -        signers.add_external(
    -            SignerId::Fingerprint(b"feed"[..].into()),
    -            SignerOrdering(3),
    -            signer3.clone(),
    -        );
    -
    -        // Check that signers are sorted from lowest to highest ordering
    -        let signers = signers.signers();
    -        assert_eq!(Arc::as_ptr(signers[0]), Arc::as_ptr(&signer1));
    -        assert_eq!(Arc::as_ptr(signers[1]), Arc::as_ptr(&signer2));
    -        assert_eq!(Arc::as_ptr(signers[2]), Arc::as_ptr(&signer3));
    -    }
    -
    -    #[test]
    -    fn find_signer_by_id() {
    -        let mut signers = SignersContainer::new();
    -        let signer1: Arc<dyn Signer> = Arc::new(DummySigner);
    -        let signer2: Arc<dyn Signer> = Arc::new(DummySigner);
    -        let signer3: Arc<dyn Signer> = Arc::new(DummySigner);
    -        let signer4: Arc<dyn Signer> = Arc::new(DummySigner);
    -
    -        let id1 = SignerId::Fingerprint(b"cafe"[..].into());
    -        let id2 = SignerId::Fingerprint(b"babe"[..].into());
    -        let id3 = SignerId::Fingerprint(b"feed"[..].into());
    -        let id_nonexistent = SignerId::Fingerprint(b"fefe"[..].into());
    -
    -        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 Arc::as_ptr(&signer1) == Arc::as_ptr(signer))
    -        );
    -        assert!(
    -            matches!(signers.find(id2), Some(signer) if Arc::as_ptr(&signer2) == Arc::as_ptr(signer))
    -        );
    -        assert!(
    -            matches!(signers.find(id3.clone()), Some(signer) if Arc::as_ptr(&signer3) == Arc::as_ptr(signer))
    -        );
    -
    -        // 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 Arc::as_ptr(&signer4) == Arc::as_ptr(signer))
    -        );
    -
    -        // Can't find anything with ID that doesn't exist
    -        assert!(matches!(signers.find(id_nonexistent), None));
    -    }
    -
    -    #[derive(Debug)]
    -    struct DummySigner;
    -    impl Signer for DummySigner {
    -        fn sign(
    -            &self,
    -            _psbt: &mut PartiallySignedTransaction,
    -            _input_index: Option<usize>,
    -            _secp: &SecpCtx,
    -        ) -> Result<(), SignerError> {
    -            Ok(())
    -        }
    -
    -        fn sign_whole_tx(&self) -> bool {
    -            true
    -        }
    -    }
    -
    -    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::ExtendedPrivKey::from_str(tprv).unwrap();
    -        let tpub = bip32::ExtendedPubKey::from_private(&secp, &tprv);
    -        let fingerprint = tprv.fingerprint(&secp);
    -        let prvkey = (tprv, path.clone()).to_descriptor_key().unwrap();
    -        let pubkey = (tpub, path).to_descriptor_key().unwrap();
    -
    -        (prvkey, pubkey, fingerprint)
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/time.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/time.rs.html deleted file mode 100644 index d45d75e8a0..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/time.rs.html +++ /dev/null @@ -1,178 +0,0 @@ -time.rs - source - -
     1
    - 2
    - 3
    - 4
    - 5
    - 6
    - 7
    - 8
    - 9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -74
    -75
    -76
    -77
    -78
    -79
    -80
    -81
    -82
    -83
    -84
    -85
    -86
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Cross-platform time
    -//!
    -//! This module provides a function to get the current timestamp that works on all the platforms
    -//! supported by the library.
    -//!
    -//! It can be useful to compare it with the timestamps found in
    -//! [`TransactionDetails`](crate::types::TransactionDetails).
    -
    -use std::time::Duration;
    -
    -#[cfg(target_arch = "wasm32")]
    -use js_sys::Date;
    -#[cfg(not(target_arch = "wasm32"))]
    -use std::time::{Instant as SystemInstant, SystemTime, UNIX_EPOCH};
    -
    -/// Return the current timestamp in seconds
    -#[cfg(not(target_arch = "wasm32"))]
    -pub fn get_timestamp() -> u64 {
    -    SystemTime::now()
    -        .duration_since(UNIX_EPOCH)
    -        .unwrap()
    -        .as_secs()
    -}
    -/// Return the current timestamp in seconds
    -#[cfg(target_arch = "wasm32")]
    -pub fn get_timestamp() -> u64 {
    -    let millis = Date::now();
    -
    -    (millis / 1000.0) as u64
    -}
    -
    -#[cfg(not(target_arch = "wasm32"))]
    -pub(crate) struct Instant(SystemInstant);
    -#[cfg(target_arch = "wasm32")]
    -pub(crate) struct Instant(Duration);
    -
    -impl Instant {
    -    #[cfg(not(target_arch = "wasm32"))]
    -    pub fn new() -> Self {
    -        Instant(SystemInstant::now())
    -    }
    -    #[cfg(target_arch = "wasm32")]
    -    pub fn new() -> Self {
    -        let millis = Date::now();
    -
    -        let secs = millis / 1000.0;
    -        let nanos = (millis % 1000.0) * 1e6;
    -
    -        Instant(Duration::new(secs as u64, nanos as u32))
    -    }
    -
    -    #[cfg(not(target_arch = "wasm32"))]
    -    pub fn elapsed(&self) -> Duration {
    -        self.0.elapsed()
    -    }
    -    #[cfg(target_arch = "wasm32")]
    -    pub fn elapsed(&self) -> Duration {
    -        let now = Instant::new();
    -
    -        now.0.checked_sub(self.0).unwrap_or(Duration::new(0, 0))
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/tx_builder.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/tx_builder.rs.html deleted file mode 100644 index eceb370c5a..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/tx_builder.rs.html +++ /dev/null @@ -1,1482 +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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -//! Transaction builder
    -//!
    -//! ## Example
    -//!
    -//! ```
    -//! # use std::str::FromStr;
    -//! # use bitcoin::*;
    -//! # use bdk::*;
    -//! # use bdk::wallet::tx_builder::CreateTx;
    -//! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -//! // Create a transaction with one output to `to_address` of 50_000 satoshi, with a custom fee rate
    -//! // of 5.0 satoshi/vbyte, only spending non-change outputs and with RBF signaling
    -//! // enabled
    -//! let builder = TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
    -//!     .fee_rate(FeeRate::from_sat_per_vb(5.0))
    -//!     .do_not_spend_change()
    -//!     .enable_rbf();
    -//! # let builder: TxBuilder<bdk::database::MemoryDatabase, _, CreateTx> = builder;
    -//! ```
    -
    -use std::collections::BTreeMap;
    -use std::collections::HashSet;
    -use std::default::Default;
    -use std::marker::PhantomData;
    -
    -use bitcoin::{OutPoint, Script, SigHashType, Transaction};
    -
    -use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm};
    -use crate::database::Database;
    -use crate::types::{FeeRate, KeychainKind, UTXO};
    -
    -/// Context in which the [`TxBuilder`] is valid
    -pub trait TxBuilderContext: std::fmt::Debug + Default + Clone {}
    -
    -/// [`Wallet::create_tx`](super::Wallet::create_tx) context
    -#[derive(Debug, Default, Clone)]
    -pub struct CreateTx;
    -impl TxBuilderContext for CreateTx {}
    -
    -/// [`Wallet::bump_fee`](super::Wallet::bump_fee) context
    -#[derive(Debug, Default, Clone)]
    -pub struct BumpFee;
    -impl TxBuilderContext for BumpFee {}
    -
    -/// A transaction builder
    -///
    -/// This structure contains the configuration that the wallet must follow to build a transaction.
    -///
    -/// For an example see [this module](super::tx_builder)'s documentation;
    -#[derive(Debug)]
    -pub struct TxBuilder<D: Database, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext> {
    -    pub(crate) recipients: Vec<(Script, u64)>,
    -    pub(crate) drain_wallet: bool,
    -    pub(crate) single_recipient: Option<Script>,
    -    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<OutPoint>,
    -    pub(crate) unspendable: HashSet<OutPoint>,
    -    pub(crate) manually_selected_only: bool,
    -    pub(crate) sighash: Option<SigHashType>,
    -    pub(crate) ordering: TxOrdering,
    -    pub(crate) locktime: Option<u32>,
    -    pub(crate) rbf: Option<RBFValue>,
    -    pub(crate) version: Option<Version>,
    -    pub(crate) change_policy: ChangeSpendPolicy,
    -    pub(crate) force_non_witness_utxo: bool,
    -    pub(crate) add_global_xpubs: bool,
    -    pub(crate) coin_selection: Cs,
    -    pub(crate) include_output_redeem_witness_script: bool,
    -
    -    phantom: PhantomData<(D, Ctx)>,
    -}
    -
    -#[derive(Debug)]
    -pub(crate) enum FeePolicy {
    -    FeeRate(FeeRate),
    -    FeeAmount(u64),
    -}
    -
    -impl std::default::Default for FeePolicy {
    -    fn default() -> Self {
    -        FeePolicy::FeeRate(FeeRate::default_min_relay_fee())
    -    }
    -}
    -
    -// Unfortunately derive doesn't work with `PhantomData`: https://github.com/rust-lang/rust/issues/26925
    -impl<D: Database, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext> Default
    -    for TxBuilder<D, Cs, Ctx>
    -where
    -    Cs: Default,
    -{
    -    fn default() -> Self {
    -        TxBuilder {
    -            recipients: Default::default(),
    -            drain_wallet: Default::default(),
    -            single_recipient: Default::default(),
    -            fee_policy: Default::default(),
    -            internal_policy_path: Default::default(),
    -            external_policy_path: Default::default(),
    -            utxos: Default::default(),
    -            unspendable: Default::default(),
    -            manually_selected_only: Default::default(),
    -            sighash: Default::default(),
    -            ordering: Default::default(),
    -            locktime: Default::default(),
    -            rbf: Default::default(),
    -            version: Default::default(),
    -            change_policy: Default::default(),
    -            force_non_witness_utxo: Default::default(),
    -            add_global_xpubs: Default::default(),
    -            coin_selection: Default::default(),
    -            include_output_redeem_witness_script: Default::default(),
    -
    -            phantom: PhantomData,
    -        }
    -    }
    -}
    -
    -// methods supported by both contexts, but only for `DefaultCoinSelectionAlgorithm`
    -impl<D: Database, Ctx: TxBuilderContext> TxBuilder<D, DefaultCoinSelectionAlgorithm, Ctx> {
    -    /// Create an empty builder
    -    pub fn new() -> Self {
    -        Self::default()
    -    }
    -}
    -
    -// methods supported by both contexts, for any CoinSelectionAlgorithm
    -impl<D: Database, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext> TxBuilder<D, Cs, Ctx> {
    -    /// Set a custom fee rate
    -    pub fn fee_rate(mut self, fee_rate: FeeRate) -> Self {
    -        self.fee_policy = Some(FeePolicy::FeeRate(fee_rate));
    -        self
    -    }
    -
    -    /// Set an absolute fee
    -    pub fn fee_absolute(mut self, fee_amount: u64) -> Self {
    -        self.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();
    -    /// let mut path = BTreeMap::new();
    -    /// path.insert("aabbccdd".to_string(), vec![0, 1]);
    -    ///
    -    /// let builder = TxBuilder::with_recipients(vec![(to_address.script_pubkey(), 50_000)])
    -    ///     .policy_path(path, KeychainKind::External);
    -    /// # let builder: TxBuilder<bdk::database::MemoryDatabase, _, _> = builder;
    -    /// ```
    -    pub fn policy_path(
    -        mut self,
    -        policy_path: BTreeMap<String, Vec<usize>>,
    -        keychain: KeychainKind,
    -    ) -> Self {
    -        let to_update = match keychain {
    -            KeychainKind::Internal => &mut self.internal_policy_path,
    -            KeychainKind::External => &mut self.external_policy_path,
    -        };
    -
    -        *to_update = Some(policy_path);
    -        self
    -    }
    -
    -    /// Replace the internal list of utxos that **must** be spent with a new list
    -    ///
    -    /// 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 utxos(mut self, utxos: Vec<OutPoint>) -> Self {
    -        self.utxos = utxos;
    -        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, utxo: OutPoint) -> Self {
    -        self.utxos.push(utxo);
    -        self
    -    }
    -
    -    /// Only spend utxos added by [`add_utxo`] and [`utxos`].
    -    ///
    -    /// 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
    -    /// [`utxos`]: Self::utxos
    -    pub fn manually_selected_only(mut self) -> Self {
    -        self.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::utxos`] and
    -    /// [`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>) -> Self {
    -        self.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::utxos`] and
    -    /// [`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) -> Self {
    -        self.unspendable.insert(unspendable);
    -        self
    -    }
    -
    -    /// Sign with a specific sig hash
    -    ///
    -    /// **Use this option very carefully**
    -    pub fn sighash(mut self, sighash: SigHashType) -> Self {
    -        self.sighash = Some(sighash);
    -        self
    -    }
    -
    -    /// Choose the ordering for inputs and outputs of the transaction
    -    pub fn ordering(mut self, ordering: TxOrdering) -> Self {
    -        self.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: u32) -> Self {
    -        self.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) -> Self {
    -        self.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) -> Self {
    -        self.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) -> Self {
    -        self.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) -> Self {
    -        self.change_policy = change_policy;
    -        self
    -    }
    -
    -    /// Fill-in the [`psbt::Input::non_witness_utxo`](bitcoin::util::psbt::Input::non_witness_utxo) field even if the wallet only has SegWit
    -    /// descriptors.
    -    ///
    -    /// This is useful for signers which always require it, like Trezor hardware wallets.
    -    pub fn force_non_witness_utxo(mut self) -> Self {
    -        self.force_non_witness_utxo = true;
    -        self
    -    }
    -
    -    /// Fill-in the [`psbt::Output::redeem_script`](bitcoin::util::psbt::Output::redeem_script) and
    -    /// [`psbt::Output::witness_script`](bitcoin::util::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) -> Self {
    -        self.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) -> Self {
    -        self.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) -> Self {
    -        self.drain_wallet = true;
    -        self
    -    }
    -
    -    /// Choose the coin selection algorithm
    -    ///
    -    /// Overrides the [`DefaultCoinSelectionAlgorithm`](super::coin_selection::DefaultCoinSelectionAlgorithm).
    -    pub fn coin_selection<P: CoinSelectionAlgorithm<D>>(
    -        self,
    -        coin_selection: P,
    -    ) -> TxBuilder<D, P, Ctx> {
    -        TxBuilder {
    -            recipients: self.recipients,
    -            drain_wallet: self.drain_wallet,
    -            single_recipient: self.single_recipient,
    -            fee_policy: self.fee_policy,
    -            internal_policy_path: self.internal_policy_path,
    -            external_policy_path: self.external_policy_path,
    -            utxos: self.utxos,
    -            unspendable: self.unspendable,
    -            manually_selected_only: self.manually_selected_only,
    -            sighash: self.sighash,
    -            ordering: self.ordering,
    -            locktime: self.locktime,
    -            rbf: self.rbf,
    -            version: self.version,
    -            change_policy: self.change_policy,
    -            force_non_witness_utxo: self.force_non_witness_utxo,
    -            add_global_xpubs: self.add_global_xpubs,
    -            include_output_redeem_witness_script: self.include_output_redeem_witness_script,
    -            coin_selection,
    -
    -            phantom: PhantomData,
    -        }
    -    }
    -}
    -
    -// methods supported only by create_tx, and only for `DefaultCoinSelectionAlgorithm`
    -impl<D: Database> TxBuilder<D, DefaultCoinSelectionAlgorithm, CreateTx> {
    -    /// Create a builder starting from a list of recipients
    -    pub fn with_recipients(recipients: Vec<(Script, u64)>) -> Self {
    -        Self::default().set_recipients(recipients)
    -    }
    -}
    -
    -// methods supported only by create_tx, for any `CoinSelectionAlgorithm`
    -impl<D: Database, Cs: CoinSelectionAlgorithm<D>> TxBuilder<D, Cs, CreateTx> {
    -    /// Replace the recipients already added with a new list
    -    pub fn set_recipients(mut self, recipients: Vec<(Script, u64)>) -> Self {
    -        self.recipients = recipients;
    -        self
    -    }
    -
    -    /// Add a recipient to the internal list
    -    pub fn add_recipient(mut self, script_pubkey: Script, amount: u64) -> Self {
    -        self.recipients.push((script_pubkey, amount));
    -        self
    -    }
    -
    -    /// Set a single recipient that will get all the selected funds minus the fee. No change will
    -    /// be created
    -    ///
    -    /// This method overrides any recipient set with [`set_recipients`](Self::set_recipients) or
    -    /// [`add_recipient`](Self::add_recipient).
    -    ///
    -    /// It can only be used in conjunction with [`drain_wallet`](Self::drain_wallet) to send the
    -    /// entire content of the wallet (minus filters) to a single recipient or with a
    -    /// list of manually selected UTXOs by enabling [`manually_selected_only`](Self::manually_selected_only)
    -    /// and selecting them with [`utxos`](Self::utxos) or [`add_utxo`](Self::add_utxo).
    -    ///
    -    /// When bumping the fees of a transaction made with this option, the user should remeber to
    -    /// add [`maintain_single_recipient`](Self::maintain_single_recipient) to correctly update the
    -    /// single output instead of adding one more for the change.
    -    pub fn set_single_recipient(mut self, recipient: Script) -> Self {
    -        self.single_recipient = Some(recipient);
    -        self.recipients.clear();
    -
    -        self
    -    }
    -
    -    /// Enable signaling RBF
    -    ///
    -    /// This will use the default nSequence value of `0xFFFFFFFD`.
    -    pub fn enable_rbf(mut self) -> Self {
    -        self.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: u32) -> Self {
    -        self.rbf = Some(RBFValue::Value(nsequence));
    -        self
    -    }
    -}
    -
    -// methods supported only by bump_fee
    -impl<D: Database> TxBuilder<D, DefaultCoinSelectionAlgorithm, BumpFee> {
    -    /// Bump the fees of a transaction made with [`set_single_recipient`](Self::set_single_recipient)
    -    ///
    -    /// Unless extra inputs are specified with [`add_utxo`] or [`utxos`], this flag will make
    -    /// `bump_fee` reduce the value of the existing output, or fail if it would be consumed
    -    /// entirely given the higher new fee rate.
    -    ///
    -    /// If extra inputs are added and they are not entirely consumed in fees, a change output will not
    -    /// be added; the existing output will simply grow in value.
    -    ///
    -    /// Fails if the transaction has more than one outputs.
    -    ///
    -    /// [`add_utxo`]: Self::add_utxo
    -    /// [`utxos`]: Self::utxos
    -    pub fn maintain_single_recipient(mut self) -> Self {
    -        self.single_recipient = Some(Script::default());
    -        self
    -    }
    -}
    -
    -/// Ordering of the transaction's inputs and outputs
    -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
    -pub enum TxOrdering {
    -    /// Randomized (default)
    -    Shuffle,
    -    /// Unchanged
    -    Untouched,
    -    /// BIP69 / Lexicographic
    -    BIP69Lexicographic,
    -}
    -
    -impl Default for TxOrdering {
    -    fn default() -> Self {
    -        TxOrdering::Shuffle
    -    }
    -}
    -
    -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;
    -                #[cfg(test)]
    -                use rand::SeedableRng;
    -
    -                #[cfg(not(test))]
    -                let mut rng = rand::thread_rng();
    -                #[cfg(test)]
    -                let mut rng = rand::rngs::StdRng::seed_from_u64(0);
    -
    -                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(u32),
    -}
    -
    -impl RBFValue {
    -    pub(crate) fn get_value(&self) -> u32 {
    -        match self {
    -            RBFValue::Default => 0xFFFFFFFD,
    -            RBFValue::Value(v) => *v,
    -        }
    -    }
    -}
    -
    -/// Policy regarding the use of change outputs when creating a transaction
    -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
    -pub enum ChangeSpendPolicy {
    -    /// Use both change and non-change outputs (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 Default for ChangeSpendPolicy {
    -    fn default() -> Self {
    -        ChangeSpendPolicy::ChangeAllowed
    -    }
    -}
    -
    -impl ChangeSpendPolicy {
    -    pub(crate) fn is_satisfied_by(&self, utxo: &UTXO) -> 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: &'static 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 bitcoin::consensus::deserialize;
    -    use bitcoin::hashes::hex::FromHex;
    -
    -    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();
    -
    -        TxOrdering::Shuffle.sort_tx(&mut tx);
    -
    -        assert_eq!(original_tx.input, tx.input);
    -        assert_ne!(original_tx.output, tx.output);
    -    }
    -
    -    #[test]
    -    fn test_output_ordering_bip69() {
    -        use std::str::FromStr;
    -
    -        let original_tx = ordering_test_tx!();
    -        let mut tx = original_tx.clone();
    -
    -        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, 800);
    -        assert_eq!(tx.output[1].script_pubkey, From::from(vec![0xAA]));
    -        assert_eq!(tx.output[2].script_pubkey, From::from(vec![0xAA, 0xEE]));
    -    }
    -
    -    fn get_test_utxos() -> Vec<UTXO> {
    -        vec![
    -            UTXO {
    -                outpoint: OutPoint {
    -                    txid: Default::default(),
    -                    vout: 0,
    -                },
    -                txout: Default::default(),
    -                keychain: KeychainKind::External,
    -            },
    -            UTXO {
    -                outpoint: OutPoint {
    -                    txid: Default::default(),
    -                    vout: 1,
    -                },
    -                txout: Default::default(),
    -                keychain: KeychainKind::Internal,
    -            },
    -        ]
    -    }
    -
    -    #[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))
    -            .collect::<Vec<_>>();
    -
    -        assert_eq!(filtered.len(), 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/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/utils.rs.html b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/utils.rs.html deleted file mode 100644 index e077192fc2..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/src/bdk/wallet/utils.rs.html +++ /dev/null @@ -1,580 +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
    -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
    -
    -// Magical Bitcoin Library
    -// Written in 2020 by
    -//     Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020 Magical Bitcoin
    -//
    -// Permission is hereby granted, free of charge, to any person obtaining a copy
    -// of this software and associated documentation files (the "Software"), to deal
    -// in the Software without restriction, including without limitation the rights
    -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    -// copies of the Software, and to permit persons to whom the Software is
    -// furnished to do so, subject to the following conditions:
    -//
    -// The above copyright notice and this permission notice shall be included in all
    -// copies or substantial portions of the Software.
    -//
    -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    -// SOFTWARE.
    -
    -use bitcoin::secp256k1::{All, Secp256k1};
    -use bitcoin::util::bip32;
    -
    -use miniscript::descriptor::DescriptorPublicKeyCtx;
    -use miniscript::{MiniscriptKey, Satisfier, ToPublicKey};
    -
    -// De-facto standard "dust limit" (even though it should change based on the output type)
    -const DUST_LIMIT_SATOSHI: u64 = 546;
    -
    -// MSB of the nSequence. If set there's no consensus-constraint, so it must be disabled when
    -// spending using CSV in order to enforce CSV rules
    -pub(crate) const SEQUENCE_LOCKTIME_DISABLE_FLAG: u32 = 1 << 31;
    -// 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;
    -// Mask for the bits used to express the timelock
    -pub(crate) const SEQUENCE_LOCKTIME_MASK: u32 = 0x0000FFFF;
    -
    -// Threshold for nLockTime to be considered a block-height-based timelock rather than time-based
    -pub(crate) const BLOCKS_TIMELOCK_THRESHOLD: u32 = 500000000;
    -
    -/// Trait to check if a value is below the dust limit
    -// we implement this trait to make sure we don't mess up the comparison with off-by-one like a <
    -// instead of a <= etc. The constant value for the dust limit is not public on purpose, to
    -// encourage the usage of this trait.
    -pub trait IsDust {
    -    /// Check whether or not a value is below dust limit
    -    fn is_dust(&self) -> bool;
    -}
    -
    -impl IsDust for u64 {
    -    fn is_dust(&self) -> bool {
    -        *self <= DUST_LIMIT_SATOSHI
    -    }
    -}
    -
    -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: u32, csv: u32) -> bool {
    -    // This flag cannot be set in the nSequence when spending using OP_CSV
    -    if rbf & SEQUENCE_LOCKTIME_DISABLE_FLAG != 0 {
    -        return false;
    -    }
    -
    -    let mask = SEQUENCE_LOCKTIME_TYPE_FLAG | SEQUENCE_LOCKTIME_MASK;
    -    let rbf = rbf & mask;
    -    let csv = csv & mask;
    -
    -    // Both values should be represented in the same unit (either time-based or
    -    // block-height based)
    -    if (rbf < SEQUENCE_LOCKTIME_TYPE_FLAG) != (csv < SEQUENCE_LOCKTIME_TYPE_FLAG) {
    -        return false;
    -    }
    -
    -    // The value should be at least `csv`
    -    if rbf < csv {
    -        return false;
    -    }
    -
    -    true
    -}
    -
    -pub(crate) fn check_nlocktime(nlocktime: u32, required: u32) -> bool {
    -    // Both values should be expressed in the same unit
    -    if (nlocktime < BLOCKS_TIMELOCK_THRESHOLD) != (required < BLOCKS_TIMELOCK_THRESHOLD) {
    -        return false;
    -    }
    -
    -    // The value should be at least `required`
    -    if nlocktime < required {
    -        return false;
    -    }
    -
    -    true
    -}
    -
    -impl<ToPkCtx: Copy, Pk: MiniscriptKey + ToPublicKey<ToPkCtx>> Satisfier<ToPkCtx, Pk> for After {
    -    fn check_after(&self, n: u32) -> bool {
    -        if let Some(current_height) = self.current_height {
    -            current_height >= n
    -        } 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<ToPkCtx: Copy, Pk: MiniscriptKey + ToPublicKey<ToPkCtx>> Satisfier<ToPkCtx, Pk> for Older {
    -    fn check_older(&self, n: u32) -> bool {
    -        if let Some(current_height) = self.current_height {
    -            // TODO: test >= / >
    -            current_height as u64 >= self.create_height.unwrap_or(0) as u64 + n as u64
    -        } else {
    -            self.assume_height_reached
    -        }
    -    }
    -}
    -
    -pub(crate) type SecpCtx = Secp256k1<All>;
    -pub(crate) fn descriptor_to_pk_ctx(secp: &SecpCtx) -> DescriptorPublicKeyCtx<'_, All> {
    -    // Create a `to_pk_ctx` with a dummy derivation index, since we always use this on descriptor
    -    // that have already been derived with `Descriptor::derive()`, so the child number added here
    -    // is ignored.
    -    DescriptorPublicKeyCtx::new(secp, bip32::ChildNumber::Normal { index: 0 })
    -}
    -
    -pub struct ChunksIterator<I: Iterator> {
    -    iter: I,
    -    size: usize,
    -}
    -
    -impl<I: Iterator> ChunksIterator<I> {
    -    #[allow(dead_code)]
    -    pub fn new(iter: I, size: usize) -> Self {
    -        ChunksIterator { iter, size }
    -    }
    -}
    -
    -impl<I: Iterator> Iterator for ChunksIterator<I> {
    -    type Item = Vec<<I as std::iter::Iterator>::Item>;
    -
    -    fn next(&mut self) -> Option<Self::Item> {
    -        let mut v = Vec::new();
    -        for _ in 0..self.size {
    -            let e = self.iter.next();
    -
    -            match e {
    -                None => break,
    -                Some(val) => v.push(val),
    -            }
    -        }
    -
    -        if v.is_empty() {
    -            return None;
    -        }
    -
    -        Some(v)
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use super::{
    -        check_nlocktime, check_nsequence_rbf, BLOCKS_TIMELOCK_THRESHOLD,
    -        SEQUENCE_LOCKTIME_TYPE_FLAG,
    -    };
    -    use crate::types::FeeRate;
    -
    -    #[test]
    -    fn test_fee_from_btc_per_kb() {
    -        let fee = FeeRate::from_btc_per_kvb(1e-5);
    -        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
    -    }
    -
    -    #[test]
    -    fn test_fee_from_sats_vbyte() {
    -        let fee = FeeRate::from_sat_per_vb(1.0);
    -        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
    -    }
    -
    -    #[test]
    -    fn test_fee_default_min_relay_fee() {
    -        let fee = FeeRate::default_min_relay_fee();
    -        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
    -    }
    -
    -    #[test]
    -    fn test_check_nsequence_rbf_msb_set() {
    -        let result = check_nsequence_rbf(0x80000000, 5000);
    -        assert_eq!(result, false);
    -    }
    -
    -    #[test]
    -    fn test_check_nsequence_rbf_lt_csv() {
    -        let result = check_nsequence_rbf(4000, 5000);
    -        assert_eq!(result, false);
    -    }
    -
    -    #[test]
    -    fn test_check_nsequence_rbf_different_unit() {
    -        let result = check_nsequence_rbf(SEQUENCE_LOCKTIME_TYPE_FLAG + 5000, 5000);
    -        assert_eq!(result, false);
    -    }
    -
    -    #[test]
    -    fn test_check_nsequence_rbf_mask() {
    -        let result = check_nsequence_rbf(0x3f + 10_000, 5000);
    -        assert_eq!(result, true);
    -    }
    -
    -    #[test]
    -    fn test_check_nsequence_rbf_same_unit_blocks() {
    -        let result = check_nsequence_rbf(10_000, 5000);
    -        assert_eq!(result, true);
    -    }
    -
    -    #[test]
    -    fn test_check_nsequence_rbf_same_unit_time() {
    -        let result = check_nsequence_rbf(
    -            SEQUENCE_LOCKTIME_TYPE_FLAG + 10_000,
    -            SEQUENCE_LOCKTIME_TYPE_FLAG + 5000,
    -        );
    -        assert_eq!(result, true);
    -    }
    -
    -    #[test]
    -    fn test_check_nlocktime_lt_cltv() {
    -        let result = check_nlocktime(4000, 5000);
    -        assert_eq!(result, false);
    -    }
    -
    -    #[test]
    -    fn test_check_nlocktime_different_unit() {
    -        let result = check_nlocktime(BLOCKS_TIMELOCK_THRESHOLD + 5000, 5000);
    -        assert_eq!(result, false);
    -    }
    -
    -    #[test]
    -    fn test_check_nlocktime_same_unit_blocks() {
    -        let result = check_nlocktime(10_000, 5000);
    -        assert_eq!(result, true);
    -    }
    -
    -    #[test]
    -    fn test_check_nlocktime_same_unit_time() {
    -        let result = check_nlocktime(
    -            BLOCKS_TIMELOCK_THRESHOLD + 10_000,
    -            BLOCKS_TIMELOCK_THRESHOLD + 5000,
    -        );
    -        assert_eq!(result, true);
    -    }
    -}
    -
    -
    \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/storage.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/storage.js deleted file mode 100644 index 318275ed34..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/storage.js +++ /dev/null @@ -1 +0,0 @@ -var resourcesSuffix="";var darkThemes=["dark","ayu"];var currentTheme=document.getElementById("themeStyle");var mainTheme=document.getElementById("mainThemeStyle");var settingsDataset=(function(){var settingsElement=document.getElementById("default-settings");if(settingsElement===null){return null}var dataset=settingsElement.dataset;if(dataset===undefined){return null}return dataset})();function getSettingValue(settingName){var current=getCurrentValue('rustdoc-'+settingName);if(current!==null){return current}if(settingsDataset!==null){var def=settingsDataset[settingName.replace(/-/g,'_')];if(def!==undefined){return def}}return null}var localStoredTheme=getSettingValue("theme");var savedHref=[];function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(!elem||!elem.classList){return}elem.classList.add(className)}function removeClass(elem,className){if(!elem||!elem.classList){return}elem.classList.remove(className)}function onEach(arr,func,reversed){if(arr&&arr.length>0&&func){var length=arr.length;var i;if(reversed!==true){for(i=0;i=0;--i){if(func(arr[i])===true){return true}}}}return false}function onEachLazy(lazyArray,func,reversed){return onEach(Array.prototype.slice.call(lazyArray),func,reversed)}function hasOwnProperty(obj,property){return Object.prototype.hasOwnProperty.call(obj,property)}function usableLocalStorage(){if(typeof Storage==="undefined"){return false}try{return window.localStorage!==null&&window.localStorage!==undefined}catch(err){return false}}function updateLocalStorage(name,value){if(usableLocalStorage()){localStorage[name]=value}else{}}function getCurrentValue(name){if(usableLocalStorage()&&localStorage[name]!==undefined){return localStorage[name]}return null}function switchTheme(styleElem,mainStyleElem,newTheme,saveTheme){var fullBasicCss="rustdoc"+resourcesSuffix+".css";var fullNewTheme=newTheme+resourcesSuffix+".css";var newHref=mainStyleElem.href.replace(fullBasicCss,fullNewTheme);if(saveTheme===true){updateLocalStorage("rustdoc-theme",newTheme)}if(styleElem.href===newHref){return}var found=false;if(savedHref.length===0){onEachLazy(document.getElementsByTagName("link"),function(el){savedHref.push(el.href)})}onEach(savedHref,function(el){if(el===newHref){found=true;return true}});if(found===true){styleElem.href=newHref}}function useSystemTheme(value){if(value===undefined){value=true}updateLocalStorage("rustdoc-use-system-theme",value);var toggle=document.getElementById("use-system-theme");if(toggle&&toggle instanceof HTMLInputElement){toggle.checked=value}}var updateSystemTheme=(function(){if(!window.matchMedia){return function(){let cssTheme=getComputedStyle(document.documentElement).getPropertyValue('content');switchTheme(currentTheme,mainTheme,JSON.parse(cssTheme)||light,true)}}var mql=window.matchMedia("(prefers-color-scheme: dark)");function handlePreferenceChange(mql){if(getSettingValue("use-system-theme")!=="false"){var lightTheme=getSettingValue("preferred-light-theme")||"light";var darkTheme=getSettingValue("preferred-dark-theme")||"dark";if(mql.matches){switchTheme(currentTheme,mainTheme,darkTheme,true)}else{switchTheme(currentTheme,mainTheme,lightTheme,true)}}}mql.addListener(handlePreferenceChange);return function(){handlePreferenceChange(mql)}})();if(getSettingValue("use-system-theme")!=="false"&&window.matchMedia){if(getSettingValue("use-system-theme")===null&&getSettingValue("preferred-dark-theme")===null&&darkThemes.indexOf(localStoredTheme)>=0){updateLocalStorage("rustdoc-preferred-dark-theme",localStoredTheme)}updateSystemTheme()}else{switchTheme(currentTheme,mainTheme,getSettingValue("theme")||"light",false)} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/theme.js b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/theme.js deleted file mode 100644 index 8f9c49a429..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/theme.js +++ /dev/null @@ -1 +0,0 @@ -var themes=document.getElementById("theme-choices");var themePicker=document.getElementById("theme-picker");function showThemeButtonState(){themes.style.display="block";themePicker.style.borderBottomRightRadius="0";themePicker.style.borderBottomLeftRadius="0"}function hideThemeButtonState(){themes.style.display="none";themePicker.style.borderBottomRightRadius="3px";themePicker.style.borderBottomLeftRadius="3px"}function switchThemeButtonState(){if(themes.style.display==="block"){hideThemeButtonState()}else{showThemeButtonState()}};function handleThemeButtonsBlur(e){var active=document.activeElement;var related=e.relatedTarget;if(active.id!=="theme-picker"&&(!active.parentNode||active.parentNode.id!=="theme-choices")&&(!related||(related.id!=="theme-picker"&&(!related.parentNode||related.parentNode.id!=="theme-choices")))){hideThemeButtonState()}}themePicker.onclick=switchThemeButtonState;themePicker.onblur=handleThemeButtonsBlur;["ayu","dark","light"].forEach(function(item){var but=document.createElement("button");but.textContent=item;but.onclick=function(el){switchTheme(currentTheme,mainTheme,item,true);useSystemTheme(false)};but.onblur=handleThemeButtonsBlur;themes.appendChild(but)}) \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/wheel.svg b/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/wheel.svg deleted file mode 100644 index 01da3b24c7..0000000000 --- a/static/docs-rs/bdk/nightly/b8c6732c74bf7d4558a85d39a9e423347acf5ea0/wheel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/.lock b/static/docs-rs/bdk/nightly/latest/.lock deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/static/docs-rs/bdk/nightly/latest/COPYRIGHT.txt b/static/docs-rs/bdk/nightly/latest/COPYRIGHT.txt deleted file mode 100644 index c2629a83f7..0000000000 --- a/static/docs-rs/bdk/nightly/latest/COPYRIGHT.txt +++ /dev/null @@ -1,50 +0,0 @@ -These documentation pages include resources by third parties. This copyright -file applies only to those resources. The following third party resources are -included, and carry their own copyright notices and license terms: - -* Fira Sans (FiraSans-Regular.woff2, FiraSans-Medium.woff2, - FiraSans-Regular.woff, FiraSans-Medium.woff): - - Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ - with Reserved Font Name Fira Sans. - - Copyright (c) 2014, Telefonica S.A. - - Licensed under the SIL Open Font License, Version 1.1. - See FiraSans-LICENSE.txt. - -* rustdoc.css, main.js, and playpen.js: - - Copyright 2015 The Rust Developers. - Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or - the MIT license (LICENSE-MIT.txt) at your option. - -* normalize.css: - - Copyright (c) Nicolas Gallagher and Jonathan Neal. - Licensed under the MIT license (see LICENSE-MIT.txt). - -* Source Code Pro (SourceCodePro-Regular.ttf.woff2, - SourceCodePro-Semibold.ttf.woff2, SourceCodePro-It.ttf.woff2, - SourceCodePro-Regular.ttf.woff, SourceCodePro-Semibold.ttf.woff, - SourceCodePro-It.ttf.woff): - - Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), - with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark - of Adobe Systems Incorporated in the United States and/or other countries. - - Licensed under the SIL Open Font License, Version 1.1. - See SourceCodePro-LICENSE.txt. - -* Source Serif 4 (SourceSerif4-Regular.ttf.woff2, SourceSerif4-Bold.ttf.woff2, - SourceSerif4-It.ttf.woff2, SourceSerif4-Regular.ttf.woff, - SourceSerif4-Bold.ttf.woff, SourceSerif4-It.ttf.woff): - - Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name - 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United - States and/or other countries. - - Licensed under the SIL Open Font License, Version 1.1. - See SourceSerif4-LICENSE.md. - -This copyright file is intended to be distributed with rustdoc output. diff --git a/static/docs-rs/bdk/nightly/latest/FiraSans-LICENSE.txt b/static/docs-rs/bdk/nightly/latest/FiraSans-LICENSE.txt deleted file mode 100644 index ff9afab064..0000000000 --- a/static/docs-rs/bdk/nightly/latest/FiraSans-LICENSE.txt +++ /dev/null @@ -1,94 +0,0 @@ -Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. -with Reserved Font Name < Fira >, - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/docs-rs/bdk/nightly/latest/FiraSans-Medium.woff b/static/docs-rs/bdk/nightly/latest/FiraSans-Medium.woff deleted file mode 100644 index 7d742c5fb7..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/FiraSans-Medium.woff and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/FiraSans-Medium.woff2 b/static/docs-rs/bdk/nightly/latest/FiraSans-Medium.woff2 deleted file mode 100644 index 7a1e5fc548..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/FiraSans-Medium.woff2 and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/FiraSans-Regular.woff b/static/docs-rs/bdk/nightly/latest/FiraSans-Regular.woff deleted file mode 100644 index d8e0363f4e..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/FiraSans-Regular.woff and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/FiraSans-Regular.woff2 b/static/docs-rs/bdk/nightly/latest/FiraSans-Regular.woff2 deleted file mode 100644 index e766e06ccb..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/FiraSans-Regular.woff2 and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/LICENSE-APACHE.txt b/static/docs-rs/bdk/nightly/latest/LICENSE-APACHE.txt deleted file mode 100644 index 16fe87b06e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/LICENSE-APACHE.txt +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - -TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - -1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - -2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - -3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - -4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - -5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - -6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - -7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - -8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - -9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - -END OF TERMS AND CONDITIONS - -APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - -Copyright [yyyy] [name of copyright owner] - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. diff --git a/static/docs-rs/bdk/nightly/latest/LICENSE-MIT.txt b/static/docs-rs/bdk/nightly/latest/LICENSE-MIT.txt deleted file mode 100644 index 31aa79387f..0000000000 --- a/static/docs-rs/bdk/nightly/latest/LICENSE-MIT.txt +++ /dev/null @@ -1,23 +0,0 @@ -Permission is hereby granted, free of charge, to any -person obtaining a copy of this software and associated -documentation files (the "Software"), to deal in the -Software without restriction, including without -limitation the rights to use, copy, modify, merge, -publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software -is furnished to do so, subject to the following -conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions -of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY -CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -DEALINGS IN THE SOFTWARE. diff --git a/static/docs-rs/bdk/nightly/latest/SourceCodePro-It.ttf.woff b/static/docs-rs/bdk/nightly/latest/SourceCodePro-It.ttf.woff deleted file mode 100644 index 8d68f2febd..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/SourceCodePro-It.ttf.woff and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/SourceCodePro-It.ttf.woff2 b/static/docs-rs/bdk/nightly/latest/SourceCodePro-It.ttf.woff2 deleted file mode 100644 index 462c34efcd..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/SourceCodePro-It.ttf.woff2 and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/SourceCodePro-LICENSE.txt b/static/docs-rs/bdk/nightly/latest/SourceCodePro-LICENSE.txt deleted file mode 100644 index 07542572e3..0000000000 --- a/static/docs-rs/bdk/nightly/latest/SourceCodePro-LICENSE.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. - -This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/docs-rs/bdk/nightly/latest/SourceCodePro-Regular.ttf.woff b/static/docs-rs/bdk/nightly/latest/SourceCodePro-Regular.ttf.woff deleted file mode 100644 index 7be076e1fc..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/SourceCodePro-Regular.ttf.woff and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/SourceCodePro-Regular.ttf.woff2 b/static/docs-rs/bdk/nightly/latest/SourceCodePro-Regular.ttf.woff2 deleted file mode 100644 index 10b558e0b6..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/SourceCodePro-Regular.ttf.woff2 and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/SourceCodePro-Semibold.ttf.woff b/static/docs-rs/bdk/nightly/latest/SourceCodePro-Semibold.ttf.woff deleted file mode 100644 index 61bc67b802..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/SourceCodePro-Semibold.ttf.woff and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/SourceCodePro-Semibold.ttf.woff2 b/static/docs-rs/bdk/nightly/latest/SourceCodePro-Semibold.ttf.woff2 deleted file mode 100644 index 5ec64eef0e..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/SourceCodePro-Semibold.ttf.woff2 and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/SourceSerif4-Bold.ttf.woff b/static/docs-rs/bdk/nightly/latest/SourceSerif4-Bold.ttf.woff deleted file mode 100644 index 8ad41888e6..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/SourceSerif4-Bold.ttf.woff and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/SourceSerif4-Bold.ttf.woff2 b/static/docs-rs/bdk/nightly/latest/SourceSerif4-Bold.ttf.woff2 deleted file mode 100644 index db57d21455..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/SourceSerif4-Bold.ttf.woff2 and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/SourceSerif4-It.ttf.woff b/static/docs-rs/bdk/nightly/latest/SourceSerif4-It.ttf.woff deleted file mode 100644 index 2a34b5c42a..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/SourceSerif4-It.ttf.woff and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/SourceSerif4-It.ttf.woff2 b/static/docs-rs/bdk/nightly/latest/SourceSerif4-It.ttf.woff2 deleted file mode 100644 index 1cbc021a3a..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/SourceSerif4-It.ttf.woff2 and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/SourceSerif4-LICENSE.md b/static/docs-rs/bdk/nightly/latest/SourceSerif4-LICENSE.md deleted file mode 100644 index 68ea189240..0000000000 --- a/static/docs-rs/bdk/nightly/latest/SourceSerif4-LICENSE.md +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2014-2021 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. - -This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/docs-rs/bdk/nightly/latest/SourceSerif4-Regular.ttf.woff b/static/docs-rs/bdk/nightly/latest/SourceSerif4-Regular.ttf.woff deleted file mode 100644 index 45a5521ab0..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/SourceSerif4-Regular.ttf.woff and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/SourceSerif4-Regular.ttf.woff2 b/static/docs-rs/bdk/nightly/latest/SourceSerif4-Regular.ttf.woff2 deleted file mode 100644 index 2db73fe2b4..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/SourceSerif4-Regular.ttf.woff2 and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/ayu.css b/static/docs-rs/bdk/nightly/latest/ayu.css deleted file mode 100644 index af24cd6cca..0000000000 --- a/static/docs-rs/bdk/nightly/latest/ayu.css +++ /dev/null @@ -1 +0,0 @@ - body{background-color:#0f1419;color:#c5c5c5;}h1,h2,h3,h4{color:white;}h1.fqn{border-bottom-color:#5c6773;}h1.fqn a{color:#fff;}h2,h3,h4{border-bottom-color:#5c6773;}h4{border:none;}.in-band{background-color:#0f1419;}.invisible{background:rgba(0,0,0,0);}.docblock code{color:#ffb454;}.code-header{color:#e6e1cf;}.docblock pre>code,pre>code{color:#e6e1cf;}span code{color:#e6e1cf;}.docblock a>code{color:#39AFD7 !important;}.docblock code,.docblock-short code{background-color:#191f26;}pre,.rustdoc.source .example-wrap{color:#e6e1cf;background-color:#191f26;}.sidebar{background-color:#14191f;}.logo-container.rust-logo>img{filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);}*{scrollbar-color:#5c6773 transparent;}.sidebar{scrollbar-color:#5c6773 transparent;}::-webkit-scrollbar-track{background-color:transparent;}::-webkit-scrollbar-thumb{background-color:#5c6773;}.sidebar::-webkit-scrollbar-track{background-color:transparent;}.sidebar::-webkit-scrollbar-thumb{background-color:#5c6773;}.sidebar .current{background-color:transparent;color:#ffb44c;}.source .sidebar{background-color:#0f1419;}.sidebar .location{border-color:#000;background-color:#0f1419;color:#fff;}.sidebar-elems .location{color:#ff7733;}.sidebar-elems .location a{color:#fff;}.sidebar .version{border-bottom-color:#424c57;}.sidebar-title{border-top-color:#5c6773;border-bottom-color:#5c6773;}.block a:hover{background:transparent;color:#ffb44c;}.line-numbers span{color:#5c6773;}.line-numbers .line-highlighted{color:#708090;background-color:rgba(255,236,164,0.06);padding-right:4px;border-right:1px solid #ffb44c;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#5c6773;}.docblock table td,.docblock table th{border-color:#5c6773;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#c5c5c5;}.search-results a:hover{background-color:#777;}.search-results a:focus{color:#000 !important;background-color:#c6afb3;}.search-results a{color:#0096cf;}.search-results a div.desc{color:#c5c5c5;}.content .item-info::before{color:#ccc;}.content span.foreigntype,.content a.foreigntype{color:#ef57ff;}.content span.union,.content a.union{color:#98a01c;}.content span.constant,.content a.constant,.content span.static,.content a.static{color:#6380a0;}.content span.primitive,.content a.primitive{color:#32889b;}.content span.traitalias,.content a.traitalias{color:#57d399;}.content span.keyword,.content a.keyword{color:#de5249;}.content span.externcrate,.content span.mod,.content a.mod{color:#acccf9;}.content span.struct,.content a.struct{color:#ffa0a5;}.content span.enum,.content a.enum{color:#99e0c9;}.content span.trait,.content a.trait{color:#39AFD7;}.content span.type,.content a.type{color:#cfbcf5;}.content span.fn,.content a.fn,.content span.method,.content a.method,.content span.tymethod,.content a.tymethod,.content .fnname{color:#fdd687;}.content span.attr,.content a.attr,.content span.derive,.content a.derive,.content span.macro,.content a.macro{color:#a37acc;}pre.rust .comment{color:#788797;}pre.rust .doccomment{color:#a1ac88;}nav:not(.sidebar){border-bottom-color:#424c57;}nav.main .current{border-top-color:#5c6773;border-bottom-color:#5c6773;}nav.main .separator{border:1px solid #5c6773;}a{color:#c5c5c5;}body.source .example-wrap pre.rust a{background:#333;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.item-info a,#help a{color:#39AFD7;}details.rustdoc-toggle>summary.hideme>span,details.rustdoc-toggle>summary::before,details.undocumented>summary::before{color:#999;}details.rustdoc-toggle>summary::before,details.undocumented>summary::before{filter:invert(100%);}#crate-search{color:#c5c5c5;background-color:#141920;box-shadow:0 0 0 1px #424c57,0 0 0 2px transparent;border-color:#424c57;}.search-input{color:#ffffff;background-color:#141920;box-shadow:0 0 0 1px #424c57,0 0 0 2px transparent;transition:box-shadow 150ms ease-in-out;}#crate-search+.search-input:focus{box-shadow:0 0 0 1px #148099,0 0 0 2px transparent;}.search-input:disabled{background-color:#3e3e3e;}.module-item .stab,.import-item .stab{color:#000;}.stab.unstable,.stab.deprecated,.stab.portability{color:#c5c5c5;background:#314559 !important;border-style:none !important;border-radius:4px;padding:3px 6px 3px 6px;}.stab.portability>code{color:#e6e1cf;background:none;}#help>div{background:#14191f;box-shadow:0px 6px 20px 0px black;border:none;border-radius:4px;}#help span.bottom,#help span.top{border-color:#5c6773;}.since{color:grey;}.result-name .primitive>i,.result-name .keyword>i{color:#788797;}.line-numbers :target{background-color:transparent;}pre.rust .number,pre.rust .string{color:#b8cc52;}pre.rust .kw,pre.rust .kw-2,pre.rust .prelude-ty,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .op,pre.rust .lifetime{color:#ff7733;}pre.rust .macro,pre.rust .macro-nonterminal{color:#a37acc;}pre.rust .question-mark{color:#ff9011;}pre.rust .self{color:#36a3d9;font-style:italic;}pre.rust .attribute{color:#e6e1cf;}pre.rust .attribute .ident,pre.rust .attribute .op{color:#e6e1cf;}.example-wrap>pre.line-number{color:#5c67736e;border:none;}a.test-arrow{font-size:100%;color:#788797;border-radius:4px;background-color:rgba(57,175,215,0.09);}a.test-arrow:hover{background-color:rgba(57,175,215,0.368);color:#c5c5c5;}.toggle-label,.code-attribute{color:#999;}:target,:target>*{background:rgba(255,236,164,0.06);}:target{border-right:3px solid rgba(255,180,76,0.85);}pre.compile_fail{border-left:2px solid rgba(255,0,0,.4);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.4);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.5);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#39AFD7;}.tooltip::after{background-color:#314559;color:#c5c5c5;border:1px solid #5c6773;}.tooltip::before{border-color:transparent #314559 transparent transparent;}.notable-traits-tooltiptext{background-color:#314559;border-color:#5c6773;}.notable-traits-tooltiptext .notable{border-bottom-color:#5c6773;}#titles>button.selected{background-color:#141920 !important;border-bottom:1px solid #ffb44c !important;border-top:none;}#titles>button:not(.selected){background-color:transparent !important;border:none;}#titles>button:hover{border-bottom:1px solid rgba(242,151,24,0.3);}#titles>button>div.count{color:#888;}.search-input:focus{}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{}.content span.struct,.content a.struct,.block a.current.struct{}#titles>button:hover,#titles>button.selected{}.content span.type,.content a.type,.block a.current.type{}.content span.union,.content a.union,.block a.current.union{}pre.rust .lifetime{}.stab.unstable{}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){}.content span.enum,.content a.enum,.block a.current.enum{}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{}.content span.keyword,.content a.keyword,.block a.current.keyword{}pre.rust .comment{}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{}pre.rust .kw{}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{}pre.rust .doccomment{}.stab.deprecated{}.content a.attr,.content a.derive,.content a.macro{}.stab.portability{}.content span.primitive,.content a.primitive,.block a.current.primitive{}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{}pre.rust .kw-2,pre.rust .prelude-ty{}.content span.trait,.content a.trait,.block a.current.trait{}.search-results a:focus span{}a.result-trait:focus{}a.result-traitalias:focus{}a.result-mod:focus,a.result-externcrate:focus{}a.result-mod:focus{}a.result-externcrate:focus{}a.result-enum:focus{}a.result-struct:focus{}a.result-union:focus{}a.result-fn:focus,a.result-method:focus,a.result-tymethod:focus{}a.result-type:focus{}a.result-foreigntype:focus{}a.result-attr:focus,a.result-derive:focus,a.result-macro:focus{}a.result-constant:focus,a.result-static:focus{}a.result-primitive:focus{}a.result-keyword:focus{}@media (max-width:700px){.sidebar-menu{background-color:#14191f;border-bottom-color:#5c6773;border-right-color:#5c6773;}.sidebar-elems{background-color:#14191f;border-right-color:#5c6773;}#sidebar-filler{background-color:#14191f;border-bottom-color:#5c6773;}}kbd{color:#c5c5c5;background-color:#314559;border-color:#5c6773;border-bottom-color:#5c6773;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu,#help-button{border-color:#5c6773;background-color:#0f1419;color:#fff;}#theme-picker>img,#settings-menu>img{filter:invert(100);}#copy-path{color:#fff;}#copy-path>img{filter:invert(70%);}#copy-path:hover>img{filter:invert(100%);}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus,#help-button:hover,#help-button:focus{border-color:#e0e0e0;}#theme-choices{border-color:#5c6773;background-color:#0f1419;}#theme-choices>button:not(:first-child){border-top-color:#5c6773;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:rgba(110,110,110,0.33);}@media (max-width:700px){#theme-picker{background:#0f1419;}}#all-types{background-color:#14191f;}#all-types:hover{background-color:rgba(70,70,70,0.33);}.search-results .result-name span.alias{color:#c5c5c5;}.search-results .result-name span.grey{color:#999;}#sidebar-toggle{background-color:#14191f;}#sidebar-toggle:hover{background-color:rgba(70,70,70,0.33);}#source-sidebar{background-color:#14191f;}#source-sidebar>.title{color:#fff;border-bottom-color:#5c6773;}div.files>a:hover,div.name:hover{background-color:#14191f;color:#ffb44c;}div.files>.selected{background-color:#14191f;color:#ffb44c;}.setting-line>.title{border-bottom-color:#5c6773;}input:checked+.slider{background-color:#ffb454 !important;} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/all.html b/static/docs-rs/bdk/nightly/latest/bdk/all.html deleted file mode 100644 index 473787d6bb..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/all.html +++ /dev/null @@ -1,5 +0,0 @@ -List of all items in this crate

    List of all items[] - -

    Structs

    Enums

    Traits

    Macros

    Functions

    Typedefs

    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchain.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchain.html deleted file mode 100644 index 86b743a374..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchain.html +++ /dev/null @@ -1,41 +0,0 @@ -AnyBlockchain in bdk::blockchain::any - Rust

    Enum bdk::blockchain::any::AnyBlockchain[][src]

    pub enum AnyBlockchain {
    -    Electrum(ElectrumBlockchain),
    -    Esplora(EsploraBlockchain),
    -    CompactFilters(CompactFiltersBlockchain),
    -}
    Expand description

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

    -

    It allows switching backend at runtime

    -

    See this module’s documentation for a usage example.

    -

    Variants

    This is supported on crate feature electrum only.

    Electrum client

    -

    Tuple Fields of Electrum

    This is supported on crate feature esplora only.

    Esplora client

    -

    Tuple Fields of Esplora

    CompactFilters(CompactFiltersBlockchain)
    This is supported on crate feature compact_filters only.

    Compact filters client

    -

    Tuple Fields of CompactFilters

    Trait Implementations

    Return the set of Capability supported by this backend

    -

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

    -

    Populate the internal database with transactions and UTXOs Read more

    -

    Fetch a transaction from the blockchain given its txid

    -

    Broadcast a transaction

    -

    Return the current height

    -

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

    -

    Type that contains the configuration

    -

    Create a new instance given a configuration

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchainConfig.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchainConfig.html deleted file mode 100644 index bacd1a1623..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/any/enum.AnyBlockchainConfig.html +++ /dev/null @@ -1,67 +0,0 @@ -AnyBlockchainConfig in bdk::blockchain::any - Rust

    Enum bdk::blockchain::any::AnyBlockchainConfig[][src]

    pub enum AnyBlockchainConfig {
    -    Electrum(ElectrumBlockchainConfig),
    -    Esplora(EsploraBlockchainConfig),
    -    CompactFilters(CompactFiltersBlockchainConfig),
    -}
    Expand description

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

    -

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

    -

    This type can be serialized from a JSON object like:

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

    Variants

    This is supported on crate feature electrum only.

    Electrum client

    -

    Tuple Fields of Electrum

    This is supported on crate feature esplora only.

    Esplora client

    -

    Tuple Fields of Esplora

    This is supported on crate feature compact_filters only.

    Compact filters client

    -

    Tuple Fields of CompactFilters

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    This method tests for self and other values to be equal, and is used -by ==. Read more

    -

    This method tests for !=.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/blockchain/any/index.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/any/index.html deleted file mode 100644 index 538f2c8270..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/any/index.html +++ /dev/null @@ -1,44 +0,0 @@ -bdk::blockchain::any - Rust

    Module bdk::blockchain::any[][src]

    Expand description

    Runtime-checked blockchain types

    -

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

    -

    Example

    -

    In this example both wallet_electrum and wallet_esplora have the same type of -Wallet<AnyBlockchain, MemoryDatabase>. This means that they could both, for instance, be -assigned to a struct member.

    - -
    let electrum_blockchain = ElectrumBlockchain::from(electrum_client::Client::new("...")?);
    -let wallet_electrum: Wallet<AnyBlockchain, _> = Wallet::new(
    -    "...",
    -    None,
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -    electrum_blockchain.into(),
    -)?;
    -
    -let esplora_blockchain = EsploraBlockchain::new("...", 20);
    -let wallet_esplora: Wallet<AnyBlockchain, _> = Wallet::new(
    -    "...",
    -    None,
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -    esplora_blockchain.into(),
    -)?;
    -
    -

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

    - -
    let config = serde_json::from_str("...")?;
    -let blockchain = AnyBlockchain::from_config(&config)?;
    -let wallet = Wallet::new(
    -    "...",
    -    None,
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -    blockchain,
    -)?;
    -

    Enums

    -

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

    -

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

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/any/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/any/sidebar-items.js deleted file mode 100644 index 14144cf693..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/any/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["AnyBlockchain","Type that can contain any of the [`Blockchain`] types defined by the library"],["AnyBlockchainConfig","Type that can contain any of the blockchain configurations defined by the library"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/enum.CompactFiltersError.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/enum.CompactFiltersError.html deleted file mode 100644 index d1bf965657..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/enum.CompactFiltersError.html +++ /dev/null @@ -1,73 +0,0 @@ -CompactFiltersError in bdk::blockchain::compact_filters - Rust

    Enum bdk::blockchain::compact_filters::CompactFiltersError[][src]

    pub enum CompactFiltersError {
    -
    Show 15 variants InvalidResponse, - InvalidHeaders, - InvalidFilterHeader, - InvalidFilter, - MissingBlock, - DataCorruption, - NotConnected, - Timeout, - PeerBloomDisabled, - NoPeers, - Db(Error), - Io(Error), - Bip158(Error), - Time(SystemTimeError), - Global(Box<Error>), -
    }
    This is supported on crate feature compact_filters only.
    Expand description

    An error that can occur during sync with a CompactFiltersBlockchain

    -

    Variants

    InvalidResponse

    A peer sent an invalid or unexpected response

    -
    InvalidHeaders

    The headers returned are invalid

    -
    InvalidFilterHeader

    The compact filter headers returned are invalid

    -
    InvalidFilter

    The compact filter returned is invalid

    -
    MissingBlock

    The peer is missing a block in the valid chain

    -
    DataCorruption

    The data stored in the block filters storage are corrupted

    -
    NotConnected

    A peer is not connected

    -
    Timeout

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

    -
    PeerBloomDisabled

    The peer doesn’t advertise the BLOOM service flag

    -
    NoPeers

    No peers have been specified

    -
    Db(Error)

    Internal database error

    -

    Tuple Fields of Db

    0: Error
    Io(Error)

    Internal I/O error

    -

    Tuple Fields of Io

    0: Error
    Bip158(Error)

    Invalid BIP158 filter

    -

    Tuple Fields of Bip158

    0: Error

    Internal system time error

    -

    Tuple Fields of Time

    Global(Box<Error>)

    Wrapper for crate::error::Error

    -

    Tuple Fields of Global

    0: Box<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

    -
    🔬 This is a nightly-only experimental API. (backtrace)

    Returns a stack backtrace, if available, of where this error occurred. 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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Converts a reference to Self into a dynamic trait object of Fail.

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Returns the “name” of the error. Read more

    -

    Returns a reference to the underlying cause of this failure, if it -is an error that wraps other errors. Read more

    -

    Returns a reference to the Backtrace carried by this failure, if it -carries one. Read more

    -

    Provides context for this failure. Read more

    -

    Wraps this failure in a compatibility wrapper that implements -std::error::Error. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/index.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/index.html deleted file mode 100644 index 14bed612f4..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/index.html +++ /dev/null @@ -1,37 +0,0 @@ -bdk::blockchain::compact_filters - Rust

    Module bdk::blockchain::compact_filters[][src]

    This is supported on crate feature compact_filters only.
    Expand description

    Compact Filters

    -

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

    -

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

    -

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

    -

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

    -

    Example

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

    Structs

    -

    Data to connect to a Bitcoin P2P peer

    -

    Structure implementing the required blockchain traits

    -

    Configuration for a CompactFiltersBlockchain

    -

    Container for unconfirmed, but valid Bitcoin transactions

    -

    A Bitcoin peer

    -

    Enums

    -

    An error that can occur during sync with a CompactFiltersBlockchain

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

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

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

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

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/sidebar-items.js deleted file mode 100644 index 187af79563..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["CompactFiltersError","An error that can occur during sync with a [`CompactFiltersBlockchain`]"]],"struct":[["BitcoinPeerConfig","Data to connect to a Bitcoin P2P peer"],["CompactFiltersBlockchain","Structure implementing the required blockchain traits"],["CompactFiltersBlockchainConfig","Configuration for a [`CompactFiltersBlockchain`]"],["Mempool","Container for unconfirmed, but valid Bitcoin transactions"],["Peer","A Bitcoin peer"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.BitcoinPeerConfig.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.BitcoinPeerConfig.html deleted file mode 100644 index 529f5ba605..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.BitcoinPeerConfig.html +++ /dev/null @@ -1,39 +0,0 @@ -BitcoinPeerConfig in bdk::blockchain::compact_filters - Rust

    Struct bdk::blockchain::compact_filters::BitcoinPeerConfig[][src]

    pub struct BitcoinPeerConfig {
    -    pub address: String,
    -    pub socks5: Option<String>,
    -    pub socks5_credentials: Option<(String, String)>,
    -}
    This is supported on crate feature compact_filters only.
    Expand description

    Data to connect to a Bitcoin P2P peer

    -

    Fields

    address: String

    Peer address such as 127.0.0.1:18333

    -
    socks5: Option<String>

    Optional socks5 proxy

    -
    socks5_credentials: Option<(String, String)>

    Optional socks5 proxy credentials

    -

    Trait Implementations

    Returns a copy of the value. Read more

    -

    Performs copy-assignment from source. Read more

    -

    Formats the value using the given formatter. Read more

    -

    Deserialize this value from the given Serde deserializer. Read more

    -

    This method tests for self and other values to be equal, and is used -by ==. Read more

    -

    This method tests for !=.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html deleted file mode 100644 index ebd9e1bb42..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchain.html +++ /dev/null @@ -1,40 +0,0 @@ -CompactFiltersBlockchain in bdk::blockchain::compact_filters - Rust

    Struct bdk::blockchain::compact_filters::CompactFiltersBlockchain[][src]

    pub struct CompactFiltersBlockchain { /* fields omitted */ }
    This is supported on crate feature compact_filters only.
    Expand description

    Structure implementing the required blockchain traits

    -

    Example

    -

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

    -

    Implementations

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

    -

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

    -

    Trait Implementations

    Return the set of Capability supported by this backend

    -

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

    -

    Fetch a transaction from the blockchain given its txid

    -

    Broadcast a transaction

    -

    Return the current height

    -

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

    -

    Populate the internal database with transactions and UTXOs Read more

    -

    Type that contains the configuration

    -

    Create a new instance given a configuration

    -

    Formats the value using the given formatter. Read more

    -

    Performs the conversion.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchainConfig.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchainConfig.html deleted file mode 100644 index b9abcf5a31..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.CompactFiltersBlockchainConfig.html +++ /dev/null @@ -1,42 +0,0 @@ -CompactFiltersBlockchainConfig in bdk::blockchain::compact_filters - Rust

    Struct bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig[][src]

    pub struct CompactFiltersBlockchainConfig {
    -    pub peers: Vec<BitcoinPeerConfig>,
    -    pub network: Network,
    -    pub storage_dir: String,
    -    pub skip_blocks: Option<usize>,
    -}
    This is supported on crate feature compact_filters only.
    Expand description

    Configuration for a CompactFiltersBlockchain

    -

    Fields

    peers: Vec<BitcoinPeerConfig>

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

    -
    network: Network

    Network used

    -
    storage_dir: String

    Storage dir to save partially downloaded headers and full blocks

    -
    skip_blocks: Option<usize>

    Optionally skip initial skip_blocks blocks (default: 0)

    -

    Trait Implementations

    Returns a copy of the value. Read more

    -

    Performs copy-assignment from source. Read more

    -

    Formats the value using the given formatter. Read more

    -

    Deserialize this value from the given Serde deserializer. Read more

    -

    Performs the conversion.

    -

    This method tests for self and other values to be equal, and is used -by ==. Read more

    -

    This method tests for !=.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Mempool.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Mempool.html deleted file mode 100644 index cfa16dc28d..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Mempool.html +++ /dev/null @@ -1,31 +0,0 @@ -Mempool in bdk::blockchain::compact_filters - Rust

    Struct bdk::blockchain::compact_filters::Mempool[][src]

    pub struct Mempool(_);
    This is supported on crate feature compact_filters only.
    Expand description

    Container for unconfirmed, but valid Bitcoin transactions

    -

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

    -

    Implementations

    Create a new empty mempool

    -

    Add a transaction to the mempool

    -

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

    -

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

    -

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

    -

    Return the list of transactions contained in the mempool

    -

    Trait Implementations

    Formats the value using the given formatter. Read more

    -

    Returns the “default value” for a type. Read more

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Peer.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Peer.html deleted file mode 100644 index c19b1edd4d..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/compact_filters/struct.Peer.html +++ /dev/null @@ -1,34 +0,0 @@ -Peer in bdk::blockchain::compact_filters - Rust

    Struct bdk::blockchain::compact_filters::Peer[][src]

    pub struct Peer { /* fields omitted */ }
    This is supported on crate feature compact_filters only.
    Expand description

    A Bitcoin peer

    -

    Implementations

    Connect to a peer over a plaintext TCP connection

    -

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

    -

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

    -

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

    -

    Return the [VersionMessage] sent by the peer

    -

    Return the Bitcoin [Network] in use

    -

    Return the mempool used by this peer

    -

    Return whether or not the peer is still connected

    -

    Send a raw Bitcoin message to the peer

    -

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

    -

    Trait Implementations

    Formats the value using the given formatter. Read more

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/index.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/index.html deleted file mode 100644 index fdf321f533..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/index.html +++ /dev/null @@ -1,13 +0,0 @@ -bdk::blockchain::electrum - Rust

    Module bdk::blockchain::electrum[][src]

    This is supported on crate feature electrum only.
    Expand description

    Electrum

    -

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

    -

    Example

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

    Structs

    -

    Wrapper over an Electrum Client that implements the required blockchain traits

    -

    Configuration for an ElectrumBlockchain

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/sidebar-items.js deleted file mode 100644 index 1bd5458912..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["ElectrumBlockchain","Wrapper over an Electrum Client that implements the required blockchain traits"],["ElectrumBlockchainConfig","Configuration for an [`ElectrumBlockchain`]"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchain.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchain.html deleted file mode 100644 index 50327ac0ae..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchain.html +++ /dev/null @@ -1,33 +0,0 @@ -ElectrumBlockchain in bdk::blockchain::electrum - Rust

    Struct bdk::blockchain::electrum::ElectrumBlockchain[][src]

    pub struct ElectrumBlockchain { /* fields omitted */ }
    This is supported on crate feature electrum only.
    Expand description

    Wrapper over an Electrum Client that implements the required blockchain traits

    -

    Example

    -

    See the blockchain::electrum module for a usage example.

    -

    Trait Implementations

    Return the set of Capability supported by this backend

    -

    Setup the backend and populate the internal database for the first time Read more

    -

    Fetch a transaction from the blockchain given its txid

    -

    Broadcast a transaction

    -

    Return the current height

    -

    Estimate the fee rate required to confirm a transaction in a given target of blocks

    -

    Populate the internal database with transactions and UTXOs Read more

    -

    Type that contains the configuration

    -

    Create a new instance given a configuration

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchainConfig.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchainConfig.html deleted file mode 100644 index 214df70de2..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/electrum/struct.ElectrumBlockchainConfig.html +++ /dev/null @@ -1,45 +0,0 @@ -ElectrumBlockchainConfig in bdk::blockchain::electrum - Rust

    Struct bdk::blockchain::electrum::ElectrumBlockchainConfig[][src]

    pub struct ElectrumBlockchainConfig {
    -    pub url: String,
    -    pub socks5: Option<String>,
    -    pub retry: u8,
    -    pub timeout: Option<u8>,
    -    pub stop_gap: usize,
    -}
    This is supported on crate feature electrum only.
    Expand description

    Configuration for an ElectrumBlockchain

    -

    Fields

    url: String

    URL of the Electrum server (such as ElectrumX, Esplora, BWT) may start with ssl:// or tcp:// and include a port

    -

    eg. ssl://electrum.blockstream.info:60002

    -
    socks5: Option<String>

    URL of the socks5 proxy server or a Tor service

    -
    retry: u8

    Request retry count

    -
    timeout: Option<u8>

    Request timeout (seconds)

    -
    stop_gap: usize

    Stop searching addresses for transactions after finding an unused gap of this length

    -

    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

    -

    Performs the conversion.

    -

    This method tests for self and other values to be equal, and is used -by ==. Read more

    -

    This method tests for !=.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/blockchain/enum.Capability.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/enum.Capability.html deleted file mode 100644 index 3f003cef14..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/enum.Capability.html +++ /dev/null @@ -1,39 +0,0 @@ -Capability in bdk::blockchain - Rust

    Enum bdk::blockchain::Capability[][src]

    pub enum Capability {
    -    FullHistory,
    -    GetAnyTx,
    -    AccurateFees,
    -}
    Expand description

    Capabilities that can be supported by a Blockchain backend

    -

    Variants

    FullHistory

    Can recover the full history of a wallet and not only the set of currently spendable UTXOs

    -
    GetAnyTx

    Can fetch any historical transaction given its txid

    -
    AccurateFees

    Can compute accurate fees for the transactions found during sync

    -

    Trait Implementations

    Returns a copy of the value. Read more

    -

    Performs copy-assignment from source. Read more

    -

    Formats the value using the given formatter. Read more

    -

    Feeds this value into the given Hasher. Read more

    -

    Feeds a slice of this type into the given Hasher. Read more

    -

    This method tests for self and other values to be equal, and is used -by ==. Read more

    -

    This method tests for !=.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/enum.EsploraError.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/enum.EsploraError.html deleted file mode 100644 index 6b4fabb600..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/enum.EsploraError.html +++ /dev/null @@ -1,66 +0,0 @@ -EsploraError in bdk::blockchain::esplora - Rust

    Enum bdk::blockchain::esplora::EsploraError[][src]

    pub enum EsploraError {
    -    Ureq(Error),
    -    UreqTransport(Transport),
    -    HttpResponse(u16),
    -    Io(Error),
    -    NoHeader,
    -    Parsing(ParseIntError),
    -    BitcoinEncoding(Error),
    -    Hex(Error),
    -    TransactionNotFound(Txid),
    -    HeaderHeightNotFound(u32),
    -    HeaderHashNotFound(BlockHash),
    -}
    This is supported on crate feature esplora only.
    Expand description

    Errors that can happen during a sync with EsploraBlockchain

    -

    Variants

    Ureq(Error)

    Error during ureq HTTP request

    -

    Tuple Fields of Ureq

    0: Error
    UreqTransport(Transport)

    Transport error during the ureq HTTP call

    -

    Tuple Fields of UreqTransport

    0: Transport
    HttpResponse(u16)

    HTTP response error

    -

    Tuple Fields of HttpResponse

    0: u16
    Io(Error)

    IO error during ureq response read

    -

    Tuple Fields of Io

    0: Error
    NoHeader

    No header found in ureq response

    -
    Parsing(ParseIntError)

    Invalid number returned

    -

    Tuple Fields of Parsing

    BitcoinEncoding(Error)

    Invalid Bitcoin data returned

    -

    Tuple Fields of BitcoinEncoding

    0: Error
    Hex(Error)

    Invalid Hex data returned

    -

    Tuple Fields of Hex

    0: Error
    TransactionNotFound(Txid)

    Transaction not found

    -

    Tuple Fields of TransactionNotFound

    0: Txid
    HeaderHeightNotFound(u32)

    Header height not found

    -

    Tuple Fields of HeaderHeightNotFound

    0: u32
    HeaderHashNotFound(BlockHash)

    Header hash not found

    -

    Tuple Fields of HeaderHashNotFound

    0: BlockHash

    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

    -
    🔬 This is a nightly-only experimental API. (backtrace)

    Returns a stack backtrace, if available, of where this error occurred. 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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Converts a reference to Self into a dynamic trait object of Fail.

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Returns the “name” of the error. Read more

    -

    Returns a reference to the underlying cause of this failure, if it -is an error that wraps other errors. Read more

    -

    Returns a reference to the Backtrace carried by this failure, if it -carries one. Read more

    -

    Provides context for this failure. Read more

    -

    Wraps this failure in a compatibility wrapper that implements -std::error::Error. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/index.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/index.html deleted file mode 100644 index 0bbf5f0304..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/index.html +++ /dev/null @@ -1,19 +0,0 @@ -bdk::blockchain::esplora - Rust

    Module bdk::blockchain::esplora[][src]

    This is supported on crate feature esplora only.
    Expand description

    Esplora

    -

    This module defines a EsploraBlockchain struct that can query an Esplora -backend populate the wallet’s database by:

    -

    Example

    -
    let blockchain = EsploraBlockchain::new("https://blockstream.info/testnet/api", 20);
    -

    Esplora blockchain can use either ureq or reqwest for the HTTP client -depending on your needs (blocking or async respectively).

    -

    Please note, to configure the Esplora HTTP client correctly use one of: -Blocking: –features=‘esplora,ureq’ -Async: –features=‘async-interface,esplora,reqwest’ –no-default-features

    -

    Structs

    -

    Structure that implements the logic to sync with Esplora

    -

    Configuration for an EsploraBlockchain

    -

    Data type used when fetching transaction history from Esplora.

    -

    Enums

    -

    Errors that can happen during a sync with EsploraBlockchain

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/sidebar-items.js deleted file mode 100644 index bf88a1a159..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["EsploraError","Errors that can happen during a sync with [`EsploraBlockchain`]"]],"struct":[["EsploraBlockchain","Structure that implements the logic to sync with Esplora"],["EsploraBlockchainConfig","Configuration for an [`EsploraBlockchain`]"],["EsploraGetHistory","Data type used when fetching transaction history from Esplora."]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchain.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchain.html deleted file mode 100644 index d275ec2a49..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchain.html +++ /dev/null @@ -1,35 +0,0 @@ -EsploraBlockchain in bdk::blockchain::esplora - Rust

    Struct bdk::blockchain::esplora::EsploraBlockchain[][src]

    pub struct EsploraBlockchain { /* fields omitted */ }
    This is supported on crate feature esplora only.
    Expand description

    Structure that implements the logic to sync with Esplora

    -

    Example

    -

    See the blockchain::esplora module for a usage example.

    -

    Implementations

    Create a new instance of the client from a base URL and the stop_gap.

    -

    Set the inner ureq agent.

    -

    Trait Implementations

    Return the set of Capability supported by this backend

    -

    Setup the backend and populate the internal database for the first time Read more

    -

    Fetch a transaction from the blockchain given its txid

    -

    Broadcast a transaction

    -

    Return the current height

    -

    Estimate the fee rate required to confirm a transaction in a given target of blocks

    -

    Populate the internal database with transactions and UTXOs Read more

    -

    Type that contains the configuration

    -

    Create a new instance given a configuration

    -

    Formats the value using the given formatter. Read more

    -

    Performs the conversion.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchainConfig.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchainConfig.html deleted file mode 100644 index d8dc87b5e7..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraBlockchainConfig.html +++ /dev/null @@ -1,50 +0,0 @@ -EsploraBlockchainConfig in bdk::blockchain::esplora - Rust

    Struct bdk::blockchain::esplora::EsploraBlockchainConfig[][src]

    pub struct EsploraBlockchainConfig {
    -    pub base_url: String,
    -    pub proxy: Option<String>,
    -    pub timeout_read: u64,
    -    pub timeout_write: u64,
    -    pub stop_gap: usize,
    -}
    This is supported on crate feature esplora only.
    Expand description

    Configuration for an EsploraBlockchain

    -

    Fields

    base_url: String

    Base URL of the esplora service eg. https://blockstream.info/api/

    -
    proxy: Option<String>

    Optional URL of the proxy to use to make requests to the Esplora server

    -

    The string should be formatted as: <protocol>://<user>:<password>@host:<port>.

    -

    Note that the format of this value and the supported protocols change slightly between the -sync version of esplora (using ureq) and the async version (using reqwest). For more -details check with the documentation of the two crates. Both of them are compiled with -the socks feature enabled.

    -

    The proxy is ignored when targeting wasm32.

    -
    timeout_read: u64

    Socket read timeout.

    -
    timeout_write: u64

    Socket write timeout.

    -
    stop_gap: usize

    Stop searching addresses for transactions after finding an unused gap of this length.

    -

    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

    -

    Performs the conversion.

    -

    This method tests for self and other values to be equal, and is used -by ==. Read more

    -

    This method tests for !=.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraGetHistory.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraGetHistory.html deleted file mode 100644 index 02fa3f15f5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/struct.EsploraGetHistory.html +++ /dev/null @@ -1,21 +0,0 @@ -EsploraGetHistory in bdk::blockchain::esplora - Rust

    Struct bdk::blockchain::esplora::EsploraGetHistory[][src]

    pub struct EsploraGetHistory { /* fields omitted */ }
    This is supported on crate feature esplora only.
    Expand description

    Data type used when fetching transaction history from Esplora.

    -

    Trait Implementations

    Deserialize this value from the given Serde deserializer. Read more

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/ureq/struct.EsploraBlockchain.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/ureq/struct.EsploraBlockchain.html deleted file mode 100644 index 9e118ac7a5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/ureq/struct.EsploraBlockchain.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../../../bdk/blockchain/esplora/struct.EsploraBlockchain.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/ureq/struct.EsploraBlockchainConfig.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/ureq/struct.EsploraBlockchainConfig.html deleted file mode 100644 index 40575d9a80..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/esplora/ureq/struct.EsploraBlockchainConfig.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../../../bdk/blockchain/esplora/struct.EsploraBlockchainConfig.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.log_progress.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.log_progress.html deleted file mode 100644 index 582d5ced7b..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.log_progress.html +++ /dev/null @@ -1,4 +0,0 @@ -log_progress in bdk::blockchain - Rust

    Function bdk::blockchain::log_progress[][src]

    pub fn log_progress() -> LogProgress
    Expand description

    Create a new instance of LogProgress

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.noop_progress.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.noop_progress.html deleted file mode 100644 index e182f4305a..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.noop_progress.html +++ /dev/null @@ -1,4 +0,0 @@ -noop_progress in bdk::blockchain - Rust

    Function bdk::blockchain::noop_progress[][src]

    pub fn noop_progress() -> NoopProgress
    Expand description

    Create a new instance of NoopProgress

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.progress.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.progress.html deleted file mode 100644 index 17ce1479b7..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/fn.progress.html +++ /dev/null @@ -1,4 +0,0 @@ -progress in bdk::blockchain - Rust

    Function bdk::blockchain::progress[][src]

    pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>)
    Expand description

    Shortcut to create a channel (pair of Sender and Receiver) that can transport ProgressData

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/index.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/index.html deleted file mode 100644 index c7deb7cdde..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/index.html +++ /dev/null @@ -1,31 +0,0 @@ -bdk::blockchain - Rust

    Module bdk::blockchain[][src]

    Expand description

    Blockchain backends

    -

    This module provides the implementation of a few commonly-used backends like -Electrum, Esplora and -Compact Filters/Neutrino, along with a generalized trait -Blockchain that can be implemented to build customized backends.

    -

    Re-exports

    -
    pub use any::AnyBlockchain;
    pub use any::AnyBlockchainConfig;
    pub use self::electrum::ElectrumBlockchain;
    pub use self::electrum::ElectrumBlockchainConfig;
    pub use self::compact_filters::CompactFiltersBlockchain;

    Modules

    -

    Runtime-checked blockchain types

    -
    compact_filterscompact_filters

    Compact Filters

    -
    electrumelectrum

    Electrum

    -
    esploraesplora

    Esplora

    -

    Structs

    -

    Structure that implements the logic to sync with Esplora

    -

    Type that implements Progress and logs at level INFO every update received

    -

    Type that implements Progress and drops every update received

    -

    Enums

    -

    Capabilities that can be supported by a Blockchain backend

    -

    Traits

    -

    Trait that defines the actions that must be supported by a blockchain backend

    -

    Trait for Blockchain types that can be created given a configuration

    -

    Trait for types that can receive and process progress updates during Blockchain::sync and -Blockchain::setup

    -

    Functions

    -

    Create a new instance of LogProgress

    -

    Create a new instance of NoopProgress

    -

    Shortcut to create a channel (pair of Sender and Receiver) that can transport ProgressData

    -

    Type Definitions

    -

    Data sent with a progress update over a channel

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/sidebar-items.js deleted file mode 100644 index 8667824b32..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Capability","Capabilities that can be supported by a [`Blockchain`] backend"]],"fn":[["log_progress","Create a new instance of [`LogProgress`]"],["noop_progress","Create a new instance of [`NoopProgress`]"],["progress","Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]"]],"mod":[["any","Runtime-checked blockchain types"],["compact_filters","Compact Filters"],["electrum","Electrum"],["esplora","Esplora"]],"struct":[["EsploraBlockchain","Structure that implements the logic to sync with Esplora"],["LogProgress","Type that implements [`Progress`] and logs at level `INFO` every update received"],["NoopProgress","Type that implements [`Progress`] and drops every update received"]],"trait":[["Blockchain","Trait that defines the actions that must be supported by a blockchain backend"],["ConfigurableBlockchain","Trait for [`Blockchain`] types that can be created given a configuration"],["Progress","Trait for types that can receive and process progress updates during [`Blockchain::sync`] and [`Blockchain::setup`]"]],"type":[["ProgressData","Data sent with a progress update over a [`channel`]"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.EsploraBlockchain.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.EsploraBlockchain.html deleted file mode 100644 index c7a19a2bed..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.EsploraBlockchain.html +++ /dev/null @@ -1,35 +0,0 @@ -EsploraBlockchain in bdk::blockchain - Rust

    Struct bdk::blockchain::EsploraBlockchain[][src]

    pub struct EsploraBlockchain { /* fields omitted */ }
    Expand description

    Structure that implements the logic to sync with Esplora

    -

    Example

    -

    See the blockchain::esplora module for a usage example.

    -

    Implementations

    This is supported on crate feature esplora only.

    Create a new instance of the client from a base URL and the stop_gap.

    -
    This is supported on crate feature esplora only.

    Set the inner ureq agent.

    -

    Trait Implementations

    Return the set of Capability supported by this backend

    -

    Setup the backend and populate the internal database for the first time Read more

    -

    Fetch a transaction from the blockchain given its txid

    -

    Broadcast a transaction

    -

    Return the current height

    -

    Estimate the fee rate required to confirm a transaction in a given target of blocks

    -

    Populate the internal database with transactions and UTXOs Read more

    -

    Type that contains the configuration

    -

    Create a new instance given a configuration

    -

    Formats the value using the given formatter. Read more

    -

    Performs the conversion.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.LogProgress.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.LogProgress.html deleted file mode 100644 index d09f52c3c4..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.LogProgress.html +++ /dev/null @@ -1,27 +0,0 @@ -LogProgress in bdk::blockchain - Rust

    Struct bdk::blockchain::LogProgress[][src]

    pub struct LogProgress;
    Expand description

    Type that implements Progress and logs at level INFO every update received

    -

    Trait Implementations

    Returns a copy of the value. Read more

    -

    Performs copy-assignment from source. Read more

    -

    Send a new progress update Read more

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.NoopProgress.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.NoopProgress.html deleted file mode 100644 index 6b2ecaf8d1..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/struct.NoopProgress.html +++ /dev/null @@ -1,27 +0,0 @@ -NoopProgress in bdk::blockchain - Rust

    Struct bdk::blockchain::NoopProgress[][src]

    pub struct NoopProgress;
    Expand description

    Type that implements Progress and drops every update received

    -

    Trait Implementations

    Returns a copy of the value. Read more

    -

    Performs copy-assignment from source. Read more

    -

    Send a new progress update Read more

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.Blockchain.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.Blockchain.html deleted file mode 100644 index ac0001fa21..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.Blockchain.html +++ /dev/null @@ -1,35 +0,0 @@ -Blockchain in bdk::blockchain - Rust

    Trait bdk::blockchain::Blockchain[][src]

    pub trait Blockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability>;
    -
    fn setup<D: BatchDatabase, P: 'static + Progress>(
            &self,
            database: &mut D,
            progress_update: P
        ) -> Result<(), Error>; -
    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>; -
    fn broadcast(&self, tx: &Transaction) -> Result<(), Error>; -
    fn get_height(&self) -> Result<u32, Error>; -
    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>; - - fn sync<D: BatchDatabase, P: 'static + Progress>(
            &self,
            database: &mut D,
            progress_update: P
        ) -> Result<(), Error> { ... } -}
    Expand description

    Trait that defines the actions that must be supported by a blockchain backend

    -

    Required methods

    Return the set of Capability supported by this backend

    -

    Setup the backend and populate the internal database for the first time

    -

    This method is the equivalent of Blockchain::sync, but it’s guaranteed to only be -called once, at the first Wallet::sync.

    -

    The rationale behind the distinction between sync and setup is that some custom backends -might need to perform specific actions only the first time they are synced.

    -

    For types that do not have that distinction, only this method can be implemented, since -Blockchain::sync defaults to calling this internally if not overridden.

    -

    Fetch a transaction from the blockchain given its txid

    -

    Broadcast a transaction

    -

    Return the current height

    -

    Estimate the fee rate required to confirm a transaction in a given target of blocks

    -

    Provided methods

    Populate the internal database with transactions and UTXOs

    -

    If not overridden, it defaults to calling Blockchain::setup internally.

    -

    This method should implement the logic required to iterate over the list of the wallet’s -script_pubkeys using Database::iter_script_pubkeys and look for relevant transactions -in the blockchain to populate the database with BatchOperations::set_tx and -BatchOperations::set_utxo.

    -

    This method should also take care of removing UTXOs that are seen as spent in the -blockchain, using BatchOperations::del_utxo.

    -

    The progress_update object can be used to give the caller updates about the progress by using -Progress::update.

    -

    Implementations on Foreign Types

    Implementors

    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.ConfigurableBlockchain.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.ConfigurableBlockchain.html deleted file mode 100644 index a3e8655ff0..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.ConfigurableBlockchain.html +++ /dev/null @@ -1,9 +0,0 @@ -ConfigurableBlockchain in bdk::blockchain - Rust

    Trait bdk::blockchain::ConfigurableBlockchain[][src]

    pub trait ConfigurableBlockchain: Blockchain + Sized {
    -    type Config: Debug;
    -    fn from_config(config: &Self::Config) -> Result<Self, Error>;
    -}
    Expand description

    Trait for Blockchain types that can be created given a configuration

    -

    Associated Types

    Type that contains the configuration

    -

    Required methods

    Create a new instance given a configuration

    -

    Implementors

    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.Progress.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.Progress.html deleted file mode 100644 index 7e670cad1a..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/trait.Progress.html +++ /dev/null @@ -1,10 +0,0 @@ -Progress in bdk::blockchain - Rust

    Trait bdk::blockchain::Progress[][src]

    pub trait Progress: Send {
    -    fn update(
            &self,
            progress: f32,
            message: Option<String>
        ) -> Result<(), Error>; -}
    Expand description

    Trait for types that can receive and process progress updates during Blockchain::sync and -Blockchain::setup

    -

    Required methods

    Send a new progress update

    -

    The progress value should be in the range 0.0 - 100.0, and the message value is an -optional text message that can be displayed to the user.

    -

    Implementations on Foreign Types

    Implementors

    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/type.ProgressData.html b/static/docs-rs/bdk/nightly/latest/bdk/blockchain/type.ProgressData.html deleted file mode 100644 index b00b9f8183..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/blockchain/type.ProgressData.html +++ /dev/null @@ -1,4 +0,0 @@ -ProgressData in bdk::blockchain - Rust

    Type Definition bdk::blockchain::ProgressData[][src]

    pub type ProgressData = (f32, Option<String>);
    Expand description

    Data sent with a progress update over a channel

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyBatch.html b/static/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyBatch.html deleted file mode 100644 index b55b849074..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyBatch.html +++ /dev/null @@ -1,42 +0,0 @@ -AnyBatch in bdk::database::any - Rust

    Enum bdk::database::any::AnyBatch[][src]

    pub enum AnyBatch {
    -    Memory(<MemoryDatabase as BatchDatabase>::Batch),
    -    Sled(<Tree as BatchDatabase>::Batch),
    -    Sqlite(<SqliteDatabase as BatchDatabase>::Batch),
    -}
    Expand description

    Type that contains any of the BatchDatabase::Batch types defined by the library

    -

    Variants

    In-memory ephemeral database

    -

    Tuple Fields of Memory

    Sled(<Tree as BatchDatabase>::Batch)
    This is supported on crate feature key-value-db only.

    Simple key-value embedded database based on [sled]

    -

    Tuple Fields of Sled

    0: <Tree as BatchDatabase>::Batch
    This is supported on crate feature sqlite only.

    Sqlite embedded database using [rusqlite]

    -

    Tuple Fields of Sqlite

    Trait Implementations

    Store a script_pubkey along with its keychain and child number.

    -

    Store a LocalUtxo

    -

    Store a raw transaction

    -

    Store the metadata of a transaction

    -

    Store the last derivation index for a given keychain.

    -

    Delete a script_pubkey given the keychain and its child number.

    -

    Delete the data related to a specific script_pubkey, meaning the keychain and the child -number. Read more

    -

    Delete a LocalUtxo given its [OutPoint]

    -

    Delete a raw transaction given its [Txid]

    -

    Delete the metadata of a transaction and optionally the raw transaction itself

    -

    Delete the last derivation index for a keychain.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyDatabase.html b/static/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyDatabase.html deleted file mode 100644 index d868ceb875..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyDatabase.html +++ /dev/null @@ -1,63 +0,0 @@ -AnyDatabase in bdk::database::any - Rust

    Enum bdk::database::any::AnyDatabase[][src]

    pub enum AnyDatabase {
    -    Memory(MemoryDatabase),
    -    Sled(Tree),
    -    Sqlite(SqliteDatabase),
    -}
    Expand description

    Type that can contain any of the Database types defined by the library

    -

    It allows switching database type at runtime.

    -

    See this module’s documentation for a usage example.

    -

    Variants

    In-memory ephemeral database

    -

    Tuple Fields of Memory

    Sled(Tree)
    This is supported on crate feature key-value-db only.

    Simple key-value embedded database based on [sled]

    -

    Tuple Fields of Sled

    0: Tree
    This is supported on crate feature sqlite only.

    Sqlite embedded database using [rusqlite]

    -

    Tuple Fields of Sqlite

    Trait Implementations

    Container for the operations

    -

    Create a new batch container

    -

    Consume and apply a batch of operations

    -

    Store a script_pubkey along with its keychain and child number.

    -

    Store a LocalUtxo

    -

    Store a raw transaction

    -

    Store the metadata of a transaction

    -

    Store the last derivation index for a given keychain.

    -

    Delete a script_pubkey given the keychain and its child number.

    -

    Delete the data related to a specific script_pubkey, meaning the keychain and the child -number. Read more

    -

    Delete a LocalUtxo given its [OutPoint]

    -

    Delete a raw transaction given its [Txid]

    -

    Delete the metadata of a transaction and optionally the raw transaction itself

    -

    Delete the last derivation index for a keychain.

    -

    Type that contains the configuration

    -

    Create a new instance given a configuration

    -

    Read and checks the descriptor checksum for a given keychain. Read more

    -

    Return the list of script_pubkeys

    -

    Return the list of LocalUtxos

    -

    Return the list of raw transactions

    -

    Return the list of transactions metadata

    -

    Fetch a script_pubkey given the child number of a keychain.

    -

    Fetch the keychain and child number of a given script_pubkey

    -

    Fetch a LocalUtxo given its [OutPoint]

    -

    Fetch a raw transaction given its [Txid]

    -

    Fetch the transaction metadata and optionally also the raw transaction

    -

    Return the last defivation index for a keychain.

    -

    Increment the last derivation index for a keychain and return it Read more

    -

    Force changes to be written to disk

    -

    Formats the value using the given formatter. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyDatabaseConfig.html b/static/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyDatabaseConfig.html deleted file mode 100644 index d00058c87f..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/any/enum.AnyDatabaseConfig.html +++ /dev/null @@ -1,36 +0,0 @@ -AnyDatabaseConfig in bdk::database::any - Rust

    Enum bdk::database::any::AnyDatabaseConfig[][src]

    pub enum AnyDatabaseConfig {
    -    Memory(()),
    -    Sled(SledDbConfiguration),
    -    Sqlite(SqliteDbConfiguration),
    -}
    Expand description

    Type that can contain any of the database configurations defined by the library

    -

    This allows storing a single configuration that can be loaded into an AnyDatabase -instance. Wallets that plan to offer users the ability to switch blockchain backend at runtime -will find this particularly useful.

    -

    Variants

    Memory(())

    Memory database has no config

    -

    Tuple Fields of Memory

    0: ()
    This is supported on crate feature key-value-db only.

    Simple key-value embedded database based on [sled]

    -

    Tuple Fields of Sled

    This is supported on crate feature sqlite only.

    Sqlite embedded database using [rusqlite]

    -

    Tuple Fields of Sqlite

    Trait Implementations

    Formats the value using the given formatter. Read more

    -

    Deserialize this value from the given Serde deserializer. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/any/index.html b/static/docs-rs/bdk/nightly/latest/bdk/database/any/index.html deleted file mode 100644 index 32a137b083..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/any/index.html +++ /dev/null @@ -1,27 +0,0 @@ -bdk::database::any - Rust

    Module bdk::database::any[][src]

    Expand description

    Runtime-checked database types

    -

    This module provides the implementation of AnyDatabase which allows switching the -inner Database type at runtime.

    -

    Example

    -

    In this example, wallet_memory and wallet_sled have the same type of Wallet<(), AnyDatabase>.

    - -
    let memory = MemoryDatabase::default();
    -let wallet_memory = Wallet::new_offline("...", None, Network::Testnet, memory)?;
    -
    -let sled = sled::open("my-database")?.open_tree("default_tree")?;
    -let wallet_sled = Wallet::new_offline("...", None, Network::Testnet, sled)?;
    -

    When paired with the use of ConfigurableDatabase, it allows creating wallets with any -database supported using a single line of code:

    - -
    let config = serde_json::from_str("...")?;
    -let database = AnyDatabase::from_config(&config)?;
    -let wallet = Wallet::new_offline("...", None, Network::Testnet, database)?;
    -

    Structs

    -

    Configuration type for a [sled::Tree] database

    -

    Configuration type for a sqlite::SqliteDatabase database

    -

    Enums

    -

    Type that contains any of the BatchDatabase::Batch types defined by the library

    -

    Type that can contain any of the Database types defined by the library

    -

    Type that can contain any of the database configurations defined by the library

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/any/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/database/any/sidebar-items.js deleted file mode 100644 index b10a47631b..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/any/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["AnyBatch","Type that contains any of the [`BatchDatabase::Batch`] types defined by the library"],["AnyDatabase","Type that can contain any of the [`Database`] types defined by the library"],["AnyDatabaseConfig","Type that can contain any of the database configurations defined by the library"]],"struct":[["SledDbConfiguration","Configuration type for a [`sled::Tree`] database"],["SqliteDbConfiguration","Configuration type for a [`sqlite::SqliteDatabase`] database"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SledDbConfiguration.html b/static/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SledDbConfiguration.html deleted file mode 100644 index b6e90414ab..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SledDbConfiguration.html +++ /dev/null @@ -1,29 +0,0 @@ -SledDbConfiguration in bdk::database::any - Rust

    Struct bdk::database::any::SledDbConfiguration[][src]

    pub struct SledDbConfiguration {
    -    pub path: String,
    -    pub tree_name: String,
    -}
    Expand description

    Configuration type for a [sled::Tree] database

    -

    Fields

    path: String

    Main directory of the db

    -
    tree_name: String

    Name of the database tree, a separated namespace for the data

    -

    Trait Implementations

    Formats the value using the given formatter. Read more

    -

    Deserialize this value from the given Serde deserializer. Read more

    -

    Performs the conversion.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SqliteDbConfiguration.html b/static/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SqliteDbConfiguration.html deleted file mode 100644 index 9afc907488..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/any/struct.SqliteDbConfiguration.html +++ /dev/null @@ -1,27 +0,0 @@ -SqliteDbConfiguration in bdk::database::any - Rust

    Struct bdk::database::any::SqliteDbConfiguration[][src]

    pub struct SqliteDbConfiguration {
    -    pub path: String,
    -}
    Expand description

    Configuration type for a sqlite::SqliteDatabase database

    -

    Fields

    path: String

    Main directory of the db

    -

    Trait Implementations

    Formats the value using the given formatter. Read more

    -

    Deserialize this value from the given Serde deserializer. Read more

    -

    Performs the conversion.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/index.html b/static/docs-rs/bdk/nightly/latest/bdk/database/index.html deleted file mode 100644 index a09050fc73..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/index.html +++ /dev/null @@ -1,23 +0,0 @@ -bdk::database - Rust

    Module bdk::database[][src]

    Expand description

    Database types

    -

    This module provides the implementation of some defaults database types, along with traits that -can be implemented externally to let Wallets use customized databases.

    -

    It’s important to note that the databases defined here only contains “blockchain-related” data. -They can be seen more as a cache than a critical piece of storage that contains secrets and -keys.

    -

    The currently recommended database is [sled], which is a pretty simple key-value embedded -database written in Rust. If the key-value-db feature is enabled (which by default is), -this library automatically implements all the required traits for [sled::Tree].

    -

    Re-exports

    -
    pub use any::AnyDatabase;
    pub use any::AnyDatabaseConfig;
    pub use memory::MemoryDatabase;

    Modules

    -

    Runtime-checked database types

    -

    In-memory ephemeral database

    -

    Structs

    -

    Sqlite database stored on filesystem

    -

    Traits

    -

    Trait for a database that supports batch operations

    -

    Trait for operations that can be batched

    -

    Trait for Database types that can be created given a configuration

    -

    Trait for reading data from a database

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/memory/index.html b/static/docs-rs/bdk/nightly/latest/bdk/database/memory/index.html deleted file mode 100644 index 9a202f2ef4..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/memory/index.html +++ /dev/null @@ -1,8 +0,0 @@ -bdk::database::memory - Rust

    Module bdk::database::memory[][src]

    Expand description

    In-memory ephemeral database

    -

    This module defines an in-memory database type called MemoryDatabase that is based on a -BTreeMap.

    -

    Structs

    -

    In-memory ephemeral database

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/memory/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/database/memory/sidebar-items.js deleted file mode 100644 index 665f6718d0..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/memory/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["MemoryDatabase","In-memory ephemeral database"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/memory/struct.MemoryDatabase.html b/static/docs-rs/bdk/nightly/latest/bdk/database/memory/struct.MemoryDatabase.html deleted file mode 100644 index afb930e59e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/memory/struct.MemoryDatabase.html +++ /dev/null @@ -1,60 +0,0 @@ -MemoryDatabase in bdk::database::memory - Rust

    Struct bdk::database::memory::MemoryDatabase[][src]

    pub struct MemoryDatabase { /* fields omitted */ }
    Expand description

    In-memory ephemeral database

    -

    This database can be used as a temporary storage for wallets that are not kept permanently on -a device, or on platforms that don’t provide a filesystem, like wasm32.

    -

    Once it’s dropped its content will be lost.

    -

    If you are looking for a permanent storage solution, you can try with the default key-value -database called [sled]. See the database module documentation for more defailts.

    -

    Implementations

    Create a new empty database

    -

    Trait Implementations

    Container for the operations

    -

    Create a new batch container

    -

    Consume and apply a batch of operations

    -

    Store a script_pubkey along with its keychain and child number.

    -

    Store a LocalUtxo

    -

    Store a raw transaction

    -

    Store the metadata of a transaction

    -

    Store the last derivation index for a given keychain.

    -

    Delete a script_pubkey given the keychain and its child number.

    -

    Delete the data related to a specific script_pubkey, meaning the keychain and the child -number. Read more

    -

    Delete a LocalUtxo given its [OutPoint]

    -

    Delete a raw transaction given its [Txid]

    -

    Delete the metadata of a transaction and optionally the raw transaction itself

    -

    Delete the last derivation index for a keychain.

    -

    Type that contains the configuration

    -

    Create a new instance given a configuration

    -

    Read and checks the descriptor checksum for a given keychain. Read more

    -

    Return the list of script_pubkeys

    -

    Return the list of LocalUtxos

    -

    Return the list of raw transactions

    -

    Return the list of transactions metadata

    -

    Fetch a script_pubkey given the child number of a keychain.

    -

    Fetch the keychain and child number of a given script_pubkey

    -

    Fetch a LocalUtxo given its [OutPoint]

    -

    Fetch a raw transaction given its [Txid]

    -

    Fetch the transaction metadata and optionally also the raw transaction

    -

    Return the last defivation index for a keychain.

    -

    Increment the last derivation index for a keychain and return it Read more

    -

    Force changes to be written to disk

    -

    Formats the value using the given formatter. Read more

    -

    Returns the “default value” for a type. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/database/sidebar-items.js deleted file mode 100644 index 3856fe121b..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"mod":[["any","Runtime-checked database types"],["memory","In-memory ephemeral database"]],"struct":[["SqliteDatabase","Sqlite database stored on filesystem"]],"trait":[["BatchDatabase","Trait for a database that supports batch operations"],["BatchOperations","Trait for operations that can be batched"],["ConfigurableDatabase","Trait for [`Database`] types that can be created given a configuration"],["Database","Trait for reading data from a database"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/sqlite/struct.SqliteDatabase.html b/static/docs-rs/bdk/nightly/latest/bdk/database/sqlite/struct.SqliteDatabase.html deleted file mode 100644 index 803ba38ba6..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/sqlite/struct.SqliteDatabase.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../../bdk/database/struct.SqliteDatabase.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/struct.SqliteDatabase.html b/static/docs-rs/bdk/nightly/latest/bdk/database/struct.SqliteDatabase.html deleted file mode 100644 index fc14591c39..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/struct.SqliteDatabase.html +++ /dev/null @@ -1,62 +0,0 @@ -SqliteDatabase in bdk::database - Rust

    Struct bdk::database::SqliteDatabase[][src]

    pub struct SqliteDatabase {
    -    pub path: String,
    -    pub connection: Connection,
    -}
    Expand description

    Sqlite database stored on filesystem

    -

    This is a permanent storage solution for devices and platforms that provide a filesystem. -crate::database

    -

    Fields

    path: String

    Path on the local filesystem to store the sqlite file

    -
    connection: Connection

    A rusqlite connection object to the sqlite database

    -

    Implementations

    Instantiate a new SqliteDatabase instance by creating a connection -to the database stored at path

    -

    Trait Implementations

    Container for the operations

    -

    Create a new batch container

    -

    Consume and apply a batch of operations

    -

    Store a script_pubkey along with its keychain and child number.

    -

    Store a LocalUtxo

    -

    Store a raw transaction

    -

    Store the metadata of a transaction

    -

    Store the last derivation index for a given keychain.

    -

    Delete a script_pubkey given the keychain and its child number.

    -

    Delete the data related to a specific script_pubkey, meaning the keychain and the child -number. Read more

    -

    Delete a LocalUtxo given its [OutPoint]

    -

    Delete a raw transaction given its [Txid]

    -

    Delete the metadata of a transaction and optionally the raw transaction itself

    -

    Delete the last derivation index for a keychain.

    -

    Type that contains the configuration

    -

    Create a new instance given a configuration

    -

    Read and checks the descriptor checksum for a given keychain. Read more

    -

    Return the list of script_pubkeys

    -

    Return the list of LocalUtxos

    -

    Return the list of raw transactions

    -

    Return the list of transactions metadata

    -

    Fetch a script_pubkey given the child number of a keychain.

    -

    Fetch the keychain and child number of a given script_pubkey

    -

    Fetch a LocalUtxo given its [OutPoint]

    -

    Fetch a raw transaction given its [Txid]

    -

    Fetch the transaction metadata and optionally also the raw transaction

    -

    Return the last defivation index for a keychain.

    -

    Increment the last derivation index for a keychain and return it Read more

    -

    Force changes to be written to disk

    -

    Formats the value using the given formatter. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/trait.BatchDatabase.html b/static/docs-rs/bdk/nightly/latest/bdk/database/trait.BatchDatabase.html deleted file mode 100644 index acbea968b7..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/trait.BatchDatabase.html +++ /dev/null @@ -1,12 +0,0 @@ -BatchDatabase in bdk::database - Rust

    Trait bdk::database::BatchDatabase[][src]

    pub trait BatchDatabase: Database {
    -    type Batch: BatchOperations;
    -    fn begin_batch(&self) -> Self::Batch;
    -
    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>; -}
    Expand description

    Trait for a database that supports batch operations

    -

    This trait defines the methods to start and apply a batch of operations.

    -

    Associated Types

    Container for the operations

    -

    Required methods

    Create a new batch container

    -

    Consume and apply a batch of operations

    -

    Implementations on Foreign Types

    Implementors

    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/trait.BatchOperations.html b/static/docs-rs/bdk/nightly/latest/bdk/database/trait.BatchOperations.html deleted file mode 100644 index cc5faecac2..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/trait.BatchOperations.html +++ /dev/null @@ -1,30 +0,0 @@ -BatchOperations in bdk::database - Rust

    Trait bdk::database::BatchOperations[][src]

    pub trait BatchOperations {
    -    fn set_script_pubkey(
            &mut self,
            script: &Script,
            keychain: KeychainKind,
            child: u32
        ) -> Result<(), Error>; -
    fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error>; -
    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>; -
    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>; -
    fn set_last_index(
            &mut self,
            keychain: KeychainKind,
            value: u32
        ) -> Result<(), Error>; -
    fn del_script_pubkey_from_path(
            &mut self,
            keychain: KeychainKind,
            child: u32
        ) -> Result<Option<Script>, Error>; -
    fn del_path_from_script_pubkey(
            &mut self,
            script: &Script
        ) -> Result<Option<(KeychainKind, u32)>, Error>; -
    fn del_utxo(
            &mut self,
            outpoint: &OutPoint
        ) -> Result<Option<LocalUtxo>, Error>; -
    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>; -
    fn del_tx(
            &mut self,
            txid: &Txid,
            include_raw: bool
        ) -> Result<Option<TransactionDetails>, Error>; -
    fn del_last_index(
            &mut self,
            keychain: KeychainKind
        ) -> Result<Option<u32>, Error>; -}
    Expand description

    Trait for operations that can be batched

    -

    This trait defines the list of operations that must be implemented on the Database type and -the BatchDatabase::Batch type.

    -

    Required methods

    Store a script_pubkey along with its keychain and child number.

    -

    Store a LocalUtxo

    -

    Store a raw transaction

    -

    Store the metadata of a transaction

    -

    Store the last derivation index for a given keychain.

    -

    Delete a script_pubkey given the keychain and its child number.

    -

    Delete the data related to a specific script_pubkey, meaning the keychain and the child -number.

    -

    Delete a LocalUtxo given its [OutPoint]

    -

    Delete a raw transaction given its [Txid]

    -

    Delete the metadata of a transaction and optionally the raw transaction itself

    -

    Delete the last derivation index for a keychain.

    -

    Implementations on Foreign Types

    Implementors

    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/trait.ConfigurableDatabase.html b/static/docs-rs/bdk/nightly/latest/bdk/database/trait.ConfigurableDatabase.html deleted file mode 100644 index 230a6c5ae1..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/trait.ConfigurableDatabase.html +++ /dev/null @@ -1,9 +0,0 @@ -ConfigurableDatabase in bdk::database - Rust

    Trait bdk::database::ConfigurableDatabase[][src]

    pub trait ConfigurableDatabase: Database + Sized {
    -    type Config: Debug;
    -    fn from_config(config: &Self::Config) -> Result<Self, Error>;
    -}
    Expand description

    Trait for Database types that can be created given a configuration

    -

    Associated Types

    Type that contains the configuration

    -

    Required methods

    Create a new instance given a configuration

    -

    Implementations on Foreign Types

    Implementors

    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/database/trait.Database.html b/static/docs-rs/bdk/nightly/latest/bdk/database/trait.Database.html deleted file mode 100644 index e58fa2d43c..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/database/trait.Database.html +++ /dev/null @@ -1,36 +0,0 @@ -Database in bdk::database - Rust

    Trait bdk::database::Database[][src]

    pub trait Database: BatchOperations {
    -
    Show 13 methods fn check_descriptor_checksum<B: AsRef<[u8]>>(
            &mut self,
            keychain: KeychainKind,
            bytes: B
        ) -> Result<(), Error>; -
    fn iter_script_pubkeys(
            &self,
            keychain: Option<KeychainKind>
        ) -> Result<Vec<Script>, Error>; -
    fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error>; -
    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>; -
    fn iter_txs(
            &self,
            include_raw: bool
        ) -> Result<Vec<TransactionDetails>, Error>; -
    fn get_script_pubkey_from_path(
            &self,
            keychain: KeychainKind,
            child: u32
        ) -> Result<Option<Script>, Error>; -
    fn get_path_from_script_pubkey(
            &self,
            script: &Script
        ) -> Result<Option<(KeychainKind, u32)>, Error>; -
    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error>; -
    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>; -
    fn get_tx(
            &self,
            txid: &Txid,
            include_raw: bool
        ) -> Result<Option<TransactionDetails>, Error>; -
    fn get_last_index(
            &self,
            keychain: KeychainKind
        ) -> Result<Option<u32>, Error>; -
    fn increment_last_index(
            &mut self,
            keychain: KeychainKind
        ) -> Result<u32, Error>; -
    fn flush(&mut self) -> Result<(), Error>; -
    }
    Expand description

    Trait for reading data from a database

    -

    This traits defines the operations that can be used to read data out of a database

    -

    Required methods

    Read and checks the descriptor checksum for a given keychain.

    -

    Should return Error::ChecksumMismatch if the -checksum doesn’t match. If there’s no checksum in the database, simply store it for the -next time.

    -

    Return the list of script_pubkeys

    -

    Return the list of LocalUtxos

    -

    Return the list of raw transactions

    -

    Return the list of transactions metadata

    -

    Fetch a script_pubkey given the child number of a keychain.

    -

    Fetch the keychain and child number of a given script_pubkey

    -

    Fetch a LocalUtxo given its [OutPoint]

    -

    Fetch a raw transaction given its [Txid]

    -

    Fetch the transaction metadata and optionally also the raw transaction

    -

    Return the last defivation index for a keychain.

    -

    Increment the last derivation index for a keychain and return it

    -

    It should insert and return 0 if not present in the database

    -

    Force changes to be written to disk

    -

    Implementations on Foreign Types

    Implementors

    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.get_checksum.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.get_checksum.html deleted file mode 100644 index 55ce0b83b6..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/fn.get_checksum.html +++ /dev/null @@ -1,4 +0,0 @@ -get_checksum in bdk::descriptor::checksum - Rust

    Function bdk::descriptor::checksum::get_checksum[][src]

    pub fn get_checksum(desc: &str) -> Result<String, DescriptorError>
    Expand description

    Compute the checksum of a descriptor

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/index.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/index.html deleted file mode 100644 index 019adf3d57..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/index.html +++ /dev/null @@ -1,8 +0,0 @@ -bdk::descriptor::checksum - Rust

    Module bdk::descriptor::checksum[][src]

    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

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/sidebar-items.js deleted file mode 100644 index e1add094a5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/checksum/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"fn":[["get_checksum","Compute the checksum of a descriptor"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Descriptor.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Descriptor.html deleted file mode 100644 index d0003f40ac..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Descriptor.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../../bdk/descriptor/enum.Descriptor.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.DescriptorPublicKey.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.DescriptorPublicKey.html deleted file mode 100644 index 05f9388e84..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.DescriptorPublicKey.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../../bdk/keys/enum.DescriptorPublicKey.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Legacy.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Legacy.html deleted file mode 100644 index fb2dd3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Legacy.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../../bdk/descriptor/enum.Legacy.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Segwitv0.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Segwitv0.html deleted file mode 100644 index 194aba17ab..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/enum.Segwitv0.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../../bdk/descriptor/enum.Segwitv0.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/struct.DerivedDescriptorKey.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/struct.DerivedDescriptorKey.html deleted file mode 100644 index 3d9e091385..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/struct.DerivedDescriptorKey.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../../bdk/descriptor/struct.DerivedDescriptorKey.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/struct.Miniscript.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/struct.Miniscript.html deleted file mode 100644 index ca1ccb5a6e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/struct.Miniscript.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../../bdk/descriptor/struct.Miniscript.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/trait.ScriptContext.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/trait.ScriptContext.html deleted file mode 100644 index 08af1d1289..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/trait.ScriptContext.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../../bdk/keys/trait.ScriptContext.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/type.KeyMap.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/type.KeyMap.html deleted file mode 100644 index 2fdaa9d33d..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/derived/type.KeyMap.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../../bdk/keys/type.KeyMap.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Descriptor.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Descriptor.html deleted file mode 100644 index 7bdf70a2ad..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Descriptor.html +++ /dev/null @@ -1,153 +0,0 @@ -Descriptor in bdk::descriptor - Rust

    Enum bdk::descriptor::Descriptor[]

    pub enum Descriptor<Pk> where
        Pk: MiniscriptKey, 
    { - Bare(Bare<Pk>), - Pkh(Pkh<Pk>), - Wpkh(Wpkh<Pk>), - Sh(Sh<Pk>), - Wsh(Wsh<Pk>), -}
    Expand description

    Script descriptor

    -

    Variants

    Bare(Bare<Pk>)

    A raw scriptpubkey (including pay-to-pubkey) under Legacy context

    -

    Tuple Fields of Bare

    0: Bare<Pk>
    Pkh(Pkh<Pk>)

    Pay-to-PubKey-Hash

    -

    Tuple Fields of Pkh

    0: Pkh<Pk>
    Wpkh(Wpkh<Pk>)

    Pay-to-Witness-PubKey-Hash

    -

    Tuple Fields of Wpkh

    0: Wpkh<Pk>
    Sh(Sh<Pk>)

    Pay-to-ScriptHash(includes nested wsh/wpkh/sorted multi)

    -

    Tuple Fields of Sh

    0: Sh<Pk>
    Wsh(Wsh<Pk>)

    Pay-to-Witness-ScriptHash with Segwitv0 context

    -

    Tuple Fields of Wsh

    0: Wsh<Pk>

    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 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

    -

    Get the [DescriptorType] of Descriptor

    -

    Whether or not the descriptor has any wildcards

    -

    Derives all wildcard keys in the descriptor using the supplied index

    -

    Panics if given an index ≥ 2^31

    -

    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

    -

    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

    -

    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 signauture on all spend paths -And whether the script is malleable. -In general, all the guarantees of miniscript hold only for safe scripts. -All the analysis guarantees of miniscript only hold safe scripts. -The signer may not be able to find satisfactions even if one exists

    -

    Computes the Bitcoin address of the descriptor, if one exists

    -

    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 “witness script” of the descriptor, i.e. 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.

    -

    Returns satisfying witness and scriptSig to spend an -output controlled by the given descriptor if it possible to -construct one using the satisfier S.

    -

    Computes an upper bound on the weight of a satisfying witness to the -transaction. Assumes all signatures are 73 bytes, including push opcode -and sighash suffix. Includes the weight of the VarInts encoding the -scriptSig and witness stack length.

    -

    Get 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.

    -

    Attempts to produce a satisfying witness and scriptSig to spend an -output controlled by the given descriptor; add the data to a given -TxIn output. 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

    -

    The associated error which can be returned from parsing.

    -

    Parses a string s to return a value of this type. Read more

    -

    Parse an expression tree into a descriptor

    -

    Feeds this value into the given Hasher. Read more

    -

    Feeds a slice of this type into the given Hasher. Read more

    -

    Convert the object into an abstract policy

    -

    This method returns an Ordering between self and other. Read more

    -

    Compares and returns the maximum of two values. Read more

    -

    Compares and returns the minimum of two values. Read more

    -

    Restrict a value to a certain interval. Read more

    -

    This method tests for self and other values to be equal, and is used -by ==. Read more

    -

    This method tests for !=.

    -

    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

    -

    Convert a descriptor using abstract keys to one using specific keys -This will panic if translatefpk returns an uncompressed key when -converting to a Segwit descriptor. To prevent this panic, ensure -translatefpk returns an error in this case instead.

    -

    The associated output type. This must be Self

    -

    Calls translate_pk with conversion functions that cannot fail

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    Uses borrowed data to replace owned data, usually by cloning. Read more

    -

    Converts the given value to a String. Read more

    -

    Translate a struct from one generic to another where the -translation for Pk is provided by translatefpk Read more

    -

    Translate a struct from one generic to another where the -translation for Pk is provided by translatefpk Read more

    -

    Translate a struct from one generic to another where the -translation for Pk is provided by translatefpk Read more

    -

    Translate a struct from one generic to another where the -translation for Pk is provided by translatefpk Read more

    -

    Translate a struct from one generic to another where the -translation for Pk is provided by translatefpk Read more

    -

    Translate a struct from one generic to another where the -translation for Pk is provided by translatefpk Read more

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Legacy.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Legacy.html deleted file mode 100644 index 839a91fcf1..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Legacy.html +++ /dev/null @@ -1,95 +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 !=.

    -

    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

    -

    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

    -

    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.

    -

    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 the ScriptContext as a ScriptContextEnum

    -

    Returns whether the script context is Legacy

    -

    Returns whether the script context is Segwitv0

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Segwitv0.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Segwitv0.html deleted file mode 100644 index 11e3d518c9..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/enum.Segwitv0.html +++ /dev/null @@ -1,92 +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 !=.

    -

    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

    -

    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

    -

    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.

    -

    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 the ScriptContext as a ScriptContextEnum

    -

    Returns whether the script context is Legacy

    -

    Returns whether the script context is Segwitv0

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/error/enum.Error.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/error/enum.Error.html deleted file mode 100644 index ec4d949d3a..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/error/enum.Error.html +++ /dev/null @@ -1,69 +0,0 @@ -Error in bdk::descriptor::error - Rust

    Enum bdk::descriptor::error::Error[][src]

    pub enum Error {
    -    InvalidHdKeyPath,
    -    InvalidDescriptorChecksum,
    -    HardenedDerivationXpub,
    -    DuplicatedKeys,
    -    Key(KeyError),
    -    Policy(PolicyError),
    -    InvalidDescriptorCharacter(char),
    -    Bip32(Error),
    -    Base58(Error),
    -    Pk(Error),
    -    Miniscript(Error),
    -    Hex(Error),
    -}
    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

    -
    DuplicatedKeys

    The descriptor contains multiple keys with the same BIP32 fingerprint

    -

    Error thrown while working with keys

    -

    Tuple Fields of Key

    Policy(PolicyError)

    Error while extracting and manipulating policies

    -

    Tuple Fields of Policy

    InvalidDescriptorCharacter(char)

    Invalid character found in the descriptor checksum

    -

    Tuple Fields of InvalidDescriptorCharacter

    0: char
    Bip32(Error)

    BIP32 error

    -

    Tuple Fields of Bip32

    0: Error
    Base58(Error)

    Error during base58 decoding

    -

    Tuple Fields of Base58

    0: Error
    Pk(Error)

    Key-related error

    -

    Tuple Fields of Pk

    0: Error
    Miniscript(Error)

    Miniscript error

    -

    Tuple Fields of Miniscript

    0: Error
    Hex(Error)

    Hex decoding error

    -

    Tuple Fields of Hex

    0: 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

    -
    🔬 This is a nightly-only experimental API. (backtrace)

    Returns a stack backtrace, if available, of where this error occurred. 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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Converts a reference to Self into a dynamic trait object of Fail.

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Returns the “name” of the error. Read more

    -

    Returns a reference to the underlying cause of this failure, if it -is an error that wraps other errors. Read more

    -

    Returns a reference to the Backtrace carried by this failure, if it -carries one. Read more

    -

    Provides context for this failure. Read more

    -

    Wraps this failure in a compatibility wrapper that implements -std::error::Error. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/error/index.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/error/index.html deleted file mode 100644 index 932150123c..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/error/index.html +++ /dev/null @@ -1,6 +0,0 @@ -bdk::descriptor::error - Rust

    Module bdk::descriptor::error[][src]

    Expand description

    Descriptor errors

    -

    Enums

    -

    Errors related to the parsing and usage of descriptors

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/error/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/error/sidebar-items.js deleted file mode 100644 index 1ad99d4faf..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/error/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Error","Errors related to the parsing and usage of descriptors"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/index.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/index.html deleted file mode 100644 index 4c2d3b96f0..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/index.html +++ /dev/null @@ -1,35 +0,0 @@ -bdk::descriptor - Rust

    Module bdk::descriptor[][src]

    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::get_checksum;
    pub use self::error::Error as DescriptorError;
    pub use self::policy::Policy;

    Modules

    -

    Descriptor checksum

    -

    Descriptor errors

    -

    Descriptor policy

    -

    Descriptor templates

    -

    Structs

    -

    Extended DescriptorPublicKey that has been derived

    -

    Top-level script AST type

    -

    Enums

    -

    Script descriptor

    -

    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 type for a map of public key to secret key

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.BuildSatisfaction.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.BuildSatisfaction.html deleted file mode 100644 index fd9eddbd4f..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.BuildSatisfaction.html +++ /dev/null @@ -1,42 +0,0 @@ -BuildSatisfaction in bdk::descriptor::policy - Rust

    Enum bdk::descriptor::policy::BuildSatisfaction[][src]

    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

    -

    Tuple Fields of Psbt

    0: &'a Psbt
    PsbtTimelocks

    Like Psbt variant and also check for expired timelocks

    -

    Fields of PsbtTimelocks

    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

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.PolicyError.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.PolicyError.html deleted file mode 100644 index 0412f4a82f..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.PolicyError.html +++ /dev/null @@ -1,54 +0,0 @@ -PolicyError in bdk::descriptor::policy - Rust

    Enum bdk::descriptor::policy::PolicyError[][src]

    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

    -

    Tuple Fields of NotEnoughItemsSelected

    0: String
    IndexOutOfRange(usize)

    Index out of range for an item to satisfy a SatisfiableItem::Thresh or a SatisfiableItem::Multisig

    -

    Tuple Fields of IndexOutOfRange

    0: usize
    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

    -
    🔬 This is a nightly-only experimental API. (backtrace)

    Returns a stack backtrace, if available, of where this error occurred. 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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    This method tests for self and other values to be equal, and is used -by ==. Read more

    -

    This method tests for !=.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Converts a reference to Self into a dynamic trait object of Fail.

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Returns the “name” of the error. Read more

    -

    Returns a reference to the underlying cause of this failure, if it -is an error that wraps other errors. Read more

    -

    Returns a reference to the Backtrace carried by this failure, if it -carries one. Read more

    -

    Provides context for this failure. Read more

    -

    Wraps this failure in a compatibility wrapper that implements -std::error::Error. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.Satisfaction.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.Satisfaction.html deleted file mode 100644 index a58bf0bb83..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.Satisfaction.html +++ /dev/null @@ -1,64 +0,0 @@ -Satisfaction in bdk::descriptor::policy - Rust

    Enum bdk::descriptor::policy::Satisfaction[][src]

    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

    Only a partial satisfaction of some kind of threshold policy

    -

    Fields of Partial

    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

    -
    PartialComplete

    Can reach the threshold of some kind of threshold policy

    -

    Fields of PartialComplete

    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

    -
    Complete

    Can satisfy the policy item

    -

    Fields of Complete

    condition: Condition

    Extra conditions that also need to be satisfied

    -
    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

    -

    Performs the conversion.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.SatisfiableItem.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.SatisfiableItem.html deleted file mode 100644 index 10e4daecb0..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/enum.SatisfiableItem.html +++ /dev/null @@ -1,80 +0,0 @@ -SatisfiableItem in bdk::descriptor::policy - Rust

    Enum bdk::descriptor::policy::SatisfiableItem[][src]

    pub enum SatisfiableItem {
    -    Signature(PkOrF),
    -    SignatureKey(PkOrF),
    -    Sha256Preimage {
    -        hash: Hash,
    -    },
    -    Hash256Preimage {
    -        hash: Hash,
    -    },
    -    Ripemd160Preimage {
    -        hash: Hash,
    -    },
    -    Hash160Preimage {
    -        hash: Hash,
    -    },
    -    AbsoluteTimelock {
    -        value: u32,
    -    },
    -    RelativeTimelock {
    -        value: u32,
    -    },
    -    Multisig {
    -        keys: Vec<PkOrF>,
    -        threshold: usize,
    -    },
    -    Thresh {
    -        items: Vec<Policy>,
    -        threshold: usize,
    -    },
    -}
    Expand description

    An item that needs to be satisfied

    -

    Variants

    Signature(PkOrF)

    Signature for a raw public key

    -

    Tuple Fields of Signature

    0: PkOrF
    SignatureKey(PkOrF)

    Signature for an extended key fingerprint

    -

    Tuple Fields of SignatureKey

    0: PkOrF
    Sha256Preimage

    SHA256 preimage hash

    -

    Fields of Sha256Preimage

    hash: Hash

    The digest value

    -
    Hash256Preimage

    Double SHA256 preimage hash

    -

    Fields of Hash256Preimage

    hash: Hash

    The digest value

    -
    Ripemd160Preimage

    RIPEMD160 preimage hash

    -

    Fields of Ripemd160Preimage

    hash: Hash

    The digest value

    -
    Hash160Preimage

    SHA256 then RIPEMD160 preimage hash

    -

    Fields of Hash160Preimage

    hash: Hash

    The digest value

    -
    AbsoluteTimelock

    Absolute timeclock timestamp

    -

    Fields of AbsoluteTimelock

    value: u32

    The timestamp value

    -
    RelativeTimelock

    Relative timelock locktime

    -

    Fields of RelativeTimelock

    value: u32

    The locktime value

    -
    Multisig

    Multi-signature public keys with threshold count

    -

    Fields of Multisig

    keys: Vec<PkOrF>

    The raw public key or extended key fingerprint

    -
    threshold: usize

    The required threshold count

    -
    Thresh

    Threshold items with threshold count

    -

    Fields of Thresh

    items: Vec<Policy>

    The policy items

    -
    threshold: usize

    The required 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

    -

    Performs the conversion.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/index.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/index.html deleted file mode 100644 index c9fc4315a8..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/index.html +++ /dev/null @@ -1,30 +0,0 @@ -bdk::descriptor::policy - Rust

    Module bdk::descriptor::policy[][src]

    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(key_map.into());
    -let policy = extended_desc.extract_policy(&signers, BuildSatisfaction::None, &secp)?;
    -println!("policy: {}", serde_json::to_string(&policy)?);
    -

    Structs

    -

    An extra condition that must be satisfied but that is out of control of the user

    -

    Raw public key or extended key fingerprint

    -

    Descriptor spending policy

    -

    Enums

    -

    Options to build the satisfaction field in the policy

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/sidebar-items.js deleted file mode 100644 index 40fd0e48aa..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["BuildSatisfaction","Options to build the satisfaction field in the policy"],["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"],["PkOrF","Raw public key or extended key fingerprint"],["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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Condition.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Condition.html deleted file mode 100644 index accab7d501..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Condition.html +++ /dev/null @@ -1,51 +0,0 @@ -Condition in bdk::descriptor::policy - Rust

    Struct bdk::descriptor::policy::Condition[][src]

    pub struct Condition {
    -    pub csv: Option<u32>,
    -    pub timelock: Option<u32>,
    -}
    Expand description

    An extra condition that must be satisfied but that is out of control of the user

    -

    Fields

    csv: Option<u32>

    Optional CheckSequenceVerify condition

    -
    timelock: Option<u32>

    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 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 !=.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.PkOrF.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.PkOrF.html deleted file mode 100644 index aecf0a08a7..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.PkOrF.html +++ /dev/null @@ -1,29 +0,0 @@ -PkOrF in bdk::descriptor::policy - Rust

    Struct bdk::descriptor::policy::PkOrF[][src]

    pub struct PkOrF { /* fields omitted */ }
    Expand description

    Raw public key or 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

    -

    Returns the “default value” for a 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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Policy.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Policy.html deleted file mode 100644 index cf4cd6599e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/struct.Policy.html +++ /dev/null @@ -1,45 +0,0 @@ -Policy in bdk::descriptor::policy - Rust

    Struct bdk::descriptor::policy::Policy[][src]

    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

    -

    Performs the conversion.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.ConditionMap.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.ConditionMap.html deleted file mode 100644 index c222634d0b..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.ConditionMap.html +++ /dev/null @@ -1,4 +0,0 @@ -ConditionMap in bdk::descriptor::policy - Rust

    Type Definition bdk::descriptor::policy::ConditionMap[][src]

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.FoldedConditionMap.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.FoldedConditionMap.html deleted file mode 100644 index a878b45589..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/policy/type.FoldedConditionMap.html +++ /dev/null @@ -1,4 +0,0 @@ -FoldedConditionMap in bdk::descriptor::policy - Rust

    Type Definition bdk::descriptor::policy::FoldedConditionMap[][src]

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/sidebar-items.js deleted file mode 100644 index e324d2a835..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Descriptor","Script descriptor"],["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":[["DerivedDescriptorKey","Extended [`DescriptorPublicKey`] that has been derived"],["Miniscript","Top-level script AST type"]],"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`"],["KeyMap","Alias type for a map of public key to secret key"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.DerivedDescriptorKey.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.DerivedDescriptorKey.html deleted file mode 100644 index 9cdf7671f9..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.DerivedDescriptorKey.html +++ /dev/null @@ -1,71 +0,0 @@ -DerivedDescriptorKey in bdk::descriptor - Rust

    Struct bdk::descriptor::DerivedDescriptorKey[][src]

    pub struct DerivedDescriptorKey<'s>(_, _);
    Expand description

    Extended DescriptorPublicKey that has been derived

    -

    Derived keys are guaranteed to never contain wildcards of any kind

    -

    Implementations

    Construct a new derived key

    -

    Panics if the key is wildcard

    -

    Methods from Deref<Target = DescriptorPublicKey>

    The fingerprint of the master key associated with this key

    -

    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)

    -

    Whether or not the key has a wildcards

    -

    Computes the public key corresponding to this descriptor key

    -

    Will return an error if the descriptor key has any hardened -derivation steps in its path, or if the key has any wildcards.

    -

    To ensure there are no wildcards, call .derive(0) or similar; -to avoid hardened derivation steps, start from a DescriptorSecretKey -and call as_public, or call TranslatePk2::translate_pk2 with -some function which has access to secret key data.

    -

    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.

    -

    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

    -

    The associated Hash type with the publicKey

    -

    Converts an object to PublicHash

    -

    Check if the publicKey is uncompressed. The default -implementation returns false Read more

    -

    Computes the size of a public key when serialized in a script, -including the length bytes 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 !=.

    -

    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

    -

    Converts an object to a public key

    -

    Converts a hashed version of the public key to a hash160 hash. Read more

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.Miniscript.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.Miniscript.html deleted file mode 100644 index 3bf9c9b0ac..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/struct.Miniscript.html +++ /dev/null @@ -1,215 +0,0 @@ -Miniscript in bdk::descriptor - Rust

    Struct bdk::descriptor::Miniscript[]

    pub struct Miniscript<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey, 
    { - pub node: Terminal<Pk, Ctx>, - pub ty: Type, - pub ext: ExtData, - // some fields omitted -}
    Expand description

    Top-level script AST type

    -

    Fields

    node: Terminal<Pk, Ctx>

    A node in the Abstract Syntax Tree(

    -
    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

    -

    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

    -

    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.

    -

    Creates a new [PkhIter] iterator that will iterate over all public keys hashes (and not -plain public keys) present in Miniscript items within AST by traversing all its branches. -For the specific algorithm please see [PkhIter::next] function.

    -

    Creates a new [PkPkhIter] iterator that will iterate over all plain public keys and -key hash values present in Miniscript items within AST by traversing all its branches. -For the specific algorithm please see [PkPkhIter::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 Vec with cloned version of all public keys from the current miniscript item, -if any. Otherwise returns an empty Vec.

    -

    NB: The function analyzes only single miniscript item and not any of its descendants in AST. -To obtain a list of all public keys within AST use Miniscript::iter_pk() function, for example -miniscript.iter_pubkeys().collect().

    -

    Returns Vec with hashes of all public keys from the current miniscript item, if any. -Otherwise returns an empty Vec.

    -

    For each public key the function computes hash; for each hash of the public key the function -returns its cloned copy.

    -

    NB: The function analyzes only single miniscript item and not any of its descendants in AST. -To obtain a list of all public key hashes within AST use Miniscript::iter_pkh() function, -for example miniscript.iter_pubkey_hashes().collect().

    -

    Returns Vec of [PkPkh] entries, representing either public keys or public key -hashes, depending on the data from the current miniscript item. If there is no public -keys or hashes, the function returns an empty Vec.

    -

    NB: The function analyzes only single miniscript item and not any of its descendants in AST. -To obtain a list of all public keys or hashes within AST use Miniscript::iter_pk_pkh() -function, for example miniscript.iter_pubkeys_and_hashes().collect().

    -

    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.

    -

    Returns Option::Some with hash of n’th public key from the current miniscript item, -if any. Otherwise returns Option::None.

    -

    For each public key the function computes hash; for each hash of the public key the function -returns it cloned copy.

    -

    NB: The function analyzes only single miniscript item and not any of its descendants in AST.

    -

    Returns Option::Some with hash of n’th public key or hash 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.

    -

    Extracts the AstElem representing the root of the miniscript

    -

    Get a reference to the inner AstElem representing the root of miniscript

    -

    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 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.

    -

    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 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 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

    -

    Lifting corresponds conversion of miniscript into Policy -[policy.semantic.Policy] for human readable or machine analysis. -However, naively lifting miniscripts can result in incorrect -interpretations that don’t correspond underlying semantics when -we try to spend them on bitcoin network. -This can occur if the miniscript contains a

    -
      -
    1. Timelock combination
    2. -
    3. Contains 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.

    -

    Parses a string s to return a value of this type. Read more

    -

    Parse an expression tree into a Miniscript. As a general rule, this -should not be called directly; rather go through the descriptor API.

    -

    Feeds this value into the given Hasher. Read more

    -

    Feeds a slice of this type into the given Hasher. Read more

    -

    Convert the object into an abstract policy

    -

    Ord of Miniscript must depend only on node and not the type information. -The type information and extra_properties can be deterministically determined -by the ast.

    -

    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 can be deterministically determined -by the ast.

    -

    This method tests for self and other values to be equal, and is used -by ==. Read more

    -

    This method tests for !=.

    -

    PartialOrd of Miniscript must depend only on node and not the type information. -The type information and extra_properties can be deterministically determined -by the ast.

    -

    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

    -

    This will panic if translatefpk returns an uncompressed key when -converting to a Segwit descriptor. To prevent this panic, ensure -translatefpk returns an error in this case instead.

    -

    The associated output type. This must be Self

    -

    Calls translate_pk with conversion functions that cannot fail

    -

    Eq of Miniscript must depend only on node and not the type information. -The type information and extra_properties can be deterministically determined -by the ast.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    Uses borrowed data to replace owned data, usually by cloning. Read more

    -

    Converts the given value to a String. Read more

    -

    Translate a struct from one generic to another where the -translation for Pk is provided by translatefpk Read more

    -

    Translate a struct from one generic to another where the -translation for Pk is provided by translatefpk Read more

    -

    Translate a struct from one generic to another where the -translation for Pk is provided by translatefpk Read more

    -

    Translate a struct from one generic to another where the -translation for Pk is provided by translatefpk Read more

    -

    Translate a struct from one generic to another where the -translation for Pk is provided by translatefpk Read more

    -

    Translate a struct from one generic to another where the -translation for Pk is provided by translatefpk Read more

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/index.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/index.html deleted file mode 100644 index 2edd73980f..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/index.html +++ /dev/null @@ -1,20 +0,0 @@ -bdk::descriptor::template - Rust

    Module bdk::descriptor::template[][src]

    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'/0'/{0,1}/*)

    -

    BIP44 public template. Expands to pkh(key/{0,1}/*)

    -

    BIP49 template. Expands to sh(wpkh(key/49'/0'/0'/{0,1}/*))

    -

    BIP49 public template. Expands to sh(wpkh(key/{0,1}/*))

    -

    BIP84 template. Expands to wpkh(key/84'/0'/0'/{0,1}/*)

    -

    BIP84 public template. Expands to wpkh(key/{0,1}/*)

    -

    P2PKH template. Expands to a descriptor pkh(key)

    -

    P2WPKH template. Expands to a descriptor wpkh(key)

    -

    P2WPKH-P2SH template. Expands to a descriptor sh(wpkh(key))

    -

    Traits

    -

    Trait for descriptor templates that can be built into a full descriptor

    -

    Type Definitions

    -

    Type alias for the return type of DescriptorTemplate, descriptor! and others

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/sidebar-items.js deleted file mode 100644 index 4ea3e793ef..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["Bip44","BIP44 template. Expands to `pkh(key/44'/0'/0'/{0,1}/*)`"],["Bip44Public","BIP44 public template. Expands to `pkh(key/{0,1}/*)`"],["Bip49","BIP49 template. Expands to `sh(wpkh(key/49'/0'/0'/{0,1}/*))`"],["Bip49Public","BIP49 public template. Expands to `sh(wpkh(key/{0,1}/*))`"],["Bip84","BIP84 template. Expands to `wpkh(key/84'/0'/0'/{0,1}/*)`"],["Bip84Public","BIP84 public template. Expands to `wpkh(key/{0,1}/*)`"],["P2Pkh","P2PKH template. Expands to a descriptor `pkh(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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44.html deleted file mode 100644 index 5f7c8bbff0..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44.html +++ /dev/null @@ -1,37 +0,0 @@ -Bip44 in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::Bip44[][src]

    pub struct Bip44<K: DerivableKey<Legacy>>(pub K, pub KeychainKind);
    Expand description

    BIP44 template. Expands to pkh(key/44'/0'/0'/{0,1}/*)

    -

    Since there are hardened derivation steps, this template requires a private derivable key (generally a xprv/tprv).

    -

    See Bip44Public for a template that can work with a xpub/tpub.

    -

    Example

    -
    use bdk::template::Bip44;
    -
    -let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -let wallet = Wallet::new_offline(
    -    Bip44(key.clone(), KeychainKind::External),
    -    Some(Bip44(key, KeychainKind::Internal)),
    -    Network::Testnet,
    -    MemoryDatabase::default()
    -)?;
    -
    -assert_eq!(wallet.get_address(New)?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
    -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#xgaaevjx");
    -

    Tuple Fields

    0: K1: 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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Convert to wallet descriptor

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44Public.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44Public.html deleted file mode 100644 index 28874d293e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip44Public.html +++ /dev/null @@ -1,40 +0,0 @@ -Bip44Public in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::Bip44Public[][src]

    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'.

    -

    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::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
    -let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
    -let wallet = Wallet::new_offline(
    -    Bip44Public(key.clone(), fingerprint, KeychainKind::External),
    -    Some(Bip44Public(key, fingerprint, KeychainKind::Internal)),
    -    Network::Testnet,
    -    MemoryDatabase::default()
    -)?;
    -
    -assert_eq!(wallet.get_address(New)?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
    -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#xgaaevjx");
    -

    Tuple Fields

    0: K1: Fingerprint2: KeychainKind

    Trait Implementations

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Convert to wallet descriptor

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49.html deleted file mode 100644 index bdf6d79374..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49.html +++ /dev/null @@ -1,37 +0,0 @@ -Bip49 in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::Bip49[][src]

    pub struct Bip49<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
    Expand description

    BIP49 template. Expands to sh(wpkh(key/49'/0'/0'/{0,1}/*))

    -

    Since there are hardened derivation steps, this template requires a private derivable key (generally a xprv/tprv).

    -

    See Bip49Public for a template that can work with a xpub/tpub.

    -

    Example

    -
    use bdk::template::Bip49;
    -
    -let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -let wallet = Wallet::new_offline(
    -    Bip49(key.clone(), KeychainKind::External),
    -    Some(Bip49(key, KeychainKind::Internal)),
    -    Network::Testnet,
    -    MemoryDatabase::default()
    -)?;
    -
    -assert_eq!(wallet.get_address(New)?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
    -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))#gsmdv4xr");
    -

    Tuple Fields

    0: K1: 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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Convert to wallet descriptor

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49Public.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49Public.html deleted file mode 100644 index 990701de24..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip49Public.html +++ /dev/null @@ -1,40 +0,0 @@ -Bip49Public in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::Bip49Public[][src]

    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'.

    -

    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::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
    -let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
    -let wallet = Wallet::new_offline(
    -    Bip49Public(key.clone(), fingerprint, KeychainKind::External),
    -    Some(Bip49Public(key, fingerprint, KeychainKind::Internal)),
    -    Network::Testnet,
    -    MemoryDatabase::default()
    -)?;
    -
    -assert_eq!(wallet.get_address(New)?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
    -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))#gsmdv4xr");
    -

    Tuple Fields

    0: K1: Fingerprint2: KeychainKind

    Trait Implementations

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Convert to wallet descriptor

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84.html deleted file mode 100644 index 340052e2f1..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84.html +++ /dev/null @@ -1,37 +0,0 @@ -Bip84 in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::Bip84[][src]

    pub struct Bip84<K: DerivableKey<Segwitv0>>(pub K, pub KeychainKind);
    Expand description

    BIP84 template. Expands to wpkh(key/84'/0'/0'/{0,1}/*)

    -

    Since there are hardened derivation steps, this template requires a private derivable key (generally a xprv/tprv).

    -

    See Bip84Public for a template that can work with a xpub/tpub.

    -

    Example

    -
    use bdk::template::Bip84;
    -
    -let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -let wallet = Wallet::new_offline(
    -    Bip84(key.clone(), KeychainKind::External),
    -    Some(Bip84(key, KeychainKind::Internal)),
    -    Network::Testnet,
    -    MemoryDatabase::default()
    -)?;
    -
    -assert_eq!(wallet.get_address(New)?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
    -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#nkk5dtkg");
    -

    Tuple Fields

    0: K1: 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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Convert to wallet descriptor

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84Public.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84Public.html deleted file mode 100644 index d946de1a23..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.Bip84Public.html +++ /dev/null @@ -1,40 +0,0 @@ -Bip84Public in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::Bip84Public[][src]

    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'.

    -

    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::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
    -let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
    -let wallet = Wallet::new_offline(
    -    Bip84Public(key.clone(), fingerprint, KeychainKind::External),
    -    Some(Bip84Public(key, fingerprint, KeychainKind::Internal)),
    -    Network::Testnet,
    -    MemoryDatabase::default()
    -)?;
    -
    -assert_eq!(wallet.get_address(New)?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
    -assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#nkk5dtkg");
    -

    Tuple Fields

    0: K1: Fingerprint2: KeychainKind

    Trait Implementations

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Convert to wallet descriptor

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Pkh.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Pkh.html deleted file mode 100644 index 9f00d81a24..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Pkh.html +++ /dev/null @@ -1,38 +0,0 @@ -P2Pkh in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::P2Pkh[][src]

    pub struct P2Pkh<K: IntoDescriptorKey<Legacy>>(pub K);
    Expand description

    P2PKH template. Expands to a descriptor pkh(key)

    -

    Example

    -
    use bdk::template::P2Pkh;
    -
    -let key =
    -    bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
    -let wallet = Wallet::new_offline(
    -    P2Pkh(key),
    -    None,
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -)?;
    -
    -assert_eq!(
    -    wallet.get_address(New)?.to_string(),
    -    "mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"
    -);
    -

    Tuple Fields

    0: K

    Trait Implementations

    Build the complete descriptor

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Convert to wallet descriptor

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh.html deleted file mode 100644 index cdb5cf12c8..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh.html +++ /dev/null @@ -1,38 +0,0 @@ -P2Wpkh in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::P2Wpkh[][src]

    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 wallet = Wallet::new_offline(
    -    P2Wpkh(key),
    -    None,
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -)?;
    -
    -assert_eq!(
    -    wallet.get_address(New)?.to_string(),
    -    "tb1q4525hmgw265tl3drrl8jjta7ayffu6jf68ltjd"
    -);
    -

    Tuple Fields

    0: K

    Trait Implementations

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Convert to wallet descriptor

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh_P2Sh.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh_P2Sh.html deleted file mode 100644 index 3caa912c30..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/struct.P2Wpkh_P2Sh.html +++ /dev/null @@ -1,38 +0,0 @@ -P2Wpkh_P2Sh in bdk::descriptor::template - Rust

    Struct bdk::descriptor::template::P2Wpkh_P2Sh[][src]

    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 wallet = Wallet::new_offline(
    -    P2Wpkh_P2Sh(key),
    -    None,
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -)?;
    -
    -assert_eq!(
    -    wallet.get_address(New)?.to_string(),
    -    "2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"
    -);
    -

    Tuple Fields

    0: K

    Trait Implementations

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Convert to wallet descriptor

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/trait.DescriptorTemplate.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/trait.DescriptorTemplate.html deleted file mode 100644 index 4fcbe7b52c..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/trait.DescriptorTemplate.html +++ /dev/null @@ -1,22 +0,0 @@ -DescriptorTemplate in bdk::descriptor::template - Rust

    Trait bdk::descriptor::template::DescriptorTemplate[][src]

    pub trait DescriptorTemplate {
    -    fn build(self) -> 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};
    -
    -struct MyP2PKH<K: IntoDescriptorKey<Legacy>>(K);
    -
    -impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for MyP2PKH<K> {
    -    fn build(self) -> 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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/type.DescriptorTemplateOut.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/type.DescriptorTemplateOut.html deleted file mode 100644 index d5a999d18b..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/template/type.DescriptorTemplateOut.html +++ /dev/null @@ -1,5 +0,0 @@ -DescriptorTemplateOut in bdk::descriptor::template - Rust

    Type Definition bdk::descriptor::template::DescriptorTemplateOut[][src]

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ExtractPolicy.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ExtractPolicy.html deleted file mode 100644 index 6e9c6f1081..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ExtractPolicy.html +++ /dev/null @@ -1,7 +0,0 @@ -ExtractPolicy in bdk::descriptor - Rust

    Trait bdk::descriptor::ExtractPolicy[][src]

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.IntoWalletDescriptor.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.IntoWalletDescriptor.html deleted file mode 100644 index 29b6762f60..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.IntoWalletDescriptor.html +++ /dev/null @@ -1,9 +0,0 @@ -IntoWalletDescriptor in bdk::descriptor - Rust

    Trait bdk::descriptor::IntoWalletDescriptor[][src]

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ScriptContext.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ScriptContext.html deleted file mode 100644 index 92abbd0176..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/trait.ScriptContext.html +++ /dev/null @@ -1,77 +0,0 @@ -ScriptContext in bdk::descriptor - Rust

    Trait bdk::descriptor::ScriptContext[]

    pub trait ScriptContext: Debug + Clone + Ord + PartialOrd<Self> + Eq + PartialEq<Self> + Hash + Sealed {
    -    fn check_terminal_non_malleable<Pk, Ctx>(
            _frag: &Terminal<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    ; -
    fn max_satisfaction_size<Pk, Ctx>(ms: &Miniscript<Pk, Ctx>) -> Option<usize>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    ; - - fn check_witness<Pk, Ctx>(
            _witness: &[Vec<u8, Global>]
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn check_global_consensus_validity<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn check_global_policy_validity<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn check_local_consensus_validity<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn check_local_policy_validity<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn check_global_validity<Pk, Ctx>(
            ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn check_local_validity<Pk, Ctx>(
            ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn top_level_type_check<Pk, Ctx>(
            ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), Error>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn other_top_level_checks<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), Error>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn top_level_checks<Pk, Ctx>(ms: &Miniscript<Pk, Ctx>) -> Result<(), Error>
        where
            Ctx: ScriptContext,
            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 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.

    -

    Depending on script context, the size of a satifaction witness may slightly differ.

    -

    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.

    -

    Implementations on Foreign Types

    Implementors

    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/type.DerivedDescriptor.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/type.DerivedDescriptor.html deleted file mode 100644 index 97508febab..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/type.DerivedDescriptor.html +++ /dev/null @@ -1,4 +0,0 @@ -DerivedDescriptor in bdk::descriptor - Rust

    Type Definition bdk::descriptor::DerivedDescriptor[][src]

    pub type DerivedDescriptor<'s> = Descriptor<DerivedDescriptorKey<'s>>;
    Expand description

    Alias for a Descriptor that contains extended derived keys

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/type.ExtendedDescriptor.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/type.ExtendedDescriptor.html deleted file mode 100644 index 207f54a03e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/type.ExtendedDescriptor.html +++ /dev/null @@ -1,5 +0,0 @@ -ExtendedDescriptor in bdk::descriptor - Rust

    Type Definition bdk::descriptor::ExtendedDescriptor[][src]

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/type.HdKeyPaths.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/type.HdKeyPaths.html deleted file mode 100644 index 0f31e1f774..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/type.HdKeyPaths.html +++ /dev/null @@ -1,5 +0,0 @@ -HdKeyPaths in bdk::descriptor - Rust

    Type Definition bdk::descriptor::HdKeyPaths[][src]

    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/static/docs-rs/bdk/nightly/latest/bdk/descriptor/type.KeyMap.html b/static/docs-rs/bdk/nightly/latest/bdk/descriptor/type.KeyMap.html deleted file mode 100644 index 417fe088cf..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/descriptor/type.KeyMap.html +++ /dev/null @@ -1,8 +0,0 @@ -KeyMap in bdk::descriptor - Rust

    Type Definition bdk::descriptor::KeyMap[]

    pub type KeyMap = HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>;
    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/static/docs-rs/bdk/nightly/latest/bdk/enum.Error.html b/static/docs-rs/bdk/nightly/latest/bdk/enum.Error.html deleted file mode 100644 index a383630561..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/enum.Error.html +++ /dev/null @@ -1,158 +0,0 @@ -Error in bdk - Rust

    Enum bdk::Error[][src]

    pub enum Error {
    -
    Show 41 variants InvalidU32Bytes(Vec<u8>), - Generic(String), - ScriptDoesntHaveAddressForm, - NoRecipients, - NoUtxosSelected, - OutputBelowDustLimit(usize), - InsufficientFunds { - needed: u64, - available: u64, - }, - BnBTotalTriesExceeded, - BnBNoExactMatch, - UnknownUtxo, - TransactionNotFound, - TransactionConfirmed, - IrreplaceableTransaction, - FeeRateTooLow { - required: FeeRate, - }, - FeeTooLow { - required: u64, - }, - FeeRateUnavailable, - MissingKeyOrigin(String), - Key(KeyError), - ChecksumMismatch, - SpendingPolicyRequired(KeychainKind), - InvalidPolicyPathError(PolicyError), - Signer(SignerError), - InvalidNetwork { - requested: Network, - found: Network, - }, - InvalidProgressValue(f32), - ProgressUpdateError, - InvalidOutpoint(OutPoint), - Descriptor(Error), - AddressValidator(AddressValidatorError), - Encode(Error), - Miniscript(Error), - Bip32(Error), - Secp256k1(Error), - Json(Error), - Hex(Error), - Psbt(Error), - PsbtParse(PsbtParseError), - Electrum(Error), - Esplora(Box<EsploraError>), - CompactFilters(CompactFiltersError), - Sled(Error), - Rusqlite(Error), -
    }
    Expand description

    Errors that can be thrown by the Wallet

    -

    Variants

    InvalidU32Bytes(Vec<u8>)

    Wrong number of bytes found when trying to convert to u32

    -

    Tuple Fields of InvalidU32Bytes

    0: Vec<u8>
    Generic(String)

    Generic error

    -

    Tuple Fields of Generic

    0: String
    ScriptDoesntHaveAddressForm

    This error is thrown when trying to convert Bare and Public key script to address

    -
    NoRecipients

    Cannot build a tx without recipients

    -
    NoUtxosSelected

    manually_selected_only option is selected but no utxo has been passed

    -
    OutputBelowDustLimit(usize)

    Output created is under the dust limit, 546 satoshis

    -

    Tuple Fields of OutputBelowDustLimit

    0: usize
    InsufficientFunds

    Wallet’s UTXO set is not enough to cover recipient’s requested plus fee

    -

    Fields of InsufficientFunds

    needed: u64

    Sats needed for some transaction

    -
    available: u64

    Sats available for spending

    -
    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

    -
    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

    -
    UnknownUtxo

    Happens when trying to spend an UTXO that is not in the internal database

    -
    TransactionNotFound

    Thrown when a tx is not found in the internal database

    -
    TransactionConfirmed

    Happens when trying to bump a transaction that is already confirmed

    -
    IrreplaceableTransaction

    Trying to replace a tx that has a sequence >= 0xFFFFFFFE

    -
    FeeRateTooLow

    When bumping a tx the fee rate requested is lower than required

    -

    Fields of FeeRateTooLow

    required: FeeRate

    Required fee rate (satoshi/vbyte)

    -
    FeeTooLow

    When bumping a tx the absolute fee requested is lower than replaced tx absolute fee

    -

    Fields of FeeTooLow

    required: u64

    Required fee absolute value (satoshi)

    -
    FeeRateUnavailable

    Node doesn’t have data to estimate a fee rate

    -
    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

    -

    Tuple Fields of MissingKeyOrigin

    0: String

    Error while working with keys

    -

    Tuple Fields of Key

    ChecksumMismatch

    Descriptor checksum mismatch

    -
    SpendingPolicyRequired(KeychainKind)

    Spending policy is not compatible with this KeychainKind

    -

    Tuple Fields of SpendingPolicyRequired

    InvalidPolicyPathError(PolicyError)

    Error while extracting and manipulating policies

    -

    Tuple Fields of InvalidPolicyPathError

    Signer(SignerError)

    Signing error

    -

    Tuple Fields of Signer

    InvalidNetwork

    Invalid network

    -

    Fields of InvalidNetwork

    requested: Network

    requested network, for example what is given as bdk-cli option

    -
    found: Network

    found network, for example the network of the bitcoin node

    -
    InvalidProgressValue(f32)

    Progress value must be between 0.0 (included) and 100.0 (included)

    -

    Tuple Fields of InvalidProgressValue

    0: f32
    ProgressUpdateError

    Progress update error (maybe the channel has been closed)

    -
    InvalidOutpoint(OutPoint)

    Requested outpoint doesn’t exist in the tx (vout greater than available outputs)

    -

    Tuple Fields of InvalidOutpoint

    0: OutPoint
    Descriptor(Error)

    Error related to the parsing and usage of descriptors

    -

    Tuple Fields of Descriptor

    0: Error
    AddressValidator(AddressValidatorError)

    Error that can be returned to fail the validation of an address

    -

    Tuple Fields of AddressValidator

    Encode(Error)

    Encoding error

    -

    Tuple Fields of Encode

    0: Error
    Miniscript(Error)

    Miniscript error

    -

    Tuple Fields of Miniscript

    0: Error
    Bip32(Error)

    BIP32 error

    -

    Tuple Fields of Bip32

    0: Error
    Secp256k1(Error)

    An ECDSA error

    -

    Tuple Fields of Secp256k1

    0: Error
    Json(Error)

    Error serializing or deserializing JSON data

    -

    Tuple Fields of Json

    0: Error
    Hex(Error)

    Hex decoding error

    -

    Tuple Fields of Hex

    0: Error
    Psbt(Error)

    Partially signed bitcoin transaction error

    -

    Tuple Fields of Psbt

    0: Error
    PsbtParse(PsbtParseError)

    Partially signed bitcoin transaction parseerror

    -

    Tuple Fields of PsbtParse

    0: PsbtParseError
    Electrum(Error)

    Electrum client error

    -

    Tuple Fields of Electrum

    0: Error
    Esplora(Box<EsploraError>)

    Esplora client error

    -

    Tuple Fields of Esplora

    CompactFilters(CompactFiltersError)

    Compact filters client error)

    -

    Tuple Fields of CompactFilters

    Sled(Error)

    Sled database error

    -

    Tuple Fields of Sled

    0: Error
    Rusqlite(Error)

    Rusqlite client error

    -

    Tuple Fields of Rusqlite

    0: 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

    -
    🔬 This is a nightly-only experimental API. (backtrace)

    Returns a stack backtrace, if available, of where this error occurred. 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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Converts a reference to Self into a dynamic trait object of Fail.

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Returns the “name” of the error. Read more

    -

    Returns a reference to the underlying cause of this failure, if it -is an error that wraps other errors. Read more

    -

    Returns a reference to the Backtrace carried by this failure, if it -carries one. Read more

    -

    Provides context for this failure. Read more

    -

    Wraps this failure in a compatibility wrapper that implements -std::error::Error. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/enum.KeychainKind.html b/static/docs-rs/bdk/nightly/latest/bdk/enum.KeychainKind.html deleted file mode 100644 index b7202193d0..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/enum.KeychainKind.html +++ /dev/null @@ -1,47 +0,0 @@ -KeychainKind in bdk - Rust

    Enum bdk::KeychainKind[][src]

    pub enum KeychainKind {
    -    External,
    -    Internal,
    -}
    Expand description

    Types of keychains

    -

    Variants

    External

    External

    -
    Internal

    Internal, usually used for change outputs

    -

    Implementations

    Return KeychainKind as a byte

    -

    Trait Implementations

    Performs the conversion.

    -

    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 !=.

    -

    Serialize this value into the given Serde serializer. Read more

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Calculate the base32 serialized length

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Error type if conversion fails

    -

    Check if all values are in range and return array-like struct of u5 values

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    Encode as base32 and write it to the supplied writer -Implementations shouldn’t allocate. Read more

    -

    Convert Self to base32 vector

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/enum.Utxo.html b/static/docs-rs/bdk/nightly/latest/bdk/enum.Utxo.html deleted file mode 100644 index 02d5db3d00..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/enum.Utxo.html +++ /dev/null @@ -1,42 +0,0 @@ -Utxo in bdk - Rust

    Enum bdk::Utxo[][src]

    pub enum Utxo {
    -    Local(LocalUtxo),
    -    Foreign {
    -        outpoint: OutPoint,
    -        psbt_input: Box<Input>,
    -    },
    -}
    Expand description

    An unspent transaction output (UTXO).

    -

    Variants

    Local(LocalUtxo)

    A UTXO owned by the local wallet.

    -

    Tuple Fields of Local

    Foreign

    A UTXO owned by another wallet.

    -

    Fields of Foreign

    outpoint: OutPoint

    The location of the output.

    -
    psbt_input: Box<Input>

    The information about the input we require to add it to a PSBT.

    -

    Implementations

    Get the location of the UTXO

    -

    Get the TxOut of the UTXO

    -

    Trait Implementations

    Returns a copy of the value. Read more

    -

    Performs copy-assignment from source. Read more

    -

    Formats the value using the given formatter. Read more

    -

    This method tests for self and other values to be equal, and is used -by ==. Read more

    -

    This method tests for !=.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/error/enum.Error.html b/static/docs-rs/bdk/nightly/latest/bdk/error/enum.Error.html deleted file mode 100644 index 9abf6d4a9c..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/error/enum.Error.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../bdk/enum.Error.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/fn.version.html b/static/docs-rs/bdk/nightly/latest/bdk/fn.version.html deleted file mode 100644 index 32eb32ae0c..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/fn.version.html +++ /dev/null @@ -1,4 +0,0 @@ -version in bdk - Rust

    Function bdk::version[][src]

    pub fn version() -> &'static str
    Expand description

    Get the version of BDK at runtime

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/index.html b/static/docs-rs/bdk/nightly/latest/bdk/index.html deleted file mode 100644 index f8225ea782..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/index.html +++ /dev/null @@ -1,169 +0,0 @@ -bdk - Rust

    Crate bdk[][src]

    Expand description

    A modern, lightweight, descriptor-based wallet library written in Rust.

    -

    About

    -

    The BDK library aims to be the core building block for Bitcoin wallets of any kind.

    -
      -
    • It uses Miniscript to support descriptors with generalized conditions. This exact same library can be used to build -single-sig wallets, multisigs, timelocked contracts and more.
    • -
    • It supports multiple blockchain backends and databases, allowing developers to choose exactly what’s right for their projects.
    • -
    • It is built to be cross-platform: the core logic works on desktop, mobile, and even WebAssembly.
    • -
    • It is very easy to extend: developers can implement customized logic for blockchain backends, databases, signers, coin selection, and more, without having to fork and modify this library.
    • -
    -

    A Tour of BDK

    -

    BDK consists of a number of modules that provide a range of functionality -essential for implementing descriptor based Bitcoin wallet applications in Rust. In this -section, we will take a brief tour of BDK, summarizing the major APIs and -their uses.

    -

    The easiest way to get started is to add bdk to your dependencies with the default features. -The default features include a simple key-value database (sled) to cache -blockchain data and an electrum blockchain client to -interact with the bitcoin P2P network.

    -
    bdk = "0.11.0"

    Sync the balance of a descriptor

    Example

    -
    use bdk::Wallet;
    -use bdk::database::MemoryDatabase;
    -use bdk::blockchain::{noop_progress, ElectrumBlockchain};
    -use bdk::electrum_client::Client;
    -
    -fn main() -> Result<(), bdk::Error> {
    -    let client = Client::new("ssl://electrum.blockstream.info:60002")?;
    -    let wallet = Wallet::new(
    -        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
    -        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
    -        bitcoin::Network::Testnet,
    -        MemoryDatabase::default(),
    -        ElectrumBlockchain::from(client)
    -    )?;
    -
    -    wallet.sync(noop_progress(), None)?;
    -
    -    println!("Descriptor balance: {} SAT", wallet.get_balance()?);
    -
    -    Ok(())
    -}
    -

    Generate a few addresses

    Example

    -
    use bdk::{Wallet};
    -use bdk::database::MemoryDatabase;
    -use bdk::wallet::AddressIndex::New;
    -
    -fn main() -> Result<(), bdk::Error> {
    -let wallet = Wallet::new_offline(
    -        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
    -        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
    -        bitcoin::Network::Testnet,
    -        MemoryDatabase::default(),
    -    )?;
    -
    -    println!("Address #0: {}", wallet.get_address(New)?);
    -    println!("Address #1: {}", wallet.get_address(New)?);
    -    println!("Address #2: {}", wallet.get_address(New)?);
    -
    -    Ok(())
    -}
    -

    Create a transaction

    Example

    -
    use bdk::{FeeRate, Wallet};
    -use bdk::database::MemoryDatabase;
    -use bdk::blockchain::{noop_progress, ElectrumBlockchain};
    -use bdk::electrum_client::Client;
    -
    -use bitcoin::consensus::serialize;
    -use bdk::wallet::AddressIndex::New;
    -
    -fn main() -> Result<(), bdk::Error> {
    -    let client = Client::new("ssl://electrum.blockstream.info:60002")?;
    -    let wallet = Wallet::new(
    -        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
    -        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
    -        bitcoin::Network::Testnet,
    -        MemoryDatabase::default(),
    -        ElectrumBlockchain::from(client)
    -    )?;
    -
    -    wallet.sync(noop_progress(), None)?;
    -
    -    let send_to = wallet.get_address(New)?;
    -    let (psbt, details) = {
    -        let mut builder =  wallet.build_tx();
    -        builder
    -            .add_recipient(send_to.script_pubkey(), 50_000)
    -            .enable_rbf()
    -            .do_not_spend_change()
    -            .fee_rate(FeeRate::from_sat_per_vb(5.0));
    -        builder.finish()?
    -    };
    -
    -    println!("Transaction details: {:#?}", details);
    -    println!("Unsigned PSBT: {}", &psbt);
    -
    -    Ok(())
    -}
    -

    Sign a transaction

    Example

    -
    use std::str::FromStr;
    -
    -use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
    -
    -use bdk::{Wallet, SignOptions};
    -use bdk::database::MemoryDatabase;
    -
    -fn main() -> Result<(), bdk::Error> {
    -    let wallet = Wallet::new_offline(
    -        "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
    -        Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
    -        bitcoin::Network::Testnet,
    -        MemoryDatabase::default(),
    -    )?;
    -
    -    let psbt = "...";
    -    let mut psbt = Psbt::from_str(psbt)?;
    -
    -    let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
    -
    -    Ok(())
    -}
    -

    Feature flags

    -

    BDK uses a set of feature flags -to reduce the amount of compiled code by allowing projects to only enable the features they need. -By default, BDK enables two internal features, key-value-db and electrum.

    -

    If you are new to BDK we recommended that you use the default features which will enable -basic descriptor wallet functionality. More advanced users can disable the default features -(--no-default-features) and build the BDK library with only the features you need. -Below is a list of the available feature flags and the additional functionality they provide.

    -
      -
    • all-keys: all features for working with bitcoin keys
    • -
    • async-interface: async functions in bdk traits
    • -
    • keys-bip39: BIP-39 mnemonic codes for generating deterministic keys
    • -
    -

    Internal features

    -

    These features do not expose any new API, but influence internal implementation aspects of -BDK.

    -
      -
    • compact_filters: compact_filters client protocol for interacting with the bitcoin P2P network
    • -
    • electrum: electrum client protocol for interacting with electrum servers
    • -
    • esplora: esplora client protocol for interacting with blockstream electrs servers
    • -
    • key-value-db: key value database based on sled for caching blockchain data
    • -
    -

    Re-exports

    -
    pub extern crate bitcoin;
    pub extern crate electrum_client;
    pub extern crate miniscript;
    pub extern crate rusqlite;
    pub extern crate sled;
    pub use descriptor::template;
    pub use descriptor::HdKeyPaths;
    pub use wallet::address_validator;
    pub use wallet::signer;
    pub use wallet::signer::SignOptions;
    pub use wallet::tx_builder::TxBuilder;
    pub use wallet::Wallet;

    Modules

    -

    Blockchain backends

    -

    Database types

    -

    Descriptors

    -

    Key formats

    -

    Wallet

    -

    Macros

    -

    Macro to write full descriptors with code

    -

    Macro to write descriptor fragments with code

    -

    Structs

    -

    Block height and timestamp of the block containing the confirmed transaction

    -

    Fee rate

    -

    An unspent output owned by a Wallet.

    -

    A wallet transaction

    -

    A Utxo with its satisfaction_weight.

    -

    Enums

    -

    Errors that can be thrown by the Wallet

    -

    Types of keychains

    -

    An unspent transaction output (UTXO).

    -

    Traits

    -

    Trait implemented by types that can be used to measure weight units.

    -

    Functions

    -

    Get the version of BDK at runtime

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.Language.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.Language.html deleted file mode 100644 index 64cd628ef5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.Language.html +++ /dev/null @@ -1,49 +0,0 @@ -Language in bdk::keys::bip39 - Rust

    Enum bdk::keys::bip39::Language[]

    pub enum Language {
    -    English,
    -    ChineseSimplified,
    -    ChineseTraditional,
    -    French,
    -    Italian,
    -    Japanese,
    -    Korean,
    -    Spanish,
    -}
    This is supported on crate feature keys-bip39 only.
    Expand description

    The language determines which words will be used in a mnemonic phrase, but also indirectly -determines the binary value of each word when a Mnemonic is turned into a Seed.

    -

    These are not of much use right now, and may even be removed from the crate, as there is no -official language specified by the standard except English.

    -

    Variants

    English
    ChineseSimplified
    ChineseTraditional
    French
    Italian
    Japanese
    Korean
    Spanish

    Implementations

    Construct a word list from its language code. Returns None -if the language code is not valid or not supported.

    -

    Get the word list for this language

    -

    Get a [WordMap][WordMap] that allows word -> index lookups in the word list

    -

    The index of an individual word in the word list is used as the binary value of that word -when the phrase is turned into a [Seed][Seed].

    -

    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 !=.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.MnemonicType.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.MnemonicType.html deleted file mode 100644 index f7c6746c0e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/enum.MnemonicType.html +++ /dev/null @@ -1,111 +0,0 @@ -MnemonicType in bdk::keys::bip39 - Rust

    Enum bdk::keys::bip39::MnemonicType[]

    pub enum MnemonicType {
    -    Words12,
    -    Words15,
    -    Words18,
    -    Words21,
    -    Words24,
    -}
    This is supported on crate feature keys-bip39 only.
    Expand description

    Determines the number of words that will be present in a Mnemonic phrase

    -

    Also directly affects the amount of entropy that will be used to create a Mnemonic, -and therefore the cryptographic strength of the HD wallet keys/addresses that can be derived from -it using the Seed.

    -

    For example, a 12 word mnemonic phrase is essentially a friendly representation of a 128-bit key, -while a 24 word mnemonic phrase is essentially a 256-bit key.

    -

    If you know you want a specific phrase length, you can use the enum variant directly, for example -MnemonicType::Words12.

    -

    You can also get a MnemonicType that corresponds to one of the standard BIP39 key sizes by -passing arbitrary usize values:

    - -
    use bip39::{MnemonicType};
    -
    -let mnemonic_type = MnemonicType::for_key_size(128).unwrap();
    -

    Variants

    Words12
    Words15
    Words18
    Words21
    Words24

    Implementations

    Get a MnemonicType for a mnemonic phrase with a specific number of words

    -

    Specifying a word count not provided for by the BIP39 standard will return an Error -of kind ErrorKind::InvalidWordLength.

    -

    Example

    -
    use bip39::{MnemonicType};
    -
    -let mnemonic_type = MnemonicType::for_word_count(12).unwrap();
    -

    Get a MnemonicType for a mnemonic phrase representing the given key size as bits

    -

    Specifying a key size not provided for by the BIP39 standard will return an Error -of kind ErrorKind::InvalidKeysize.

    -

    Example

    -
    use bip39::{MnemonicType};
    -
    -let mnemonic_type = MnemonicType::for_key_size(128).unwrap();
    -

    Get a MnemonicType for an existing mnemonic phrase

    -

    This can be used when you need information about a mnemonic phrase based on the number of -words, for example you can get the entropy value using MnemonicType::entropy_bits.

    -

    Specifying a phrase that does not match one of the standard BIP39 phrase lengths will return -an Error of kind ErrorKind::InvalidWordLength. The phrase will not be validated in any -other way.

    -

    Example

    -
    use bip39::{MnemonicType};
    -
    -let test_mnemonic = "park remain person kitchen mule spell knee armed position rail grid ankle";
    -
    -let mnemonic_type = MnemonicType::for_phrase(test_mnemonic).unwrap();
    -
    -let entropy_bits = mnemonic_type.entropy_bits();
    -

    Return the number of entropy+checksum bits

    -

    Example

    -
    use bip39::{MnemonicType};
    -
    -let test_mnemonic = "park remain person kitchen mule spell knee armed position rail grid ankle";
    -
    -let mnemonic_type = MnemonicType::for_phrase(test_mnemonic).unwrap();
    -
    -let total_bits = mnemonic_type.total_bits();
    -

    Return the number of entropy bits

    -

    Example

    -
    use bip39::{MnemonicType};
    -
    -let test_mnemonic = "park remain person kitchen mule spell knee armed position rail grid ankle";
    -
    -let mnemonic_type = MnemonicType::for_phrase(test_mnemonic).unwrap();
    -
    -let entropy_bits = mnemonic_type.entropy_bits();
    -

    Return the number of checksum bits

    -

    Example

    -
    use bip39::{MnemonicType};
    -
    -let test_mnemonic = "park remain person kitchen mule spell knee armed position rail grid ankle";
    -
    -let mnemonic_type = MnemonicType::for_phrase(test_mnemonic).unwrap();
    -
    -let checksum_bits = mnemonic_type.checksum_bits();
    -

    Return the number of words

    -

    Example

    -
    use bip39::{MnemonicType};
    -
    -let mnemonic_type = MnemonicType::Words12;
    -
    -let word_count = mnemonic_type.word_count();
    -

    Trait Implementations

    Returns a copy of the value. Read more

    -

    Performs copy-assignment from source. Read more

    -

    Formats the value using the given formatter. Read more

    -

    Returns the “default value” for a type. Read more

    -

    Formats the value using the given formatter. Read more

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/index.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/index.html deleted file mode 100644 index 01e929c430..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/index.html +++ /dev/null @@ -1,13 +0,0 @@ -bdk::keys::bip39 - Rust

    Module bdk::keys::bip39[][src]

    This is supported on crate feature keys-bip39 only.
    Expand description

    BIP-0039

    -

    Structs

    -

    The primary type in this crate, most tasks require creating or using one.

    -

    The secret value used to derive HD wallet addresses from a Mnemonic phrase.

    -

    Enums

    -

    The language determines which words will be used in a mnemonic phrase, but also indirectly -determines the binary value of each word when a Mnemonic is turned into a Seed.

    -

    Determines the number of words that will be present in a Mnemonic phrase

    -

    Type Definitions

    -

    Type for a BIP39 mnemonic with an optional passphrase

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/sidebar-items.js deleted file mode 100644 index 4c0779de63..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Language","The language determines which words will be used in a mnemonic phrase, but also indirectly determines the binary value of each word when a `Mnemonic` is turned into a `Seed`."],["MnemonicType","Determines the number of words that will be present in a `Mnemonic` phrase"]],"struct":[["Mnemonic","The primary type in this crate, most tasks require creating or using one."],["Seed","The secret value used to derive HD wallet addresses from a `Mnemonic` phrase."]],"type":[["MnemonicWithPassphrase","Type for a BIP39 mnemonic with an optional passphrase"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/struct.Mnemonic.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/struct.Mnemonic.html deleted file mode 100644 index c7b3c9a84c..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/struct.Mnemonic.html +++ /dev/null @@ -1,104 +0,0 @@ -Mnemonic in bdk::keys::bip39 - Rust

    Struct bdk::keys::bip39::Mnemonic[]

    pub struct Mnemonic { /* fields omitted */ }
    This is supported on crate feature keys-bip39 only.
    Expand description

    The primary type in this crate, most tasks require creating or using one.

    -

    To create a new Mnemonic from a randomly generated key, call Mnemonic::new().

    -

    To get a Mnemonic instance for an existing mnemonic phrase, including -those generated by other software or hardware wallets, use Mnemonic::from_phrase().

    -

    You can get the HD wallet Seed from a Mnemonic by calling Seed::new(). -From there you can either get the raw byte value with Seed::as_bytes(), or the hex -representation using Rust formatting: format!("{:X}", seed).

    -

    You can also get the original entropy value back from a Mnemonic with Mnemonic::entropy(), -but beware that the entropy value is not the same thing as an HD wallet seed, and should -never be used that way.

    -

    Implementations

    Generates a new Mnemonic

    -

    Use Mnemonic::phrase() to get an str slice of the generated phrase.

    -

    Example

    -
    use bip39::{Mnemonic, MnemonicType, Language};
    -
    -let mnemonic = Mnemonic::new(MnemonicType::Words12, Language::English);
    -let phrase = mnemonic.phrase();
    -
    -println!("phrase: {}", phrase);
    -
    -assert_eq!(phrase.split(" ").count(), 12);
    -

    Create a Mnemonic from pre-generated entropy

    -

    Example

    -
    use bip39::{Mnemonic, MnemonicType, Language};
    -
    -let entropy = &[0x33, 0xE4, 0x6B, 0xB1, 0x3A, 0x74, 0x6E, 0xA4, 0x1C, 0xDD, 0xE4, 0x5C, 0x90, 0x84, 0x6A, 0x79];
    -let mnemonic = Mnemonic::from_entropy(entropy, Language::English).unwrap();
    -
    -assert_eq!("crop cash unable insane eight faith inflict route frame loud box vibrant", mnemonic.phrase());
    -assert_eq!("33E46BB13A746EA41CDDE45C90846A79", format!("{:X}", mnemonic));
    -

    Create a Mnemonic from an existing mnemonic phrase

    -

    The phrase supplied will be checked for word length and validated according to the checksum -specified in BIP0039

    -

    Example

    -
    use bip39::{Mnemonic, Language};
    -
    -let phrase = "park remain person kitchen mule spell knee armed position rail grid ankle";
    -let mnemonic = Mnemonic::from_phrase(phrase, Language::English).unwrap();
    -
    -assert_eq!(phrase, mnemonic.phrase());
    -

    Validate a mnemonic phrase

    -

    The phrase supplied will be checked for word length and validated according to the checksum -specified in BIP0039.

    -

    Example

    -
    use bip39::{Mnemonic, Language};
    -
    -let test_mnemonic = "park remain person kitchen mule spell knee armed position rail grid ankle";
    -
    -assert!(Mnemonic::validate(test_mnemonic, Language::English).is_ok());
    -

    Get the mnemonic phrase as a string reference.

    -

    Consume the Mnemonic and return the phrase as a String.

    -

    This operation doesn’t perform any allocations.

    -

    Get the original entropy value of the mnemonic phrase as a slice.

    -

    Example

    -
    use bip39::{Mnemonic, Language};
    -
    -let phrase = "park remain person kitchen mule spell knee armed position rail grid ankle";
    -
    -let mnemonic = Mnemonic::from_phrase(phrase, Language::English).unwrap();
    -
    -let entropy: &[u8] = mnemonic.entropy();
    -

    Note: You shouldn’t use the generated entropy as secrets, for that generate a new -Seed from the Mnemonic.

    -

    Get the Language

    -

    Trait Implementations

    Performs the conversion.

    -

    Returns a copy of the value. Read more

    -

    Performs copy-assignment from source. Read more

    -

    Formats the value using the given formatter. Read more

    -

    Consume self and turn it into an ExtendedKey Read more

    -

    Consume self and turn it into a DescriptorKey by adding the extra metadata, such as -key origin and derivation path Read more

    -

    Formats the value using the given formatter. Read more

    -

    Type specifying the amount of entropy required e.g. [u8;32]

    -

    Extra options required by the generate_with_entropy

    -

    Returned error in case of failure

    -

    Generate a key given the extra options and the entropy

    -

    Generate a key given the options with a random entropy

    -

    Formats the value using the given formatter.

    -

    Formats the value using the given formatter.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    Outputs the hash in hexadecimal form

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/struct.Seed.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/struct.Seed.html deleted file mode 100644 index 383c9685a5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/struct.Seed.html +++ /dev/null @@ -1,48 +0,0 @@ -Seed in bdk::keys::bip39 - Rust

    Struct bdk::keys::bip39::Seed[]

    pub struct Seed { /* fields omitted */ }
    This is supported on crate feature keys-bip39 only.
    Expand description

    The secret value used to derive HD wallet addresses from a Mnemonic phrase.

    -

    Because it is not possible to create a Mnemonic instance that is invalid, it is -therefore impossible to have a Seed instance that is invalid. This guarantees that only -a valid, intact mnemonic phrase can be used to derive HD wallet addresses.

    -

    To get the raw byte value use Seed::as_bytes(). These can be used to derive -HD wallet addresses using another crate (deriving HD wallet addresses is outside the scope of this -crate and the BIP39 standard).

    -

    Implementations

    Generates the seed from the Mnemonic and the password.

    -

    Get the seed value as a byte slice

    -

    Trait Implementations

    Performs the conversion.

    -

    Returns a copy of the value. Read more

    -

    Performs copy-assignment from source. Read more

    -

    Formats the value using the given formatter. Read more

    -

    Consume self and turn it into an ExtendedKey Read more

    -

    Consume self and turn it into a DescriptorKey by adding the extra metadata, such as -key origin and derivation path Read more

    -

    Formats the value using the given formatter.

    -

    Formats the value using the given formatter.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Calculate the base32 serialized length

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Error type if conversion fails

    -

    Check if all values are in range and return array-like struct of u5 values

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    Encode as base32 and write it to the supplied writer -Implementations shouldn’t allocate. Read more

    -

    Convert Self to base32 vector

    -

    Outputs the hash in hexadecimal form

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/type.MnemonicWithPassphrase.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/type.MnemonicWithPassphrase.html deleted file mode 100644 index 1b98adebbf..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/bip39/type.MnemonicWithPassphrase.html +++ /dev/null @@ -1,7 +0,0 @@ -MnemonicWithPassphrase in bdk::keys::bip39 - Rust

    Type Definition bdk::keys::bip39::MnemonicWithPassphrase[][src]

    pub type MnemonicWithPassphrase = (Mnemonic, Option<String>);
    This is supported on crate feature keys-bip39 only.
    Expand description

    Type for a BIP39 mnemonic with an optional passphrase

    -

    Trait Implementations

    Consume self and turn it into an ExtendedKey Read more

    -

    Consume self and turn it into a DescriptorKey by adding the extra metadata, such as -key origin and derivation path Read more

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorKey.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorKey.html deleted file mode 100644 index 8a5149114e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorKey.html +++ /dev/null @@ -1,28 +0,0 @@ -DescriptorKey in bdk::keys - Rust

    Enum bdk::keys::DescriptorKey[][src]

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorPublicKey.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorPublicKey.html deleted file mode 100644 index 4253281299..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorPublicKey.html +++ /dev/null @@ -1,75 +0,0 @@ -DescriptorPublicKey in bdk::keys - Rust

    Enum bdk::keys::DescriptorPublicKey[]

    pub enum DescriptorPublicKey {
    -    SinglePub(DescriptorSinglePub),
    -    XPub(DescriptorXKey<ExtendedPubKey>),
    -}
    Expand description

    The MiniscriptKey corresponding to Descriptors. This can -either be Single public key or a Xpub

    -

    Variants

    Single Public Key

    -

    Tuple Fields of SinglePub

    XPub(DescriptorXKey<ExtendedPubKey>)

    Xpub

    -

    Tuple Fields of XPub

    0: DescriptorXKey<ExtendedPubKey>

    Implementations

    The fingerprint of the master key associated with this key

    -

    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)

    -

    Whether or not the key has a wildcards

    -

    If this public key has a wildcard, replace it by the given index

    -

    Panics if given an index ≥ 2^31

    -

    Computes the public key corresponding to this descriptor key

    -

    Will return an error if the descriptor key has any hardened -derivation steps in its path, or if the key has any wildcards.

    -

    To ensure there are no wildcards, call .derive(0) or similar; -to avoid hardened derivation steps, start from a DescriptorSecretKey -and call as_public, or call TranslatePk2::translate_pk2 with -some function which has access to secret key data.

    -

    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

    -

    Feeds this value into the given Hasher. Read more

    -

    Feeds a slice of this type into the given Hasher. Read more

    -

    Turn the key into a DescriptorKey within the requested ScriptContext

    -

    The associated Hash type with the publicKey

    -

    Check if the publicKey is uncompressed. The default -implementation returns false Read more

    -

    Converts an object to PublicHash

    -

    Computes the size of a public key when serialized in a script, -including the length bytes 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 !=.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorSecretKey.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorSecretKey.html deleted file mode 100644 index 9359492fb1..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.DescriptorSecretKey.html +++ /dev/null @@ -1,37 +0,0 @@ -DescriptorSecretKey in bdk::keys - Rust

    Enum bdk::keys::DescriptorSecretKey[]

    pub enum DescriptorSecretKey {
    -    SinglePriv(DescriptorSinglePriv),
    -    XPrv(DescriptorXKey<ExtendedPrivKey>),
    -}
    Expand description

    A Secret Key that can be either a single key or an Xprv

    -

    Variants

    Single Secret Key

    -

    Tuple Fields of SinglePriv

    XPrv(DescriptorXKey<ExtendedPrivKey>)

    Xprv

    -

    Tuple Fields of XPrv

    0: DescriptorXKey<ExtendedPrivKey>

    Implementations

    Return the public version of this key, by applying either -DescriptorSinglePriv::as_public or [DescriptorXKey<bip32::ExtendedPrivKey>::as_public] -depending on the type of key.

    -

    If the key is an “XPrv”, the hardened derivation steps will be applied before converting it -to a public key. See the documentation of [DescriptorXKey<bip32::ExtendedPrivKey>::as_public] -for more details.

    -

    Trait Implementations

    Formats the value using the given formatter. Read more

    -

    Formats the value using the given formatter. Read more

    -

    The associated error which can be returned from parsing.

    -

    Parses a string s to return a value of this type. Read more

    -

    Turn the key into a DescriptorKey within the requested ScriptContext

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.ExtendedKey.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.ExtendedKey.html deleted file mode 100644 index 495b49355f..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.ExtendedKey.html +++ /dev/null @@ -1,39 +0,0 @@ -ExtendedKey in bdk::keys - Rust

    Enum bdk::keys::ExtendedKey[][src]

    pub enum ExtendedKey<Ctx: ScriptContext = Legacy> {
    -    Private((ExtendedPrivKey, PhantomData<Ctx>)),
    -    Public((ExtendedPubKey, PhantomData<Ctx>)),
    -}
    Expand description

    Enum for extended keys that can be either xprv or xpub

    -

    An instance of ExtendedKey can be constructed from an ExtendedPrivKey -or an ExtendedPubKey by using the From trait.

    -

    Defaults to the Legacy context.

    -

    Variants

    Private((ExtendedPrivKey, PhantomData<Ctx>))

    A private extended key, aka an xprv

    -

    Tuple Fields of Private

    0: (ExtendedPrivKey, PhantomData<Ctx>)
    Public((ExtendedPubKey, PhantomData<Ctx>))

    A public extended key, aka an xpub

    -

    Tuple Fields of Public

    0: (ExtendedPubKey, PhantomData<Ctx>)

    Implementations

    Return whether or not the key contains the private data

    -

    Transform the ExtendedKey into an ExtendedPrivKey for the -given [Network], if the key contains the private data

    -

    Transform the ExtendedKey into an ExtendedPubKey for the -given [Network]

    -

    Trait Implementations

    Identity conversion

    -

    Consume self and turn it into an ExtendedKey Read more

    -

    Consume self and turn it into a DescriptorKey by adding the extra metadata, such as -key origin and derivation path Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.KeyError.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.KeyError.html deleted file mode 100644 index e06474c06f..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.KeyError.html +++ /dev/null @@ -1,53 +0,0 @@ -KeyError in bdk::keys - Rust

    Enum bdk::keys::KeyError[][src]

    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

    -

    Tuple Fields of Message

    0: String
    Bip32(Error)

    BIP32 error

    -

    Tuple Fields of Bip32

    0: Error
    Miniscript(Error)

    Miniscript error

    -

    Tuple Fields of Miniscript

    0: 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

    -
    🔬 This is a nightly-only experimental API. (backtrace)

    Returns a stack backtrace, if available, of where this error occurred. 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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Converts a reference to Self into a dynamic trait object of Fail.

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Returns the “name” of the error. Read more

    -

    Returns a reference to the underlying cause of this failure, if it -is an error that wraps other errors. Read more

    -

    Returns a reference to the Backtrace carried by this failure, if it -carries one. Read more

    -

    Provides context for this failure. Read more

    -

    Wraps this failure in a compatibility wrapper that implements -std::error::Error. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.ScriptContextEnum.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.ScriptContextEnum.html deleted file mode 100644 index 1a209b5c87..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/enum.ScriptContextEnum.html +++ /dev/null @@ -1,37 +0,0 @@ -ScriptContextEnum in bdk::keys - Rust

    Enum bdk::keys::ScriptContextEnum[][src]

    pub enum ScriptContextEnum {
    -    Legacy,
    -    Segwitv0,
    -}
    Expand description

    Enum representation of the known valid ScriptContexts

    -

    Variants

    Legacy

    Legacy scripts

    -
    Segwitv0

    Segwitv0 scripts

    -

    Implementations

    Returns whether the script context is ScriptContextEnum::Legacy

    -

    Returns whether the script context is ScriptContextEnum::Segwitv0

    -

    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 !=.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/keys/fn.any_network.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/fn.any_network.html deleted file mode 100644 index 3fdb567cb4..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/fn.any_network.html +++ /dev/null @@ -1,4 +0,0 @@ -any_network in bdk::keys - Rust

    Function bdk::keys::any_network[][src]

    pub fn any_network() -> ValidNetworks
    Expand description

    Create a set containing mainnet, testnet and regtest

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/keys/fn.mainnet_network.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/fn.mainnet_network.html deleted file mode 100644 index 5753bd5e40..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/fn.mainnet_network.html +++ /dev/null @@ -1,4 +0,0 @@ -mainnet_network in bdk::keys - Rust

    Function bdk::keys::mainnet_network[][src]

    pub fn mainnet_network() -> ValidNetworks
    Expand description

    Create a set only containing mainnet

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/keys/fn.merge_networks.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/fn.merge_networks.html deleted file mode 100644 index 9b15a7abda..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/fn.merge_networks.html +++ /dev/null @@ -1,4 +0,0 @@ -merge_networks in bdk::keys - Rust

    Function bdk::keys::merge_networks[][src]

    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/static/docs-rs/bdk/nightly/latest/bdk/keys/fn.test_networks.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/fn.test_networks.html deleted file mode 100644 index efa8335377..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/fn.test_networks.html +++ /dev/null @@ -1,4 +0,0 @@ -test_networks in bdk::keys - Rust

    Function bdk::keys::test_networks[][src]

    pub fn test_networks() -> ValidNetworks
    Expand description

    Create a set containing testnet and regtest

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/keys/index.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/index.html deleted file mode 100644 index 45a9223788..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/index.html +++ /dev/null @@ -1,38 +0,0 @@ -bdk::keys - Rust

    Module bdk::keys[][src]

    Expand description

    Key formats

    -

    Modules

    -
    bip39keys-bip39

    BIP-0039

    -

    Structs

    -

    A Single Descriptor Secret Key with optional origin information

    -

    A Single Descriptor Key with optional origin information

    -

    Output of a GeneratableKey key generation

    -

    Options for generating a [PrivateKey]

    -

    Contents of a “sortedmulti” descriptor

    -

    Enums

    -

    Container for public or secret keys

    -

    The MiniscriptKey corresponding to Descriptors. This can -either be Single public key or a Xpub

    -

    A Secret Key that can be either a single 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

    -

    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 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/static/docs-rs/bdk/nightly/latest/bdk/keys/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/keys/sidebar-items.js deleted file mode 100644 index 9b1ae8b56f..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["DescriptorKey","Container for public or secret keys"],["DescriptorPublicKey","The MiniscriptKey corresponding to Descriptors. This can either be Single public key or a Xpub"],["DescriptorSecretKey","A Secret Key that can be either a single 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"]],"fn":[["any_network","Create a set containing mainnet, testnet and regtest"],["mainnet_network","Create a set only containing mainnet"],["merge_networks","Compute the intersection of two sets"],["test_networks","Create a set containing testnet and regtest"]],"mod":[["bip39","BIP-0039"]],"struct":[["DescriptorSinglePriv","A Single Descriptor Secret Key with optional origin information"],["DescriptorSinglePub","A Single Descriptor Key with optional origin information"],["GeneratedKey","Output of a [`GeneratableKey`] key generation"],["PrivateKeyGenerateOptions","Options for generating a [`PrivateKey`]"],["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/static/docs-rs/bdk/nightly/latest/bdk/keys/struct.DescriptorSinglePriv.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/struct.DescriptorSinglePriv.html deleted file mode 100644 index cafc8126d2..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/struct.DescriptorSinglePriv.html +++ /dev/null @@ -1,26 +0,0 @@ -DescriptorSinglePriv in bdk::keys - Rust

    Struct bdk::keys::DescriptorSinglePriv[]

    pub struct DescriptorSinglePriv {
    -    pub origin: Option<(Fingerprint, DerivationPath)>,
    -    pub key: PrivateKey,
    -}
    Expand description

    A Single Descriptor Secret Key with optional origin information

    -

    Fields

    origin: Option<(Fingerprint, DerivationPath)>

    Origin information

    -
    key: PrivateKey

    The key

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/keys/struct.DescriptorSinglePub.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/struct.DescriptorSinglePub.html deleted file mode 100644 index c568502a7d..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/struct.DescriptorSinglePub.html +++ /dev/null @@ -1,48 +0,0 @@ -DescriptorSinglePub in bdk::keys - Rust

    Struct bdk::keys::DescriptorSinglePub[]

    pub struct DescriptorSinglePub {
    -    pub origin: Option<(Fingerprint, DerivationPath)>,
    -    pub key: PublicKey,
    -}
    Expand description

    A Single Descriptor Key with optional origin information

    -

    Fields

    origin: Option<(Fingerprint, DerivationPath)>

    Origin information

    -
    key: PublicKey

    The 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 !=.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/keys/struct.GeneratedKey.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/struct.GeneratedKey.html deleted file mode 100644 index 8f36f2d9a5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/struct.GeneratedKey.html +++ /dev/null @@ -1,27 +0,0 @@ -GeneratedKey in bdk::keys - Rust

    Struct bdk::keys::GeneratedKey[][src]

    pub struct GeneratedKey<K, Ctx: ScriptContext> { /* fields omitted */ }
    Expand description

    Output of a GeneratableKey key generation

    -

    Implementations

    Consumes self and returns the key

    -

    Trait Implementations

    The resulting type after dereferencing.

    -

    Dereferences the value.

    -

    Consume self and turn it into an ExtendedKey Read more

    -

    Consume self and turn it into a DescriptorKey by adding the extra metadata, such as -key origin and derivation path Read more

    -

    Turn the key into a DescriptorKey within the requested ScriptContext

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/keys/struct.PrivateKeyGenerateOptions.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/struct.PrivateKeyGenerateOptions.html deleted file mode 100644 index 672f14fa46..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/struct.PrivateKeyGenerateOptions.html +++ /dev/null @@ -1,32 +0,0 @@ -PrivateKeyGenerateOptions in bdk::keys - Rust

    Struct bdk::keys::PrivateKeyGenerateOptions[][src]

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/keys/struct.SortedMultiVec.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/struct.SortedMultiVec.html deleted file mode 100644 index 3b6320d80b..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/struct.SortedMultiVec.html +++ /dev/null @@ -1,87 +0,0 @@ -SortedMultiVec in bdk::keys - Rust

    Struct bdk::keys::SortedMultiVec[]

    pub struct SortedMultiVec<Pk, Ctx> where
        Ctx: ScriptContext,
        Pk: MiniscriptKey, 
    { - pub k: usize, - pub pks: Vec<Pk, Global>, - // some fields omitted -}
    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 translatefpk returns an uncompressed key when -converting to a Segwit descriptor. To prevent this panic, ensure -translatefpk 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

    -

    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

    -

    Convert the object into an abstract policy

    -

    This method returns an Ordering between self and other. Read more

    -

    Compares and returns the maximum of two values. Read more

    -

    Compares and returns the minimum of two values. Read more

    -

    Restrict a value to a certain interval. Read more

    -

    This method tests for self and other values to be equal, and is used -by ==. Read more

    -

    This method tests for !=.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.DerivableKey.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.DerivableKey.html deleted file mode 100644 index cff040115c..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.DerivableKey.html +++ /dev/null @@ -1,103 +0,0 @@ -DerivableKey in bdk::keys - Rust

    Trait bdk::keys::DerivableKey[][src]

    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 transofrmed 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 implemented 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 ExtendedPrivKey or -an ExtendedPubKey can implement only the required into_extended_key() method.

    - -
    use bdk::bitcoin;
    -use bdk::bitcoin::util::bip32;
    -use bdk::keys::{DerivableKey, ExtendedKey, KeyError, ScriptContext};
    -
    -struct MyCustomKeyType {
    -    key_data: bitcoin::PrivateKey,
    -    chain_code: Vec<u8>,
    -    network: bitcoin::Network,
    -}
    -
    -impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
    -    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
    -        let xprv = bip32::ExtendedPrivKey {
    -            network: self.network,
    -            depth: 0,
    -            parent_fingerprint: bip32::Fingerprint::default(),
    -            private_key: self.key_data,
    -            chain_code: bip32::ChainCode::from(self.chain_code.as_ref()),
    -            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 -ExtendedPrivKey or ExtendedPubKey will be considered valid.

    - -
    use bdk::bitcoin;
    -use bdk::bitcoin::util::bip32;
    -use bdk::keys::{
    -    any_network, DerivableKey, DescriptorKey, ExtendedKey, KeyError, ScriptContext,
    -};
    -
    -struct MyCustomKeyType {
    -    key_data: bitcoin::PrivateKey,
    -    chain_code: Vec<u8>,
    -}
    -
    -impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
    -    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
    -        let xprv = bip32::ExtendedPrivKey {
    -            network: bitcoin::Network::Bitcoin, // pick an arbitrary network here
    -            depth: 0,
    -            parent_fingerprint: bip32::Fingerprint::default(),
    -            private_key: self.key_data,
    -            chain_code: bip32::ChainCode::from(self.chain_code.as_ref()),
    -            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

    -

    This can be used to get direct access to xprvs and xpubs for types that implement this trait, -like Mnemonic when the keys-bip39 feature is enabled.

    - -
    use bdk::bitcoin::Network;
    -use bdk::keys::{DerivableKey, ExtendedKey};
    -use bdk::keys::bip39::{Mnemonic, Language};
    -
    -let xkey: ExtendedKey =
    -    Mnemonic::from_phrase(
    -        "jelly crash boy whisper mouse ecology tuna soccer memory million news short",
    -        Language::English
    -    )?
    -    .into_extended_key()?;
    -let xprv = xkey.into_xprv(Network::Bitcoin).unwrap();
    -

    Provided methods

    Consume self and turn it into a DescriptorKey by adding the extra metadata, such as -key origin and derivation path

    -

    Implementations on Foreign Types

    Implementors

    Identity conversion

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.ExtScriptContext.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.ExtScriptContext.html deleted file mode 100644 index 80e9abffa1..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.ExtScriptContext.html +++ /dev/null @@ -1,12 +0,0 @@ -ExtScriptContext in bdk::keys - Rust

    Trait bdk::keys::ExtScriptContext[][src]

    pub trait ExtScriptContext: ScriptContext {
    -    fn as_enum() -> ScriptContextEnum;
    -
    -    fn is_legacy() -> bool { ... }
    -
    fn is_segwit_v0() -> 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

    -

    Implementors

    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableDefaultOptions.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableDefaultOptions.html deleted file mode 100644 index 4e6cf622b1..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableDefaultOptions.html +++ /dev/null @@ -1,12 +0,0 @@ -GeneratableDefaultOptions in bdk::keys - Rust

    Trait bdk::keys::GeneratableDefaultOptions[][src]

    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/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableKey.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.GeneratableKey.html deleted file mode 100644 index 49dc544363..0000000000 --- a/static/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[][src]

    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.

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.IntoDescriptorKey.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.IntoDescriptorKey.html deleted file mode 100644 index 5287a61afd..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.IntoDescriptorKey.html +++ /dev/null @@ -1,107 +0,0 @@ -IntoDescriptorKey in bdk::keys - Rust

    Trait bdk::keys::IntoDescriptorKey[][src]

    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, DescriptorSinglePub,
    -    IntoDescriptorKey, KeyError, ScriptContext,
    -};
    -
    -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::SinglePub(DescriptorSinglePub {
    -                origin: None,
    -                key: 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 std::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/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.ScriptContext.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.ScriptContext.html deleted file mode 100644 index b7710b728e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/trait.ScriptContext.html +++ /dev/null @@ -1,77 +0,0 @@ -ScriptContext in bdk::keys - Rust

    Trait bdk::keys::ScriptContext[]

    pub trait ScriptContext: Debug + Clone + Ord + PartialOrd<Self> + Eq + PartialEq<Self> + Hash + Sealed {
    -    fn check_terminal_non_malleable<Pk, Ctx>(
            _frag: &Terminal<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    ; -
    fn max_satisfaction_size<Pk, Ctx>(ms: &Miniscript<Pk, Ctx>) -> Option<usize>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    ; - - fn check_witness<Pk, Ctx>(
            _witness: &[Vec<u8, Global>]
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn check_global_consensus_validity<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn check_global_policy_validity<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn check_local_consensus_validity<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn check_local_policy_validity<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn check_global_validity<Pk, Ctx>(
            ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn check_local_validity<Pk, Ctx>(
            ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), ScriptContextError>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn top_level_type_check<Pk, Ctx>(
            ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), Error>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn other_top_level_checks<Pk, Ctx>(
            _ms: &Miniscript<Pk, Ctx>
        ) -> Result<(), Error>
        where
            Ctx: ScriptContext,
            Pk: MiniscriptKey
    , - { ... } -
    fn top_level_checks<Pk, Ctx>(ms: &Miniscript<Pk, Ctx>) -> Result<(), Error>
        where
            Ctx: ScriptContext,
            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 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.

    -

    Depending on script context, the size of a satifaction witness may slightly differ.

    -

    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.

    -

    Implementations on Foreign Types

    Implementors

    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/keys/type.KeyMap.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/type.KeyMap.html deleted file mode 100644 index 29c7f03dff..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/type.KeyMap.html +++ /dev/null @@ -1,8 +0,0 @@ -KeyMap in bdk::keys - Rust

    Type Definition bdk::keys::KeyMap[]

    pub type KeyMap = HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>;
    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/static/docs-rs/bdk/nightly/latest/bdk/keys/type.ValidNetworks.html b/static/docs-rs/bdk/nightly/latest/bdk/keys/type.ValidNetworks.html deleted file mode 100644 index 9265ef2898..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/keys/type.ValidNetworks.html +++ /dev/null @@ -1,4 +0,0 @@ -ValidNetworks in bdk::keys - Rust

    Type Definition bdk::keys::ValidNetworks[][src]

    pub type ValidNetworks = HashSet<Network>;
    Expand description

    Set of valid networks for a key

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/macro.descriptor!.html b/static/docs-rs/bdk/nightly/latest/bdk/macro.descriptor!.html deleted file mode 100644 index 976e018bd9..0000000000 --- a/static/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/static/docs-rs/bdk/nightly/latest/bdk/macro.descriptor.html b/static/docs-rs/bdk/nightly/latest/bdk/macro.descriptor.html deleted file mode 100644 index c5d8ac8e4a..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/macro.descriptor.html +++ /dev/null @@ -1,79 +0,0 @@ -descriptor in bdk - Rust

    Macro bdk::descriptor[][src]

    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) *)) => { ... };
    -}
    -
    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(...),sdv: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: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: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/static/docs-rs/bdk/nightly/latest/bdk/macro.fragment!.html b/static/docs-rs/bdk/nightly/latest/bdk/macro.fragment!.html deleted file mode 100644 index 6eeebba321..0000000000 --- a/static/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/static/docs-rs/bdk/nightly/latest/bdk/macro.fragment.html b/static/docs-rs/bdk/nightly/latest/bdk/macro.fragment.html deleted file mode 100644 index 9f748be2b1..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/macro.fragment.html +++ /dev/null @@ -1,35 +0,0 @@ -fragment in bdk - Rust

    Macro bdk::fragment[][src]

    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) +)) => { ... };
    -    (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/static/docs-rs/bdk/nightly/latest/bdk/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/sidebar-items.js deleted file mode 100644 index 5670daf604..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["Error","Errors that can be thrown by the `Wallet`"],["KeychainKind","Types of keychains"],["Utxo","An unspent transaction output (UTXO)."]],"externcrate":[["bitcoin",""],["electrum_client",""],["miniscript",""],["rusqlite",""],["sled",""]],"fn":[["version","Get the version of BDK at runtime"]],"macro":[["descriptor","Macro to write full descriptors with code"],["fragment","Macro to write descriptor fragments with code"]],"mod":[["blockchain","Blockchain backends"],["database","Database types"],["descriptor","Descriptors"],["keys","Key formats"],["wallet","Wallet"]],"struct":[["ConfirmationTime","Block height and timestamp of the block containing the confirmed transaction"],["FeeRate","Fee rate"],["LocalUtxo","An unspent output owned by a `Wallet`."],["TransactionDetails","A wallet transaction"],["WeightedUtxo","A [`Utxo`] with its `satisfaction_weight`."]],"trait":[["Vbytes","Trait implemented by types that can be used to measure weight units."]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/struct.ConfirmationTime.html b/static/docs-rs/bdk/nightly/latest/bdk/struct.ConfirmationTime.html deleted file mode 100644 index 492d39ca1a..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/struct.ConfirmationTime.html +++ /dev/null @@ -1,39 +0,0 @@ -ConfirmationTime in bdk - Rust

    Struct bdk::ConfirmationTime[][src]

    pub struct ConfirmationTime {
    -    pub height: u32,
    -    pub timestamp: u64,
    -}
    Expand description

    Block height and timestamp of the block containing the confirmed transaction

    -

    Fields

    height: u32

    confirmation block height

    -
    timestamp: u64

    confirmation block timestamp

    -

    Implementations

    Returns Some ConfirmationTime if both height and timestamp are Some

    -

    Trait Implementations

    Returns a copy of the value. Read more

    -

    Performs copy-assignment from source. Read more

    -

    Formats the value using the given formatter. Read more

    -

    Returns the “default value” for a type. Read more

    -

    Deserialize this value from the given Serde deserializer. Read more

    -

    This method tests for self and other values to be equal, and is used -by ==. Read more

    -

    This method tests for !=.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/struct.FeeRate.html b/static/docs-rs/bdk/nightly/latest/bdk/struct.FeeRate.html deleted file mode 100644 index 2edd5a044f..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/struct.FeeRate.html +++ /dev/null @@ -1,48 +0,0 @@ -FeeRate in bdk - Rust

    Struct bdk::FeeRate[][src]

    pub struct FeeRate(_);
    Expand description

    Fee rate

    -

    Implementations

    Create a new instance of FeeRate given a float fee rate in btc/kvbytes

    -

    Create a new instance of FeeRate given a float fee rate in satoshi/vbyte

    -

    Create a new FeeRate with the default min relay fee value

    -

    Calculate fee rate from fee and weight units (wu).

    -

    Calculate fee rate from fee and vbytes.

    -

    Return the value as satoshi/vbyte

    -

    Calculate absolute fee in Satoshis using size in weight units.

    -

    Calculate absolute fee in Satoshis using size in virtual bytes.

    -

    Trait Implementations

    Returns a copy of the value. Read more

    -

    Performs copy-assignment from source. Read more

    -

    Formats the value using the given formatter. Read more

    -

    Returns the “default value” for a type. Read more

    -

    This method tests for self and other values to be equal, and is used -by ==. Read more

    -

    This method tests for !=.

    -

    This method returns an ordering between self and other values if one exists. Read more

    -

    This method tests less than (for self and other) and is used by the < operator. Read more

    -

    This method tests less than or equal to (for self and other) and is used by the <= -operator. Read more

    -

    This method tests greater than (for self and other) and is used by the > operator. Read more

    -

    This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more

    -

    The resulting type after applying the - operator.

    -

    Performs the - operation. Read more

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/struct.LocalUtxo.html b/static/docs-rs/bdk/nightly/latest/bdk/struct.LocalUtxo.html deleted file mode 100644 index 2ec1e93e00..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/struct.LocalUtxo.html +++ /dev/null @@ -1,41 +0,0 @@ -LocalUtxo in bdk - Rust

    Struct bdk::LocalUtxo[][src]

    pub struct LocalUtxo {
    -    pub outpoint: OutPoint,
    -    pub txout: TxOut,
    -    pub keychain: KeychainKind,
    -}
    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

    -

    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 !=.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/struct.TransactionDetails.html b/static/docs-rs/bdk/nightly/latest/bdk/struct.TransactionDetails.html deleted file mode 100644 index c15c400d81..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/struct.TransactionDetails.html +++ /dev/null @@ -1,56 +0,0 @@ -TransactionDetails in bdk - Rust

    Struct bdk::TransactionDetails[][src]

    pub struct TransactionDetails {
    -    pub transaction: Option<Transaction>,
    -    pub txid: Txid,
    -    pub received: u64,
    -    pub sent: u64,
    -    pub fee: Option<u64>,
    -    pub confirmation_time: Option<ConfirmationTime>,
    -    pub verified: bool,
    -}
    Expand description

    A wallet transaction

    -

    Fields

    transaction: Option<Transaction>

    Optional transaction

    -
    txid: Txid

    Transaction id

    -
    received: u64

    Received value (sats)

    -
    sent: u64

    Sent value (sats)

    -
    fee: Option<u64>

    Fee value (sats) if available. -The availability of the fee depends on the backend. It’s never None with an Electrum -Server backend, but it could be None with a Bitcoin RPC node without txindex that receive -funds while offline.

    -
    confirmation_time: Option<ConfirmationTime>

    If the transaction is confirmed, contains height and timestamp of the block containing the -transaction, unconfirmed transaction contains None.

    -
    verified: bool

    Whether the tx has been verified against the consensus rules

    -

    Confirmed txs are considered “verified” by default, while unconfirmed txs are checked to -ensure an unstrusted Blockchain backend can’t trick the -wallet into using an invalid tx as an RBF template.

    -

    The check is only perfomed when the verify feature is enabled.

    -

    Trait Implementations

    Returns a copy of the value. Read more

    -

    Performs copy-assignment from source. Read more

    -

    Formats the value using the given formatter. Read more

    -

    Returns the “default value” for a type. Read more

    -

    Deserialize this value from the given Serde deserializer. Read more

    -

    This method tests for self and other values to be equal, and is used -by ==. Read more

    -

    This method tests for !=.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/struct.WeightedUtxo.html b/static/docs-rs/bdk/nightly/latest/bdk/struct.WeightedUtxo.html deleted file mode 100644 index 219f9a145b..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/struct.WeightedUtxo.html +++ /dev/null @@ -1,36 +0,0 @@ -WeightedUtxo in bdk - Rust

    Struct bdk::WeightedUtxo[][src]

    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 !=.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/trait.Vbytes.html b/static/docs-rs/bdk/nightly/latest/bdk/trait.Vbytes.html deleted file mode 100644 index 3248bdd2a4..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/trait.Vbytes.html +++ /dev/null @@ -1,7 +0,0 @@ -Vbytes in bdk - Rust

    Trait bdk::Vbytes[][src]

    pub trait Vbytes {
    -    fn vbytes(self) -> usize;
    -}
    Expand description

    Trait implemented by types that can be used to measure weight units.

    -

    Required methods

    Convert weight units to virtual bytes.

    -

    Implementations on Foreign Types

    Implementors

    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/types/enum.KeychainKind.html b/static/docs-rs/bdk/nightly/latest/bdk/types/enum.KeychainKind.html deleted file mode 100644 index 03524a9b17..0000000000 --- a/static/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/static/docs-rs/bdk/nightly/latest/bdk/types/enum.Utxo.html b/static/docs-rs/bdk/nightly/latest/bdk/types/enum.Utxo.html deleted file mode 100644 index 03f5add737..0000000000 --- a/static/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/static/docs-rs/bdk/nightly/latest/bdk/types/struct.ConfirmationTime.html b/static/docs-rs/bdk/nightly/latest/bdk/types/struct.ConfirmationTime.html deleted file mode 100644 index 31758b8f04..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/types/struct.ConfirmationTime.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../bdk/struct.ConfirmationTime.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/types/struct.FeeRate.html b/static/docs-rs/bdk/nightly/latest/bdk/types/struct.FeeRate.html deleted file mode 100644 index fae2b90fdc..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/types/struct.FeeRate.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../bdk/struct.FeeRate.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/types/struct.LocalUtxo.html b/static/docs-rs/bdk/nightly/latest/bdk/types/struct.LocalUtxo.html deleted file mode 100644 index eeb7867365..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/types/struct.LocalUtxo.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../bdk/struct.LocalUtxo.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/types/struct.TransactionDetails.html b/static/docs-rs/bdk/nightly/latest/bdk/types/struct.TransactionDetails.html deleted file mode 100644 index 4348bd4a45..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/types/struct.TransactionDetails.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../bdk/struct.TransactionDetails.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/types/struct.WeightedUtxo.html b/static/docs-rs/bdk/nightly/latest/bdk/types/struct.WeightedUtxo.html deleted file mode 100644 index 5e7d643399..0000000000 --- a/static/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/static/docs-rs/bdk/nightly/latest/bdk/types/trait.Vbytes.html b/static/docs-rs/bdk/nightly/latest/bdk/types/trait.Vbytes.html deleted file mode 100644 index 1074aa3d4a..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/types/trait.Vbytes.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - Redirection - - -

    Redirecting to ../../bdk/trait.Vbytes.html...

    - - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/enum.AddressValidatorError.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/enum.AddressValidatorError.html deleted file mode 100644 index 91c9903c60..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/enum.AddressValidatorError.html +++ /dev/null @@ -1,57 +0,0 @@ -AddressValidatorError in bdk::wallet::address_validator - Rust

    Enum bdk::wallet::address_validator::AddressValidatorError[][src]

    pub enum AddressValidatorError {
    -    UserRejected,
    -    ConnectionError,
    -    TimeoutError,
    -    InvalidScript,
    -    Message(String),
    -}
    Expand description

    Errors that can be returned to fail the validation of an address

    -

    Variants

    UserRejected

    User rejected the address

    -
    ConnectionError

    Network connection error

    -
    TimeoutError

    Network request timeout error

    -
    InvalidScript

    Invalid script

    -
    Message(String)

    A custom error message

    -

    Tuple Fields of Message

    0: String

    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

    -
    🔬 This is a nightly-only experimental API. (backtrace)

    Returns a stack backtrace, if available, of where this error occurred. 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

    -

    Performs the conversion.

    -

    This method tests for self and other values to be equal, and is used -by ==. Read more

    -

    This method tests for !=.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Converts a reference to Self into a dynamic trait object of Fail.

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Returns the “name” of the error. Read more

    -

    Returns a reference to the underlying cause of this failure, if it -is an error that wraps other errors. Read more

    -

    Returns a reference to the Backtrace carried by this failure, if it -carries one. Read more

    -

    Provides context for this failure. Read more

    -

    Wraps this failure in a compatibility wrapper that implements -std::error::Error. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/index.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/index.html deleted file mode 100644 index f4f4da08f3..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/index.html +++ /dev/null @@ -1,46 +0,0 @@ -bdk::wallet::address_validator - Rust

    Module bdk::wallet::address_validator[][src]

    Expand description

    Address validation callbacks

    -

    The typical usage of those callbacks is for displaying the newly-generated address on a -hardware wallet, so that the user can cross-check its correctness.

    -

    More generally speaking though, these callbacks can also be used to “do something” every time -an address is generated, without necessarily checking or validating it.

    -

    An address validator can be attached to a Wallet by using the -Wallet::add_address_validator method, and -whenever a new address is generated (either explicitly by the user with -Wallet::get_address or internally to create a change -address) all the attached validators will be polled, in sequence. All of them must complete -successfully to continue.

    -

    Example

    -
    #[derive(Debug)]
    -struct PrintAddressAndContinue;
    -
    -impl AddressValidator for PrintAddressAndContinue {
    -    fn validate(
    -        &self,
    -        keychain: KeychainKind,
    -        hd_keypaths: &HdKeyPaths,
    -        script: &Script
    -    ) -> Result<(), AddressValidatorError> {
    -        let address = Address::from_script(script, Network::Testnet)
    -            .as_ref()
    -            .map(Address::to_string)
    -            .unwrap_or(script.to_string());
    -        println!("New address of type {:?}: {}", keychain, address);
    -        println!("HD keypaths: {:#?}", hd_keypaths);
    -
    -        Ok(())
    -    }
    -}
    -
    -let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -let mut wallet = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -wallet.add_address_validator(Arc::new(PrintAddressAndContinue));
    -
    -let address = wallet.get_address(New)?;
    -println!("Address: {}", address);
    -

    Enums

    -

    Errors that can be returned to fail the validation of an address

    -

    Traits

    -

    Trait to build address validators

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/sidebar-items.js deleted file mode 100644 index 58959ba340..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["AddressValidatorError","Errors that can be returned to fail the validation of an address"]],"trait":[["AddressValidator","Trait to build address validators"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/trait.AddressValidator.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/trait.AddressValidator.html deleted file mode 100644 index 6938b2051d..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/address_validator/trait.AddressValidator.html +++ /dev/null @@ -1,11 +0,0 @@ -AddressValidator in bdk::wallet::address_validator - Rust

    Trait bdk::wallet::address_validator::AddressValidator[][src]

    pub trait AddressValidator: Send + Sync + Debug {
    -    fn validate(
            &self,
            keychain: KeychainKind,
            hd_keypaths: &HdKeyPaths,
            script: &Script
        ) -> Result<(), AddressValidatorError>; -}
    Expand description

    Trait to build address validators

    -

    All the address validators attached to a wallet with Wallet::add_address_validator will be polled -every time an address (external or internal) is generated by the wallet. Errors returned in the -validator will be propagated up to the original caller that triggered the address generation.

    -

    For a usage example see this module’s documentation.

    -

    Required methods

    Validate or inspect an address

    -

    Implementors

    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/index.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/index.html deleted file mode 100644 index 03cda120cd..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/index.html +++ /dev/null @@ -1,73 +0,0 @@ -bdk::wallet::coin_selection - Rust

    Module bdk::wallet::coin_selection[][src]

    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<D: Database> CoinSelectionAlgorithm<D> for AlwaysSpendEverything {
    -    fn coin_select(
    -        &self,
    -        database: &D,
    -        required_utxos: Vec<WeightedUtxo>,
    -        optional_utxos: Vec<WeightedUtxo>,
    -        fee_rate: FeeRate,
    -        amount_needed: u64,
    -        fee_amount: u64,
    -    ) -> Result<CoinSelectionResult, bdk::Error> {
    -        let mut selected_amount = 0;
    -        let mut additional_weight = 0;
    -        let all_utxos_selected = required_utxos
    -            .into_iter()
    -            .chain(optional_utxos)
    -            .scan(
    -                (&mut selected_amount, &mut additional_weight),
    -                |(selected_amount, additional_weight), weighted_utxo| {
    -                    **selected_amount += weighted_utxo.utxo.txout().value;
    -                    **additional_weight += TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight;
    -                    Some(weighted_utxo.utxo)
    -                },
    -            )
    -            .collect::<Vec<_>>();
    -        let additional_fees = fee_rate.fee_wu(additional_weight);
    -        let amount_needed_with_fees = (fee_amount + additional_fees) + amount_needed;
    -        if amount_needed_with_fees > selected_amount {
    -            return Err(bdk::Error::InsufficientFunds {
    -                needed: amount_needed_with_fees,
    -                available: selected_amount,
    -            });
    -        }
    -
    -        Ok(CoinSelectionResult {
    -            selected: all_utxos_selected,
    -            fee_amount: fee_amount + additional_fees,
    -        })
    -    }
    -}
    -
    -// create wallet, sync, ...
    -
    -let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -let (psbt, details) = {
    -    let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
    -    builder.add_recipient(to_address.script_pubkey(), 50_000);
    -    builder.finish()?
    -};
    -
    -// inspect, sign, broadcast, ...
    -
    -

    Structs

    -

    Branch and bound coin selection

    -

    Result of a successful coin selection

    -

    Simple and dumb coin selection

    -

    Traits

    -

    Trait for generalized coin selection algorithms

    -

    Type Definitions

    -

    Default coin selection algorithm used by TxBuilder if not -overridden

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/sidebar-items.js deleted file mode 100644 index 8e7e293b89..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["BranchAndBoundCoinSelection","Branch and bound coin selection"],["CoinSelectionResult","Result of a successful coin selection"],["LargestFirstCoinSelection","Simple and dumb coin selection"]],"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/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html deleted file mode 100644 index da3d47f8fc..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.BranchAndBoundCoinSelection.html +++ /dev/null @@ -1,25 +0,0 @@ -BranchAndBoundCoinSelection in bdk::wallet::coin_selection - Rust

    Struct bdk::wallet::coin_selection::BranchAndBoundCoinSelection[][src]

    pub struct BranchAndBoundCoinSelection { /* fields omitted */ }
    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

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.CoinSelectionResult.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.CoinSelectionResult.html deleted file mode 100644 index 2fc68a28c6..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.CoinSelectionResult.html +++ /dev/null @@ -1,28 +0,0 @@ -CoinSelectionResult in bdk::wallet::coin_selection - Rust

    Struct bdk::wallet::coin_selection::CoinSelectionResult[][src]

    pub struct CoinSelectionResult {
    -    pub selected: Vec<Utxo>,
    -    pub fee_amount: u64,
    -}
    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 in satoshi

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html deleted file mode 100644 index 2967b66122..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/struct.LargestFirstCoinSelection.html +++ /dev/null @@ -1,31 +0,0 @@ -LargestFirstCoinSelection in bdk::wallet::coin_selection - Rust

    Struct bdk::wallet::coin_selection::LargestFirstCoinSelection[][src]

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html deleted file mode 100644 index 1aadde9c06..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.html +++ /dev/null @@ -1,22 +0,0 @@ -CoinSelectionAlgorithm in bdk::wallet::coin_selection - Rust

    Trait bdk::wallet::coin_selection::CoinSelectionAlgorithm[][src]

    pub trait CoinSelectionAlgorithm<D: Database>: Debug {
    -    fn coin_select(
            &self,
            database: &D,
            required_utxos: Vec<WeightedUtxo>,
            optional_utxos: Vec<WeightedUtxo>,
            fee_rate: FeeRate,
            amount_needed: u64,
            fee_amount: u64
        ) -> 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 amount_needed with their -weight cost
    • -
    • optional_utxos: the remaining available utxos to satisfy amount_needed with their -weight cost
    • -
    • fee_rate: fee rate to use
    • -
    • amount_needed: the amount in satoshi to select
    • -
    • fee_amount: the amount of fees in satoshi already accumulated from adding outputs and -the transaction’s header
    • -
    -

    Implementors

    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html deleted file mode 100644 index 2a7cee4c38..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/coin_selection/type.DefaultCoinSelectionAlgorithm.html +++ /dev/null @@ -1,5 +0,0 @@ -DefaultCoinSelectionAlgorithm in bdk::wallet::coin_selection - Rust

    Type Definition bdk::wallet::coin_selection::DefaultCoinSelectionAlgorithm[][src]

    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/static/docs-rs/bdk/nightly/latest/bdk/wallet/enum.AddressIndex.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/enum.AddressIndex.html deleted file mode 100644 index d20d05b94a..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/enum.AddressIndex.html +++ /dev/null @@ -1,45 +0,0 @@ -AddressIndex in bdk::wallet - Rust

    Enum bdk::wallet::AddressIndex[][src]

    pub enum AddressIndex {
    -    New,
    -    LastUnused,
    -    Peek(u32),
    -    Reset(u32),
    -}
    Expand description

    The address index selection strategy to use to derived an address from the wallet’s external -descriptor. See Wallet::get_address. If you’re unsure which one to use use WalletIndex::New.

    -

    Variants

    New

    Return a new address after incrementing the current descriptor index.

    -
    LastUnused

    Return the address for the current descriptor index if it has not been used in a received -transaction. Otherwise return a new address as with AddressIndex::New.

    -

    Use with caution, if the wallet has not yet detected an address has been used it could -return an already used address. This function is primarily meant for situations where the -caller is untrusted; for example when deriving donation addresses on-demand for a public -web page.

    -
    Peek(u32)

    Return the address for a specific descriptor index. Does not change the current descriptor -index used by AddressIndex::New and AddressIndex::LastUsed.

    -

    Use with caution, if an index is given that is less than the current descriptor index -then the returned address may have already been used.

    -

    Tuple Fields of Peek

    0: u32
    Reset(u32)

    Return the address for a specific descriptor index and reset the current descriptor index -used by AddressIndex::New and AddressIndex::LastUsed to this value.

    -

    Use with caution, if an index is given that is less than the current descriptor index -then the returned address and subsequent addresses returned by calls to AddressIndex::New -and AddressIndex::LastUsed may have already been used. Also if the index is reset to a -value earlier than the crate::blockchain::Blockchain stop_gap (default is 20) then a -larger stop_gap should be used to monitor for all possibly used addresses.

    -

    Tuple Fields of Reset

    0: u32

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/export/index.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/export/index.html deleted file mode 100644 index f5d42285ff..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/export/index.html +++ /dev/null @@ -1,33 +0,0 @@ -bdk::wallet::export - Rust

    Module bdk::wallet::export[][src]

    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 = WalletExport::from_str(import)?;
    -let wallet = Wallet::new_offline(
    -    &import.descriptor(),
    -    import.change_descriptor().as_ref(),
    -    Network::Testnet,
    -    MemoryDatabase::default(),
    -)?;
    -

    Export a Wallet

    -
    let wallet = Wallet::new_offline(
    -    "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
    -    Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
    -    Network::Testnet,
    -    MemoryDatabase::default()
    -)?;
    -let export = WalletExport::export_wallet(&wallet, "exported wallet", true)
    -    .map_err(ToString::to_string)
    -    .map_err(bdk::Error::Generic)?;
    -
    -println!("Exported: {}", export.to_string());
    -

    Structs

    -

    Structure that contains the export of a wallet

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/export/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/wallet/export/sidebar-items.js deleted file mode 100644 index 06abb3c4ee..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/export/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"struct":[["WalletExport","Structure that contains the export of a wallet"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/export/struct.WalletExport.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/export/struct.WalletExport.html deleted file mode 100644 index 6ff227a440..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/export/struct.WalletExport.html +++ /dev/null @@ -1,43 +0,0 @@ -WalletExport in bdk::wallet::export - Rust

    Struct bdk::wallet::export::WalletExport[][src]

    pub struct WalletExport {
    -    pub blockheight: u32,
    -    pub label: String,
    -    // some fields omitted
    -}
    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

    -

    The associated error which can be returned from parsing.

    -

    Parses a string s to return a value of this type. Read more

    -

    Serialize this value into the given Serde serializer. Read more

    -

    Converts the given value to a String. Read more

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/fn.get_funded_wallet.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/fn.get_funded_wallet.html deleted file mode 100644 index e93825a76c..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/fn.get_funded_wallet.html +++ /dev/null @@ -1,4 +0,0 @@ -get_funded_wallet in bdk::wallet - Rust

    Function bdk::wallet::get_funded_wallet[][src]

    pub fn get_funded_wallet(
        descriptor: &str
    ) -> (Wallet<(), MemoryDatabase>, (String, Option<String>), Txid)
    Expand description

    Return a fake wallet that appears to be funded for testing.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/index.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/index.html deleted file mode 100644 index 0d5803ce8c..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/index.html +++ /dev/null @@ -1,23 +0,0 @@ -bdk::wallet - Rust

    Module bdk::wallet[][src]

    Expand description

    Wallet

    -

    This module defines the Wallet structure.

    -

    Modules

    -

    Address validation callbacks

    -

    Coin selection

    -

    Wallet export

    -

    Generalized signers

    -

    Cross-platform time

    -

    Transaction builder

    -

    Structs

    -

    A derived address and the index it was found at -For convenience this automatically derefs to Address

    -

    A Bitcoin wallet

    -

    Enums

    -

    The address index selection strategy to use to derived an address from the wallet’s external -descriptor. See Wallet::get_address. If you’re unsure which one to use use WalletIndex::New.

    -

    Traits

    -

    Trait to check if a value is below the dust limit

    -

    Functions

    -

    Return a fake wallet that appears to be funded for testing.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/wallet/sidebar-items.js deleted file mode 100644 index 20bdf7e32f..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["AddressIndex","The address index selection strategy to use to derived an address from the wallet’s external descriptor. See [`Wallet::get_address`]. If you’re unsure which one to use use `WalletIndex::New`."]],"fn":[["get_funded_wallet","Return a fake wallet that appears to be funded for testing."]],"mod":[["address_validator","Address validation callbacks"],["coin_selection","Coin selection"],["export","Wallet export"],["signer","Generalized signers"],["time","Cross-platform time"],["tx_builder","Transaction builder"]],"struct":[["AddressInfo","A derived address and the index it was found at For convenience this automatically derefs to `Address`"],["Wallet","A Bitcoin wallet"]],"trait":[["IsDust","Trait to check if a value is below the dust limit"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerError.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerError.html deleted file mode 100644 index 3d4cceccd5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerError.html +++ /dev/null @@ -1,70 +0,0 @@ -SignerError in bdk::wallet::signer - Rust

    Enum bdk::wallet::signer::SignerError[][src]

    pub enum SignerError {
    -    MissingKey,
    -    InvalidKey,
    -    UserCanceled,
    -    InputIndexOutOfRange,
    -    MissingNonWitnessUtxo,
    -    InvalidNonWitnessUtxo,
    -    MissingWitnessUtxo,
    -    MissingWitnessScript,
    -    MissingHdKeypath,
    -    NonStandardSighash,
    -}
    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 requied 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.

    -

    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

    -
    🔬 This is a nightly-only experimental API. (backtrace)

    Returns a stack backtrace, if available, of where this error occurred. 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

    -

    Performs the conversion.

    -

    This method tests for self and other values to be equal, and is used -by ==. Read more

    -

    This method tests for !=.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Converts a reference to Self into a dynamic trait object of Fail.

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Returns the “name” of the error. Read more

    -

    Returns a reference to the underlying cause of this failure, if it -is an error that wraps other errors. Read more

    -

    Returns a reference to the Backtrace carried by this failure, if it -carries one. Read more

    -

    Provides context for this failure. Read more

    -

    Wraps this failure in a compatibility wrapper that implements -std::error::Error. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerId.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerId.html deleted file mode 100644 index 291dc0fd42..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/enum.SignerId.html +++ /dev/null @@ -1,53 +0,0 @@ -SignerId in bdk::wallet::signer - Rust

    Enum bdk::wallet::signer::SignerId[][src]

    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

    -

    Tuple Fields of PkHash

    0: Hash
    Fingerprint(Fingerprint)

    The fingerprint of a BIP32 extended key

    -

    Tuple Fields of Fingerprint

    0: Fingerprint
    Dummy(u64)

    Dummy identifier

    -

    Tuple Fields of Dummy

    0: u64

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    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 !=.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/index.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/index.html deleted file mode 100644 index 7554ca0ff6..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/index.html +++ /dev/null @@ -1,60 +0,0 @@ -bdk::wallet::signer - Rust

    Module bdk::wallet::signer[][src]

    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 Signer for CustomSigner {
    -    fn sign(
    -        &self,
    -        psbt: &mut psbt::PartiallySignedTransaction,
    -        input_index: Option<usize>,
    -        _secp: &Secp256k1<All>,
    -    ) -> Result<(), SignerError> {
    -        let input_index = input_index.ok_or(SignerError::InputIndexOutOfRange)?;
    -        self.device.sign_input(psbt, input_index)?;
    -
    -        Ok(())
    -    }
    -
    -    fn id(&self, _secp: &Secp256k1<All>) -> SignerId {
    -        self.device.get_id()
    -    }
    -
    -    fn sign_whole_tx(&self) -> bool {
    -        false
    -    }
    -}
    -
    -let custom_signer = CustomSigner::connect();
    -
    -let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -let mut wallet = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -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

    -

    Container for multiple signers

    -

    Enums

    -

    Signing error

    -

    Identifier of a signer in the SignersContainers. Used as a key to find the right signer among -multiple of them

    -

    Traits

    -

    Trait for signers

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/sidebar-items.js deleted file mode 100644 index 5700429cf3..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["SignerError","Signing error"],["SignerId","Identifier of a signer in the `SignersContainers`. Used as a key to find the right signer among multiple of them"]],"struct":[["SignOptions","Options for a software signer"],["SignerOrdering","Defines the order in which signers are called"],["SignersContainer","Container for multiple signers"]],"trait":[["Signer","Trait for signers"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignOptions.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignOptions.html deleted file mode 100644 index e981dcc3d4..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignOptions.html +++ /dev/null @@ -1,50 +0,0 @@ -SignOptions in bdk::wallet::signer - Rust

    Struct bdk::wallet::signer::SignOptions[][src]

    pub struct SignOptions {
    -    pub trust_witness_utxo: bool,
    -    pub assume_height: Option<u32>,
    -    pub allow_all_sighashes: 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 chould 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.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignerOrdering.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignerOrdering.html deleted file mode 100644 index 05b7104659..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignerOrdering.html +++ /dev/null @@ -1,45 +0,0 @@ -SignerOrdering in bdk::wallet::signer - Rust

    Struct bdk::wallet::signer::SignerOrdering[][src]

    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 !=.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignersContainer.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignersContainer.html deleted file mode 100644 index 3f8eae4d00..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/struct.SignersContainer.html +++ /dev/null @@ -1,37 +0,0 @@ -SignersContainer in bdk::wallet::signer - Rust

    Struct bdk::wallet::signer::SignersContainer[][src]

    pub struct SignersContainer(_);
    Expand description

    Container for multiple signers

    -

    Implementations

    Create a map of public keys to secret keys

    -

    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

    -

    Performs the conversion.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.Signer.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.Signer.html deleted file mode 100644 index 0ebe55a44a..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/signer/trait.Signer.html +++ /dev/null @@ -1,25 +0,0 @@ -Signer in bdk::wallet::signer - Rust

    Trait bdk::wallet::signer::Signer[][src]

    pub trait Signer: Debug + Send + Sync {
    -    fn sign(
            &self,
            psbt: &mut PartiallySignedTransaction,
            input_index: Option<usize>,
            secp: &Secp256k1<All>
        ) -> Result<(), SignerError>; -
    fn sign_whole_tx(&self) -> bool; -
    fn id(&self, secp: &Secp256k1<All>) -> SignerId; - - fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> { ... } -}
    Expand description

    Trait for signers

    -

    This trait can be implemented to provide customized signers to the wallet. For an example see -this module’s documentation.

    -

    Required methods

    Sign a PSBT

    -

    The input_index argument is only provided if the wallet doesn’t declare to sign the whole -transaction in one go (see Signer::sign_whole_tx). Otherwise its value is None and -can be ignored.

    -

    Return whether or not the signer signs the whole transaction in one go instead of every -input individually

    -

    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).

    -

    Implementations on Foreign Types

    Implementors

    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/struct.AddressInfo.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/struct.AddressInfo.html deleted file mode 100644 index bdc923b2c3..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/struct.AddressInfo.html +++ /dev/null @@ -1,46 +0,0 @@ -AddressInfo in bdk::wallet - Rust

    Struct bdk::wallet::AddressInfo[][src]

    pub struct AddressInfo {
    -    pub index: u32,
    -    pub address: Address,
    -}
    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

    -

    Methods from Deref<Target = Address>

    Get the address type of the address. -None if unknown or non-standard.

    -

    Check whether or not the address is following Bitcoin -standardness rules.

    -

    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, both the schema and the address become uppercase. -If the address is base58, the schema is lowercase and 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.”

    -

    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 !=.

    -

    Auto Trait Implementations

    Blanket Implementations

    Gets the TypeId of self. Read more

    -

    Immutably borrows from an owned value. Read more

    -

    Mutably borrows from an owned value. Read more

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Wallet.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Wallet.html deleted file mode 100644 index 927f2e3cab..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/struct.Wallet.html +++ /dev/null @@ -1,114 +0,0 @@ -Wallet in bdk::wallet - Rust

    Struct bdk::wallet::Wallet[][src]

    pub struct Wallet<B, D> { /* fields omitted */ }
    Expand description

    A Bitcoin wallet

    -

    A wallet takes descriptors, a database and a -blockchain and implements the basic functions that a Bitcoin wallets -needs to operate, like generating addresses, returning the balance, -creating transactions, etc.

    -

    A wallet can be either “online” if the blockchain type provided -implements Blockchain, or “offline” if it is the unit type (). Offline wallets only expose -methods that don’t need any interaction with the blockchain to work.

    -

    Implementations

    Create a new “offline” wallet

    -

    Get the Bitcoin network the wallet is using.

    -

    Return a derived address using the external descriptor, see AddressIndex for -available address index selection strategies. If none of the keys in the descriptor are derivable -(ie. does not end with /*) then the same address will always be returned for any AddressIndex.

    -

    Return whether or not a script is part of this wallet (either internal or external)

    -

    Return the list of unspent outputs of this wallet

    -

    Note that this methods only operate on the internal database, which first needs to be -Wallet::sync manually.

    -

    Returns the UTXO owned by this wallet corresponding to outpoint if it exists in the -wallet’s database.

    -

    Return the list of transactions made and received by the wallet

    -

    Optionally fill the TransactionDetails::transaction field with the raw transaction if -include_raw is true.

    -

    Note that this methods only operate on the internal database, which first needs to be -Wallet::sync manually.

    -

    Return the balance, meaning the sum of this wallet’s unspent outputs’ values

    -

    Note that this methods only operate on the internal database, which first needs to be -Wallet::sync manually.

    -

    Add an external signer

    -

    See the signer module for an example.

    -

    Add an address validator

    -

    See the address_validator module for an example.

    -

    Start building a transaction.

    -

    This returns a blank TxBuilder from which you can specify the parameters for the transaction.

    -

    Example

    -
    let (psbt, details) = {
    -   let mut builder =  wallet.build_tx();
    -   builder
    -       .add_recipient(to_address.script_pubkey(), 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 -repalce 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(), 50_000)
    -        .enable_rbf();
    -    builder.finish()?
    -};
    -let _ = wallet.sign(&mut psbt, SignOptions::default())?;
    -let tx = psbt.extract_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.0));
    -    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

    -

    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(), 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

    -

    Try to finalize a PSBT

    -

    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 adddresses for a particular keychain.

    -

    get the corresponding PSBT Input for a LocalUtxo

    -

    Create a new “online” wallet

    -

    Sync the internal database with the blockchain

    -

    Return a reference to the internal blockchain client

    -

    Broadcast a transaction to the network

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -

    The type returned in the event of a conversion error.

    -

    Performs the conversion.

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/time/fn.get_timestamp.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/time/fn.get_timestamp.html deleted file mode 100644 index b08cbaaa2a..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/time/fn.get_timestamp.html +++ /dev/null @@ -1,4 +0,0 @@ -get_timestamp in bdk::wallet::time - Rust

    Function bdk::wallet::time::get_timestamp[][src]

    pub fn get_timestamp() -> u64
    Expand description

    Return the current timestamp in seconds

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/time/index.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/time/index.html deleted file mode 100644 index 8b626f260e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/time/index.html +++ /dev/null @@ -1,10 +0,0 @@ -bdk::wallet::time - Rust

    Module bdk::wallet::time[][src]

    Expand description

    Cross-platform time

    -

    This module provides a function to get the current timestamp that works on all the platforms -supported by the library.

    -

    It can be useful to compare it with the timestamps found in -TransactionDetails.

    -

    Functions

    -

    Return the current timestamp in seconds

    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/time/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/wallet/time/sidebar-items.js deleted file mode 100644 index 22164ef49f..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/time/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"fn":[["get_timestamp","Return the current timestamp in seconds"]]}); \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/bdk/wallet/trait.IsDust.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/trait.IsDust.html deleted file mode 100644 index 368609d8ab..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/trait.IsDust.html +++ /dev/null @@ -1,7 +0,0 @@ -IsDust in bdk::wallet - Rust

    Trait bdk::wallet::IsDust[][src]

    pub trait IsDust {
    -    fn is_dust(&self) -> bool;
    -}
    Expand description

    Trait to check if a value is below the dust limit

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html deleted file mode 100644 index ee7b4f8ee2..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.ChangeSpendPolicy.html +++ /dev/null @@ -1,51 +0,0 @@ -ChangeSpendPolicy in bdk::wallet::tx_builder - Rust

    Enum bdk::wallet::tx_builder::ChangeSpendPolicy[][src]

    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 !=.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.TxOrdering.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.TxOrdering.html deleted file mode 100644 index dbc248f800..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/enum.TxOrdering.html +++ /dev/null @@ -1,52 +0,0 @@ -TxOrdering in bdk::wallet::tx_builder - Rust

    Enum bdk::wallet::tx_builder::TxOrdering[][src]

    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 !=.

    -

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/index.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/index.html deleted file mode 100644 index abe616a8c4..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/index.html +++ /dev/null @@ -1,28 +0,0 @@ -bdk::wallet::tx_builder - Rust

    Module bdk::wallet::tx_builder[][src]

    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(), 50_000)
    -    // With a custom fee rate of 5.0 satoshi/vbyte
    -    .fee_rate(FeeRate::from_sat_per_vb(5.0))
    -    // Only spend non-change outputs
    -    .do_not_spend_change()
    -    // Turn on RBF signaling
    -    .enable_rbf();
    -let (psbt, tx_details) = 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/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/sidebar-items.js b/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/sidebar-items.js deleted file mode 100644 index dcd52e5dff..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/sidebar-items.js +++ /dev/null @@ -1 +0,0 @@ -initSidebarItems({"enum":[["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/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.BumpFee.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.BumpFee.html deleted file mode 100644 index 82a9195942..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.BumpFee.html +++ /dev/null @@ -1,28 +0,0 @@ -BumpFee in bdk::wallet::tx_builder - Rust

    Struct bdk::wallet::tx_builder::BumpFee[][src]

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.CreateTx.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.CreateTx.html deleted file mode 100644 index bc3c167a86..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.CreateTx.html +++ /dev/null @@ -1,29 +0,0 @@ -CreateTx in bdk::wallet::tx_builder - Rust

    Struct bdk::wallet::tx_builder::CreateTx[][src]

    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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.TxBuilder.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.TxBuilder.html deleted file mode 100644 index 2cad412b0e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/struct.TxBuilder.html +++ /dev/null @@ -1,226 +0,0 @@ -TxBuilder in bdk::wallet::tx_builder - Rust

    Struct bdk::wallet::tx_builder::TxBuilder[][src]

    pub struct TxBuilder<'a, B, D, Cs, Ctx> { /* fields omitted */ }
    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, details) = {
    -    let mut builder = wallet.build_tx();
    -    builder
    -        .ordering(TxOrdering::Untouched)
    -        .add_recipient(addr1.script_pubkey(), 50_000)
    -        .add_recipient(addr2.script_pubkey(), 50_000);
    -    builder.finish()?
    -};
    -
    -// non-chaining
    -let (psbt2, details) = {
    -    let mut builder = wallet.build_tx();
    -    builder.ordering(TxOrdering::Untouched);
    -    for addr in &[addr1, addr2] {
    -        builder.add_recipient(addr.script_pubkey(), 50_000);
    -    }
    -    builder.finish()?
    -};
    -
    -assert_eq!(
    -    psbt1.global.unsigned_tx.output[..2],
    -    psbt2.global.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

    -

    Set an absolute fee

    -

    Set the policy path to use while creating the transaction for a given keychain.

    -

    This method accepts a map where the key is the policy node id (see -Policy::id) and the value is the list of the indexes of -the items that are intended to be satisfied from the policy node (see -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.

    - -
    let mut path = BTreeMap::new();
    -path.insert("aabbccdd".to_string(), vec![0, 1]);
    -
    -let builder = wallet
    -    .build_tx()
    -    .add_recipient(to_address.script_pubkey(), 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 foregin 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 satisfaction_weight 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_satisfaction_weight.

    -

    This is an EXPERIMENTAL feature, API and other major changes are expected.

    -

    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 psbt_input you pass to this method must -have non_witness_utxo set otherwise you will get an error when finish is called.

    -

    Only spend utxos added by add_utxo.

    -

    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.

    -

    Finish the building the transaction.

    -

    Returns the BIP174 “PSBT” and summary details about the transaction.

    -

    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.

    -

    Replace the recipients already added with a new list

    -

    Add a recipient to the internal list

    -

    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).

    -

    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.

    - -
    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.0))
    -    .enable_rbf();
    -let (psbt, tx_details) = tx_builder.finish()?;
    -

    Explicitly tells the wallet that it is allowed to reduce the fee 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

    -

    Performs the conversion.

    -

    Performs the conversion.

    -

    The alignment of pointer.

    -

    The type for initializers.

    -

    Initializes a with the given initializer. Read more

    -

    Dereferences the given pointer. Read more

    -

    Mutably dereferences the given pointer. Read more

    -

    Drops the object pointed to by the given pointer. Read more

    -

    Should always be Self

    -

    The resulting type after obtaining ownership.

    -

    Creates owned data from borrowed data, usually by cloning. Read more

    -
    🔬 This is a nightly-only experimental API. (toowned_clone_into)

    recently added

    -

    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/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/trait.TxBuilderContext.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/trait.TxBuilderContext.html deleted file mode 100644 index 15e506e385..0000000000 --- a/static/docs-rs/bdk/nightly/latest/bdk/wallet/tx_builder/trait.TxBuilderContext.html +++ /dev/null @@ -1,4 +0,0 @@ -TxBuilderContext in bdk::wallet::tx_builder - Rust

    Trait bdk::wallet::tx_builder::TxBuilderContext[][src]

    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/static/docs-rs/bdk/nightly/latest/bdk/wallet/utils/trait.IsDust.html b/static/docs-rs/bdk/nightly/latest/bdk/wallet/utils/trait.IsDust.html deleted file mode 100644 index c0e56858e7..0000000000 --- a/static/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/static/docs-rs/bdk/nightly/latest/brush.svg b/static/docs-rs/bdk/nightly/latest/brush.svg deleted file mode 100644 index ea266e856a..0000000000 --- a/static/docs-rs/bdk/nightly/latest/brush.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/clipboard.svg b/static/docs-rs/bdk/nightly/latest/clipboard.svg deleted file mode 100644 index 8adbd99630..0000000000 --- a/static/docs-rs/bdk/nightly/latest/clipboard.svg +++ /dev/null @@ -1 +0,0 @@ - diff --git a/static/docs-rs/bdk/nightly/latest/crates.js b/static/docs-rs/bdk/nightly/latest/crates.js deleted file mode 100644 index 0abc2ef87a..0000000000 --- a/static/docs-rs/bdk/nightly/latest/crates.js +++ /dev/null @@ -1 +0,0 @@ -window.ALL_CRATES = ["bdk"]; \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/dark.css b/static/docs-rs/bdk/nightly/latest/dark.css deleted file mode 100644 index 56782e49a2..0000000000 --- a/static/docs-rs/bdk/nightly/latest/dark.css +++ /dev/null @@ -1 +0,0 @@ -body{background-color:#353535;color:#ddd;}h1,h2,h3,h4{color:#ddd;}h1.fqn{border-bottom-color:#d2d2d2;}h2,h3,h4{border-bottom-color:#d2d2d2;}.in-band{background-color:#353535;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#2A2A2A;}pre,.rustdoc.source .example-wrap{background-color:#2A2A2A;}.sidebar{background-color:#505050;}.logo-container.rust-logo>img{filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff)}*{scrollbar-color:rgb(64,65,67) #717171;}.sidebar{scrollbar-color:rgba(32,34,37,.6) transparent;}::-webkit-scrollbar-track{background-color:#717171;}::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar::-webkit-scrollbar-track{background-color:#717171;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar .current{background-color:#333;}.source .sidebar{background-color:#353535;}.sidebar .location{border-color:#fff;background:#575757;color:#DDD;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#444;}.line-numbers span{color:#3B91E2;}.line-numbers .line-highlighted{background-color:#0a042f !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#DDD;}.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#ddd;}.search-results a:hover{background-color:#777;}.search-results a:focus{color:#eee !important;background-color:#616161;}.search-results a:focus span{color:#eee !important;}a.result-trait:focus{background-color:#013191;}a.result-traitalias:focus{background-color:#013191;}a.result-mod:focus,a.result-externcrate:focus{background-color:#afc6e4;}a.result-mod:focus{background-color:#803a1b;}a.result-externcrate:focus{background-color:#396bac;}a.result-enum:focus{background-color:#5b4e68;}a.result-struct:focus{background-color:#194e9f;}a.result-union:focus{background-color:#b7bd49;}a.result-fn:focus,a.result-method:focus,a.result-tymethod:focus{background-color:#4950ed;}a.result-type:focus{background-color:#38902c;}a.result-foreigntype:focus{background-color:#b200d6;}a.result-attr:focus,a.result-derive:focus,a.result-macro:focus{background-color:#217d1c;}a.result-constant:focus,a.result-static:focus{background-color:#0063cc;}a.result-primitive:focus{background-color:#00708a;}a.result-keyword:focus{background-color:#884719;}.content .item-info::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#82b089;}.content span.struct,.content a.struct,.block a.current.struct{color:#2dbfb8;}.content span.type,.content a.type,.block a.current.type{color:#ff7f00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#dd7de8;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#09bd00;}.content span.union,.content a.union,.block a.current.union{color:#a6ae37;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#82a5c9;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#43aec7;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#bda000;}.content span.trait,.content a.trait,.block a.current.trait{color:#b78cf2;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#b397da;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#2BAB63;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}pre.rust .comment{color:#8d8d8b;}pre.rust .doccomment{color:#8ca375;}nav:not(.sidebar){border-bottom-color:#4e4e4e;}nav.main .current{border-top-color:#eee;border-bottom-color:#eee;}nav.main .separator{border-color:#eee;}a{color:#ddd;}body.source .example-wrap pre.rust a{background:#333;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.item-info a,#help a{color:#D2991D;}a.test-arrow{color:#dedede;}details.rustdoc-toggle>summary.hideme>span,details.rustdoc-toggle>summary::before,details.undocumented>summary::before{color:#999;}details.rustdoc-toggle>summary::before,details.undocumented>summary::before{filter:invert(100%);}#crate-search{color:#111;background-color:#f0f0f0;border-color:#000;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input{color:#111;background-color:#f0f0f0;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input:focus{border-color:#008dfd;}.search-input:disabled{background-color:#c5c4c4;}#crate-search+.search-input:focus{box-shadow:0 0 8px 4px #078dd8;}.module-item .stab,.import-item .stab{color:#ddd;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;color:#2f2f2f;}.stab.deprecated{background:#ffc4c4;border-color:#db7b7b;color:#2f2f2f;}.stab.portability{background:#F3DFFF;border-color:#b07bdb;color:#2f2f2f;}.stab.portability>code{background:none;}#help>div{background:#4d4d4d;border-color:#bfbfbf;}#help span.bottom,#help span.top{border-color:#bfbfbf;}#help dt{border-color:#bfbfbf;background:rgba(0,0,0,0);}.since{color:grey;}.result-name .primitive>i,.result-name .keyword>i{color:#ddd;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#ab8ac1;}pre.rust .kw-2,pre.rust .prelude-ty{color:#769acb;}pre.rust .number,pre.rust .string{color:#83a300;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#ee6868;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#d97f26;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#4a4949;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label,.code-attribute{color:#999;}:target,:target>*{background-color:#494a3d;}:target{border-right:3px solid #bb7410;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.8);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.8);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.8);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.8);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip::after{background-color:#000;color:#fff;border-color:#000;}.tooltip::before{border-color:transparent black transparent transparent;}.notable-traits-tooltiptext{background-color:#111;border-color:#777;}.notable-traits-tooltiptext .notable{border-bottom-color:#d2d2d2;}#titles>button:not(.selected){background-color:#252525;border-top-color:#252525;}#titles>button:hover,#titles>button.selected{border-top-color:#0089ff;background-color:#353535;}#titles>button>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#505050;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#505050;border-right-color:#000;}#sidebar-filler{background-color:#505050;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu,#help-button{border-color:#e0e0e0;background:#f0f0f0;color:#000;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus,#help-button:hover,#help-button:focus{border-color:#ffb900;}#copy-path{color:#999;}#copy-path>img{filter:invert(50%);}#copy-path:hover>img{filter:invert(65%);}#theme-choices{border-color:#e0e0e0;background-color:#353535;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#4e4e4e;}@media (max-width:700px){#theme-picker{background:#f0f0f0;}}#all-types{background-color:#505050;}#all-types:hover{background-color:#606060;}.search-results .result-name span.alias{color:#fff;}.search-results .result-name span.grey{color:#ccc;}#sidebar-toggle{background-color:#565656;}#sidebar-toggle:hover{background-color:#676767;}#source-sidebar{background-color:#565656;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#444;}div.files>.selected{background-color:#333;}.setting-line>.title{border-bottom-color:#ddd;} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/down-arrow.svg b/static/docs-rs/bdk/nightly/latest/down-arrow.svg deleted file mode 100644 index 35437e77a7..0000000000 --- a/static/docs-rs/bdk/nightly/latest/down-arrow.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/favicon-16x16.png b/static/docs-rs/bdk/nightly/latest/favicon-16x16.png deleted file mode 100644 index 7cfe6c1355..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/favicon-16x16.png and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/favicon-32x32.png b/static/docs-rs/bdk/nightly/latest/favicon-32x32.png deleted file mode 100644 index 5109c1de8b..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/favicon-32x32.png and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/favicon.svg b/static/docs-rs/bdk/nightly/latest/favicon.svg deleted file mode 100644 index 8b34b51198..0000000000 --- a/static/docs-rs/bdk/nightly/latest/favicon.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - diff --git a/static/docs-rs/bdk/nightly/latest/implementors/alloc/string/trait.ToString.js b/static/docs-rs/bdk/nightly/latest/implementors/alloc/string/trait.ToString.js deleted file mode 100644 index f3e935dbe1..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/alloc/string/trait.ToString.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl ToString for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Blockchain.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Blockchain.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Blockchain.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.ConfigurableBlockchain.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.ConfigurableBlockchain.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.ConfigurableBlockchain.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Progress.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Progress.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/blockchain/trait.Progress.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchDatabase.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchDatabase.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchDatabase.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchOperations.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchOperations.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.BatchOperations.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.ConfigurableDatabase.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.ConfigurableDatabase.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.ConfigurableDatabase.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.Database.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.Database.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/database/trait.Database.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/template/trait.DescriptorTemplate.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/template/trait.DescriptorTemplate.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/template/trait.DescriptorTemplate.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/trait.ExtractPolicy.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/trait.ExtractPolicy.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/trait.ExtractPolicy.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/trait.IntoWalletDescriptor.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/trait.IntoWalletDescriptor.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/descriptor/trait.IntoWalletDescriptor.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.DerivableKey.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.DerivableKey.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.DerivableKey.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.ExtScriptContext.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.ExtScriptContext.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.ExtScriptContext.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.GeneratableDefaultOptions.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.GeneratableDefaultOptions.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.GeneratableDefaultOptions.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.GeneratableKey.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.GeneratableKey.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.GeneratableKey.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.IntoDescriptorKey.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.IntoDescriptorKey.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.IntoDescriptorKey.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.ScriptContext.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.ScriptContext.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/keys/trait.ScriptContext.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/trait.Vbytes.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/trait.Vbytes.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/trait.Vbytes.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/coin_selection/trait.CoinSelectionAlgorithm.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.Signer.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.Signer.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/signer/trait.Signer.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/trait.IsDust.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/trait.IsDust.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/trait.IsDust.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/tx_builder/trait.TxBuilderContext.js b/static/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/tx_builder/trait.TxBuilderContext.js deleted file mode 100644 index 8262d3bea5..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/bdk/wallet/tx_builder/trait.TxBuilderContext.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = []; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/clone/trait.Clone.js b/static/docs-rs/bdk/nightly/latest/implementors/core/clone/trait.Clone.js deleted file mode 100644 index fc88bc958d..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/clone/trait.Clone.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Clone for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl Clone for ElectrumBlockchainConfig","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl Clone for EsploraBlockchainConfig","synthetic":false,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl Clone for BitcoinPeerConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl Clone for CompactFiltersBlockchainConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl Clone for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Clone for NoopProgress","synthetic":false,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Clone for LogProgress","synthetic":false,"types":["bdk::blockchain::LogProgress"]},{"text":"impl<'s> Clone for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Clone for PkOrF","synthetic":false,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl Clone for SatisfiableItem","synthetic":false,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Clone for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Clone for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Clone for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl<'a> Clone for BuildSatisfaction<'a>","synthetic":false,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl Clone for ScriptContextEnum","synthetic":false,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl Clone for PrivateKeyGenerateOptions","synthetic":false,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl Clone for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl Clone for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Clone for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl Clone for WeightedUtxo","synthetic":false,"types":["bdk::types::WeightedUtxo"]},{"text":"impl Clone for Utxo","synthetic":false,"types":["bdk::types::Utxo"]},{"text":"impl Clone for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Clone for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Clone for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Clone for LargestFirstCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl Clone for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Clone for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Clone for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Clone for SignersContainer","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Clone for SignOptions","synthetic":false,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl Clone for CreateTx","synthetic":false,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl Clone for BumpFee","synthetic":false,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl<'a, Cs: Clone, Ctx, B, D> Clone for TxBuilder<'a, B, D, Cs, Ctx>","synthetic":false,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Clone for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Clone for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Eq.js b/static/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Eq.js deleted file mode 100644 index f7925a3bf8..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Eq.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Eq for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl<'s> Eq for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Eq for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Eq for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl Eq for ScriptContextEnum","synthetic":false,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl Eq for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl Eq for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl Eq for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Eq for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Eq for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Eq for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Eq for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Eq for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Eq for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Eq for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Ord.js b/static/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Ord.js deleted file mode 100644 index d19ffc9f15..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.Ord.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl<'s> Ord for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Ord for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Ord for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Ord for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Ord for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Ord for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialEq.js b/static/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialEq.js deleted file mode 100644 index d505fe207f..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialEq.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl PartialEq<AnyBlockchainConfig> for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl PartialEq<ElectrumBlockchainConfig> for ElectrumBlockchainConfig","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl PartialEq<EsploraBlockchainConfig> for EsploraBlockchainConfig","synthetic":false,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl PartialEq<BitcoinPeerConfig> for BitcoinPeerConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl PartialEq<CompactFiltersBlockchainConfig> for CompactFiltersBlockchainConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl PartialEq<Capability> for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl<'s> PartialEq<DerivedDescriptorKey<'s>> for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl PartialEq<Condition> for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl PartialEq<PolicyError> for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl PartialEq<ScriptContextEnum> for ScriptContextEnum","synthetic":false,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl PartialEq<KeychainKind> for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl PartialEq<FeeRate> for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl PartialEq<LocalUtxo> for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl PartialEq<WeightedUtxo> for WeightedUtxo","synthetic":false,"types":["bdk::types::WeightedUtxo"]},{"text":"impl PartialEq<Utxo> for Utxo","synthetic":false,"types":["bdk::types::Utxo"]},{"text":"impl PartialEq<TransactionDetails> for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl PartialEq<ConfirmationTime> for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl PartialEq<AddressValidatorError> for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl PartialEq<SignerId> for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl PartialEq<SignerError> for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl PartialEq<SignerOrdering> for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl PartialEq<TxOrdering> for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl PartialEq<ChangeSpendPolicy> for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl PartialEq<AddressInfo> for AddressInfo","synthetic":false,"types":["bdk::wallet::AddressInfo"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialOrd.js b/static/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialOrd.js deleted file mode 100644 index 1e33ba386e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/cmp/trait.PartialOrd.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl<'s> PartialOrd<DerivedDescriptorKey<'s>> for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl PartialOrd<Condition> for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl PartialOrd<FeeRate> for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl PartialOrd<SignerId> for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl PartialOrd<SignerOrdering> for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl PartialOrd<TxOrdering> for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl PartialOrd<ChangeSpendPolicy> for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.AsRef.js b/static/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.AsRef.js deleted file mode 100644 index cc88354e83..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.AsRef.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl AsRef<[u8]> for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.From.js b/static/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.From.js deleted file mode 100644 index ee9e5bfa5c..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/convert/trait.From.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<AddressValidatorError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<PolicyError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<SignerError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<KeyError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<PsbtParseError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<CompactFiltersError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<EsploraError> for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl From<ElectrumBlockchain> for AnyBlockchain","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl From<EsploraBlockchain> for AnyBlockchain","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl From<CompactFiltersBlockchain> for AnyBlockchain","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl From<ElectrumBlockchainConfig> for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl From<EsploraBlockchainConfig> for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl From<CompactFiltersBlockchainConfig> for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl From<Client> for ElectrumBlockchain","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<Transport> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<ParseIntError> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<Error> for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<SystemTimeError> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<Error> for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl From<MemoryDatabase> for AnyDatabase","synthetic":false,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl From<Tree> for AnyDatabase","synthetic":false,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl From<SqliteDatabase> for AnyDatabase","synthetic":false,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl From<<MemoryDatabase as BatchDatabase>::Batch> for AnyBatch","synthetic":false,"types":["bdk::database::any::AnyBatch"]},{"text":"impl From<<Tree as BatchDatabase>::Batch> for AnyBatch","synthetic":false,"types":["bdk::database::any::AnyBatch"]},{"text":"impl From<<SqliteDatabase as BatchDatabase>::Batch> for AnyBatch","synthetic":false,"types":["bdk::database::any::AnyBatch"]},{"text":"impl From<()> for AnyDatabaseConfig","synthetic":false,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl From<SledDbConfiguration> for AnyDatabaseConfig","synthetic":false,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl From<SqliteDbConfiguration> for AnyDatabaseConfig","synthetic":false,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl From<KeyError> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<Error> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<PolicyError> for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl From<bool> for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl From<SatisfiableItem> for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl<Ctx: ScriptContext> From<ExtendedPubKey> for ExtendedKey<Ctx>","synthetic":false,"types":["bdk::keys::ExtendedKey"]},{"text":"impl<Ctx: ScriptContext> From<ExtendedPrivKey> for ExtendedKey<Ctx>","synthetic":false,"types":["bdk::keys::ExtendedKey"]},{"text":"impl From<Error> for KeyError","synthetic":false,"types":["bdk::keys::KeyError"]},{"text":"impl From<Error> for KeyError","synthetic":false,"types":["bdk::keys::KeyError"]},{"text":"impl From<Hash> for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl From<Fingerprint> for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl From<HashMap<DescriptorPublicKey, DescriptorSecretKey, RandomState>> for SignersContainer","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/default/trait.Default.js b/static/docs-rs/bdk/nightly/latest/implementors/core/default/trait.Default.js deleted file mode 100644 index f8973ba8b2..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/default/trait.Default.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Default for Mempool","synthetic":false,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Default for MemoryDatabase","synthetic":false,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl Default for PkOrF","synthetic":false,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl Default for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Default for PrivateKeyGenerateOptions","synthetic":false,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl Default for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Default for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Default for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Default for LargestFirstCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl Default for BranchAndBoundCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]},{"text":"impl Default for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Default for SignersContainer","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Default for SignOptions","synthetic":false,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl Default for CreateTx","synthetic":false,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl Default for BumpFee","synthetic":false,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl Default for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Default for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Debug.js b/static/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Debug.js deleted file mode 100644 index f8b8e915aa..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Debug.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Debug for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl Debug for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl Debug for ElectrumBlockchainConfig","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl Debug for EsploraBlockchain","synthetic":false,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchain"]},{"text":"impl Debug for EsploraBlockchainConfig","synthetic":false,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl Debug for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Debug for Mempool","synthetic":false,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Debug for Peer","synthetic":false,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Debug for CompactFiltersBlockchain","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Debug for BitcoinPeerConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl Debug for CompactFiltersBlockchainConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl Debug for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Debug for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Debug for AnyDatabase","synthetic":false,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl Debug for SledDbConfiguration","synthetic":false,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl Debug for SqliteDbConfiguration","synthetic":false,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl Debug for AnyDatabaseConfig","synthetic":false,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl Debug for SqliteDatabase","synthetic":false,"types":["bdk::database::sqlite::SqliteDatabase"]},{"text":"impl Debug for MemoryDatabase","synthetic":false,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl<'s> Debug for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Debug for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl Debug for PkOrF","synthetic":false,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl Debug for SatisfiableItem","synthetic":false,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Debug for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Debug for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Debug for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Debug for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<'a> Debug for BuildSatisfaction<'a>","synthetic":false,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl<Ctx: Debug + ScriptContext> Debug for DescriptorKey<Ctx>","synthetic":false,"types":["bdk::keys::DescriptorKey"]},{"text":"impl Debug for ScriptContextEnum","synthetic":false,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl Debug for PrivateKeyGenerateOptions","synthetic":false,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl Debug for KeyError","synthetic":false,"types":["bdk::keys::KeyError"]},{"text":"impl Debug for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl Debug for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Debug for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl Debug for WeightedUtxo","synthetic":false,"types":["bdk::types::WeightedUtxo"]},{"text":"impl Debug for Utxo","synthetic":false,"types":["bdk::types::Utxo"]},{"text":"impl Debug for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Debug for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Debug for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Debug for CoinSelectionResult","synthetic":false,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Debug for LargestFirstCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl Debug for BranchAndBoundCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]},{"text":"impl Debug for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Debug for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Debug for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Debug for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Debug for SignersContainer","synthetic":false,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Debug for SignOptions","synthetic":false,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl Debug for CreateTx","synthetic":false,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl Debug for BumpFee","synthetic":false,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl<'a, B: Debug, D: Debug, Cs: Debug, Ctx: Debug> Debug for TxBuilder<'a, B, D, Cs, Ctx>","synthetic":false,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Debug for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Debug for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl<B: Debug, D: Debug> Debug for Wallet<B, D>","synthetic":false,"types":["bdk::wallet::Wallet"]},{"text":"impl Debug for AddressIndex","synthetic":false,"types":["bdk::wallet::AddressIndex"]},{"text":"impl Debug for AddressInfo","synthetic":false,"types":["bdk::wallet::AddressInfo"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Display.js b/static/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Display.js deleted file mode 100644 index 01fb89d0ac..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/fmt/trait.Display.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Display for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl Display for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Display for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl<'s> Display for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Display for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl Display for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl Display for KeyError","synthetic":false,"types":["bdk::keys::KeyError"]},{"text":"impl Display for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Display for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Display for AddressInfo","synthetic":false,"types":["bdk::wallet::AddressInfo"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/hash/trait.Hash.js b/static/docs-rs/bdk/nightly/latest/implementors/core/hash/trait.Hash.js deleted file mode 100644 index c02f002754..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/hash/trait.Hash.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Hash for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl<'s> Hash for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Hash for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Hash for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl Hash for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl Hash for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Hash for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Hash for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Copy.js b/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Copy.js deleted file mode 100644 index b95912a278..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Copy.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Copy for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl Copy for NoopProgress","synthetic":false,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Copy for LogProgress","synthetic":false,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Copy for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl<'a> Copy for BuildSatisfaction<'a>","synthetic":false,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl Copy for ScriptContextEnum","synthetic":false,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl Copy for PrivateKeyGenerateOptions","synthetic":false,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl Copy for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl Copy for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl Copy for LargestFirstCoinSelection","synthetic":false,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl Copy for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Copy for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Freeze.js b/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Freeze.js deleted file mode 100644 index 469a139430..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Freeze.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Freeze for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl !Freeze for AnyBlockchain","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl Freeze for AnyBlockchainConfig","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl !Freeze for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Freeze for ElectrumBlockchainConfig","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl Freeze for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchain"]},{"text":"impl Freeze for EsploraBlockchainConfig","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl Freeze for EsploraGetHistory","synthetic":true,"types":["bdk::blockchain::esplora::EsploraGetHistory"]},{"text":"impl Freeze for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl !Freeze for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Freeze for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Freeze for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Freeze for BitcoinPeerConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl Freeze for CompactFiltersBlockchainConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl Freeze for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Freeze for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Freeze for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Freeze for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl !Freeze for AnyDatabase","synthetic":true,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl !Freeze for AnyBatch","synthetic":true,"types":["bdk::database::any::AnyBatch"]},{"text":"impl Freeze for SledDbConfiguration","synthetic":true,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl Freeze for SqliteDbConfiguration","synthetic":true,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl Freeze for AnyDatabaseConfig","synthetic":true,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl !Freeze for SqliteDatabase","synthetic":true,"types":["bdk::database::sqlite::SqliteDatabase"]},{"text":"impl Freeze for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl<'s> Freeze for DerivedDescriptorKey<'s>","synthetic":true,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Freeze for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Freeze for PkOrF","synthetic":true,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl Freeze for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Freeze for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Freeze for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Freeze for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Freeze for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<'a> Freeze for BuildSatisfaction<'a>","synthetic":true,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl<K> Freeze for P2Pkh<K> where
        K: Freeze, 
    ","synthetic":true,"types":["bdk::descriptor::template::P2Pkh"]},{"text":"impl<K> Freeze for P2Wpkh_P2Sh<K> where
        K: Freeze, 
    ","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh_P2Sh"]},{"text":"impl<K> Freeze for P2Wpkh<K> where
        K: Freeze, 
    ","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh"]},{"text":"impl<K> Freeze for Bip44<K> where
        K: Freeze, 
    ","synthetic":true,"types":["bdk::descriptor::template::Bip44"]},{"text":"impl<K> Freeze for Bip44Public<K> where
        K: Freeze, 
    ","synthetic":true,"types":["bdk::descriptor::template::Bip44Public"]},{"text":"impl<K> Freeze for Bip49<K> where
        K: Freeze, 
    ","synthetic":true,"types":["bdk::descriptor::template::Bip49"]},{"text":"impl<K> Freeze for Bip49Public<K> where
        K: Freeze, 
    ","synthetic":true,"types":["bdk::descriptor::template::Bip49Public"]},{"text":"impl<K> Freeze for Bip84<K> where
        K: Freeze, 
    ","synthetic":true,"types":["bdk::descriptor::template::Bip84"]},{"text":"impl<K> Freeze for Bip84Public<K> where
        K: Freeze, 
    ","synthetic":true,"types":["bdk::descriptor::template::Bip84Public"]},{"text":"impl<Ctx> Freeze for DescriptorKey<Ctx>","synthetic":true,"types":["bdk::keys::DescriptorKey"]},{"text":"impl Freeze for ScriptContextEnum","synthetic":true,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl<Ctx> Freeze for ExtendedKey<Ctx>","synthetic":true,"types":["bdk::keys::ExtendedKey"]},{"text":"impl<K, Ctx> Freeze for GeneratedKey<K, Ctx> where
        K: Freeze, 
    ","synthetic":true,"types":["bdk::keys::GeneratedKey"]},{"text":"impl Freeze for PrivateKeyGenerateOptions","synthetic":true,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl Freeze for KeyError","synthetic":true,"types":["bdk::keys::KeyError"]},{"text":"impl Freeze for KeychainKind","synthetic":true,"types":["bdk::types::KeychainKind"]},{"text":"impl Freeze for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Freeze for LocalUtxo","synthetic":true,"types":["bdk::types::LocalUtxo"]},{"text":"impl Freeze for WeightedUtxo","synthetic":true,"types":["bdk::types::WeightedUtxo"]},{"text":"impl Freeze for Utxo","synthetic":true,"types":["bdk::types::Utxo"]},{"text":"impl Freeze for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Freeze for ConfirmationTime","synthetic":true,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Freeze for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Freeze for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Freeze for LargestFirstCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl Freeze for BranchAndBoundCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]},{"text":"impl Freeze for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Freeze for SignerId","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Freeze for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Freeze for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Freeze for SignersContainer","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Freeze for SignOptions","synthetic":true,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl Freeze for CreateTx","synthetic":true,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl Freeze for BumpFee","synthetic":true,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl<'a, B, D, Cs, Ctx> Freeze for TxBuilder<'a, B, D, Cs, Ctx> where
        Cs: Freeze, 
    ","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Freeze for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Freeze for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl<B, D> !Freeze for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Freeze for AddressIndex","synthetic":true,"types":["bdk::wallet::AddressIndex"]},{"text":"impl Freeze for AddressInfo","synthetic":true,"types":["bdk::wallet::AddressInfo"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Send.js b/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Send.js deleted file mode 100644 index 8af424700c..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Send.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Send for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Send for AnyBlockchain","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl Send for AnyBlockchainConfig","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl Send for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Send for ElectrumBlockchainConfig","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl Send for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchain"]},{"text":"impl Send for EsploraBlockchainConfig","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl Send for EsploraGetHistory","synthetic":true,"types":["bdk::blockchain::esplora::EsploraGetHistory"]},{"text":"impl Send for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Send for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Send for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Send for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Send for BitcoinPeerConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl Send for CompactFiltersBlockchainConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl Send for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Send for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Send for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Send for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl !Send for AnyDatabase","synthetic":true,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl !Send for AnyBatch","synthetic":true,"types":["bdk::database::any::AnyBatch"]},{"text":"impl Send for SledDbConfiguration","synthetic":true,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl Send for SqliteDbConfiguration","synthetic":true,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl Send for AnyDatabaseConfig","synthetic":true,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl Send for SqliteDatabase","synthetic":true,"types":["bdk::database::sqlite::SqliteDatabase"]},{"text":"impl !Send for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl<'s> Send for DerivedDescriptorKey<'s>","synthetic":true,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Send for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Send for PkOrF","synthetic":true,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl Send for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Send for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Send for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Send for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Send for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<'a> Send for BuildSatisfaction<'a>","synthetic":true,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl<K> Send for P2Pkh<K> where
        K: Send
    ","synthetic":true,"types":["bdk::descriptor::template::P2Pkh"]},{"text":"impl<K> Send for P2Wpkh_P2Sh<K> where
        K: Send
    ","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh_P2Sh"]},{"text":"impl<K> Send for P2Wpkh<K> where
        K: Send
    ","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh"]},{"text":"impl<K> Send for Bip44<K> where
        K: Send
    ","synthetic":true,"types":["bdk::descriptor::template::Bip44"]},{"text":"impl<K> Send for Bip44Public<K> where
        K: Send
    ","synthetic":true,"types":["bdk::descriptor::template::Bip44Public"]},{"text":"impl<K> Send for Bip49<K> where
        K: Send
    ","synthetic":true,"types":["bdk::descriptor::template::Bip49"]},{"text":"impl<K> Send for Bip49Public<K> where
        K: Send
    ","synthetic":true,"types":["bdk::descriptor::template::Bip49Public"]},{"text":"impl<K> Send for Bip84<K> where
        K: Send
    ","synthetic":true,"types":["bdk::descriptor::template::Bip84"]},{"text":"impl<K> Send for Bip84Public<K> where
        K: Send
    ","synthetic":true,"types":["bdk::descriptor::template::Bip84Public"]},{"text":"impl<Ctx> Send for DescriptorKey<Ctx> where
        Ctx: Send
    ","synthetic":true,"types":["bdk::keys::DescriptorKey"]},{"text":"impl Send for ScriptContextEnum","synthetic":true,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl<Ctx> Send for ExtendedKey<Ctx> where
        Ctx: Send
    ","synthetic":true,"types":["bdk::keys::ExtendedKey"]},{"text":"impl<K, Ctx> Send for GeneratedKey<K, Ctx> where
        Ctx: Send,
        K: Send
    ","synthetic":true,"types":["bdk::keys::GeneratedKey"]},{"text":"impl Send for PrivateKeyGenerateOptions","synthetic":true,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl Send for KeyError","synthetic":true,"types":["bdk::keys::KeyError"]},{"text":"impl Send for KeychainKind","synthetic":true,"types":["bdk::types::KeychainKind"]},{"text":"impl Send for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Send for LocalUtxo","synthetic":true,"types":["bdk::types::LocalUtxo"]},{"text":"impl Send for WeightedUtxo","synthetic":true,"types":["bdk::types::WeightedUtxo"]},{"text":"impl Send for Utxo","synthetic":true,"types":["bdk::types::Utxo"]},{"text":"impl Send for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Send for ConfirmationTime","synthetic":true,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Send for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Send for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Send for LargestFirstCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl Send for BranchAndBoundCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]},{"text":"impl Send for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Send for SignerId","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Send for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Send for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Send for SignersContainer","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Send for SignOptions","synthetic":true,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl Send for CreateTx","synthetic":true,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl Send for BumpFee","synthetic":true,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl<'a, B, D, Cs, Ctx> !Send for TxBuilder<'a, B, D, Cs, Ctx>","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Send for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Send for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl<B, D> Send for Wallet<B, D> where
        B: Send,
        D: Send
    ","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Send for AddressIndex","synthetic":true,"types":["bdk::wallet::AddressIndex"]},{"text":"impl Send for AddressInfo","synthetic":true,"types":["bdk::wallet::AddressInfo"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralEq.js b/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralEq.js deleted file mode 100644 index f0a5dbaf05..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralEq.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl StructuralEq for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl StructuralEq for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl StructuralEq for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl StructuralEq for ScriptContextEnum","synthetic":false,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl StructuralEq for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl StructuralEq for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl StructuralEq for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl StructuralEq for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl StructuralEq for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl StructuralEq for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl StructuralEq for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl StructuralEq for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl StructuralEq for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl StructuralEq for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralPartialEq.js b/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralPartialEq.js deleted file mode 100644 index faa39c8c1e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.StructuralPartialEq.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl StructuralPartialEq for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl StructuralPartialEq for ElectrumBlockchainConfig","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl StructuralPartialEq for EsploraBlockchainConfig","synthetic":false,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl StructuralPartialEq for BitcoinPeerConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl StructuralPartialEq for CompactFiltersBlockchainConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl StructuralPartialEq for Capability","synthetic":false,"types":["bdk::blockchain::Capability"]},{"text":"impl StructuralPartialEq for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl StructuralPartialEq for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl StructuralPartialEq for ScriptContextEnum","synthetic":false,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl StructuralPartialEq for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl StructuralPartialEq for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]},{"text":"impl StructuralPartialEq for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl StructuralPartialEq for WeightedUtxo","synthetic":false,"types":["bdk::types::WeightedUtxo"]},{"text":"impl StructuralPartialEq for Utxo","synthetic":false,"types":["bdk::types::Utxo"]},{"text":"impl StructuralPartialEq for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl StructuralPartialEq for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl StructuralPartialEq for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl StructuralPartialEq for SignerId","synthetic":false,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl StructuralPartialEq for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl StructuralPartialEq for SignerOrdering","synthetic":false,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl StructuralPartialEq for TxOrdering","synthetic":false,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl StructuralPartialEq for ChangeSpendPolicy","synthetic":false,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl StructuralPartialEq for AddressInfo","synthetic":false,"types":["bdk::wallet::AddressInfo"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Sync.js b/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Sync.js deleted file mode 100644 index 2d66194d8d..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Sync.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Sync for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Sync for AnyBlockchain","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl Sync for AnyBlockchainConfig","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl Sync for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Sync for ElectrumBlockchainConfig","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl Sync for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchain"]},{"text":"impl Sync for EsploraBlockchainConfig","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl Sync for EsploraGetHistory","synthetic":true,"types":["bdk::blockchain::esplora::EsploraGetHistory"]},{"text":"impl Sync for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Sync for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Sync for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Sync for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Sync for BitcoinPeerConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl Sync for CompactFiltersBlockchainConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl Sync for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Sync for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Sync for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Sync for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl !Sync for AnyDatabase","synthetic":true,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl !Sync for AnyBatch","synthetic":true,"types":["bdk::database::any::AnyBatch"]},{"text":"impl Sync for SledDbConfiguration","synthetic":true,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl Sync for SqliteDbConfiguration","synthetic":true,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl Sync for AnyDatabaseConfig","synthetic":true,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl !Sync for SqliteDatabase","synthetic":true,"types":["bdk::database::sqlite::SqliteDatabase"]},{"text":"impl !Sync for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl<'s> Sync for DerivedDescriptorKey<'s>","synthetic":true,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Sync for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Sync for PkOrF","synthetic":true,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl Sync for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Sync for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Sync for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Sync for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Sync for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<'a> Sync for BuildSatisfaction<'a>","synthetic":true,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl<K> Sync for P2Pkh<K> where
        K: Sync
    ","synthetic":true,"types":["bdk::descriptor::template::P2Pkh"]},{"text":"impl<K> Sync for P2Wpkh_P2Sh<K> where
        K: Sync
    ","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh_P2Sh"]},{"text":"impl<K> Sync for P2Wpkh<K> where
        K: Sync
    ","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh"]},{"text":"impl<K> Sync for Bip44<K> where
        K: Sync
    ","synthetic":true,"types":["bdk::descriptor::template::Bip44"]},{"text":"impl<K> Sync for Bip44Public<K> where
        K: Sync
    ","synthetic":true,"types":["bdk::descriptor::template::Bip44Public"]},{"text":"impl<K> Sync for Bip49<K> where
        K: Sync
    ","synthetic":true,"types":["bdk::descriptor::template::Bip49"]},{"text":"impl<K> Sync for Bip49Public<K> where
        K: Sync
    ","synthetic":true,"types":["bdk::descriptor::template::Bip49Public"]},{"text":"impl<K> Sync for Bip84<K> where
        K: Sync
    ","synthetic":true,"types":["bdk::descriptor::template::Bip84"]},{"text":"impl<K> Sync for Bip84Public<K> where
        K: Sync
    ","synthetic":true,"types":["bdk::descriptor::template::Bip84Public"]},{"text":"impl<Ctx> Sync for DescriptorKey<Ctx> where
        Ctx: Sync
    ","synthetic":true,"types":["bdk::keys::DescriptorKey"]},{"text":"impl Sync for ScriptContextEnum","synthetic":true,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl<Ctx> Sync for ExtendedKey<Ctx> where
        Ctx: Sync
    ","synthetic":true,"types":["bdk::keys::ExtendedKey"]},{"text":"impl<K, Ctx> Sync for GeneratedKey<K, Ctx> where
        Ctx: Sync,
        K: Sync
    ","synthetic":true,"types":["bdk::keys::GeneratedKey"]},{"text":"impl Sync for PrivateKeyGenerateOptions","synthetic":true,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl Sync for KeyError","synthetic":true,"types":["bdk::keys::KeyError"]},{"text":"impl Sync for KeychainKind","synthetic":true,"types":["bdk::types::KeychainKind"]},{"text":"impl Sync for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Sync for LocalUtxo","synthetic":true,"types":["bdk::types::LocalUtxo"]},{"text":"impl Sync for WeightedUtxo","synthetic":true,"types":["bdk::types::WeightedUtxo"]},{"text":"impl Sync for Utxo","synthetic":true,"types":["bdk::types::Utxo"]},{"text":"impl Sync for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Sync for ConfirmationTime","synthetic":true,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Sync for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Sync for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Sync for LargestFirstCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl Sync for BranchAndBoundCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]},{"text":"impl Sync for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Sync for SignerId","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Sync for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Sync for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Sync for SignersContainer","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Sync for SignOptions","synthetic":true,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl Sync for CreateTx","synthetic":true,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl Sync for BumpFee","synthetic":true,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl<'a, B, D, Cs, Ctx> !Sync for TxBuilder<'a, B, D, Cs, Ctx>","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Sync for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Sync for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl<B, D> !Sync for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Sync for AddressIndex","synthetic":true,"types":["bdk::wallet::AddressIndex"]},{"text":"impl Sync for AddressInfo","synthetic":true,"types":["bdk::wallet::AddressInfo"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Unpin.js b/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Unpin.js deleted file mode 100644 index 834a73d904..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/marker/trait.Unpin.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Unpin for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl Unpin for AnyBlockchain","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl Unpin for AnyBlockchainConfig","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl Unpin for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl Unpin for ElectrumBlockchainConfig","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl Unpin for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchain"]},{"text":"impl Unpin for EsploraBlockchainConfig","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl Unpin for EsploraGetHistory","synthetic":true,"types":["bdk::blockchain::esplora::EsploraGetHistory"]},{"text":"impl Unpin for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Unpin for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl Unpin for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl Unpin for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl Unpin for BitcoinPeerConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl Unpin for CompactFiltersBlockchainConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl Unpin for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Unpin for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl Unpin for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl Unpin for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl Unpin for AnyDatabase","synthetic":true,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl Unpin for AnyBatch","synthetic":true,"types":["bdk::database::any::AnyBatch"]},{"text":"impl Unpin for SledDbConfiguration","synthetic":true,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl Unpin for SqliteDbConfiguration","synthetic":true,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl Unpin for AnyDatabaseConfig","synthetic":true,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl Unpin for SqliteDatabase","synthetic":true,"types":["bdk::database::sqlite::SqliteDatabase"]},{"text":"impl Unpin for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl<'s> Unpin for DerivedDescriptorKey<'s>","synthetic":true,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl Unpin for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl Unpin for PkOrF","synthetic":true,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl Unpin for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Unpin for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Unpin for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Unpin for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Unpin for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<'a> Unpin for BuildSatisfaction<'a>","synthetic":true,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl<K> Unpin for P2Pkh<K> where
        K: Unpin
    ","synthetic":true,"types":["bdk::descriptor::template::P2Pkh"]},{"text":"impl<K> Unpin for P2Wpkh_P2Sh<K> where
        K: Unpin
    ","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh_P2Sh"]},{"text":"impl<K> Unpin for P2Wpkh<K> where
        K: Unpin
    ","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh"]},{"text":"impl<K> Unpin for Bip44<K> where
        K: Unpin
    ","synthetic":true,"types":["bdk::descriptor::template::Bip44"]},{"text":"impl<K> Unpin for Bip44Public<K> where
        K: Unpin
    ","synthetic":true,"types":["bdk::descriptor::template::Bip44Public"]},{"text":"impl<K> Unpin for Bip49<K> where
        K: Unpin
    ","synthetic":true,"types":["bdk::descriptor::template::Bip49"]},{"text":"impl<K> Unpin for Bip49Public<K> where
        K: Unpin
    ","synthetic":true,"types":["bdk::descriptor::template::Bip49Public"]},{"text":"impl<K> Unpin for Bip84<K> where
        K: Unpin
    ","synthetic":true,"types":["bdk::descriptor::template::Bip84"]},{"text":"impl<K> Unpin for Bip84Public<K> where
        K: Unpin
    ","synthetic":true,"types":["bdk::descriptor::template::Bip84Public"]},{"text":"impl<Ctx> Unpin for DescriptorKey<Ctx> where
        Ctx: Unpin
    ","synthetic":true,"types":["bdk::keys::DescriptorKey"]},{"text":"impl Unpin for ScriptContextEnum","synthetic":true,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl<Ctx> Unpin for ExtendedKey<Ctx> where
        Ctx: Unpin
    ","synthetic":true,"types":["bdk::keys::ExtendedKey"]},{"text":"impl<K, Ctx> Unpin for GeneratedKey<K, Ctx> where
        Ctx: Unpin,
        K: Unpin
    ","synthetic":true,"types":["bdk::keys::GeneratedKey"]},{"text":"impl Unpin for PrivateKeyGenerateOptions","synthetic":true,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl Unpin for KeyError","synthetic":true,"types":["bdk::keys::KeyError"]},{"text":"impl Unpin for KeychainKind","synthetic":true,"types":["bdk::types::KeychainKind"]},{"text":"impl Unpin for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl Unpin for LocalUtxo","synthetic":true,"types":["bdk::types::LocalUtxo"]},{"text":"impl Unpin for WeightedUtxo","synthetic":true,"types":["bdk::types::WeightedUtxo"]},{"text":"impl Unpin for Utxo","synthetic":true,"types":["bdk::types::Utxo"]},{"text":"impl Unpin for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl Unpin for ConfirmationTime","synthetic":true,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Unpin for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Unpin for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl Unpin for LargestFirstCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl Unpin for BranchAndBoundCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]},{"text":"impl Unpin for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl Unpin for SignerId","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl Unpin for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl Unpin for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl Unpin for SignersContainer","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl Unpin for SignOptions","synthetic":true,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl Unpin for CreateTx","synthetic":true,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl Unpin for BumpFee","synthetic":true,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl<'a, B, D, Cs, Ctx> Unpin for TxBuilder<'a, B, D, Cs, Ctx> where
        Cs: Unpin,
        Ctx: Unpin
    ","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl Unpin for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl Unpin for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl<B, D> Unpin for Wallet<B, D> where
        B: Unpin,
        D: Unpin
    ","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl Unpin for AddressIndex","synthetic":true,"types":["bdk::wallet::AddressIndex"]},{"text":"impl Unpin for AddressInfo","synthetic":true,"types":["bdk::wallet::AddressInfo"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/ops/arith/trait.Sub.js b/static/docs-rs/bdk/nightly/latest/implementors/core/ops/arith/trait.Sub.js deleted file mode 100644 index 0527a76602..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/ops/arith/trait.Sub.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Sub<FeeRate> for FeeRate","synthetic":false,"types":["bdk::types::FeeRate"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/ops/deref/trait.Deref.js b/static/docs-rs/bdk/nightly/latest/implementors/core/ops/deref/trait.Deref.js deleted file mode 100644 index 172ef72b01..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/ops/deref/trait.Deref.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl<'s> Deref for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl<K, Ctx: ScriptContext> Deref for GeneratedKey<K, Ctx>","synthetic":false,"types":["bdk::keys::GeneratedKey"]},{"text":"impl Deref for AddressInfo","synthetic":false,"types":["bdk::wallet::AddressInfo"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.RefUnwindSafe.js b/static/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.RefUnwindSafe.js deleted file mode 100644 index 43f5c13951..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.RefUnwindSafe.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl !RefUnwindSafe for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl !RefUnwindSafe for AnyBlockchain","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl RefUnwindSafe for AnyBlockchainConfig","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl RefUnwindSafe for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl RefUnwindSafe for ElectrumBlockchainConfig","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl !RefUnwindSafe for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchain"]},{"text":"impl RefUnwindSafe for EsploraBlockchainConfig","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl RefUnwindSafe for EsploraGetHistory","synthetic":true,"types":["bdk::blockchain::esplora::EsploraGetHistory"]},{"text":"impl !RefUnwindSafe for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl RefUnwindSafe for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl !RefUnwindSafe for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl !RefUnwindSafe for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl RefUnwindSafe for BitcoinPeerConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl RefUnwindSafe for CompactFiltersBlockchainConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl !RefUnwindSafe for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl RefUnwindSafe for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl RefUnwindSafe for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl RefUnwindSafe for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl !RefUnwindSafe for AnyDatabase","synthetic":true,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl !RefUnwindSafe for AnyBatch","synthetic":true,"types":["bdk::database::any::AnyBatch"]},{"text":"impl RefUnwindSafe for SledDbConfiguration","synthetic":true,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl RefUnwindSafe for SqliteDbConfiguration","synthetic":true,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl RefUnwindSafe for AnyDatabaseConfig","synthetic":true,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl !RefUnwindSafe for SqliteDatabase","synthetic":true,"types":["bdk::database::sqlite::SqliteDatabase"]},{"text":"impl !RefUnwindSafe for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl<'s> RefUnwindSafe for DerivedDescriptorKey<'s>","synthetic":true,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl RefUnwindSafe for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl RefUnwindSafe for PkOrF","synthetic":true,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl RefUnwindSafe for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl RefUnwindSafe for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl RefUnwindSafe for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl RefUnwindSafe for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl RefUnwindSafe for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<'a> RefUnwindSafe for BuildSatisfaction<'a>","synthetic":true,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl<K> RefUnwindSafe for P2Pkh<K> where
        K: RefUnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::P2Pkh"]},{"text":"impl<K> RefUnwindSafe for P2Wpkh_P2Sh<K> where
        K: RefUnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh_P2Sh"]},{"text":"impl<K> RefUnwindSafe for P2Wpkh<K> where
        K: RefUnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh"]},{"text":"impl<K> RefUnwindSafe for Bip44<K> where
        K: RefUnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::Bip44"]},{"text":"impl<K> RefUnwindSafe for Bip44Public<K> where
        K: RefUnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::Bip44Public"]},{"text":"impl<K> RefUnwindSafe for Bip49<K> where
        K: RefUnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::Bip49"]},{"text":"impl<K> RefUnwindSafe for Bip49Public<K> where
        K: RefUnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::Bip49Public"]},{"text":"impl<K> RefUnwindSafe for Bip84<K> where
        K: RefUnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::Bip84"]},{"text":"impl<K> RefUnwindSafe for Bip84Public<K> where
        K: RefUnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::Bip84Public"]},{"text":"impl<Ctx> RefUnwindSafe for DescriptorKey<Ctx> where
        Ctx: RefUnwindSafe
    ","synthetic":true,"types":["bdk::keys::DescriptorKey"]},{"text":"impl RefUnwindSafe for ScriptContextEnum","synthetic":true,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl<Ctx> RefUnwindSafe for ExtendedKey<Ctx> where
        Ctx: RefUnwindSafe
    ","synthetic":true,"types":["bdk::keys::ExtendedKey"]},{"text":"impl<K, Ctx> RefUnwindSafe for GeneratedKey<K, Ctx> where
        Ctx: RefUnwindSafe,
        K: RefUnwindSafe
    ","synthetic":true,"types":["bdk::keys::GeneratedKey"]},{"text":"impl RefUnwindSafe for PrivateKeyGenerateOptions","synthetic":true,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl RefUnwindSafe for KeyError","synthetic":true,"types":["bdk::keys::KeyError"]},{"text":"impl RefUnwindSafe for KeychainKind","synthetic":true,"types":["bdk::types::KeychainKind"]},{"text":"impl RefUnwindSafe for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl RefUnwindSafe for LocalUtxo","synthetic":true,"types":["bdk::types::LocalUtxo"]},{"text":"impl RefUnwindSafe for WeightedUtxo","synthetic":true,"types":["bdk::types::WeightedUtxo"]},{"text":"impl RefUnwindSafe for Utxo","synthetic":true,"types":["bdk::types::Utxo"]},{"text":"impl RefUnwindSafe for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl RefUnwindSafe for ConfirmationTime","synthetic":true,"types":["bdk::types::ConfirmationTime"]},{"text":"impl RefUnwindSafe for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl RefUnwindSafe for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl RefUnwindSafe for LargestFirstCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl RefUnwindSafe for BranchAndBoundCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]},{"text":"impl RefUnwindSafe for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl RefUnwindSafe for SignerId","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl RefUnwindSafe for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl RefUnwindSafe for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl !RefUnwindSafe for SignersContainer","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl RefUnwindSafe for SignOptions","synthetic":true,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl RefUnwindSafe for CreateTx","synthetic":true,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl RefUnwindSafe for BumpFee","synthetic":true,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl<'a, B, D, Cs, Ctx> !RefUnwindSafe for TxBuilder<'a, B, D, Cs, Ctx>","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl RefUnwindSafe for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl RefUnwindSafe for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl<B, D> !RefUnwindSafe for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl RefUnwindSafe for AddressIndex","synthetic":true,"types":["bdk::wallet::AddressIndex"]},{"text":"impl RefUnwindSafe for AddressInfo","synthetic":true,"types":["bdk::wallet::AddressInfo"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.UnwindSafe.js b/static/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.UnwindSafe.js deleted file mode 100644 index 8eff90f98d..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/panic/unwind_safe/trait.UnwindSafe.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl !UnwindSafe for Error","synthetic":true,"types":["bdk::error::Error"]},{"text":"impl !UnwindSafe for AnyBlockchain","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchain"]},{"text":"impl UnwindSafe for AnyBlockchainConfig","synthetic":true,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl UnwindSafe for ElectrumBlockchain","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchain"]},{"text":"impl UnwindSafe for ElectrumBlockchainConfig","synthetic":true,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl !UnwindSafe for EsploraBlockchain","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchain"]},{"text":"impl UnwindSafe for EsploraBlockchainConfig","synthetic":true,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl UnwindSafe for EsploraGetHistory","synthetic":true,"types":["bdk::blockchain::esplora::EsploraGetHistory"]},{"text":"impl !UnwindSafe for EsploraError","synthetic":true,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl UnwindSafe for Mempool","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Mempool"]},{"text":"impl !UnwindSafe for Peer","synthetic":true,"types":["bdk::blockchain::compact_filters::peer::Peer"]},{"text":"impl !UnwindSafe for CompactFiltersBlockchain","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchain"]},{"text":"impl UnwindSafe for BitcoinPeerConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl UnwindSafe for CompactFiltersBlockchainConfig","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl !UnwindSafe for CompactFiltersError","synthetic":true,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl UnwindSafe for Capability","synthetic":true,"types":["bdk::blockchain::Capability"]},{"text":"impl UnwindSafe for NoopProgress","synthetic":true,"types":["bdk::blockchain::NoopProgress"]},{"text":"impl UnwindSafe for LogProgress","synthetic":true,"types":["bdk::blockchain::LogProgress"]},{"text":"impl !UnwindSafe for AnyDatabase","synthetic":true,"types":["bdk::database::any::AnyDatabase"]},{"text":"impl !UnwindSafe for AnyBatch","synthetic":true,"types":["bdk::database::any::AnyBatch"]},{"text":"impl UnwindSafe for SledDbConfiguration","synthetic":true,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl UnwindSafe for SqliteDbConfiguration","synthetic":true,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl UnwindSafe for AnyDatabaseConfig","synthetic":true,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl !UnwindSafe for SqliteDatabase","synthetic":true,"types":["bdk::database::sqlite::SqliteDatabase"]},{"text":"impl !UnwindSafe for MemoryDatabase","synthetic":true,"types":["bdk::database::memory::MemoryDatabase"]},{"text":"impl<'s> UnwindSafe for DerivedDescriptorKey<'s>","synthetic":true,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]},{"text":"impl UnwindSafe for Error","synthetic":true,"types":["bdk::descriptor::error::Error"]},{"text":"impl UnwindSafe for PkOrF","synthetic":true,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl UnwindSafe for SatisfiableItem","synthetic":true,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl UnwindSafe for Satisfaction","synthetic":true,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl UnwindSafe for Policy","synthetic":true,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl UnwindSafe for Condition","synthetic":true,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl UnwindSafe for PolicyError","synthetic":true,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl<'a> UnwindSafe for BuildSatisfaction<'a>","synthetic":true,"types":["bdk::descriptor::policy::BuildSatisfaction"]},{"text":"impl<K> UnwindSafe for P2Pkh<K> where
        K: UnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::P2Pkh"]},{"text":"impl<K> UnwindSafe for P2Wpkh_P2Sh<K> where
        K: UnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh_P2Sh"]},{"text":"impl<K> UnwindSafe for P2Wpkh<K> where
        K: UnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::P2Wpkh"]},{"text":"impl<K> UnwindSafe for Bip44<K> where
        K: UnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::Bip44"]},{"text":"impl<K> UnwindSafe for Bip44Public<K> where
        K: UnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::Bip44Public"]},{"text":"impl<K> UnwindSafe for Bip49<K> where
        K: UnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::Bip49"]},{"text":"impl<K> UnwindSafe for Bip49Public<K> where
        K: UnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::Bip49Public"]},{"text":"impl<K> UnwindSafe for Bip84<K> where
        K: UnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::Bip84"]},{"text":"impl<K> UnwindSafe for Bip84Public<K> where
        K: UnwindSafe
    ","synthetic":true,"types":["bdk::descriptor::template::Bip84Public"]},{"text":"impl<Ctx> UnwindSafe for DescriptorKey<Ctx> where
        Ctx: UnwindSafe
    ","synthetic":true,"types":["bdk::keys::DescriptorKey"]},{"text":"impl UnwindSafe for ScriptContextEnum","synthetic":true,"types":["bdk::keys::ScriptContextEnum"]},{"text":"impl<Ctx> UnwindSafe for ExtendedKey<Ctx> where
        Ctx: UnwindSafe
    ","synthetic":true,"types":["bdk::keys::ExtendedKey"]},{"text":"impl<K, Ctx> UnwindSafe for GeneratedKey<K, Ctx> where
        Ctx: UnwindSafe,
        K: UnwindSafe
    ","synthetic":true,"types":["bdk::keys::GeneratedKey"]},{"text":"impl UnwindSafe for PrivateKeyGenerateOptions","synthetic":true,"types":["bdk::keys::PrivateKeyGenerateOptions"]},{"text":"impl UnwindSafe for KeyError","synthetic":true,"types":["bdk::keys::KeyError"]},{"text":"impl UnwindSafe for KeychainKind","synthetic":true,"types":["bdk::types::KeychainKind"]},{"text":"impl UnwindSafe for FeeRate","synthetic":true,"types":["bdk::types::FeeRate"]},{"text":"impl UnwindSafe for LocalUtxo","synthetic":true,"types":["bdk::types::LocalUtxo"]},{"text":"impl UnwindSafe for WeightedUtxo","synthetic":true,"types":["bdk::types::WeightedUtxo"]},{"text":"impl UnwindSafe for Utxo","synthetic":true,"types":["bdk::types::Utxo"]},{"text":"impl UnwindSafe for TransactionDetails","synthetic":true,"types":["bdk::types::TransactionDetails"]},{"text":"impl UnwindSafe for ConfirmationTime","synthetic":true,"types":["bdk::types::ConfirmationTime"]},{"text":"impl UnwindSafe for AddressValidatorError","synthetic":true,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl UnwindSafe for CoinSelectionResult","synthetic":true,"types":["bdk::wallet::coin_selection::CoinSelectionResult"]},{"text":"impl UnwindSafe for LargestFirstCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::LargestFirstCoinSelection"]},{"text":"impl UnwindSafe for BranchAndBoundCoinSelection","synthetic":true,"types":["bdk::wallet::coin_selection::BranchAndBoundCoinSelection"]},{"text":"impl UnwindSafe for WalletExport","synthetic":true,"types":["bdk::wallet::export::WalletExport"]},{"text":"impl UnwindSafe for SignerId","synthetic":true,"types":["bdk::wallet::signer::SignerId"]},{"text":"impl UnwindSafe for SignerError","synthetic":true,"types":["bdk::wallet::signer::SignerError"]},{"text":"impl UnwindSafe for SignerOrdering","synthetic":true,"types":["bdk::wallet::signer::SignerOrdering"]},{"text":"impl !UnwindSafe for SignersContainer","synthetic":true,"types":["bdk::wallet::signer::SignersContainer"]},{"text":"impl UnwindSafe for SignOptions","synthetic":true,"types":["bdk::wallet::signer::SignOptions"]},{"text":"impl UnwindSafe for CreateTx","synthetic":true,"types":["bdk::wallet::tx_builder::CreateTx"]},{"text":"impl UnwindSafe for BumpFee","synthetic":true,"types":["bdk::wallet::tx_builder::BumpFee"]},{"text":"impl<'a, B, D, Cs, Ctx> !UnwindSafe for TxBuilder<'a, B, D, Cs, Ctx>","synthetic":true,"types":["bdk::wallet::tx_builder::TxBuilder"]},{"text":"impl UnwindSafe for TxOrdering","synthetic":true,"types":["bdk::wallet::tx_builder::TxOrdering"]},{"text":"impl UnwindSafe for ChangeSpendPolicy","synthetic":true,"types":["bdk::wallet::tx_builder::ChangeSpendPolicy"]},{"text":"impl<B, D> !UnwindSafe for Wallet<B, D>","synthetic":true,"types":["bdk::wallet::Wallet"]},{"text":"impl UnwindSafe for AddressIndex","synthetic":true,"types":["bdk::wallet::AddressIndex"]},{"text":"impl UnwindSafe for AddressInfo","synthetic":true,"types":["bdk::wallet::AddressInfo"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/core/str/traits/trait.FromStr.js b/static/docs-rs/bdk/nightly/latest/implementors/core/str/traits/trait.FromStr.js deleted file mode 100644 index b76335d1f3..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/core/str/traits/trait.FromStr.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl FromStr for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/miniscript/trait.MiniscriptKey.js b/static/docs-rs/bdk/nightly/latest/implementors/miniscript/trait.MiniscriptKey.js deleted file mode 100644 index 15310a1788..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/miniscript/trait.MiniscriptKey.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl<'s> MiniscriptKey for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/miniscript/trait.ToPublicKey.js b/static/docs-rs/bdk/nightly/latest/implementors/miniscript/trait.ToPublicKey.js deleted file mode 100644 index 6c57ee9682..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/miniscript/trait.ToPublicKey.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl<'s> ToPublicKey for DerivedDescriptorKey<'s>","synthetic":false,"types":["bdk::descriptor::derived::DerivedDescriptorKey"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/serde/de/trait.Deserialize.js b/static/docs-rs/bdk/nightly/latest/implementors/serde/de/trait.Deserialize.js deleted file mode 100644 index 4dddf8a258..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/serde/de/trait.Deserialize.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl<'de> Deserialize<'de> for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl<'de> Deserialize<'de> for ElectrumBlockchainConfig","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl<'de> Deserialize<'de> for EsploraBlockchainConfig","synthetic":false,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl<'de> Deserialize<'de> for EsploraGetHistory","synthetic":false,"types":["bdk::blockchain::esplora::EsploraGetHistory"]},{"text":"impl<'de> Deserialize<'de> for BitcoinPeerConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl<'de> Deserialize<'de> for CompactFiltersBlockchainConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl<'de> Deserialize<'de> for SledDbConfiguration","synthetic":false,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl<'de> Deserialize<'de> for SqliteDbConfiguration","synthetic":false,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl<'de> Deserialize<'de> for AnyDatabaseConfig","synthetic":false,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl<'de> Deserialize<'de> for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl<'de> Deserialize<'de> for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl<'de> Deserialize<'de> for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl<'de> Deserialize<'de> for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl<'de> Deserialize<'de> for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/serde/ser/trait.Serialize.js b/static/docs-rs/bdk/nightly/latest/implementors/serde/ser/trait.Serialize.js deleted file mode 100644 index 11272bbb51..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/serde/ser/trait.Serialize.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Serialize for AnyBlockchainConfig","synthetic":false,"types":["bdk::blockchain::any::AnyBlockchainConfig"]},{"text":"impl Serialize for ElectrumBlockchainConfig","synthetic":false,"types":["bdk::blockchain::electrum::ElectrumBlockchainConfig"]},{"text":"impl Serialize for EsploraBlockchainConfig","synthetic":false,"types":["bdk::blockchain::esplora::ureq::EsploraBlockchainConfig"]},{"text":"impl Serialize for BitcoinPeerConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::BitcoinPeerConfig"]},{"text":"impl Serialize for CompactFiltersBlockchainConfig","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersBlockchainConfig"]},{"text":"impl Serialize for SledDbConfiguration","synthetic":false,"types":["bdk::database::any::SledDbConfiguration"]},{"text":"impl Serialize for SqliteDbConfiguration","synthetic":false,"types":["bdk::database::any::SqliteDbConfiguration"]},{"text":"impl Serialize for AnyDatabaseConfig","synthetic":false,"types":["bdk::database::any::AnyDatabaseConfig"]},{"text":"impl Serialize for PkOrF","synthetic":false,"types":["bdk::descriptor::policy::PkOrF"]},{"text":"impl Serialize for SatisfiableItem","synthetic":false,"types":["bdk::descriptor::policy::SatisfiableItem"]},{"text":"impl Serialize for Satisfaction","synthetic":false,"types":["bdk::descriptor::policy::Satisfaction"]},{"text":"impl Serialize for Policy","synthetic":false,"types":["bdk::descriptor::policy::Policy"]},{"text":"impl Serialize for Condition","synthetic":false,"types":["bdk::descriptor::policy::Condition"]},{"text":"impl Serialize for KeychainKind","synthetic":false,"types":["bdk::types::KeychainKind"]},{"text":"impl Serialize for LocalUtxo","synthetic":false,"types":["bdk::types::LocalUtxo"]},{"text":"impl Serialize for TransactionDetails","synthetic":false,"types":["bdk::types::TransactionDetails"]},{"text":"impl Serialize for ConfirmationTime","synthetic":false,"types":["bdk::types::ConfirmationTime"]},{"text":"impl Serialize for WalletExport","synthetic":false,"types":["bdk::wallet::export::WalletExport"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/implementors/std/error/trait.Error.js b/static/docs-rs/bdk/nightly/latest/implementors/std/error/trait.Error.js deleted file mode 100644 index a772f567ff..0000000000 --- a/static/docs-rs/bdk/nightly/latest/implementors/std/error/trait.Error.js +++ /dev/null @@ -1,3 +0,0 @@ -(function() {var implementors = {}; -implementors["bdk"] = [{"text":"impl Error for Error","synthetic":false,"types":["bdk::error::Error"]},{"text":"impl Error for EsploraError","synthetic":false,"types":["bdk::blockchain::esplora::EsploraError"]},{"text":"impl Error for CompactFiltersError","synthetic":false,"types":["bdk::blockchain::compact_filters::CompactFiltersError"]},{"text":"impl Error for Error","synthetic":false,"types":["bdk::descriptor::error::Error"]},{"text":"impl Error for PolicyError","synthetic":false,"types":["bdk::descriptor::policy::PolicyError"]},{"text":"impl Error for KeyError","synthetic":false,"types":["bdk::keys::KeyError"]},{"text":"impl Error for AddressValidatorError","synthetic":false,"types":["bdk::wallet::address_validator::AddressValidatorError"]},{"text":"impl Error for SignerError","synthetic":false,"types":["bdk::wallet::signer::SignerError"]}]; -if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/light.css b/static/docs-rs/bdk/nightly/latest/light.css deleted file mode 100644 index 14c65509e8..0000000000 --- a/static/docs-rs/bdk/nightly/latest/light.css +++ /dev/null @@ -1 +0,0 @@ - body{background-color:white;color:black;}h1,h2,h3,h4{color:black;}h1.fqn{border-bottom-color:#D5D5D5;}h2,h3,h4{border-bottom-color:#DDDDDD;}.in-band{background-color:white;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#F5F5F5;}pre,.rustdoc.source .example-wrap{background-color:#F5F5F5;}.sidebar{background-color:#F1F1F1;}*{scrollbar-color:rgba(36,37,39,0.6) #e6e6e6;}.sidebar{scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;}.logo-container.rust-logo>img{}::-webkit-scrollbar-track{background-color:#ecebeb;}::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar::-webkit-scrollbar-track{background-color:#dcdcdc;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar .current{background-color:#fff;}.source .sidebar{background-color:#fff;}.sidebar .location{border-color:#000;background-color:#fff;color:#333;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#F5F5F5;}.line-numbers span{color:#c67e2d;}.line-numbers .line-highlighted{background-color:#f6fdb0 !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#ddd;}.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#4E4C4C;}.search-results a:hover{background-color:#ddd;}.search-results a:focus{color:#000 !important;background-color:#ccc;}.search-results a:focus span{color:#000 !important;}a.result-trait:focus{background-color:#c7b6ff;}a.result-traitalias:focus{background-color:#c7b6ff;}a.result-mod:focus,a.result-externcrate:focus{background-color:#afc6e4;}a.result-enum:focus{background-color:#b4d1b9;}a.result-struct:focus{background-color:#e7b1a0;}a.result-union:focus{background-color:#b7bd49;}a.result-fn:focus,a.result-method:focus,a.result-tymethod:focus{background-color:#c6afb3;}a.result-type:focus{background-color:#ffc891;}a.result-foreigntype:focus{background-color:#f5c4ff;}a.result-attr:focus,a.result-derive:focus,a.result-macro:focus{background-color:#8ce488;}a.result-constant:focus,a.result-static:focus{background-color:#c3e0ff;}a.result-primitive:focus{background-color:#9aecff;}a.result-keyword:focus{background-color:#f99650;}.content .item-info::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#508157;}.content span.struct,.content a.struct,.block a.current.struct{color:#ad448e;}.content span.type,.content a.type,.block a.current.type{color:#ba5d00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#cd00e2;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#068000;}.content span.union,.content a.union,.block a.current.union{color:#767b27;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#546e8a;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#2c8093;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#4d76ae;}.content span.trait,.content a.trait,.block a.current.trait{color:#7c5af3;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#6841f1;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#9a6e31;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}nav:not(.sidebar){border-bottom-color:#e0e0e0;}nav.main .current{border-top-color:#000;border-bottom-color:#000;}nav.main .separator{border:1px solid #000;}a{color:#000;}body.source .example-wrap pre.rust a{background:#eee;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.item-info a,#help a{color:#3873AD;}a.test-arrow{color:#f5f5f5;}details.rustdoc-toggle>summary.hideme>span,details.rustdoc-toggle>summary::before,details.undocumented>summary::before{color:#999;}#crate-search{color:#555;background-color:white;border-color:#e0e0e0;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input{color:#555;background-color:white;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input:focus{border-color:#66afe9;}.search-input:disabled{background-color:#e6e6e6;}#crate-search+.search-input:focus{box-shadow:0 0 8px #078dd8;}.module-item .stab,.import-item .stab{color:#000;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;}.stab.deprecated{background:#ffc4c4;border-color:#db7b7b;}.stab.portability{background:#F3DFFF;border-color:#b07bdb;}.stab.portability>code{background:none;}#help>div{background:#e9e9e9;border-color:#bfbfbf;}#help span.bottom,#help span.top{border-color:#bfbfbf;}.since{color:grey;}.result-name .primitive>i,.result-name .keyword>i{color:black;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#8959A8;}pre.rust .kw-2,pre.rust .prelude-ty{color:#4271AE;}pre.rust .number,pre.rust .string{color:#718C00;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#C82829;}pre.rust .comment{color:#8E908C;}pre.rust .doccomment{color:#4D4D4C;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#B76514;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#c7c7c7;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label,.code-attribute{color:#999;}:target,:target>*{background:#FDFFD3;}:target{border-right:3px solid #ffb44c;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.5);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.5);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.5);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip::after{background-color:#000;color:#fff;}.tooltip::before{border-color:transparent black transparent transparent;}.notable-traits-tooltiptext{background-color:#eee;border-color:#999;}.notable-traits-tooltiptext .notable{border-bottom-color:#DDDDDD;}#titles>button:not(.selected){background-color:#e6e6e6;border-top-color:#e6e6e6;}#titles>button:hover,#titles>button.selected{background-color:#ffffff;border-top-color:#0089ff;}#titles>button>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#F1F1F1;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#F1F1F1;border-right-color:#000;}#sidebar-filler{background-color:#F1F1F1;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu,#help-button{border-color:#e0e0e0;background-color:#fff;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus,#help-button:hover,#help-button:focus{border-color:#717171;}#copy-path{color:#999;}#copy-path>img{filter:invert(50%);}#copy-path:hover>img{filter:invert(35%);}#theme-choices{border-color:#ccc;background-color:#fff;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#eee;}@media (max-width:700px){#theme-picker{background:#fff;}}#all-types{background-color:#fff;}#all-types:hover{background-color:#f9f9f9;}.search-results .result-name span.alias{color:#000;}.search-results .result-name span.grey{color:#999;}#sidebar-toggle{background-color:#F1F1F1;}#sidebar-toggle:hover{background-color:#E0E0E0;}#source-sidebar{background-color:#F1F1F1;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#E0E0E0;}div.files>.selected{background-color:#fff;}.setting-line>.title{border-bottom-color:#D5D5D5;} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/main.js b/static/docs-rs/bdk/nightly/latest/main.js deleted file mode 100644 index 8ccfe56500..0000000000 --- a/static/docs-rs/bdk/nightly/latest/main.js +++ /dev/null @@ -1,8 +0,0 @@ -if(!String.prototype.startsWith){String.prototype.startsWith=function(searchString,position){position=position||0;return this.indexOf(searchString,position)===position}}if(!String.prototype.endsWith){String.prototype.endsWith=function(suffix,length){var l=length||this.length;return this.indexOf(suffix,l-suffix.length)!==-1}}if(!DOMTokenList.prototype.add){DOMTokenList.prototype.add=function(className){if(className&&!hasClass(this,className)){if(this.className&&this.className.length>0){this.className+=" "+className}else{this.className=className}}}}if(!DOMTokenList.prototype.remove){DOMTokenList.prototype.remove=function(className){if(className&&this.className){this.className=(" "+this.className+" ").replace(" "+className+" "," ").trim()}}}(function(){var rustdocVars=document.getElementById("rustdoc-vars");if(rustdocVars){window.rootPath=rustdocVars.attributes["data-root-path"].value;window.currentCrate=rustdocVars.attributes["data-current-crate"].value;window.searchJS=rustdocVars.attributes["data-search-js"].value;window.searchIndexJS=rustdocVars.attributes["data-search-index-js"].value}var sidebarVars=document.getElementById("sidebar-vars");if(sidebarVars){window.sidebarCurrent={name:sidebarVars.attributes["data-name"].value,ty:sidebarVars.attributes["data-ty"].value,relpath:sidebarVars.attributes["data-relpath"].value,}}}());function getVirtualKey(ev){if("key"in ev&&typeof ev.key!="undefined"){return ev.key}var c=ev.charCode||ev.keyCode;if(c==27){return"Escape"}return String.fromCharCode(c)}var THEME_PICKER_ELEMENT_ID="theme-picker";var THEMES_ELEMENT_ID="theme-choices";function getThemesElement(){return document.getElementById(THEMES_ELEMENT_ID)}function getThemePickerElement(){return document.getElementById(THEME_PICKER_ELEMENT_ID)}function getNakedUrl(){return window.location.href.split("?")[0].split("#")[0]}function showThemeButtonState(){var themePicker=getThemePickerElement();var themeChoices=getThemesElement();themeChoices.style.display="block";themePicker.style.borderBottomRightRadius="0";themePicker.style.borderBottomLeftRadius="0"}function hideThemeButtonState(){var themePicker=getThemePickerElement();var themeChoices=getThemesElement();themeChoices.style.display="none";themePicker.style.borderBottomRightRadius="3px";themePicker.style.borderBottomLeftRadius="3px"}(function(){var themeChoices=getThemesElement();var themePicker=getThemePickerElement();var availableThemes=["ayu","dark","light"];function switchThemeButtonState(){if(themeChoices.style.display==="block"){hideThemeButtonState()}else{showThemeButtonState()}}function handleThemeButtonsBlur(e){var active=document.activeElement;var related=e.relatedTarget;if(active.id!==THEME_PICKER_ELEMENT_ID&&(!active.parentNode||active.parentNode.id!==THEMES_ELEMENT_ID)&&(!related||(related.id!==THEME_PICKER_ELEMENT_ID&&(!related.parentNode||related.parentNode.id!==THEMES_ELEMENT_ID)))){hideThemeButtonState()}}themePicker.onclick=switchThemeButtonState;themePicker.onblur=handleThemeButtonsBlur;availableThemes.forEach(function(item){var but=document.createElement("button");but.textContent=item;but.onclick=function(){switchTheme(window.currentTheme,window.mainTheme,item,true);useSystemTheme(false)};but.onblur=handleThemeButtonsBlur;themeChoices.appendChild(but)})}());(function(){"use strict";window.searchState={loadingText:"Loading search results...",input:document.getElementsByClassName("search-input")[0],outputElement:function(){return document.getElementById("search")},title:document.title,titleBeforeSearch:document.title,timeout:null,currentTab:0,focusedByTab:[null,null,null],clearInputTimeout:function(){if(searchState.timeout!==null){clearTimeout(searchState.timeout);searchState.timeout=null}},focus:function(){searchState.input.focus()},defocus:function(){searchState.input.blur()},showResults:function(search){if(search===null||typeof search==='undefined'){search=searchState.outputElement()}addClass(main,"hidden");removeClass(search,"hidden");searchState.mouseMovedAfterSearch=false;document.title=searchState.title},hideResults:function(search){if(search===null||typeof search==='undefined'){search=searchState.outputElement()}addClass(search,"hidden");removeClass(main,"hidden");document.title=searchState.titleBeforeSearch;if(searchState.browserSupportsHistoryApi()){history.replaceState("",window.currentCrate+" - Rust",getNakedUrl()+window.location.hash)}},getQueryStringParams:function(){var params={};window.location.search.substring(1).split("&").map(function(s){var pair=s.split("=");params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params},putBackSearch:function(search_input){var search=searchState.outputElement();if(search_input.value!==""&&hasClass(search,"hidden")){searchState.showResults(search);if(searchState.browserSupportsHistoryApi()){var extra="?search="+encodeURIComponent(search_input.value);history.replaceState(search_input.value,"",getNakedUrl()+extra+window.location.hash)}document.title=searchState.title}},browserSupportsHistoryApi:function(){return window.history&&typeof window.history.pushState==="function"},setup:function(){var search_input=searchState.input;if(!searchState.input){return}function loadScript(url){var script=document.createElement('script');script.src=url;document.head.append(script)}var searchLoaded=false;function loadSearch(){if(!searchLoaded){searchLoaded=true;loadScript(window.searchJS);loadScript(window.searchIndexJS)}}search_input.addEventListener("focus",function(){searchState.putBackSearch(this);search_input.origPlaceholder=searchState.input.placeholder;search_input.placeholder="Type your search here.";loadSearch()});search_input.addEventListener("blur",function(){search_input.placeholder=searchState.input.origPlaceholder});search_input.removeAttribute('disabled');searchState.addCrateDropdown(window.ALL_CRATES);var params=searchState.getQueryStringParams();if(params.search!==undefined){var search=searchState.outputElement();search.innerHTML="

    "+searchState.loadingText+"

    ";searchState.showResults(search);loadSearch()}},addCrateDropdown:function(crates){var elem=document.getElementById("crate-search");if(!elem){return}var savedCrate=getSettingValue("saved-filter-crate");for(var i=0,len=crates.length;i0){return tmp}}return null}function showSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){addClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];if(sidebar){addClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(!filler){var div=document.createElement("div");div.id="sidebar-filler";sidebar.appendChild(div)}}}function hideSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){removeClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(filler){filler.remove()}document.getElementsByTagName("body")[0].style.marginTop=""}var toggleAllDocsId="toggle-all-docs";var main=document.getElementById("main");var savedHash="";function handleHashes(ev){var elem;var search=searchState.outputElement();if(ev!==null&&search&&!hasClass(search,"hidden")&&ev.newURL){searchState.hideResults(search);var hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(searchState.browserSupportsHistoryApi()){history.replaceState(hash,"",getNakedUrl()+window.location.search+"#"+hash)}elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}if(savedHash!==window.location.hash){savedHash=window.location.hash;if(savedHash.length===0){return}expandSection(savedHash.slice(1))}}function onHashChange(ev){hideSidebar();handleHashes(ev)}function openParentDetails(elem){while(elem){if(elem.tagName==="DETAILS"){elem.open=true}elem=elem.parentNode}}function expandSection(id){openParentDetails(document.getElementById(id))}function getHelpElement(build){if(build){buildHelperPopup()}return document.getElementById("help")}function displayHelp(display,ev,help){if(display){help=help?help:getHelpElement(true);if(hasClass(help,"hidden")){ev.preventDefault();removeClass(help,"hidden");addClass(document.body,"blur")}}else{help=help?help:getHelpElement(false);if(help&&!hasClass(help,"hidden")){ev.preventDefault();addClass(help,"hidden");removeClass(document.body,"blur")}}}function handleEscape(ev){var help=getHelpElement(false);var search=searchState.outputElement();if(help&&!hasClass(help,"hidden")){displayHelp(false,ev,help)}else if(search&&!hasClass(search,"hidden")){searchState.clearInputTimeout();ev.preventDefault();searchState.hideResults(search)}searchState.defocus();hideThemeButtonState()}var disableShortcuts=getSettingValue("disable-shortcuts")==="true";function handleShortcut(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts){return}if(document.activeElement.tagName==="INPUT"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":displayHelp(false,ev);ev.preventDefault();searchState.focus();break;case"+":case"-":ev.preventDefault();toggleAllDocs();break;case"?":displayHelp(true,ev);break;case"t":case"T":displayHelp(false,ev);ev.preventDefault();var themePicker=getThemePickerElement();themePicker.click();themePicker.focus();break;default:if(getThemePickerElement().parentNode.contains(ev.target)){handleThemeKeyDown(ev)}}}}function handleThemeKeyDown(ev){var active=document.activeElement;var themes=getThemesElement();switch(getVirtualKey(ev)){case"ArrowUp":ev.preventDefault();if(active.previousElementSibling&&ev.target.id!==THEME_PICKER_ELEMENT_ID){active.previousElementSibling.focus()}else{showThemeButtonState();themes.lastElementChild.focus()}break;case"ArrowDown":ev.preventDefault();if(active.nextElementSibling&&ev.target.id!==THEME_PICKER_ELEMENT_ID){active.nextElementSibling.focus()}else{showThemeButtonState();themes.firstElementChild.focus()}break;case"Enter":case"Return":case"Space":if(ev.target.id===THEME_PICKER_ELEMENT_ID&&themes.style.display==="none"){ev.preventDefault();showThemeButtonState();themes.firstElementChild.focus()}break;case"Home":ev.preventDefault();themes.firstElementChild.focus();break;case"End":ev.preventDefault();themes.lastElementChild.focus();break}}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);(function(){var x=document.getElementsByClassName("version-selector");if(x.length>0){x[0].onchange=function(){var i,match,url=document.location.href,stripped="",len=window.rootPath.match(/\.\.\//g).length+1;for(i=0;i .in-band > .trait").textContent;var baseIdName="impl-"+traitName+"-";var libs=Object.getOwnPropertyNames(imp);for(var i=0,llength=libs.length;ithe rustdoc book.";var container=document.createElement("div");var shortcuts=[["?","Show this help dialog"],["S","Focus the search field"],["T","Focus the theme picker menu"],["↑","Move up in search results"],["↓","Move down in search results"],["← / →","Switch result tab (when results focused)"],["⏎","Go to active search result"],["+","Expand all sections"],["-","Collapse all sections"],].map(function(x){return"
    "+x[0].split(" ").map(function(y,index){return(index&1)===0?""+y+"":" "+y+" "}).join("")+"
    "+x[1]+"
    "}).join("");var div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

    Keyboard Shortcuts

    "+shortcuts+"
    ";var infos=["Prefix searches with a type followed by a colon (e.g., fn:) to \ - restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \ - enum, trait, type, macro, \ - and const.","Search functions by type signature (e.g., vec -> usize or \ - * -> vec)","Search multiple things at once by splitting your query with comma (e.g., \ - str,u8 or String,struct:Vec,test)","You can look for items with an exact name by putting double quotes around \ - your request: \"string\"","Look for items inside another one by searching for a path: vec::Vec",].map(function(x){return"

    "+x+"

    "}).join("");var div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

    Search Tricks

    "+infos;container.appendChild(book_info);container.appendChild(div_shortcuts);container.appendChild(div_infos);var rustdoc_version=document.createElement("span");rustdoc_version.className="bottom";var rustdoc_version_code=document.createElement("code");rustdoc_version_code.innerText="rustdoc 1.57.0-nightly (05044c2e6 2021-09-26)";rustdoc_version.appendChild(rustdoc_version_code);container.appendChild(rustdoc_version);popup.appendChild(container);insertAfter(popup,searchState.outputElement());buildHelperPopup=function(){}};onHashChange(null);window.addEventListener("hashchange",onHashChange);searchState.setup()}());(function(){var reset_button_timeout=null;window.copy_path=function(but){var parent=but.parentElement;var path=[];onEach(parent.childNodes,function(child){if(child.tagName==='A'){path.push(child.textContent)}});var el=document.createElement('textarea');el.value=path.join('::');el.setAttribute('readonly','');el.style.position='absolute';el.style.left='-9999px';document.body.appendChild(el);el.select();document.execCommand('copy');document.body.removeChild(el);but.children[0].style.display='none';var tmp;if(but.childNodes.length<2){tmp=document.createTextNode('✓');but.appendChild(tmp)}else{onEachLazy(but.childNodes,function(e){if(e.nodeType===Node.TEXT_NODE){tmp=e;return true}});tmp.textContent='✓'}if(reset_button_timeout!==null){window.clearTimeout(reset_button_timeout)}function reset_button(){tmp.textContent='';reset_button_timeout=null;but.children[0].style.display=""}reset_button_timeout=window.setTimeout(reset_button,1000)}}()) \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/normalize.css b/static/docs-rs/bdk/nightly/latest/normalize.css deleted file mode 100644 index 469959f137..0000000000 --- a/static/docs-rs/bdk/nightly/latest/normalize.css +++ /dev/null @@ -1,2 +0,0 @@ - /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ -html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:0.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type="button"],[type="reset"],[type="submit"],button{-webkit-appearance:button}[type="button"]::-moz-focus-inner,[type="reset"]::-moz-focus-inner,[type="submit"]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type="button"]:-moz-focusring,[type="reset"]:-moz-focusring,[type="submit"]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:0.35em 0.75em 0.625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type="checkbox"],[type="radio"]{box-sizing:border-box;padding:0}[type="number"]::-webkit-inner-spin-button,[type="number"]::-webkit-outer-spin-button{height:auto}[type="search"]{-webkit-appearance:textfield;outline-offset:-2px}[type="search"]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/noscript.css b/static/docs-rs/bdk/nightly/latest/noscript.css deleted file mode 100644 index aea68efbc9..0000000000 --- a/static/docs-rs/bdk/nightly/latest/noscript.css +++ /dev/null @@ -1 +0,0 @@ - #main .attributes{margin-left:0 !important;}#copy-path{display:none;} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/noto-sans-kr-v13-korean-regular-LICENSE.txt b/static/docs-rs/bdk/nightly/latest/noto-sans-kr-v13-korean-regular-LICENSE.txt deleted file mode 100644 index 922d5fdc18..0000000000 --- a/static/docs-rs/bdk/nightly/latest/noto-sans-kr-v13-korean-regular-LICENSE.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2014, 2015 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. - -This Font Software is licensed under the SIL Open Font License, Version 1.1. - -This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/static/docs-rs/bdk/nightly/latest/noto-sans-kr-v13-korean-regular.woff b/static/docs-rs/bdk/nightly/latest/noto-sans-kr-v13-korean-regular.woff deleted file mode 100644 index 01d6b6b546..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/noto-sans-kr-v13-korean-regular.woff and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/rust-logo.png b/static/docs-rs/bdk/nightly/latest/rust-logo.png deleted file mode 100644 index 74b4bd6950..0000000000 Binary files a/static/docs-rs/bdk/nightly/latest/rust-logo.png and /dev/null differ diff --git a/static/docs-rs/bdk/nightly/latest/rustdoc.css b/static/docs-rs/bdk/nightly/latest/rustdoc.css deleted file mode 100644 index 79235e3d63..0000000000 --- a/static/docs-rs/bdk/nightly/latest/rustdoc.css +++ /dev/null @@ -1 +0,0 @@ - @font-face {font-family:'Fira Sans';font-style:normal;font-weight:400;src:local('Fira Sans'),url("FiraSans-Regular.woff2") format("woff2"),url("FiraSans-Regular.woff") format('woff');font-display:swap;}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:500;src:local('Fira Sans Medium'),url("FiraSans-Medium.woff2") format("woff2"),url("FiraSans-Medium.woff") format('woff');font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:400;src:local('Source Serif 4'),url("SourceSerif4-Regular.ttf.woff2") format("woff2"),url("SourceSerif4-Regular.ttf.woff") format("woff");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:italic;font-weight:400;src:local('Source Serif 4 Italic'),url("SourceSerif4-It.ttf.woff2") format("woff2"),url("SourceSerif4-It.ttf.woff") format("woff");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:700;src:local('Source Serif 4 Bold'),url("SourceSerif4-Bold.ttf.woff2") format("woff2"),url("SourceSerif4-Bold.ttf.woff") format("woff");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("SourceCodePro-Regular.ttf.woff2") format("woff2"),url("SourceCodePro-Regular.ttf.woff") format("woff");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:italic;font-weight:400;src:url("SourceCodePro-It.ttf.woff2") format("woff2"),url("SourceCodePro-It.ttf.woff") format("woff");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("SourceCodePro-Semibold.ttf.woff2") format("woff2"),url("SourceCodePro-Semibold.ttf.woff") format("woff");font-display:swap;}@font-face {font-family:'Noto Sans KR';src:url("noto-sans-kr-v13-korean-regular.woff") format("woff");font-display:swap;unicode-range:U+A960-A97F,U+AC00-D7AF,U+D7B0-D7FF;}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}html{content:"";}@media (prefers-color-scheme:light){html{content:"light";}}@media (prefers-color-scheme:dark){html{content:"dark";}}body{font:16px/1.4 "Source Serif 4","Noto Sans KR",serif;margin:0;position:relative;padding:10px 15px 20px 15px;-webkit-font-feature-settings:"kern","liga";-moz-font-feature-settings:"kern","liga";font-feature-settings:"kern","liga";}h1{font-size:1.5em;}h2{font-size:1.4em;}h3{font-size:1.3em;}h1,h2,h3,h4{font-weight:500;margin:20px 0 15px 0;padding-bottom:6px;}h1.fqn{display:flex;border-bottom:1px dashed;margin-top:0;padding-left:1px;}h1.fqn>.in-band>a:hover{text-decoration:underline;}h2,h3,h4{border-bottom:1px solid;}h3.code-header,h4.code-header{font-size:1em;font-weight:600;border:none;padding:0;margin:0;}.impl,.impl-items .method,.methods .method,.impl-items .type,.methods .type,.impl-items .associatedconstant,.methods .associatedconstant,.impl-items .associatedtype,.methods .associatedtype{flex-basis:100%;font-weight:600;margin-top:16px;margin-bottom:10px;position:relative;}.impl,.method.trait-impl,.type.trait-impl,.associatedconstant.trait-impl,.associatedtype.trait-impl{padding-left:15px;}div.impl-items>div{padding-left:0;}h1,h2,h3,h4,.sidebar,a.source,.search-input,.search-results .result-name,.content table td:first-child>a,.item-left>a,div.item-list .out-of-band,span.since,#source-sidebar,#sidebar-toggle,details.rustdoc-toggle>summary::before,details.undocumented>summary::before,div.impl-items>div:not(.docblock):not(.item-info),.content ul.crate a.crate,a.srclink,#main>ul.docblock>li>a{font-family:"Fira Sans",Arial,sans-serif;}.content ul.crate a.crate{font-size:16px/1.6;}ol,ul{padding-left:25px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:.6em;}p{margin:0 0 .6em 0;}summary{outline:none;}td,th{padding:0;}table{border-collapse:collapse;}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0;}details:not(.rustdoc-toggle) summary{margin-bottom:.6em;}code,pre,a.test-arrow,.code-header{font-family:"Source Code Pro",monospace;}.docblock code,.docblock-short code{border-radius:3px;padding:0 0.1em;}.docblock pre code,.docblock-short pre code{padding:0;}pre{padding:14px;}.type-decl pre{overflow-x:auto;}.source .content pre{padding:20px;}img{max-width:100%;}li{position:relative;}.source .content{margin-top:50px;max-width:none;overflow:visible;margin-left:0px;}nav.sub{font-size:16px;text-transform:uppercase;}.sidebar{width:200px;position:fixed;left:0;top:0;bottom:0;overflow:auto;}*{scrollbar-width:initial;}.sidebar{scrollbar-width:thin;}::-webkit-scrollbar{width:12px;}.sidebar::-webkit-scrollbar{width:8px;}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0;}.sidebar .block>ul>li{margin-right:-10px;}.content,nav{max-width:960px;}.hidden{display:none !important;}.logo-container{height:100px;width:100px;position:relative;margin:20px auto;display:block;margin-top:10px;}.logo-container>img{max-width:100px;max-height:100px;height:100%;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);display:block;}.sidebar .location{border:1px solid;font-size:17px;margin:30px 10px 20px 10px;text-align:center;word-wrap:break-word;font-weight:inherit;padding:0;}.sidebar .version{font-size:15px;text-align:center;border-bottom:1px solid;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;}.location:empty{border:none;}.location a:first-of-type{font-weight:500;}.location a:hover{text-decoration:underline;}.block{padding:0;margin-bottom:14px;}.block h2,.block h3{text-align:center;}.block ul,.block li{margin:0 10px;padding:0;list-style:none;}.block a{display:block;text-overflow:ellipsis;overflow:hidden;line-height:15px;padding:7px 5px;font-size:14px;font-weight:300;transition:border 500ms ease-out;}.sidebar-title{border-top:1px solid;border-bottom:1px solid;text-align:center;font-size:17px;margin-bottom:5px;font-weight:inherit;padding:0;}.sidebar-links{margin-bottom:15px;}.sidebar-links>a{padding-left:10px;width:100%;}.sidebar-menu{display:none;}.content{padding:15px 0;}.source .content pre.rust{white-space:pre;overflow:auto;padding-left:0;}.rustdoc .example-wrap{display:inline-flex;margin-bottom:10px;}.example-wrap{position:relative;width:100%;}.example-wrap>pre.line-number{overflow:initial;border:1px solid;padding:13px 8px;text-align:right;border-top-left-radius:5px;border-bottom-left-radius:5px;}.example-wrap>pre.rust a:hover{text-decoration:underline;}.rustdoc:not(.source) .example-wrap>pre:not(.line-number){width:100%;overflow-x:auto;}.rustdoc .example-wrap>pre{margin:0;}#search{margin-left:230px;position:relative;}#results>table{width:100%;table-layout:fixed;}.content>.example-wrap pre.line-numbers{position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}.line-numbers span{cursor:pointer;}.docblock-short{overflow-wrap:anywhere;}.docblock-short p{display:inline;}.docblock-short p{overflow:hidden;text-overflow:ellipsis;margin:0;}.docblock>:not(pre)>code,.docblock-short>:not(pre)>code{white-space:pre-wrap;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom:1px solid;}.top-doc .docblock h1{font-size:1.3em;}.top-doc .docblock h2{font-size:1.15em;}.top-doc .docblock h3,.top-doc .docblock h4,.top-doc .docblock h5{font-size:1em;}.docblock h1{font-size:1em;}.docblock h2{font-size:0.95em;}.docblock h3,.docblock h4,.docblock h5{font-size:0.9em;}.docblock{margin-left:24px;position:relative;}.docblock>*{max-width:100%;overflow-x:auto;}.content .out-of-band{flex-grow:0;text-align:right;font-size:23px;margin:0px;padding:0 0 0 12px;font-weight:normal;}.method>.code-header,.trait-impl>.code-header,.invisible>.code-header{max-width:calc(100% - 41px);display:block;}.invisible{width:100%;display:inline-block;}.content .in-band{flex-grow:1;margin:0px;padding:0px;}.in-band>code,.in-band>.code-header{display:inline-block;}#main{position:relative;}#main>.since{top:inherit;font-family:"Fira Sans",Arial,sans-serif;}.content table:not(.table-display){border-spacing:0 5px;}.content td{vertical-align:top;}.content td:first-child{padding-right:20px;}.content td p:first-child{margin-top:0;}.content td h1,.content td h2{margin-left:0;font-size:1.1em;}.content tr:first-child td{border-top:0;}.docblock table{margin:.5em 0;width:calc(100% - 2px);overflow-x:auto;display:block;}.docblock table td{padding:.5em;border:1px dashed;}.docblock table th{padding:.5em;text-align:left;border:1px solid;}.fields+table{margin-bottom:1em;}.content .item-list{list-style-type:none;padding:0;}.content .multi-column{-moz-column-count:5;-moz-column-gap:2.5em;-webkit-column-count:5;-webkit-column-gap:2.5em;column-count:5;column-gap:2.5em;}.content .multi-column li{width:100%;display:inline-block;}.content>.methods>.method{font-size:1em;position:relative;}.content .method .where,.content .fn .where,.content .where.fmt-newline{display:block;font-size:0.8em;}.content .methods>div:not(.notable-traits):not(.method){margin-left:40px;margin-bottom:15px;}.content .docblock>.impl-items{margin-left:20px;margin-top:-34px;}.content .docblock>.impl-items .table-display{margin:0;}.content .docblock>.impl-items table td{padding:0;}.content .docblock>.impl-items .table-display,.impl-items table td{border:none;}.content .item-info code{font-size:90%;}.content .item-info{position:relative;margin-left:33px;}.sub-variant>div>.item-info{margin-top:initial;}.content .item-info::before{content:'⬑';font-size:25px;position:absolute;top:-6px;left:-19px;}.content .impl-items .method,.content .impl-items>.type,.impl-items>.associatedconstant,.impl-items>.associatedtype,.content .impl-items details>summary>.type,.impl-items details>summary>.associatedconstant,.impl-items details>summary>.associatedtype{margin-left:20px;}.content .impl-items .docblock,.content .impl-items .item-info{margin-bottom:.6em;}.content .impl-items>.item-info{margin-left:40px;}.methods>.item-info,.content .impl-items>.item-info{margin-top:-8px;}.impl-items{flex-basis:100%;}#main>.item-info{margin-top:0;}nav:not(.sidebar){border-bottom:1px solid;padding-bottom:10px;margin-bottom:10px;}nav.main{padding:20px 0;text-align:center;}nav.main .current{border-top:1px solid;border-bottom:1px solid;}nav.main .separator{border:1px solid;display:inline-block;height:23px;margin:0 20px;}nav.sum{text-align:right;}nav.sub form{display:inline;}nav.sub,.content{margin-left:230px;}a{text-decoration:none;background:transparent;}.small-section-header{display:flex;justify-content:space-between;position:relative;}.small-section-header:hover>.anchor{display:initial;}.in-band:hover>.anchor,.impl:hover>.anchor,.method.trait-impl:hover>.anchor,.type.trait-impl:hover>.anchor,.associatedconstant.trait-impl:hover>.anchor,.associatedtype.trait-impl:hover>.anchor{display:inline-block;position:absolute;}.anchor{display:none;position:absolute;left:0;background:none !important;}.anchor.field{left:-5px;}.small-section-header>.anchor{left:-15px;padding-right:8px;}h2.small-section-header>.anchor{padding-right:6px;}.anchor::before{content:'§';}.docblock a:not(.srclink):not(.test-arrow):hover,.docblock-short a:not(.srclink):not(.test-arrow):hover,.item-info a{text-decoration:underline;}.invisible>.srclink,.method>.code-header+.srclink{position:absolute;top:0;right:0;font-size:17px;font-weight:normal;}.block a.current.crate{font-weight:500;}.item-table{display:grid;column-gap:1.2rem;row-gap:0.0rem;grid-template-columns:auto 1fr;justify-items:start;}.item-left,.item-right{display:block;}.item-left{grid-column:1;}.item-right{grid-column:2;}.search-container{position:relative;}.search-container>div{display:inline-flex;width:calc(100% - 63px);}#crate-search{min-width:115px;margin-top:5px;padding:6px;padding-right:19px;flex:none;border:0;border-right:0;border-radius:4px 0 0 4px;outline:none;cursor:pointer;border-right:1px solid;-moz-appearance:none;-webkit-appearance:none;text-indent:0.01px;text-overflow:"";background-repeat:no-repeat;background-color:transparent;background-size:20px;background-position:calc(100% - 1px) 56%;}.search-container>.top-button{position:absolute;right:0;top:10px;}.search-input{-moz-box-sizing:border-box !important;box-sizing:border-box !important;outline:none;border:none;border-radius:1px;margin-top:5px;padding:10px 16px;font-size:17px;transition:border-color 300ms ease;transition:border-radius 300ms ease-in-out;transition:box-shadow 300ms ease-in-out;width:100%;}#crate-search+.search-input{border-radius:0 1px 1px 0;width:calc(100% - 32px);}.search-input:focus{border-radius:2px;border:0;outline:0;}.search-results{display:none;padding-bottom:2em;}.search-results.active{display:block;clear:both;}.search-results .desc>span{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;display:block;}.search-results>a{display:block;width:100%;margin-left:2px;margin-right:2px;border-bottom:1px solid #aaa3;}.search-results>a>div{display:flex;flex-flow:row wrap;}.search-results .result-name,.search-results div.desc,.search-results .result-description{width:50%;}.search-results .result-name{padding-right:1em;}.search-results .result-name>span{display:inline-block;margin:0;font-weight:normal;}body.blur>:not(#help){filter:blur(8px);-webkit-filter:blur(8px);opacity:.7;}#help{width:100%;height:100vh;position:fixed;top:0;left:0;display:flex;justify-content:center;align-items:center;}#help>div{flex:0 0 auto;box-shadow:0 0 6px rgba(0,0,0,.2);width:550px;height:auto;border:1px solid;}#help dt{float:left;clear:left;display:block;margin-right:0.5rem;}#help span.top,#help span.bottom{text-align:center;display:block;font-size:18px;}#help span.top{text-align:center;display:block;margin:10px 0;border-bottom:1px solid;padding-bottom:4px;margin-bottom:6px;}#help span.bottom{clear:both;border-top:1px solid;}#help dd{margin:5px 35px;}#help .infos{padding-left:0;}#help h1,#help h2{margin-top:0;}#help>div div{width:50%;float:left;padding:0 20px 20px 17px;;}.item-info .stab{display:table;}.stab{border-width:1px;border-style:solid;padding:3px;margin-bottom:5px;font-size:90%;font-weight:normal;}.stab p{display:inline;}.stab .emoji{font-size:1.5em;}.emoji{text-shadow:1px 0 0 black,-1px 0 0 black,0 1px 0 black,0 -1px 0 black;}.module-item .stab,.import-item .stab{border-radius:3px;display:inline-block;font-size:80%;line-height:1.2;margin-bottom:0;margin-left:.3em;padding:2px;vertical-align:text-bottom;}.module-item.unstable,.import-item.unstable{opacity:0.65;}.since{font-weight:normal;font-size:initial;}.impl-items .since,.impl .since,.methods .since{padding-left:12px;padding-right:2px;position:initial;}.impl-items .srclink,.impl .srclink,.methods .srclink{font-size:17px;font-weight:normal;}.rightside{float:right;}.has-srclink{font-size:16px;margin-bottom:12px;justify-content:space-between;}.variants_table{width:100%;}.variants_table tbody tr td:first-child{width:1%;}td.summary-column{width:100%;}.summary{padding-right:0px;}pre.rust .question-mark{font-weight:bold;}a.test-arrow{display:inline-block;position:absolute;padding:5px 10px 5px 10px;border-radius:5px;font-size:130%;top:5px;right:5px;z-index:1;}a.test-arrow:hover{text-decoration:none;}.section-header:hover a:before{position:absolute;left:-25px;padding-right:10px;content:'\2002\00a7\2002';}.section-header:hover a{text-decoration:none;}.section-header a{color:inherit;}.code-attribute{font-weight:300;}.since+.srclink{padding-left:10px;}.item-spacer{width:100%;height:12px;}.out-of-band>span.since{position:initial;font-size:20px;margin-right:5px;}.sub-variant,.sub-variant>h3{margin-top:0px !important;padding-top:1px;}#main .sub-variant>h3{font-size:15px;margin-left:25px;margin-bottom:5px;}.sub-variant>div{margin-left:20px;margin-bottom:10px;}.sub-variant>div>span{display:block;position:relative;}.toggle-label{display:inline-block;margin-left:4px;margin-top:3px;}.docblock>.section-header:first-child{margin-left:15px;margin-top:0;}.docblock>.section-header:first-child:hover>a:before{left:-10px;}:target>code,:target>.code-header{opacity:1;}:target{padding-right:3px;}.information{position:absolute;left:-25px;margin-top:7px;z-index:1;}.tooltip{position:relative;display:inline-block;cursor:pointer;}.tooltip::after{display:none;text-align:center;padding:5px 3px 3px 3px;border-radius:6px;margin-left:5px;font-size:16px;}.tooltip.ignore::after{content:"This example is not tested";}.tooltip.compile_fail::after{content:"This example deliberately fails to compile";}.tooltip.should_panic::after{content:"This example panics";}.tooltip.edition::after{content:"This code runs with edition " attr(data-edition);}.tooltip::before{content:" ";position:absolute;top:50%;left:16px;margin-top:-5px;border-width:5px;border-style:solid;display:none;}.tooltip:hover::before,.tooltip:hover::after{display:inline;}.tooltip.compile_fail,.tooltip.should_panic,.tooltip.ignore{font-weight:bold;font-size:20px;}.notable-traits-tooltip{display:inline-block;cursor:pointer;}.notable-traits:hover .notable-traits-tooltiptext,.notable-traits .notable-traits-tooltiptext.force-tooltip{display:inline-block;}.notable-traits .notable-traits-tooltiptext{display:none;padding:5px 3px 3px 3px;border-radius:6px;margin-left:5px;z-index:10;font-size:16px;cursor:default;position:absolute;border:1px solid;}.notable-traits-tooltip::after{content:"\00a0\00a0\00a0";}.notable-traits .notable,.notable-traits .docblock{margin:0;}.notable-traits .notable{margin:0;margin-bottom:13px;font-size:19px;font-weight:600;}.notable-traits .docblock code.content{margin:0;padding:0;font-size:20px;}pre.rust.rust-example-rendered{position:relative;}pre.rust{tab-size:4;-moz-tab-size:4;}.search-failed{text-align:center;margin-top:20px;display:none;}.search-failed.active{display:block;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#titles{height:35px;}#titles>button{float:left;width:33.3%;text-align:center;font-size:18px;cursor:pointer;border:0;border-top:2px solid;}#titles>button:not(:last-child){margin-right:1px;width:calc(33.3% - 1px);}#titles>button>div.count{display:inline-block;font-size:16px;}.notable-traits{cursor:pointer;z-index:2;margin-left:5px;}#all-types{text-align:center;border:1px solid;margin:0 10px;margin-bottom:10px;display:block;border-radius:7px;}#all-types>p{margin:5px 0;}#sidebar-toggle{position:fixed;top:30px;left:300px;z-index:10;padding:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;cursor:pointer;font-weight:bold;transition:left .5s;font-size:1.2em;border:1px solid;border-left:0;}#source-sidebar{position:fixed;top:0;bottom:0;left:0;width:300px;z-index:1;overflow:auto;transition:left .5s;border-right:1px solid;}#source-sidebar>.title{font-size:1.5em;text-align:center;border-bottom:1px solid;margin-bottom:6px;}.theme-picker{position:absolute;left:211px;top:19px;}.theme-picker button{outline:none;}#settings-menu,#help-button{position:absolute;top:10px;}#settings-menu{right:0;outline:none;}#theme-picker,#settings-menu,#help-button,#copy-path{padding:4px;width:27px;height:29px;border:1px solid;border-radius:3px;cursor:pointer;}#help-button{right:30px;font-family:"Fira Sans",Arial,sans-serif;text-align:center;font-size:17px;padding-top:2px;}#copy-path{background:initial;margin-left:10px;padding:0;padding-left:2px;border:0;}#theme-choices{display:none;position:absolute;left:0;top:28px;border:1px solid;border-radius:3px;z-index:1;cursor:pointer;}#theme-choices>button{border:none;width:100%;padding:4px 8px;text-align:center;background:rgba(0,0,0,0);}#theme-choices>button:not(:first-child){border-top:1px solid;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px;border-radius:3px;box-shadow:inset 0 -1px 0;cursor:default;}.hidden-by-impl-hider,.hidden-by-usual-hider{display:none !important;}#implementations-list>h3>span.in-band{width:100%;}.table-display{width:100%;border:0;border-collapse:collapse;border-spacing:0;font-size:16px;}.table-display tr td:first-child{padding-right:0;}.table-display tr td:last-child{float:right;}.table-display .out-of-band{position:relative;font-size:19px;display:block;}#implementors-list>.impl-items .table-display .out-of-band{font-size:17px;}.table-display td:hover .anchor{display:block;top:2px;left:-5px;}#main>ul{padding-left:10px;}#main>ul>li{list-style:none;}.non-exhaustive{margin-bottom:1em;}div.children{padding-left:27px;display:none;}div.name{cursor:pointer;position:relative;margin-left:16px;}div.files>a{display:block;padding:0 3px;}div.files>a:hover,div.name:hover{background-color:#a14b4b;}div.name.expand+.children{display:block;}div.name::before{content:"\25B6";padding-left:4px;font-size:0.7em;position:absolute;left:-16px;top:4px;}div.name.expand::before{transform:rotate(90deg);left:-15px;top:2px;}details.rustdoc-toggle>summary.hideme{cursor:pointer;}details.rustdoc-toggle>summary,details.undocumented>summary{list-style:none;}details.rustdoc-toggle>summary::-webkit-details-marker,details.rustdoc-toggle>summary::marker,details.undocumented>summary::-webkit-details-marker,details.undocumented>summary::marker{display:none;}details.rustdoc-toggle>summary.hideme>span{margin-left:9px;}details.rustdoc-toggle>summary::before{content:"";cursor:pointer;width:17px;height:max(17px,1.1em);background-repeat:no-repeat;background-position:top left;display:inline-block;vertical-align:middle;opacity:.5;}details.rustdoc-toggle>summary::after{content:"Expand";overflow:hidden;width:0;height:0;position:absolute;}details.rustdoc-toggle>summary.hideme::after{content:"";}details.rustdoc-toggle>summary:focus::before,details.rustdoc-toggle>summary:hover::before{opacity:1;}details.rustdoc-toggle.top-doc>summary,details.rustdoc-toggle.top-doc>summary::before,details.rustdoc-toggle.non-exhaustive>summary,details.rustdoc-toggle.non-exhaustive>summary::before{font-family:'Fira Sans';font-size:16px;}details.non-exhaustive{margin-bottom:8px;}details.rustdoc-toggle>summary.hideme::before{position:relative;}details.rustdoc-toggle>summary:not(.hideme)::before{position:absolute;left:-23px;top:3px;}.impl-items>details.rustdoc-toggle>summary:not(.hideme)::before,.undocumented>details.rustdoc-toggle>summary:not(.hideme)::before{position:absolute;left:-2px;}details.rustdoc-toggle[open] >summary.hideme{position:absolute;}details.rustdoc-toggle,details.undocumented{position:relative;}details.rustdoc-toggle[open] >summary.hideme>span{display:none;}details.rustdoc-toggle[open] >summary::before,details.rustdoc-toggle[open] >summary.hideme::before{width:17px;height:max(17px,1.1em);background-repeat:no-repeat;background-position:top left;display:inline-block;content:"";}details.rustdoc-toggle[open] >summary::after,details.rustdoc-toggle[open] >summary.hideme::after{content:"Collapse";}details.undocumented>summary::before{padding-left:17px;height:max(17px,1.1em);background-repeat:no-repeat;background-position:top left;content:"Show hidden undocumented items";cursor:pointer;font-size:16px;font-weight:300;opacity:.5;}details.undocumented>summary:focus::before,details.undocumented>summary:hover::before{opacity:1;}details.undocumented[open] >summary::before{padding-left:17px;height:max(17px,1.1em);background-repeat:no-repeat background-position:top left;content:"Hide undocumented items";}@media (min-width:701px){.docblock>.information:first-child>.tooltip{margin-top:16px;}}@media (max-width:700px){body{padding-top:0px;}.rustdoc>.sidebar{height:45px;min-height:40px;margin:0;margin-left:-15px;padding:0 15px;position:static;z-index:11;}.sidebar>.location{float:right;margin:0px;margin-top:2px;padding:3px 10px 1px 10px;min-height:39px;background:inherit;text-align:left;font-size:24px;}.sidebar .location:empty{padding:0;}.sidebar .logo-container{width:35px;height:35px;margin-top:5px;margin-bottom:5px;float:left;margin-left:50px;}.sidebar .logo-container>img{max-width:35px;max-height:35px;}.sidebar-menu{position:fixed;z-index:10;font-size:2rem;cursor:pointer;width:45px;left:0;text-align:center;display:block;border-bottom:1px solid;border-right:1px solid;height:45px;}.rustdoc.source>.sidebar>.sidebar-menu{display:none;}.sidebar-elems{position:fixed;z-index:1;top:45px;bottom:0;width:246px;left:-246px;overflow-y:auto;border-right:1px solid;}.sidebar>.block.version{overflow:hidden;border-bottom:none;margin-bottom:0;height:100%;padding-left:12px;}.sidebar>.block.version>div.narrow-helper{float:left;width:1px;height:100%;}.sidebar>.block.version>p{margin:0;min-width:55px;display:flex;align-items:center;height:100%;}nav.sub{width:calc(100% - 32px);float:right;}.content{margin-left:0px;}#main,#search{margin-top:45px;padding:0;}#search{margin-left:0;}.anchor{display:none !important;}.theme-picker{left:10px;top:54px;z-index:1;}.notable-traits{position:absolute;left:-22px;top:24px;}#titles>button>div.count{float:left;width:100%;}#titles{height:50px;}.sidebar.mobile{position:fixed;width:100%;margin-left:0;background-color:rgba(0,0,0,0);height:100%;}.sidebar.mobile>div.version{overflow:hidden;max-height:33px;}.sidebar{width:calc(100% + 30px);}.show-it,.sidebar-elems:focus-within{z-index:2;left:0;}.show-it>.block.items{margin:8px 0;}.show-it>.block.items>ul{margin:0;}.show-it>.block.items>ul>li{text-align:center;margin:2px 0;}.show-it>.block.items>ul>li>a{font-size:21px;}#sidebar-filler{position:fixed;left:45px;width:calc(100% - 45px);top:0;height:45px;z-index:-1;border-bottom:1px solid;}#main>details.rustdoc-toggle>summary::before,#main>div>details.rustdoc-toggle>summary::before{left:-11px;}#all-types{margin:10px;}#sidebar-toggle{top:100px;width:30px;font-size:1.5rem;text-align:center;padding:0;}#source-sidebar{z-index:11;}#main>.line-numbers{margin-top:0;}.notable-traits .notable-traits-tooltiptext{left:0;top:100%;}#help-button{display:none;}.item-table{display:flex;flex-flow:column wrap;}.item-left,.item-right{width:100%;}.search-container>div{width:calc(100% - 32px);}.search-results>a{border-bottom:1px solid #aaa9;padding:5px 0px;}.search-results .result-name,.search-results div.desc,.search-results .result-description{width:100%;}.search-results div.desc,.search-results .result-description,.item-right{padding-left:2em;}}@media print{nav.sub,.content .out-of-band{display:none;}}@media (max-width:464px){#titles,#titles>button{height:73px;}#main,#search{margin-top:100px;}#main>table:not(.table-display) td{word-break:break-word;width:50%;}.search-container>div{display:block;width:calc(100% - 37px);}#crate-search{width:100%;border-radius:4px;border:0;}#crate-search+.search-input{width:calc(100% + 71px);margin-left:-36px;}#theme-picker,#settings-menu{padding:5px;width:31px;height:31px;}#theme-picker{margin-top:-2px;}#settings-menu{top:7px;}.docblock{margin-left:12px;}}details.undocumented[open] >summary::before,details.rustdoc-toggle[open] >summary::before,details.rustdoc-toggle[open] >summary.hideme::before{background-image:url(toggle-minus.svg);}details.undocumented>summary::before,details.rustdoc-toggle>summary::before{background-image:url(toggle-plus.svg);} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/search-index.js b/static/docs-rs/bdk/nightly/latest/search-index.js deleted file mode 100644 index 48240e03f9..0000000000 --- a/static/docs-rs/bdk/nightly/latest/search-index.js +++ /dev/null @@ -1,4 +0,0 @@ -var searchIndex = JSON.parse('{\ -"bdk":{"doc":"A modern, lightweight, descriptor-based wallet library …","t":[13,13,13,13,13,13,3,13,13,13,4,13,13,3,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,4,13,3,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,3,13,13,4,8,3,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,14,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,14,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,0,11,11,11,11,11,11,11,11,12,11,12,12,12,11,11,11,11,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,12,11,12,11,11,11,11,11,11,11,11,12,10,12,5,11,11,11,11,11,11,11,11,0,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,12,12,12,12,12,12,12,12,12,12,13,8,4,16,8,3,13,13,3,3,8,6,0,11,11,11,11,11,11,10,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,0,11,0,10,11,11,11,11,10,10,11,10,10,11,11,11,11,11,11,11,5,5,5,10,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,4,4,13,13,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,13,3,3,3,4,13,13,13,13,13,13,13,13,3,13,13,13,3,13,13,13,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,12,11,11,11,11,11,12,12,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,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,12,11,11,12,12,12,11,11,11,11,11,11,11,12,11,11,13,3,3,4,3,13,13,13,13,13,13,13,13,13,13,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,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,12,12,12,12,16,8,8,16,8,8,3,0,10,11,11,11,10,11,10,11,12,10,11,10,11,10,11,10,11,10,11,10,11,11,11,11,10,11,11,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,10,11,11,11,10,11,10,11,10,11,10,11,0,11,12,10,11,10,11,10,11,10,11,10,11,11,11,11,11,4,4,4,13,13,13,13,13,13,3,13,13,13,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,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,12,12,12,12,12,12,12,12,12,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,13,6,3,4,6,8,6,8,6,4,3,13,8,4,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,10,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,0,11,12,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,10,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,11,11,11,11,11,11,11,11,11,0,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,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,12,12,5,13,13,13,4,13,13,13,13,13,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,13,13,13,4,13,3,6,6,13,13,13,13,13,13,13,13,13,13,13,3,3,4,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,11,11,12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,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,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,3,3,3,3,3,3,8,6,3,3,3,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,13,8,4,4,4,3,3,16,16,8,4,8,8,3,8,13,13,13,4,6,13,13,13,16,13,3,13,8,4,13,13,13,3,6,13,13,5,10,11,11,0,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,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,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,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,10,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,12,12,12,11,5,11,10,11,11,5,11,11,11,11,12,12,11,11,11,11,11,11,12,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,11,11,11,11,11,11,11,11,11,11,11,11,11,11,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,13,13,13,13,13,13,13,4,3,4,6,3,13,13,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,4,3,8,13,13,13,13,3,11,11,12,0,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,0,11,11,11,11,11,11,11,11,11,11,11,5,11,11,12,11,11,11,11,11,11,10,11,11,11,11,11,11,11,11,11,11,11,0,11,0,11,11,11,11,11,11,11,0,11,11,11,11,11,11,12,12,8,4,13,13,13,13,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,11,12,3,8,3,6,3,11,11,11,11,11,11,11,11,10,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,11,11,11,11,11,11,11,3,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,11,11,11,11,11,11,12,13,13,13,13,13,13,13,13,13,13,13,13,3,8,4,4,3,3,13,11,12,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,10,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,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,5,13,3,13,13,4,3,13,13,3,8,4,13,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11],"n":["AddressValidator","Bip32","BnBNoExactMatch","BnBTotalTriesExceeded","ChecksumMismatch","CompactFilters","ConfirmationTime","Descriptor","Electrum","Encode","Error","Esplora","External","FeeRate","FeeRateTooLow","FeeRateUnavailable","FeeTooLow","Foreign","Generic","Hex","InsufficientFunds","Internal","InvalidNetwork","InvalidOutpoint","InvalidPolicyPathError","InvalidProgressValue","InvalidU32Bytes","IrreplaceableTransaction","Json","Key","KeychainKind","Local","LocalUtxo","Miniscript","MissingKeyOrigin","NoRecipients","NoUtxosSelected","OutputBelowDustLimit","ProgressUpdateError","Psbt","PsbtParse","Rusqlite","ScriptDoesntHaveAddressForm","Secp256k1","Signer","Sled","SpendingPolicyRequired","TransactionConfirmed","TransactionDetails","TransactionNotFound","UnknownUtxo","Utxo","Vbytes","WeightedUtxo","as_byte","as_fail","as_ref","as_sat_vb","base32_len","blockchain","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","check_base32","clone","clone","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","clone_into","confirmation_time","database","default","default","default","default_min_relay_fee","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","descriptor","descriptor","deserialize","deserialize","deserialize","deserialize","drop","drop","drop","drop","drop","drop","drop","drop","eq","eq","eq","eq","eq","eq","eq","fee","fee_vb","fee_wu","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fragment","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_btc_per_kvb","from_sat_per_vb","from_vb","from_wu","get_hash","get_hash","hash","hash","height","init","init","init","init","init","init","init","init","into","into","into","into","into","into","into","into","into_descriptor_key","into_extended_key","into_wallet_descriptor","into_wallet_descriptor","keychain","keys","ne","ne","ne","ne","ne","ne","new","outpoint","outpoint","partial_cmp","received","satisfaction_weight","sent","serialize","serialize","serialize","serialize","sub","timestamp","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","transaction","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","txid","txout","txout","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","utxo","vbytes","verified","version","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","wallet","write_base32","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","available","found","needed","requested","required","required","0","outpoint","psbt_input","AccurateFees","Blockchain","Capability","Config","ConfigurableBlockchain","EsploraBlockchain","FullHistory","GetAnyTx","LogProgress","NoopProgress","Progress","ProgressData","any","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","broadcast","clone","clone","clone","clone_into","clone_into","clone_into","compact_filters","deref","deref","deref","deref_mut","deref_mut","deref_mut","drop","drop","drop","electrum","eq","esplora","estimate_fee","fmt","from","from","from","from_config","get_capabilities","get_hash","get_height","get_tx","hash","init","init","init","into","into","into","log_progress","noop_progress","progress","setup","sync","to_owned","to_owned","to_owned","try_from","try_from","try_from","try_into","try_into","try_into","type_id","type_id","type_id","update","update","update","vzip","vzip","vzip","AnyBlockchain","AnyBlockchainConfig","CompactFilters","CompactFilters","Electrum","Electrum","Esplora","Esplora","borrow","borrow","borrow_mut","borrow_mut","broadcast","clone","clone_into","deref","deref","deref_mut","deref_mut","deserialize","drop","drop","eq","estimate_fee","fmt","from","from","from","from","from","from","from","from","from_config","get_capabilities","get_height","get_tx","init","init","into","into","ne","serialize","setup","sync","to_owned","try_from","try_from","try_into","try_into","type_id","type_id","vzip","vzip","0","0","0","0","0","0","Bip158","BitcoinPeerConfig","CompactFiltersBlockchain","CompactFiltersBlockchainConfig","CompactFiltersError","DataCorruption","Db","Global","InvalidFilter","InvalidFilterHeader","InvalidHeaders","InvalidResponse","Io","Mempool","MissingBlock","NoPeers","NotConnected","Peer","PeerBloomDisabled","Time","Timeout","add_tx","address","as_fail","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","broadcast","clone","clone","clone_into","clone_into","connect","connect_proxy","default","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","deserialize","drop","drop","drop","drop","drop","drop","eq","eq","estimate_fee","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from_config","get_capabilities","get_height","get_mempool","get_network","get_tx","get_tx","get_version","has_tx","init","init","init","init","init","init","into","into","into","into","into","into","is_connected","iter_txs","ne","ne","network","new","new","peers","recv","send","serialize","serialize","setup","skip_blocks","socks5","socks5_credentials","storage_dir","to_owned","to_owned","to_string","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","0","0","0","0","0","ElectrumBlockchain","ElectrumBlockchainConfig","borrow","borrow","borrow_mut","borrow_mut","broadcast","clone","clone_into","deref","deref","deref_mut","deref_mut","deserialize","drop","drop","eq","estimate_fee","fmt","from","from","from","from_config","get_capabilities","get_height","get_tx","init","init","into","into","ne","retry","serialize","setup","socks5","stop_gap","timeout","to_owned","try_from","try_from","try_into","try_into","type_id","type_id","url","vzip","vzip","BitcoinEncoding","EsploraBlockchain","EsploraBlockchainConfig","EsploraError","EsploraGetHistory","HeaderHashNotFound","HeaderHeightNotFound","Hex","HttpResponse","Io","NoHeader","Parsing","TransactionNotFound","Ureq","UreqTransport","as_fail","base_url","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","broadcast","clone","clone_into","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","deserialize","drop","drop","drop","drop","eq","estimate_fee","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from_config","get_capabilities","get_height","get_tx","init","init","init","init","into","into","into","into","ne","new","proxy","serialize","setup","stop_gap","timeout_read","timeout_write","to_owned","to_string","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","with_agent","0","0","0","0","0","0","0","0","0","0","Batch","BatchDatabase","BatchOperations","Config","ConfigurableDatabase","Database","SqliteDatabase","any","begin_batch","begin_batch","borrow","borrow_mut","check_descriptor_checksum","check_descriptor_checksum","commit_batch","commit_batch","connection","del_last_index","del_last_index","del_path_from_script_pubkey","del_path_from_script_pubkey","del_raw_tx","del_raw_tx","del_script_pubkey_from_path","del_script_pubkey_from_path","del_tx","del_tx","del_utxo","del_utxo","deref","deref_mut","drop","flush","flush","fmt","from","from_config","from_config","get_last_index","get_last_index","get_path_from_script_pubkey","get_path_from_script_pubkey","get_raw_tx","get_raw_tx","get_script_pubkey_from_path","get_script_pubkey_from_path","get_tx","get_tx","get_utxo","get_utxo","increment_last_index","increment_last_index","init","into","iter_raw_txs","iter_raw_txs","iter_script_pubkeys","iter_script_pubkeys","iter_txs","iter_txs","iter_utxos","iter_utxos","memory","new","path","set_last_index","set_last_index","set_raw_tx","set_raw_tx","set_script_pubkey","set_script_pubkey","set_tx","set_tx","set_utxo","set_utxo","try_from","try_into","type_id","vzip","AnyBatch","AnyDatabase","AnyDatabaseConfig","Memory","Memory","Memory","Sled","Sled","Sled","SledDbConfiguration","Sqlite","Sqlite","Sqlite","SqliteDbConfiguration","begin_batch","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","check_descriptor_checksum","commit_batch","del_last_index","del_last_index","del_path_from_script_pubkey","del_path_from_script_pubkey","del_raw_tx","del_raw_tx","del_script_pubkey_from_path","del_script_pubkey_from_path","del_tx","del_tx","del_utxo","del_utxo","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deserialize","deserialize","deserialize","drop","drop","drop","drop","drop","flush","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","from","from","from","from","from","from_config","get_last_index","get_path_from_script_pubkey","get_raw_tx","get_script_pubkey_from_path","get_tx","get_utxo","increment_last_index","init","init","init","init","init","into","into","into","into","into","iter_raw_txs","iter_script_pubkeys","iter_txs","iter_utxos","path","path","serialize","serialize","serialize","set_last_index","set_last_index","set_raw_tx","set_raw_tx","set_script_pubkey","set_script_pubkey","set_tx","set_tx","set_utxo","set_utxo","tree_name","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","0","0","0","0","0","0","0","0","0","MemoryDatabase","begin_batch","borrow","borrow_mut","check_descriptor_checksum","commit_batch","default","del_last_index","del_path_from_script_pubkey","del_raw_tx","del_script_pubkey_from_path","del_tx","del_utxo","deref","deref_mut","drop","flush","fmt","from","from_config","get_last_index","get_path_from_script_pubkey","get_raw_tx","get_script_pubkey_from_path","get_tx","get_utxo","increment_last_index","init","into","iter_raw_txs","iter_script_pubkeys","iter_txs","iter_utxos","new","set_last_index","set_raw_tx","set_script_pubkey","set_tx","set_utxo","try_from","try_into","type_id","vzip","Bare","DerivedDescriptor","DerivedDescriptorKey","Descriptor","ExtendedDescriptor","ExtractPolicy","HdKeyPaths","IntoWalletDescriptor","KeyMap","Legacy","Miniscript","Pkh","ScriptContext","Segwitv0","Sh","Wpkh","Wsh","address","as_enum","as_enum","as_inner","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","branches","check_global_consensus_validity","check_global_consensus_validity","check_global_consensus_validity","check_global_policy_validity","check_global_policy_validity","check_global_validity","check_local_consensus_validity","check_local_consensus_validity","check_local_consensus_validity","check_local_policy_validity","check_local_policy_validity","check_local_policy_validity","check_local_validity","check_terminal_non_malleable","check_terminal_non_malleable","check_terminal_non_malleable","check_witness","check_witness","check_witness","checksum","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","cmp","cmp","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","derive","desc_type","deserialize","deserialize","drop","drop","drop","drop","drop","encode","eq","eq","eq","eq","eq","error","explicit_script","ext","extract_policy","extract_policy","extract_policy","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","for_each_key","for_each_key","from","from","from","from","from","from_ast","from_str","from_str","from_str_insane","from_tree","from_tree","get_hash","get_hash","get_hash","get_hash","get_hash","get_leaf_pk","get_leaf_pk_pkh","get_leaf_pkh","get_nth_child","get_nth_pk","get_nth_pk_pkh","get_nth_pkh","get_satisfaction","has_mixed_timelocks","has_repeated_keys","hash","hash","hash","hash","hash","hash_to_hash160","init","init","init","init","init","into","into","into","into","into","into_inner","into_wallet_descriptor","is_deriveable","is_non_malleable","is_uncompressed","iter","iter_pk","iter_pk_pkh","iter_pkh","lift","lift","lift_check","max_satisfaction_size","max_satisfaction_size","max_satisfaction_size","max_satisfaction_size","max_satisfaction_weight","max_satisfaction_witness_elements","ne","new","new_bare","new_pk","new_pkh","new_sh","new_sh_sortedmulti","new_sh_wpkh","new_sh_wsh","new_sh_wsh_sortedmulti","new_wpkh","new_wsh","new_wsh_sortedmulti","node","other_top_level_checks","parse","parse_descriptor","parse_insane","partial_cmp","partial_cmp","partial_cmp","partial_cmp","partial_cmp","policy","requires_sig","sanity_check","sanity_check","satisfy","satisfy_malleable","script_code","script_pubkey","script_size","serialize","serialize","serialized_len","template","to_owned","to_owned","to_owned","to_owned","to_owned","to_pubkeyhash","to_public_key","to_string","to_string","to_string","to_string_with_secret","top_level_checks","top_level_type_check","translate_pk","translate_pk","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","ty","type_id","type_id","type_id","type_id","type_id","unsigned_script_sig","vzip","vzip","vzip","vzip","vzip","within_resource_limits","0","0","0","0","0","get_checksum","Base58","Bip32","DuplicatedKeys","Error","HardenedDerivationXpub","Hex","InvalidDescriptorCharacter","InvalidDescriptorChecksum","InvalidHdKeyPath","Key","Miniscript","Pk","Policy","as_fail","borrow","borrow_mut","deref","deref_mut","drop","fmt","fmt","from","from","from","from","from","from","from","from","init","into","to_string","try_from","try_into","type_id","vzip","0","0","0","0","0","0","0","0","AbsoluteTimelock","AddOnLeaf","AddOnPartialComplete","BuildSatisfaction","Complete","Condition","ConditionMap","FoldedConditionMap","Hash160Preimage","Hash256Preimage","IncompatibleConditions","IndexOutOfRange","MixedTimelockUnits","Multisig","None","None","NotEnoughItemsSelected","Partial","PartialComplete","PkOrF","Policy","PolicyError","Psbt","PsbtTimelocks","RelativeTimelock","Ripemd160Preimage","Satisfaction","SatisfiableItem","Sha256Preimage","Signature","SignatureKey","Thresh","as_fail","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","cmp","contribution","csv","default","default","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","drop","drop","drop","drop","drop","drop","drop","eq","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","from","get_condition","get_hash","hash","id","id","init","init","init","init","init","init","init","into","into","into","into","into","into","into","is_leaf","is_leaf","is_null","item","ne","ne","partial_cmp","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","0","current_height","input_max_height","psbt","0","0","condition","conditions","conditions","items","items","m","m","n","n","sorted","sorted","0","0","hash","hash","hash","hash","items","keys","threshold","threshold","value","value","0","0","0","0","0","0","0","0","0","1","1","1","1","1","1","2","2","2","Bip44","Bip44Public","Bip49","Bip49Public","Bip84","Bip84Public","DescriptorTemplate","DescriptorTemplateOut","P2Pkh","P2Wpkh","P2Wpkh_P2Sh","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","build","build","build","build","build","build","build","build","build","build","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","drop","drop","drop","drop","drop","drop","drop","drop","drop","from","from","from","from","from","from","from","from","from","init","init","init","init","init","init","init","init","init","into","into","into","into","into","into","into","into","into","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","into_wallet_descriptor","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","Bip32","DerivableKey","DescriptorKey","DescriptorPublicKey","DescriptorSecretKey","DescriptorSinglePriv","DescriptorSinglePub","Entropy","Error","ExtScriptContext","ExtendedKey","GeneratableDefaultOptions","GeneratableKey","GeneratedKey","IntoDescriptorKey","InvalidChecksum","InvalidNetwork","InvalidScriptContext","KeyError","KeyMap","Legacy","Message","Miniscript","Options","Private","PrivateKeyGenerateOptions","Public","ScriptContext","ScriptContextEnum","Segwitv0","SinglePriv","SinglePub","SortedMultiVec","ValidNetworks","XPrv","XPub","any_network","as_enum","as_fail","as_public","bip39","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","check_global_consensus_validity","check_global_consensus_validity","check_global_policy_validity","check_global_policy_validity","check_global_validity","check_global_validity","check_local_consensus_validity","check_local_consensus_validity","check_local_policy_validity","check_local_policy_validity","check_local_validity","check_local_validity","check_terminal_non_malleable","check_witness","check_witness","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","cmp","compressed","default","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","derive","derive_public_key","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","drop","encode","eq","eq","eq","eq","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_public","from_secret","from_str","from_str","from_tree","full_derivation_path","generate","generate_default","generate_with_entropy","generate_with_entropy_default","get_hash","get_hash","get_hash","has_secret","hash","hash","hash","init","init","init","init","init","init","init","init","init","init","init","into","into","into","into","into","into","into","into","into","into","into","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_descriptor_key","into_extended_key","into_extended_key","into_extended_key","into_key","into_xprv","into_xpub","is_deriveable","is_legacy","is_legacy","is_segwit_v0","is_segwit_v0","is_uncompressed","k","key","key","lift","mainnet_network","master_fingerprint","max_satisfaction_size","max_satisfaction_size","max_satisfaction_witness_elements","merge_networks","ne","ne","ne","new","origin","origin","other_top_level_checks","other_top_level_checks","override_valid_networks","partial_cmp","partial_cmp","partial_cmp","pks","sanity_check","satisfy","script_size","sorted_node","test_networks","to_owned","to_owned","to_owned","to_owned","to_owned","to_pubkeyhash","to_string","to_string","to_string","to_string","top_level_checks","top_level_checks","top_level_type_check","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_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","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","vzip","0","0","0","0","0","0","0","0","0","ChineseSimplified","ChineseTraditional","English","French","Italian","Japanese","Korean","Language","Mnemonic","MnemonicType","MnemonicWithPassphrase","Seed","Spanish","Words12","Words15","Words18","Words21","Words24","as_bytes","as_ref","as_ref","base32_len","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","check_base32","checksum_bits","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","default","default","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","drop","drop","drop","drop","entropy","entropy_bits","eq","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","fmt","for_key_size","for_phrase","for_word_count","from","from","from","from","from_entropy","from_language_code","from_phrase","generate_with_entropy","init","init","init","init","into","into","into","into","into_descriptor_key","into_descriptor_key","into_extended_key","into_extended_key","into_phrase","language","new","new","phrase","to_hex","to_hex","to_owned","to_owned","to_owned","to_owned","to_string","to_string","total_bits","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","validate","vzip","vzip","vzip","vzip","word_count","wordlist","wordmap","write_base32","AddressIndex","AddressInfo","IsDust","LastUnused","New","Peek","Reset","Wallet","add_address_validator","add_signer","address","address_validator","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","broadcast","build_fee_bump","build_tx","client","coin_selection","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","drop","drop","drop","eq","export","finalize_psbt","fmt","fmt","fmt","fmt","from","from","from","get_address","get_balance","get_descriptor_for_keychain","get_funded_wallet","get_psbt_input","get_utxo","index","init","init","init","into","into","into","is_dust","is_mine","list_transactions","list_unspent","ne","network","new","new_offline","policies","public_descriptor","secp_ctx","sign","signer","sync","time","to_string","try_from","try_from","try_from","try_into","try_into","try_into","tx_builder","type_id","type_id","type_id","vzip","vzip","vzip","0","0","AddressValidator","AddressValidatorError","ConnectionError","InvalidScript","Message","TimeoutError","UserRejected","as_fail","borrow","borrow_mut","clone","clone_into","deref","deref_mut","drop","eq","fmt","fmt","from","init","into","ne","to_owned","to_string","try_from","try_into","type_id","validate","vzip","0","BranchAndBoundCoinSelection","CoinSelectionAlgorithm","CoinSelectionResult","DefaultCoinSelectionAlgorithm","LargestFirstCoinSelection","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","clone","clone_into","coin_select","coin_select","coin_select","default","default","deref","deref","deref","deref_mut","deref_mut","deref_mut","drop","drop","drop","fee_amount","fmt","fmt","fmt","from","from","from","init","init","init","into","into","into","local_selected_amount","new","selected","selected_amount","to_owned","try_from","try_from","try_from","try_into","try_into","try_into","type_id","type_id","type_id","vzip","vzip","vzip","WalletExport","blockheight","borrow","borrow_mut","change_descriptor","deref","deref_mut","descriptor","deserialize","drop","export_wallet","fmt","from","from_str","init","into","label","serialize","to_string","try_from","try_into","type_id","vzip","0","Dummy","Fingerprint","InputIndexOutOfRange","InvalidKey","InvalidNonWitnessUtxo","MissingHdKeypath","MissingKey","MissingNonWitnessUtxo","MissingWitnessScript","MissingWitnessUtxo","NonStandardSighash","PkHash","SignOptions","Signer","SignerError","SignerId","SignerOrdering","SignersContainer","UserCanceled","add_external","allow_all_sighashes","as_fail","as_key_map","assume_height","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","default","default","default","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","descriptor_secret_key","drop","drop","drop","drop","drop","eq","eq","eq","find","fmt","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from","get_hash","hash","id","ids","init","init","init","init","init","into","into","into","into","into","ne","ne","new","partial_cmp","partial_cmp","remove","sign","sign_whole_tx","signers","to_owned","to_owned","to_owned","to_owned","to_owned","to_string","trust_witness_utxo","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip","vzip","0","0","0","get_timestamp","Bip69Lexicographic","BumpFee","ChangeAllowed","ChangeForbidden","ChangeSpendPolicy","CreateTx","OnlyChange","Shuffle","TxBuilder","TxBuilderContext","TxOrdering","Untouched","add_foreign_utxo","add_global_xpubs","add_recipient","add_unspendable","add_utxo","add_utxos","allow_shrinking","borrow","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","borrow_mut","change_policy","clone","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","clone_into","cmp","cmp","coin_selection","default","default","default","default","deref","deref","deref","deref","deref","deref_mut","deref_mut","deref_mut","deref_mut","deref_mut","do_not_spend_change","drain_to","drain_wallet","drop","drop","drop","drop","drop","enable_rbf","enable_rbf_with_sequence","eq","eq","fee_absolute","fee_rate","finish","fmt","fmt","fmt","fmt","fmt","from","from","from","from","from","get_hash","get_hash","hash","hash","include_output_redeem_witness_script","init","init","init","init","init","into","into","into","into","into","manually_selected_only","nlocktime","only_spend_change","only_witness_utxo","ordering","partial_cmp","partial_cmp","policy_path","set_recipients","sighash","sort_tx","to_owned","to_owned","to_owned","to_owned","to_owned","try_from","try_from","try_from","try_from","try_from","try_into","try_into","try_into","try_into","try_into","type_id","type_id","type_id","type_id","type_id","unspendable","version","vzip","vzip","vzip","vzip","vzip"],"q":["bdk","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::Error","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::Utxo","","","bdk::blockchain","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::blockchain::any","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::blockchain::any::AnyBlockchain","","","bdk::blockchain::any::AnyBlockchainConfig","","","bdk::blockchain::compact_filters","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::blockchain::compact_filters::CompactFiltersError","","","","","bdk::blockchain::electrum","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::blockchain::esplora","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::blockchain::esplora::EsploraError","","","","","","","","","","bdk::database","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::database::any","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::database::any::AnyBatch","","","bdk::database::any::AnyDatabase","","","bdk::database::any::AnyDatabaseConfig","","","bdk::database::memory","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::Descriptor","","","","","bdk::descriptor::checksum","bdk::descriptor::error","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::error::Error","","","","","","","","bdk::descriptor::policy","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::descriptor::policy::BuildSatisfaction","","","","bdk::descriptor::policy::PolicyError","","bdk::descriptor::policy::Satisfaction","","","","","","","","","","","bdk::descriptor::policy::SatisfiableItem","","","","","","","","","","","","bdk::descriptor::template","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::keys","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::keys::DescriptorPublicKey","","bdk::keys::DescriptorSecretKey","","bdk::keys::ExtendedKey","","bdk::keys::KeyError","","","bdk::keys::bip39","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::AddressIndex","","bdk::wallet::address_validator","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::address_validator::AddressValidatorError","bdk::wallet::coin_selection","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::export","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::signer","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","bdk::wallet::signer::SignerId","","","bdk::wallet::time","bdk::wallet::tx_builder","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","",""],"d":["Error that can be returned to fail the validation of an …","BIP32 error","Branch and bound coin selection tries to avoid needing a …","Branch and bound coin selection possible attempts with …","Descriptor checksum mismatch","Compact filters client error)","Block height and timestamp of the block containing the …","Error related to the parsing and usage of descriptors","Electrum client error","Encoding error","Errors that can be thrown by the Wallet","Esplora client error","External","Fee rate","When bumping a tx the fee rate requested is lower than …","Node doesn’t have data to estimate a fee rate","When bumping a tx the absolute fee requested is lower than …","A UTXO owned by another wallet.","Generic error","Hex decoding error","Wallet’s UTXO set is not enough to cover recipient’s …","Internal, usually used for change outputs","Invalid network","Requested outpoint doesn’t exist in the tx (vout greater …","Error while extracting and manipulating policies","Progress value must be between 0.0 (included) and 100.0 …","Wrong number of bytes found when trying to convert to u32","Trying to replace a tx that has a sequence >= 0xFFFFFFFE","Error serializing or deserializing JSON data","Error while working with keys","Types of keychains","A UTXO owned by the local wallet.","An unspent output owned by a Wallet.","Miniscript error","In order to use the TxBuilder::add_global_xpubs option …","Cannot build a tx without recipients","manually_selected_only option is selected but no utxo has …","Output created is under the dust limit, 546 satoshis","Progress update error (maybe the channel has been closed)","Partially signed bitcoin transaction error","Partially signed bitcoin transaction parseerror","Rusqlite client error","This error is thrown when trying to convert Bare and …","An ECDSA error","Signing error","Sled database error","Spending policy is not compatible with this KeychainKind","Happens when trying to bump a transaction that is already …","A wallet transaction","Thrown when a tx is not found in the internal database","Happens when trying to spend an UTXO that is not in the …","An unspent transaction output (UTXO).","Trait implemented by types that can be used to measure …","A Utxo with its satisfaction_weight.","Return KeychainKind as a byte","","","Return the value as satoshi/vbyte","","Blockchain backends","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","If the transaction is confirmed, contains height and …","Database types","","","","Create a new FeeRate with the default min relay fee value","","","","","","","","","","","","","","","","","Descriptors","Macro to write full descriptors with code","","","","","","","","","","","","","","","","","","","","Fee value (sats) if available. The availability of the fee …","Calculate absolute fee in Satoshis using size in virtual …","Calculate absolute fee in Satoshis using size in weight …","","","","","","","","","","Macro to write descriptor fragments with code","","","","","","","","","","","","","","","","","","","","","","","","","","","Create a new instance of FeeRate given a float fee rate in …","Create a new instance of FeeRate given a float fee rate in …","Calculate fee rate from fee and vbytes.","Calculate fee rate from fee and weight units (wu).","","","","","confirmation block height","","","","","","","","","","","","","","","","","","","","","Type of keychain","Key formats","","","","","","","Returns Some ConfirmationTime if both height and timestamp …","Get the location of the UTXO","Reference to a transaction output","","Received value (sats)","The weight of the witness data and scriptSig expressed in …","Sent value (sats)","","","","","","confirmation block timestamp","","","","","","","","","Optional transaction","","","","","","","","","","","","","","","","","Transaction id","Get the TxOut of the UTXO","Transaction output","","","","","","","","","The UTXO","Convert weight units to virtual bytes.","Whether the tx has been verified against the consensus …","Get the version of BDK at runtime","","","","","","","","","Wallet","","","","","","","","","","","","","","","","","","","","","","","","","","","Sats available for spending","found network, for example the network of the bitcoin node","Sats needed for some transaction","requested network, for example what is given as bdk-cli …","Required fee rate (satoshi/vbyte)","Required fee absolute value (satoshi)","","The location of the output.","The information about the input we require to add it to a …","Can compute accurate fees for the transactions found …","Trait that defines the actions that must be supported by a …","Capabilities that can be supported by a Blockchain backend","Type that contains the configuration","Trait for Blockchain types that can be created given a …","Structure that implements the logic to sync with Esplora","Can recover the full history of a wallet and not only the …","Can fetch any historical transaction given its txid","Type that implements Progress and logs at level INFO every …","Type that implements Progress and drops every update …","Trait for types that can receive and process progress …","Data sent with a progress update over a channel","Runtime-checked blockchain types","","","","","","","Broadcast a transaction","","","","","","","Compact Filters","","","","","","","","","","Electrum","","Esplora","Estimate the fee rate required to confirm a transaction in …","","","","","Create a new instance given a configuration","Return the set of Capability supported by this backend","","Return the current height","Fetch a transaction from the blockchain given its txid","","","","","","","","Create a new instance of LogProgress","Create a new instance of NoopProgress","Shortcut to create a channel (pair of Sender and Receiver) …","Setup the backend and populate the internal database for …","Populate the internal database with transactions and UTXOs","","","","","","","","","","","","","Send a new progress update","","","","","","Type that can contain any of the Blockchain types defined …","Type that can contain any of the blockchain configurations …","Compact filters client","Compact filters client","Electrum client","Electrum client","Esplora client","Esplora client","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Invalid BIP158 filter","Data to connect to a Bitcoin P2P peer","Structure implementing the required blockchain traits","Configuration for a CompactFiltersBlockchain","An error that can occur during sync with a …","The data stored in the block filters storage are corrupted","Internal database error","Wrapper for crate::error::Error","The compact filter returned is invalid","The compact filter headers returned are invalid","The headers returned are invalid","A peer sent an invalid or unexpected response","Internal I/O error","Container for unconfirmed, but valid Bitcoin transactions","The peer is missing a block in the valid chain","No peers have been specified","A peer is not connected","A Bitcoin peer","The peer doesn’t advertise the BLOOM service flag","Internal system time error","A peer took too long to reply to one of our messages","Add a transaction to the mempool","Peer address such as 127.0.0.1:18333","","","","","","","","","","","","","","","","","","","Connect to a peer over a plaintext TCP connection","Connect to a peer through a SOCKS5 proxy, optionally by …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Return the mempool used by this peer","Return the Bitcoin Network in use","Look-up a transaction in the mempool given an Inventory …","","Return the VersionMessage sent by the peer","Return whether or not the mempool contains a transaction …","","","","","","","","","","","","","Return whether or not the peer is still connected","Return the list of transactions contained in the mempool","","","Network used","Create a new empty mempool","Construct a new instance given a list of peers, a path to …","List of peers to try to connect to for asking headers and …","Waits for a specific incoming Bitcoin message, optionally …","Send a raw Bitcoin message to the peer","","","","Optionally skip initial skip_blocks blocks (default: 0)","Optional socks5 proxy","Optional socks5 proxy credentials","Storage dir to save partially downloaded headers and full …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Wrapper over an Electrum Client that implements the …","Configuration for an ElectrumBlockchain","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Request retry count","","","URL of the socks5 proxy server or a Tor service","Stop searching addresses for transactions after finding an …","Request timeout (seconds)","","","","","","","","URL of the Electrum server (such as ElectrumX, Esplora, …","","","Invalid Bitcoin data returned","Structure that implements the logic to sync with Esplora","Configuration for an EsploraBlockchain","Errors that can happen during a sync with EsploraBlockchain","Data type used when fetching transaction history from …","Header hash not found","Header height not found","Invalid Hex data returned","HTTP response error","IO error during ureq response read","No header found in ureq response","Invalid number returned","Transaction not found","Error during ureq HTTP request","Transport error during the ureq HTTP call","","Base URL of the esplora service eg. …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Create a new instance of the client from a base URL and …","Optional URL of the proxy to use to make requests to the …","","","Stop searching addresses for transactions after finding an …","Socket read timeout.","Socket write timeout.","","","","","","","","","","","","","","","","","","","Set the inner ureq agent.","","","","","","","","","","","Container for the operations","Trait for a database that supports batch operations","Trait for operations that can be batched","Type that contains the configuration","Trait for Database types that can be created given a …","Trait for reading data from a database","Sqlite database stored on filesystem","Runtime-checked database types","Create a new batch container","","","","Read and checks the descriptor checksum for a given …","","Consume and apply a batch of operations","","A rusqlite connection object to the sqlite database","Delete the last derivation index for a keychain.","","Delete the data related to a specific script_pubkey, …","","Delete a raw transaction given its Txid","","Delete a script_pubkey given the keychain and its child …","","Delete the metadata of a transaction and optionally the …","","Delete a LocalUtxo given its OutPoint","","","","","Force changes to be written to disk","","","","Create a new instance given a configuration","","Return the last defivation index for a keychain.","","Fetch the keychain and child number of a given …","","Fetch a raw transaction given its Txid","","Fetch a script_pubkey given the child number of a keychain.","","Fetch the transaction metadata and optionally also the raw …","","Fetch a LocalUtxo given its OutPoint","","Increment the last derivation index for a keychain and …","","","","Return the list of raw transactions","","Return the list of script_pubkeys","","Return the list of transactions metadata","","Return the list of LocalUtxos","","In-memory ephemeral database","Instantiate a new SqliteDatabase instance by creating a …","Path on the local filesystem to store the sqlite file","Store the last derivation index for a given keychain.","","Store a raw transaction","","Store a script_pubkey along with its keychain and child …","","Store the metadata of a transaction","","Store a LocalUtxo","","","","","","Type that contains any of the BatchDatabase::Batch types …","Type that can contain any of the Database types defined by …","Type that can contain any of the database configurations …","In-memory ephemeral database","In-memory ephemeral database","Memory database has no config","Simple key-value embedded database based on sled","Simple key-value embedded database based on sled","Simple key-value embedded database based on sled","Configuration type for a sled::Tree database","Sqlite embedded database using rusqlite","Sqlite embedded database using rusqlite","Sqlite embedded database using rusqlite","Configuration type for a sqlite::SqliteDatabase database","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Main directory of the db","Main directory of the db","","","","","","","","","","","","","","Name of the database tree, a separated namespace for the …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","In-memory ephemeral database","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Create a new empty database","","","","","","","","","","A raw scriptpubkey (including pay-to-pubkey) under Legacy …","Alias for a Descriptor that contains extended derived keys","Extended DescriptorPublicKey that has been derived","Script descriptor","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 …","Alias type for a map of public key to secret key","Legacy ScriptContext To be used as P2SH scripts For …","Top-level script AST type","Pay-to-PubKey-Hash","The ScriptContext for Miniscript. Additional type …","Segwitv0 ScriptContext","Pay-to-ScriptHash(includes nested wsh/wpkh/sorted multi)","Pay-to-Witness-PubKey-Hash","Pay-to-Witness-ScriptHash with Segwitv0 context","Computes the Bitcoin address of the descriptor, if one …","","","Get a reference to the inner AstElem representing the root …","","","","","","","","","","","Enumerates all child nodes of the current AST node (self) …","Depending on script Context, some of the Terminals might …","","","Depending on script Context, some of the script resource …","","Check the consensus + policy(if not disabled) rules that …","Consensus rules at the Miniscript satisfaction time. It is …","","","Policy rules at the Miniscript satisfaction time. It is …","","","Check the consensus + policy(if not disabled) rules …","Depending on ScriptContext, fragments can be malleable. …","","","Check whether the given satisfaction is valid under the …","","","Descriptor checksum","","","","","","","","","","","","","","","","","","","","","","","","","","","Derives all wildcard keys in the descriptor using the …","Get the DescriptorType of Descriptor","","","","","","","","Encode as a Bitcoin script","","","","","","Descriptor errors","Computes the “witness script” of the descriptor, i.e. …","Additional information helpful for extra analysis.","Extract the spending policy","","","","","","","","","","","","","","","","","","Add type information(Type and Extdata) to Miniscript based …","","","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 Vec with cloned version of all public keys from …","Returns Vec of PkPkh entries, representing either public …","Returns Vec with hashes of all public keys from the …","Returns child node with given index, if any","Returns Option::Some with cloned n’th public key from …","Returns Option::Some with hash of n’th public key or …","Returns Option::Some with hash of n’th public key from …","Returns satisfying witness and scriptSig to spend an …","Whether the miniscript contains a combination of timelocks","Whether the miniscript has repeated Pk or Pkh","","","","","","","","","","","","","","","","","Extracts the AstElem representing the root of the …","Convert to wallet descriptor","Whether or not the descriptor has any wildcards","Whether the miniscript is malleable","","Creates a new Iter iterator that will iterate over all …","Creates a new PkIter iterator that will iterate over all …","Creates a new PkPkhIter iterator that will iterate over …","Creates a new PkhIter iterator that will iterate over all …","","","Lifting corresponds conversion of miniscript into Policy […","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 …","","Construct a new derived key","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 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 a new Wpkh descriptor Will return Err if …","Create a new wsh descriptor from witness script Errors …","Create a new wsh sorted multi descriptor Errors when …","A node in the Abstract Syntax Tree(","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 …","","","","","","Descriptor policy","Whether all spend paths of miniscript require a signature","Whether the descriptor is safe Checks whether all the …","Check whether the underlying Miniscript is safe under the …","Attempt to produce non-malleable satisfying witness for the","Attempt to produce a malleable satisfying witness for the …","Get the scriptCode of a transaction output.","Computes the scriptpubkey of the descriptor","Size, in bytes of the script-pubkey. If this Miniscript is …","","","","Descriptor templates","","","","","","","","","","","Serialize a descriptor to string with its secret keys","Check top level consensus rules.","Check whether the top-level is type B","Convert a descriptor using abstract keys to one using …","This will panic if translatefpk returns an uncompressed …","","","","","","","","","","","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","Error during base58 decoding","BIP32 error","The descriptor contains multiple keys with the same BIP32 …","Errors related to the parsing and usage of descriptors","The descriptor contains hardened derivation steps on …","Hex decoding error","Invalid character found in the descriptor checksum","The provided descriptor doesn’t match its checksum","Invalid HD Key path, such as having a wildcard but a …","Error thrown while working with keys","Miniscript error","Key-related error","Error while extracting and manipulating policies","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","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…","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","Raw public key or extended key fingerprint","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","Relative timelock locktime","RIPEMD160 preimage hash","Represent if and how much a policy item is satisfied by …","An item that needs to be satisfied","SHA256 preimage hash","Signature for a raw public key","Signature for an extended key fingerprint","Threshold items with threshold count","","","","","","","","","","","","","","","","","","","","","","","","","","","","","How the wallet’s descriptor can satisfy this policy node","Optional CheckSequenceVerify condition","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Return the conditions that are set by the spending policy …","","","Returns a unique id for the SatisfiableItem","Identifier for this policy node","","","","","","","","","","","","","","","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 timestamp value","The locktime value","","","","","","","","","","","","","","","","","","","BIP44 template. Expands to pkh(key/44'/0'/0'/{0,1}/*)","BIP44 public template. Expands to pkh(key/{0,1}/*)","BIP49 template. Expands to sh(wpkh(key/49'/0'/0'/{0,1}/*))","BIP49 public template. Expands to sh(wpkh(key/{0,1}/*))","BIP84 template. Expands to wpkh(key/84'/0'/0'/{0,1}/*)","BIP84 public template. Expands to wpkh(key/{0,1}/*)","Trait for descriptor templates that can be built into a …","Type alias for the return type of DescriptorTemplate, …","P2PKH template. Expands to a descriptor pkh(key)","P2WPKH template. Expands to a descriptor wpkh(key)","P2WPKH-P2SH template. Expands to a descriptor sh(wpkh(key))","","","","","","","","","","","","","","","","","","","Build the complete descriptor","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","BIP32 error","Trait for keys that can be derived.","Container for public or secret keys","The MiniscriptKey corresponding to Descriptors. This can …","A Secret Key that can be either a single key or an Xprv","A Single Descriptor Secret Key with optional origin …","A Single Descriptor Key with optional origin information","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","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","Errors thrown while working with keys","Alias type for a map of public key to secret key","Legacy scripts","Custom error message","Miniscript error","Extra options required by the generate_with_entropy","A private extended key, aka an xprv","Options for generating a PrivateKey","A public extended key, aka an xpub","The ScriptContext for Miniscript. Additional type …","Enum representation of the known valid ScriptContexts","Segwitv0 scripts","Single Secret Key","Single Public Key","Contents of a “sortedmulti” descriptor","Set of valid networks for a key","Xprv","Xpub","Create a set containing mainnet, testnet and regtest","Returns the ScriptContext as a ScriptContextEnum","","Return the public version of this key, by applying either …","BIP-0039","","","","","","","","","","","","","","","","","","","","","","","Depending on script Context, some of the Terminals might …","Depending on script Context, some of the Terminals might …","Depending on script Context, some of the script resource …","Depending on script Context, some of the script resource …","Check the consensus + policy(if not disabled) rules that …","Check the consensus + policy(if not disabled) rules that …","Consensus rules at the Miniscript satisfaction time. It is …","Consensus rules at the Miniscript satisfaction time. It is …","Policy 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 …","Check the consensus + policy(if not disabled) rules …","Depending on ScriptContext, fragments can be malleable. …","Check whether the given satisfaction is valid under the …","Check whether the given satisfaction is valid under the …","","","","","","","","","","","","","","Whether the generated key should be “compressed” or not","","","","","","","","","","","","","","","","","","","","","","","","","If this public key has a wildcard, replace it by the given …","Computes the public key corresponding to this descriptor …","","","","","","","","","","","","Encode as a Bitcoin script","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Create an instance given a public key and a set of valid …","Create an instance given a secret key and a set of valid …","","","Parse an expression tree into a SortedMultiVec","Full path, from the master key","Generate a key given the options with a random entropy","Generate a key with the default options and a random …","Generate a key given the extra options and the entropy","Generate a key with the default options and a given entropy","","","","Return whether or not the key contains the private data","","","","","","","","","","","","","","","","","","","","","","","","","","Turn the key into a DescriptorKey within the requested …","Consume self and turn it into a DescriptorKey by adding …","","","","","","Consume self and turn it into an ExtendedKey","","","Consumes self and returns the key","Transform the ExtendedKey into an ExtendedPrivKey for the …","Transform the ExtendedKey into an ExtendedPubKey for the …","Whether or not the key has a wildcards","Returns whether the script context is Legacy","Returns whether the script context is …","Returns whether the script context is Segwitv0","Returns whether the script context is …","","signatures required","The key","The key","","Create a set only containing mainnet","The fingerprint of the master key associated with this key","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","","","","Create a new instance of SortedMultiVec given a list of …","Origin information","Origin information","Other top level checks that are context specific","Other top level checks that are context specific","Override the computed set of valid networks","","","","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 …","Create Terminal::Multi containing sorted pubkeys","Create a set containing testnet and regtest","","","","","","","","","","","Check top level consensus rules.","Check top level consensus rules.","Check whether the top-level is type B","Check whether the top-level is type B","This will panic if translatefpk returns an uncompressed …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","The language determines which words will be used in a …","The primary type in this crate, most tasks require …","Determines the number of words that will be present in a …","Type for a BIP39 mnemonic with an optional passphrase","The secret value used to derive HD wallet addresses from a …","","","","","","","Get the seed value as a byte slice","","","","","","","","","","","","","Return the number of checksum bits","","","","","","","","","","","","","","","","","","","","","","","Get the original entropy value of the mnemonic phrase as a …","Return the number of entropy bits","","","","","","","","","","","","Get a MnemonicType for a mnemonic phrase representing the …","Get a MnemonicType for an existing mnemonic phrase","Get a MnemonicType for a mnemonic phrase with a specific …","","","","","Create a Mnemonic from pre-generated entropy","Construct a word list from its language code. Returns None …","Create a Mnemonic from an existing mnemonic phrase","","","","","","","","","","","","","","Consume the Mnemonic and return the phrase as a String.","Get the Language","Generates a new Mnemonic","Generates the seed from the Mnemonic and the password.","Get the mnemonic phrase as a string reference.","Outputs the hash in hexadecimal form","Outputs the hash in hexadecimal form","","","","","","","Return the number of entropy+checksum bits","","","","","","","","","","","","","Validate a mnemonic phrase","","","","","Return the number of words","Get the word list for this language","Get a WordMap that allows word -> index lookups in the …","","The address index selection strategy to use to derived an …","A derived address and the index it was found at For …","Trait to check if a value is below the dust limit","Return the address for the current descriptor index if it …","Return a new address after incrementing the current …","Return the address for a specific descriptor index. Does …","Return the address for a specific descriptor index and …","A Bitcoin wallet","Add an address validator","Add an external signer","Address","Address validation callbacks","","","","","","","Broadcast a transaction to the network","Bump the fee of a transaction previously created with this …","Start building a transaction.","Return a reference to the internal blockchain client","Coin selection","","","","","","","","","","","","Wallet export","Try to finalize a PSBT","","","","","","","","Return a derived address using the external descriptor, …","Return the balance, meaning the sum of this wallet’s …","Returns the descriptor used to create adddresses for a …","Return a fake wallet that appears to be funded for testing.","get the corresponding PSBT Input for a LocalUtxo","Returns the UTXO owned by this wallet corresponding to …","Child index of this address","","","","","","","Check whether or not a value is below dust limit","Return whether or not a script is part of this wallet …","Return the list of transactions made and received by the …","Return the list of unspent outputs of this wallet","","Get the Bitcoin network the wallet is using.","Create a new “online” wallet","Create a new “offline” wallet","Return the spending policies for the wallet’s descriptor","Return the “public” version of the wallet’s …","Return the secp256k1 context used for all signing …","Sign a transaction with all the wallet’s signers, in the …","Generalized signers","Sync the internal database with the blockchain","Cross-platform time","","","","","","","","Transaction builder","","","","","","","","","Trait to build address validators","Errors that can be returned to fail the validation of an …","Network connection error","Invalid script","A custom error message","Network request timeout error","User rejected the address","","","","","","","","","","","","","","","","","","","","","Validate or inspect an address","","","Branch and bound coin selection","Trait for generalized coin selection algorithms","Result of a successful coin selection","Default coin selection algorithm used by TxBuilder if not …","Simple and dumb coin selection","","","","","","","","","Perform the coin selection","","","","","","","","","","","","","","Total fee amount in satoshi","","","","","","","","","","","","","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.","","","","","","","","","","","","","","Structure that contains the export of a wallet","Earliest block to rescan when looking for the wallet’s …","","","Return the internal descriptor, if present","","","Return the external descriptor","","","Export a wallet","","","","","","Arbitrary label for the wallet","","","","","","","","Dummy identifier","The fingerprint of a BIP32 extended key","Input index is out of range","The private key in use has the right fingerprint but …","The non_witness_utxo specified is invalid","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 requied to …","The witness_utxo field of the transaction is required to …","The psbt contains a non-SIGHASH_ALL sighash in one of its …","Bitcoin HASH160 (RIPEMD160 after SHA256) hash of an ECDSA …","Options for a software signer","Trait for signers","Signing error","Identifier of a signer in the SignersContainers. Used as a …","Defines the order in which signers are called","Container for multiple signers","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 …","","Create a map of public keys to secret keys","Whether the wallet should assume a specific height has …","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","Return the secret key for the signer","","","","","","","","","Finds the signer with lowest ordering for a given id in …","","","","","","","","","","","","","","","","","Return the SignerId for this signer","Returns the list of identifiers of all the signers in the …","","","","","","","","","","","","","Default constructor","","","Removes a signer from the container and returns it","Sign a PSBT","Return whether or not the signer signs the whole …","Returns the list of signers in the container, sorted by …","","","","","","","Whether the signer should trust the witness_utxo, if the …","","","","","","","","","","","","","","","","","","","","","","","","Return the current timestamp in seconds","BIP69 / Lexicographic","Marker type to indicate the TxBuilder is being used to …","Use both change and non-change outputs (default)","Only use non-change outputs (see …","Policy regarding the use of change outputs when creating a …","Marker type to indicate the TxBuilder is being used to …","Only use change outputs (see TxBuilder::only_spend_change)","Randomized (default)","A transaction builder","Context in which the TxBuilder is valid","Ordering of the transaction’s inputs and outputs","Unchanged","Add a foreign UTXO i.e. a UTXO not owned by this wallet.","Fill-in the PSBT_GLOBAL_XPUB field with the extended keys …","Add a recipient to the internal list","Add a utxo to the internal list of unspendable utxos","Add a utxo to the internal list of utxos that must be spent","Add the list of outpoints to the internal list of UTXOs …","Explicitly tells the wallet that it is allowed to reduce …","","","","","","","","","","","Set a specific ChangeSpendPolicy. See …","","","","","","","","","","","","","Choose the coin selection algorithm","","","","","","","","","","","","","","","Do not spend change outputs","Sets the address to drain excess coins to.","Spend all the available inputs. This respects filters like …","","","","","","Enable signaling RBF","Enable signaling RBF with a specific nSequence value","","","Set an absolute fee","Set a custom fee rate","Finish the building the transaction.","","","","","","","","","","","","","","","Fill-in the psbt::Output::redeem_script and …","","","","","","","","","","","Only spend utxos added by add_utxo.","Use a specific nLockTime while creating the transaction","Only spend change outputs","Only Fill-in the psbt::Input::witness_utxo field when …","Choose the ordering for inputs and outputs of the …","","","Set the policy path to use while creating the transaction …","Replace the recipients already added with a new list","Sign with a specific sig hash","Sort transaction inputs and outputs by TxOrdering variant","","","","","","","","","","","","","","","","","","","","","Replace the internal list of unspendable utxos with a new …","Build a transaction with a specific version","","","","",""],"i":[1,1,1,1,1,1,0,1,1,1,0,1,2,0,1,1,1,3,1,1,1,2,1,1,1,1,1,1,1,1,0,3,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,0,0,0,2,1,2,4,2,0,1,2,4,5,6,3,7,8,1,2,4,5,6,3,7,8,2,2,4,5,6,3,7,8,2,4,5,6,3,7,8,7,0,4,7,8,4,1,2,4,5,6,3,7,8,1,2,4,5,6,3,7,8,0,0,2,5,7,8,1,2,4,5,6,3,7,8,2,4,5,6,3,7,8,7,4,4,1,1,2,4,5,6,3,7,8,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,4,5,6,3,7,8,4,4,4,4,2,5,2,5,8,1,2,4,5,6,3,7,8,1,2,4,5,6,3,7,8,9,9,10,11,5,0,4,5,6,3,7,8,8,3,5,4,7,6,7,2,5,7,8,4,8,2,4,5,6,3,7,8,1,7,1,2,4,5,6,3,7,8,1,2,4,5,6,3,7,8,7,3,5,1,2,4,5,6,3,7,8,6,12,7,0,1,2,4,5,6,3,7,8,0,2,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,38,39,40,41,42,43,43,44,0,0,45,0,0,44,44,0,0,0,0,0,44,46,47,44,46,47,48,44,46,47,44,46,47,0,44,46,47,44,46,47,44,46,47,0,44,0,48,44,44,46,47,45,48,44,48,48,44,44,46,47,44,46,47,0,0,0,48,48,44,46,47,44,46,47,44,46,47,44,46,47,49,46,47,44,46,47,0,0,50,51,50,51,50,51,50,51,50,51,50,51,51,50,51,50,51,51,50,51,51,50,51,50,50,50,50,51,51,51,51,50,50,50,50,50,51,50,51,51,51,50,50,51,50,51,50,51,50,51,50,51,52,53,54,55,56,57,58,0,0,0,0,58,58,58,58,58,58,58,58,0,58,58,58,0,58,58,58,59,60,58,59,61,62,60,63,58,59,61,62,60,63,58,62,60,63,60,63,61,61,59,59,61,62,60,63,58,59,61,62,60,63,58,60,63,59,61,62,60,63,58,60,63,62,59,61,62,60,63,58,58,59,61,62,60,63,58,58,58,58,58,58,62,62,62,61,61,59,62,61,59,59,61,62,60,63,58,59,61,62,60,63,58,61,59,60,63,63,59,62,63,61,61,60,63,62,63,60,60,63,60,63,58,59,61,62,60,63,58,59,61,62,60,63,58,59,61,62,60,63,58,59,61,62,60,63,58,64,65,66,67,68,0,0,69,70,69,70,69,70,70,69,70,69,70,70,69,70,70,69,70,69,69,70,69,69,69,69,69,70,69,70,70,70,70,69,70,70,70,70,69,70,69,70,69,70,70,69,70,71,0,0,0,0,71,71,71,71,71,71,71,71,71,71,71,72,73,72,74,71,73,72,74,71,73,72,72,73,72,74,71,73,72,74,71,72,74,73,72,74,71,72,73,73,72,71,71,73,72,74,71,71,71,71,71,71,71,73,73,73,73,73,72,74,71,73,72,74,71,72,73,72,72,73,72,72,72,72,71,73,72,74,71,73,72,74,71,73,72,74,71,73,72,74,71,73,75,76,77,78,79,80,81,82,83,84,85,0,0,86,0,0,0,0,85,87,87,87,88,87,85,87,87,89,87,89,87,89,87,89,87,89,87,89,87,87,87,87,88,87,87,87,86,87,88,87,88,87,88,87,88,87,88,87,88,87,88,87,87,87,88,87,88,87,88,87,88,87,0,87,87,89,87,89,87,89,87,89,87,89,87,87,87,87,87,0,0,0,90,91,92,90,91,92,0,90,91,92,0,91,90,91,93,94,92,90,91,93,94,92,91,91,90,91,90,91,90,91,90,91,90,91,90,91,90,91,93,94,92,90,91,93,94,92,93,94,92,90,91,93,94,92,91,91,93,94,92,90,90,90,90,91,91,91,91,93,94,92,92,92,92,91,91,91,91,91,91,91,91,90,91,93,94,92,90,91,93,94,92,91,91,91,91,93,94,93,94,92,90,91,90,91,90,91,90,91,90,91,93,90,91,93,94,92,90,91,93,94,92,90,91,93,94,92,90,91,93,94,92,95,96,97,98,99,100,101,102,103,0,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,104,105,0,0,0,0,0,0,0,0,0,0,105,0,0,105,105,105,105,106,107,108,109,105,106,107,108,109,105,106,107,108,108,110,106,107,110,107,110,110,106,107,110,106,107,110,110,106,107,110,106,107,0,109,105,106,107,108,109,105,106,107,108,109,105,106,107,108,109,109,105,106,107,108,109,105,106,107,108,105,105,105,108,109,105,106,107,108,108,109,105,106,107,108,0,105,108,111,105,108,109,109,105,105,106,107,108,108,105,108,109,105,106,107,108,108,105,108,108,105,108,109,105,106,107,108,108,108,108,108,108,108,108,105,108,108,109,105,106,107,108,109,109,105,106,107,108,109,105,106,107,108,108,112,105,108,109,108,108,108,108,105,108,108,110,106,107,108,105,108,105,109,105,105,105,105,105,105,105,105,105,105,105,108,110,108,105,108,109,105,106,107,108,0,108,105,108,108,108,105,105,108,105,108,109,0,109,105,106,107,108,109,109,109,105,108,105,110,110,105,108,109,105,106,107,108,109,105,106,107,108,108,109,105,106,107,108,105,109,105,106,107,108,108,113,114,115,116,117,0,118,118,118,0,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,118,119,120,121,122,123,124,125,126,127,128,128,0,129,0,0,0,127,127,128,128,128,127,129,130,128,129,129,0,0,0,130,130,127,127,0,0,127,127,127,127,128,131,127,129,132,133,128,130,131,127,129,132,133,128,130,131,127,129,132,133,130,131,127,129,132,133,130,133,132,133,131,133,131,127,129,132,133,128,130,131,127,129,132,133,128,130,131,127,129,132,133,128,130,133,128,131,127,129,132,133,128,128,130,131,127,129,129,132,132,133,128,130,132,133,133,127,132,131,127,129,132,133,128,130,131,127,129,132,133,128,130,127,129,133,132,133,128,133,132,132,131,127,129,132,133,133,131,127,129,132,133,130,128,131,127,129,132,133,128,130,131,127,129,132,133,128,130,131,127,129,132,133,128,130,131,127,129,132,133,128,130,134,135,135,135,136,137,138,139,140,139,140,139,140,139,140,139,140,141,142,143,144,145,146,147,148,148,147,149,150,151,152,153,154,155,156,157,158,159,154,155,156,157,158,159,155,157,159,0,0,0,0,0,0,0,0,0,0,0,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,160,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,151,152,153,154,155,156,157,158,159,161,0,0,0,0,0,0,162,162,0,0,0,0,0,0,161,161,161,0,0,163,161,161,162,164,0,164,0,0,163,165,166,0,0,165,166,0,167,161,165,0,164,168,169,163,170,161,171,166,172,173,165,164,168,169,163,170,161,171,166,172,173,165,110,110,110,110,110,110,110,110,110,110,110,110,110,110,110,163,170,171,166,172,163,170,171,166,172,171,166,172,170,170,164,168,168,169,163,170,161,171,166,172,173,165,164,168,169,163,170,161,171,166,172,173,165,166,166,164,168,169,163,170,161,171,166,172,173,165,171,163,171,166,172,169,163,170,161,161,171,171,166,166,172,173,165,165,171,164,164,164,168,169,163,170,161,161,161,171,166,172,173,165,169,169,166,165,171,166,162,174,162,174,171,166,172,164,171,166,172,164,168,169,163,170,161,171,166,172,173,165,164,168,169,163,170,161,171,166,172,173,165,175,176,168,168,169,166,165,176,164,168,168,164,164,166,167,163,167,163,166,171,172,173,171,0,166,110,171,171,0,171,166,172,171,172,173,110,110,169,171,166,172,171,171,171,171,171,0,163,170,171,166,172,166,161,171,166,165,110,110,110,110,171,164,168,169,163,170,161,171,166,172,173,165,164,168,169,163,170,161,171,166,172,173,165,164,168,169,163,170,161,171,166,172,173,165,164,168,169,163,170,161,171,166,172,173,165,177,178,179,180,181,182,183,184,185,186,186,186,186,186,186,186,0,0,0,0,0,186,187,187,187,187,187,188,189,188,188,186,189,187,188,186,189,187,188,188,187,186,189,187,188,186,189,187,188,186,187,186,189,187,188,186,189,187,188,186,189,187,188,189,187,186,186,189,189,189,189,187,187,188,188,188,187,187,187,186,189,187,188,189,186,189,189,186,189,187,188,186,189,187,188,189,188,189,188,189,189,189,188,189,189,188,186,189,187,188,189,187,187,186,189,187,188,186,189,187,188,186,189,187,188,189,186,189,187,188,187,186,186,188,0,0,0,190,190,190,190,0,191,191,192,0,191,190,192,191,190,192,191,191,191,191,0,191,190,192,192,191,190,192,191,190,192,192,0,191,191,190,192,192,191,190,192,191,191,191,0,191,191,192,191,190,192,191,190,192,193,191,191,191,192,191,191,191,191,191,191,191,0,191,0,192,191,190,192,191,190,192,0,191,190,192,191,190,192,194,195,0,0,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,196,197,196,198,0,0,0,0,0,199,200,201,199,200,201,200,200,202,200,201,200,201,199,200,201,199,200,201,199,200,201,199,199,200,201,199,200,201,199,200,201,199,200,201,199,201,199,199,200,199,200,201,199,200,201,199,200,201,199,200,201,0,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,203,204,205,205,206,206,206,206,206,206,206,206,206,205,0,0,0,0,0,0,206,207,208,206,207,208,205,206,204,207,208,205,206,204,207,208,205,206,204,207,208,205,206,204,207,208,205,204,204,207,208,205,206,204,207,208,205,206,204,207,208,209,205,206,204,207,208,205,206,204,207,205,206,206,204,207,208,205,205,205,206,204,207,207,208,205,205,209,207,205,206,204,207,208,205,206,204,207,208,205,204,207,205,204,207,209,209,207,205,206,204,207,208,206,208,205,206,204,207,208,205,206,204,207,208,205,206,204,207,208,205,206,204,207,208,210,211,212,0,213,0,214,214,0,0,214,213,0,0,0,213,215,215,215,215,215,215,215,216,217,215,213,214,216,217,215,213,214,215,216,217,215,213,214,216,217,215,213,214,213,214,215,216,217,213,214,216,217,215,213,214,216,217,215,213,214,215,215,215,216,217,215,213,214,215,215,213,214,215,215,215,216,217,215,213,214,216,217,215,213,214,213,214,213,214,215,216,217,215,213,214,216,217,215,213,214,215,215,215,215,215,213,214,215,215,215,213,216,217,215,213,214,216,217,215,213,214,216,217,215,213,214,216,217,215,213,214,215,215,216,217,215,213,214],"f":[null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[],["u8",15]],[[],["fail",8]],[[]],[[],["f32",15]],[[],["usize",15]],null,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],[["result",4,["vec"]],["vec",3,["u5","global"]]]],[[],["keychainkind",4]],[[],["feerate",3]],[[],["localutxo",3]],[[],["weightedutxo",3]],[[],["utxo",4]],[[],["transactiondetails",3]],[[],["confirmationtime",3]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],null,null,[[]],[[],["transactiondetails",3]],[[],["confirmationtime",3]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],null,null,[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["keychainkind",4]],["bool",15]],[[["feerate",3]],["bool",15]],[[["localutxo",3]],["bool",15]],[[["weightedutxo",3]],["bool",15]],[[["utxo",4]],["bool",15]],[[["transactiondetails",3]],["bool",15]],[[["confirmationtime",3]],["bool",15]],null,[[["usize",15]],["u64",15]],[[["usize",15]],["u64",15]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],null,[[]],[[["error",3]]],[[["error",4]]],[[["error",4]]],[[["error",4]]],[[["psbtparseerror",4]]],[[["error",4]]],[[["error",4]]],[[["esploraerror",4]]],[[["compactfilterserror",4]]],[[["error",4]]],[[["error",4]]],[[["error",4]]],[[["error",4]]],[[["keyerror",4]],["error",4]],[[["signererror",4]]],[[["error",4]]],[[["addressvalidatorerror",4]]],[[["policyerror",4]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["f32",15]]],[[["f32",15]]],[[["u64",15],["usize",15]],["feerate",3]],[[["u64",15],["usize",15]],["feerate",3]],[[],["u64",15]],[[],["u64",15]],[[]],[[]],null,[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["keysource",6],["option",4,["keysource"]],["derivationpath",3]],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[],[["keyerror",4],["result",4,["extendedkey","keyerror"]],["extendedkey",4]]],[[["network",4],["secp256k1",3]],[["descriptorerror",4],["result",4,["descriptorerror"]]]],[[["network",4],["secp256k1",3]],[["descriptorerror",4],["result",4,["descriptorerror"]]]],null,null,[[["feerate",3]],["bool",15]],[[["localutxo",3]],["bool",15]],[[["weightedutxo",3]],["bool",15]],[[["utxo",4]],["bool",15]],[[["transactiondetails",3]],["bool",15]],[[["confirmationtime",3]],["bool",15]],[[["u64",15],["u32",15],["option",4,["u64"]],["option",4,["u32"]]],["option",4]],[[],["outpoint",3]],null,[[["feerate",3]],[["ordering",4],["option",4,["ordering"]]]],null,null,null,[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[["feerate",3]]],null,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],["string",3]],null,[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],null,[[],["txout",3]],null,[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],null,[[],["usize",15]],null,[[],["str",15]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],null,[[],["result",4]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[]],[[]],[[]],[[]],[[]],[[]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[],["capability",4]],[[],["noopprogress",3]],[[],["logprogress",3]],[[]],[[]],[[]],null,[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],null,[[["capability",4]],["bool",15]],null,[[["usize",15]],[["feerate",3],["error",4],["result",4,["feerate","error"]]]],[[["formatter",3]],["result",6]],[[]],[[]],[[]],[[],[["result",4,["error"]],["error",4]]],[[],[["hashset",3,["capability"]],["capability",4]]],[[],["u64",15]],[[],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[],["logprogress",3]],[[],["noopprogress",3]],[[]],[[["progress",8]],[["result",4,["error"]],["error",4]]],[[["progress",8]],[["result",4,["error"]],["error",4]]],[[]],[[]],[[]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[["f32",15],["option",4,["string"]],["string",3]],[["result",4,["error"]],["error",4]]],[[["f32",15],["option",4,["string"]],["string",3]],[["result",4,["error"]],["error",4]]],[[["f32",15],["option",4,["string"]],["string",3]],[["result",4,["error"]],["error",4]]],[[]],[[]],[[]],null,null,null,null,null,null,null,null,[[]],[[]],[[]],[[]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[],["anyblockchainconfig",4]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],["result",4]],[[["usize",15]]],[[["usize",15]]],[[["anyblockchainconfig",4]],["bool",15]],[[["usize",15]],[["feerate",3],["error",4],["result",4,["feerate","error"]]]],[[["formatter",3]],["result",6]],[[["compactfiltersblockchain",3]]],[[]],[[["electrumblockchain",3]]],[[["esplorablockchain",3]]],[[]],[[["compactfiltersblockchainconfig",3]]],[[["esplorablockchainconfig",3]]],[[["electrumblockchainconfig",3]]],[[],[["result",4,["error"]],["error",4]]],[[],[["hashset",3,["capability"]],["capability",4]]],[[],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[["anyblockchainconfig",4]],["bool",15]],[[],["result",4]],[[["progress",8]],[["result",4,["error"]],["error",4]]],[[["progress",8]],[["result",4,["error"]],["error",4]]],[[]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[["transaction",3]]],null,[[],["fail",8]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[],["bitcoinpeerconfig",3]],[[],["compactfiltersblockchainconfig",3]],[[]],[[]],[[["network",4],["tosocketaddrs",8],["arc",3,["mempool"]],["mempool",3]],[["result",4,["compactfilterserror"]],["compactfilterserror",4]]],[[["totargetaddr",8],["tosocketaddrs",8],["arc",3,["mempool"]],["mempool",3],["network",4],["option",4]],[["result",4,["compactfilterserror"]],["compactfilterserror",4]]],[[],["mempool",3]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],["result",4]],[[],["result",4]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["bitcoinpeerconfig",3]],["bool",15]],[[["compactfiltersblockchainconfig",3]],["bool",15]],[[["usize",15]],[["feerate",3],["error",4],["result",4,["feerate","error"]]]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[]],[[]],[[]],[[]],[[]],[[["error",4]]],[[["error",3]]],[[]],[[["error",4]]],[[["error",3]]],[[["systemtimeerror",3]]],[[],[["result",4,["error"]],["error",4]]],[[],[["hashset",3,["capability"]],["capability",4]]],[[],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[],[["arc",3,["mempool"]],["mempool",3]]],[[],["network",4]],[[["inventory",4]],[["option",4,["transaction"]],["transaction",3]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[],["versionmessage",3]],[[["txid",3]],["bool",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[]],[[],["bool",15]],[[],[["transaction",3],["vec",3,["transaction"]]]],[[["bitcoinpeerconfig",3]],["bool",15]],[[["compactfiltersblockchainconfig",3]],["bool",15]],null,[[]],[[["peer",3],["vec",3,["peer"]],["option",4,["usize"]],["usize",15],["path",3],["asref",8,["path"]]],[["result",4,["compactfilterserror"]],["compactfilterserror",4]]],null,[[["duration",3],["option",4,["duration"]],["str",15]],[["compactfilterserror",4],["result",4,["option","compactfilterserror"]],["option",4,["networkmessage"]]]],[[["networkmessage",4]],[["result",4,["compactfilterserror"]],["compactfilterserror",4]]],[[],["result",4]],[[],["result",4]],[[["progress",8]],[["result",4,["error"]],["error",4]]],null,null,null,null,[[]],[[]],[[],["string",3]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],[[]],[[]],[[]],null,null,null,null,null,null,null,[[]],[[]],[[]],[[]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[],["electrumblockchainconfig",3]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],["result",4]],[[["usize",15]]],[[["usize",15]]],[[["electrumblockchainconfig",3]],["bool",15]],[[["usize",15]],[["feerate",3],["error",4],["result",4,["feerate","error"]]]],[[["formatter",3]],["result",6]],[[["client",3]]],[[]],[[]],[[],[["result",4,["error"]],["error",4]]],[[],[["hashset",3,["capability"]],["capability",4]]],[[],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[["electrumblockchainconfig",3]],["bool",15]],null,[[],["result",4]],[[["progress",8]],[["result",4,["error"]],["error",4]]],null,null,null,[[]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],null,[[]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[],["fail",8]],null,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[],["esplorablockchainconfig",3]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],["result",4]],[[],["result",4]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["esplorablockchainconfig",3]],["bool",15]],[[["usize",15]],[["feerate",3],["error",4],["result",4,["feerate","error"]]]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[]],[[]],[[]],[[["parseinterror",3]]],[[["transport",3]]],[[["error",4]]],[[["error",4]]],[[["error",4]]],[[]],[[["error",3]]],[[],[["result",4,["error"]],["error",4]]],[[],[["hashset",3,["capability"]],["capability",4]]],[[],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[["esplorablockchainconfig",3]],["bool",15]],[[["usize",15],["str",15]]],null,[[],["result",4]],[[["progress",8]],[["result",4,["error"]],["error",4]]],null,null,null,[[]],[[],["string",3]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],[[]],[[["agent",3]]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[]],[[]],[[]],[[]],[[["keychainkind",4],["asref",8]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4],["asref",8]],[["result",4,["error"]],["error",4]]],[[],[["result",4,["error"]],["error",4]]],[[],[["result",4,["error"]],["error",4]]],null,[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],[["result",4,["error"]],["error",4]]],[[],[["result",4,["error"]],["error",4]]],[[["formatter",3]],["result",6]],[[]],[[],[["result",4,["error"]],["error",4]]],[[],[["result",4,["error"]],["error",4]]],[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["keychainkind",4]],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[["keychainkind",4]],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[],["usize",15]],[[]],[[],[["vec",3,["transaction"]],["error",4],["result",4,["vec","error"]]]],[[],[["vec",3,["transaction"]],["error",4],["result",4,["vec","error"]]]],[[["keychainkind",4],["option",4,["keychainkind"]]],[["error",4],["result",4,["vec","error"]],["vec",3,["script"]]]],[[["keychainkind",4],["option",4,["keychainkind"]]],[["error",4],["result",4,["vec","error"]],["vec",3,["script"]]]],[[["bool",15]],[["vec",3,["transactiondetails"]],["error",4],["result",4,["vec","error"]]]],[[["bool",15]],[["vec",3,["transactiondetails"]],["error",4],["result",4,["vec","error"]]]],[[],[["vec",3,["localutxo"]],["error",4],["result",4,["vec","error"]]]],[[],[["vec",3,["localutxo"]],["error",4],["result",4,["vec","error"]]]],null,[[["string",3]]],null,[[["keychainkind",4],["u32",15]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4],["u32",15]],[["result",4,["error"]],["error",4]]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4],["script",3],["u32",15]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4],["script",3],["u32",15]],[["result",4,["error"]],["error",4]]],[[["transactiondetails",3]],[["result",4,["error"]],["error",4]]],[[["transactiondetails",3]],[["result",4,["error"]],["error",4]]],[[["localutxo",3]],[["result",4,["error"]],["error",4]]],[[["localutxo",3]],[["result",4,["error"]],["error",4]]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["keychainkind",4],["asref",8]],[["result",4,["error"]],["error",4]]],[[],[["result",4,["error"]],["error",4]]],[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],[["result",4,["error"]],["error",4]]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[]],[[]],[[]],[[]],[[["sqlitedatabase",3]]],[[["tree",3]]],[[["memorydatabase",3]]],[[]],[[]],[[]],[[["sleddbconfiguration",3]]],[[]],[[["sqlitedbconfiguration",3]]],[[]],[[],[["result",4,["error"]],["error",4]]],[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["keychainkind",4]],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[],[["vec",3,["transaction"]],["error",4],["result",4,["vec","error"]]]],[[["keychainkind",4],["option",4,["keychainkind"]]],[["error",4],["result",4,["vec","error"]],["vec",3,["script"]]]],[[["bool",15]],[["vec",3,["transactiondetails"]],["error",4],["result",4,["vec","error"]]]],[[],[["vec",3,["localutxo"]],["error",4],["result",4,["vec","error"]]]],null,null,[[],["result",4]],[[],["result",4]],[[],["result",4]],[[["keychainkind",4],["u32",15]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4],["u32",15]],[["result",4,["error"]],["error",4]]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4],["script",3],["u32",15]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4],["script",3],["u32",15]],[["result",4,["error"]],["error",4]]],[[["transactiondetails",3]],[["result",4,["error"]],["error",4]]],[[["transactiondetails",3]],[["result",4,["error"]],["error",4]]],[[["localutxo",3]],[["result",4,["error"]],["error",4]]],[[["localutxo",3]],[["result",4,["error"]],["error",4]]],null,[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],[[]],[[]],null,null,null,null,null,null,null,null,null,null,[[]],[[]],[[]],[[["keychainkind",4],["asref",8]],[["result",4,["error"]],["error",4]]],[[],[["result",4,["error"]],["error",4]]],[[],["memorydatabase",3]],[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],[["result",4,["error"]],["error",4]]],[[["formatter",3]],["result",6]],[[]],[[],[["result",4,["error"]],["error",4]]],[[["keychainkind",4]],[["option",4,["u32"]],["error",4],["result",4,["option","error"]]]],[[["script",3]],[["option",4],["result",4,["option","error"]],["error",4]]],[[["txid",3]],[["error",4],["result",4,["option","error"]],["option",4,["transaction"]]]],[[["keychainkind",4],["u32",15]],[["result",4,["option","error"]],["option",4,["script"]],["error",4]]],[[["bool",15],["txid",3]],[["result",4,["option","error"]],["option",4,["transactiondetails"]],["error",4]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],[[["keychainkind",4]],[["result",4,["u32","error"]],["error",4],["u32",15]]],[[],["usize",15]],[[]],[[],[["vec",3,["transaction"]],["error",4],["result",4,["vec","error"]]]],[[["keychainkind",4],["option",4,["keychainkind"]]],[["error",4],["result",4,["vec","error"]],["vec",3,["script"]]]],[[["bool",15]],[["vec",3,["transactiondetails"]],["error",4],["result",4,["vec","error"]]]],[[],[["vec",3,["localutxo"]],["error",4],["result",4,["vec","error"]]]],[[]],[[["keychainkind",4],["u32",15]],[["result",4,["error"]],["error",4]]],[[["transaction",3]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4],["script",3],["u32",15]],[["result",4,["error"]],["error",4]]],[[["transactiondetails",3]],[["result",4,["error"]],["error",4]]],[[["localutxo",3]],[["result",4,["error"]],["error",4]]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[["network",4]],[["result",4,["address","error"]],["address",3],["error",4]]],[[],["scriptcontextenum",4]],[[],["scriptcontextenum",4]],[[],["terminal",4]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],[["global",3],["miniscript",3],["vec",3,["miniscript","global"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["terminal",4]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["terminal",4]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["terminal",4]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],null,[[],["deriveddescriptorkey",3]],[[],["descriptor",4]],[[],["legacy",4]],[[],["segwitv0",4]],[[],["miniscript",3]],[[]],[[]],[[]],[[]],[[]],[[],["ordering",4]],[[["descriptor",4]],["ordering",4]],[[["legacy",4]],["ordering",4]],[[["segwitv0",4]],["ordering",4]],[[["miniscript",3]],["ordering",4]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["u32",15]],[["descriptorpublickey",4],["descriptor",4,["descriptorpublickey"]]]],[[],["descriptortype",4]],[[],[["result",4,["descriptor"]],["descriptor",4]]],[[],[["result",4,["miniscript"]],["miniscript",3]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],["script",3]],[[],["bool",15]],[[["descriptor",4]],["bool",15]],[[["legacy",4]],["bool",15]],[[["segwitv0",4]],["bool",15]],[[["miniscript",3]],["bool",15]],null,[[],["script",3]],null,[[["secp256k1",3],["buildsatisfaction",4],["signerscontainer",3]],[["option",4,["policy"]],["descriptorerror",4],["result",4,["option","descriptorerror"]]]],[[["secp256k1",3],["buildsatisfaction",4],["signerscontainer",3]],[["result",4,["option","error"]],["option",4,["policy"]],["error",4]]],[[["secp256k1",3],["buildsatisfaction",4],["signerscontainer",3]],[["result",4,["option","error"]],["option",4,["policy"]],["error",4]]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[],["bool",15]],[[],["bool",15]],[[]],[[]],[[]],[[]],[[]],[[["terminal",4]],[["result",4,["miniscript","error"]],["miniscript",3],["error",4]]],[[["str",15]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[["str",15]],[["result",4,["miniscript","error"]],["miniscript",3],["error",4]]],[[["str",15]],[["result",4,["miniscript","error"]],["miniscript",3],["error",4]]],[[["tree",3]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[["tree",3]],[["result",4,["miniscript","error"]],["miniscript",3],["error",4]]],[[],["u64",15]],[[],["u64",15]],[[],["u64",15]],[[],["u64",15]],[[],["u64",15]],[[],[["global",3],["vec",3,["global"]]]],[[],[["vec",3,["pkpkh","global"]],["pkpkh",4],["global",3]]],[[],[["vec",3,["global"]],["global",3]]],[[["usize",15]],[["option",4,["miniscript"]],["miniscript",3]]],[[["usize",15]],["option",4]],[[["usize",15]],[["option",4,["pkpkh"]],["pkpkh",4]]],[[["usize",15]],["option",4]],[[],[["result",4,["error"]],["error",4]]],[[],["bool",15]],[[],["bool",15]],[[]],[[]],[[]],[[]],[[]],[[],["hash",3]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[],["terminal",4]],[[["network",4],["secp256k1",3]],[["descriptorerror",4],["result",4,["descriptorerror"]]]],[[],["bool",15]],[[],["bool",15]],[[],["bool",15]],[[],["iter",3]],[[],["pkiter",3]],[[],["pkpkhiter",3]],[[],["pkhiter",3]],[[],[["error",4],["result",4,["policy","error"]],["policy",4]]],[[],[["error",4],["result",4,["policy","error"]],["policy",4]]],[[],[["result",4,["lifterror"]],["lifterror",4]]],[[["miniscript",3]],[["option",4,["usize"]],["usize",15]]],[[["miniscript",3]],[["option",4,["usize"]],["usize",15]]],[[["miniscript",3]],[["option",4,["usize"]],["usize",15]]],[[],[["usize",15],["result",4,["usize","error"]],["error",4]]],[[],[["usize",15],["result",4,["usize","error"]],["error",4]]],[[],[["usize",15],["result",4,["usize","error"]],["error",4]]],[[["descriptor",4]],["bool",15]],[[["descriptorpublickey",4],["secp256k1",3]],["deriveddescriptorkey",3]],[[["barectx",4],["miniscript",3,["barectx"]]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[],["descriptor",4]],[[],["descriptor",4]],[[["miniscript",3,["legacy"]],["legacy",4]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[["usize",15],["vec",3,["global"]],["global",3]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[["miniscript",3,["segwitv0"]],["segwitv0",4]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[["usize",15],["vec",3,["global"]],["global",3]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[["miniscript",3,["segwitv0"]],["segwitv0",4]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],[[["usize",15],["vec",3,["global"]],["global",3]],[["descriptor",4],["error",4],["result",4,["descriptor","error"]]]],null,[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[["script",3]],[["miniscript",3,["publickey"]],["result",4,["miniscript","error"]],["error",4]]],[[["secp256k1",3],["str",15]],[["error",4],["result",4,["error"]]]],[[["script",3]],[["miniscript",3,["publickey"]],["result",4,["miniscript","error"]],["error",4]]],[[],[["option",4,["ordering"]],["ordering",4]]],[[["descriptor",4]],[["option",4,["ordering"]],["ordering",4]]],[[["legacy",4]],[["option",4,["ordering"]],["ordering",4]]],[[["segwitv0",4]],[["option",4,["ordering"]],["ordering",4]]],[[["miniscript",3]],[["option",4,["ordering"]],["ordering",4]]],null,[[],["bool",15]],[[],[["error",4],["result",4,["error"]]]],[[],[["analysiserror",4],["result",4,["analysiserror"]]]],[[],[["error",4],["vec",3,["vec","global"]],["result",4,["vec","error"]]]],[[],[["error",4],["vec",3,["vec","global"]],["result",4,["vec","error"]]]],[[],["script",3]],[[],["script",3]],[[],["usize",15]],[[],["result",4]],[[],["result",4]],[[],["usize",15]],null,[[]],[[]],[[]],[[]],[[]],[[]],[[],["publickey",3]],[[],["string",3]],[[],["string",3]],[[],["string",3]],[[["hashmap",3]],["string",3]],[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[],[["result",4,["descriptor"]],["descriptor",4]]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],null,[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["script",3]],[[]],[[]],[[]],[[]],[[]],[[],["bool",15]],null,null,null,null,null,[[["str",15]],[["descriptorerror",4],["string",3],["result",4,["string","descriptorerror"]]]],null,null,null,null,null,null,null,null,null,null,null,null,null,[[],["fail",8]],[[]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["keyerror",4]],["error",4]],[[["error",4]]],[[["error",4]]],[[["error",4]]],[[["error",4]]],[[["error",4]]],[[["policyerror",4]]],[[]],[[],["usize",15]],[[]],[[],["string",3]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[],["fail",8]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],["pkorf",3]],[[],["satisfiableitem",4]],[[],["satisfaction",4]],[[],["policy",3]],[[],["condition",3]],[[],["buildsatisfaction",4]],[[]],[[]],[[]],[[]],[[]],[[]],[[["condition",3]],["ordering",4]],null,null,[[],["pkorf",3]],[[],["condition",3]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["condition",3]],["bool",15]],[[["policyerror",4]],["bool",15]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[]],[[]],[[["bool",15]]],[[]],[[["satisfiableitem",4]]],[[]],[[]],[[]],[[]],[[["btreemap",3]],[["policyerror",4],["condition",3],["result",4,["condition","policyerror"]]]],[[],["u64",15]],[[]],[[],["string",3]],null,[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],["bool",15]],[[],["bool",15]],[[],["bool",15]],null,[[["condition",3]],["bool",15]],[[["policyerror",4]],["bool",15]],[[["condition",3]],[["ordering",4],["option",4,["ordering"]]]],[[],["bool",15]],null,[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],null,[[]],[[]],[[]],[[]],[[]],[[]],[[],["string",3]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[],[["descriptortemplateout",6],["result",4,["descriptortemplateout","descriptorerror"]],["descriptorerror",4]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[["network",4],["secp256k1",3]],[["error",4],["result",4,["error"]]]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[],["validnetworks",6]],[[],["scriptcontextenum",4]],[[],["fail",8]],[[["secp256k1",3]],[["descriptorpublickey",4],["descriptorkeyparseerror",3],["result",4,["descriptorpublickey","descriptorkeyparseerror"]]]],null,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["miniscript",3]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[["terminal",4]],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[],[["scriptcontexterror",4],["result",4,["scriptcontexterror"]]]],[[],["scriptcontextenum",4]],[[],["privatekeygenerateoptions",3]],[[],["sortedmultivec",3]],[[],["descriptorpublickey",4]],[[],["descriptorsinglepub",3]],[[]],[[]],[[]],[[]],[[]],[[["sortedmultivec",3]],["ordering",4]],[[["descriptorpublickey",4]],["ordering",4]],[[["descriptorsinglepub",3]],["ordering",4]],null,[[]],[[["usize",15]]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["u32",15]],["descriptorpublickey",4]],[[["secp256k1",3]],[["publickey",3],["result",4,["publickey","conversionerror"]],["conversionerror",4]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],["script",3]],[[["scriptcontextenum",4]],["bool",15]],[[["sortedmultivec",3]],["bool",15]],[[["descriptorpublickey",4]],["bool",15]],[[["descriptorsinglepub",3]],["bool",15]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[],["bool",15]],[[["extendedpubkey",3]]],[[["extendedprivkey",3]]],[[]],[[]],[[]],[[]],[[]],[[["error",4]]],[[]],[[["error",4]]],[[]],[[]],[[]],[[]],[[]],[[["descriptorpublickey",4],["validnetworks",6]]],[[["validnetworks",6],["descriptorsecretkey",4]]],[[["str",15]],[["descriptorpublickey",4],["result",4,["descriptorpublickey"]]]],[[["str",15]],[["result",4,["descriptorsecretkey"]],["descriptorsecretkey",4]]],[[["tree",3]],[["sortedmultivec",3],["result",4,["sortedmultivec","error"]],["error",4]]],[[],["derivationpath",3]],[[],[["generatedkey",3],["result",4,["generatedkey"]]]],[[],[["generatedkey",3],["result",4,["generatedkey"]]]],[[],[["generatedkey",3],["result",4,["generatedkey"]]]],[[],[["generatedkey",3],["result",4,["generatedkey"]]]],[[],["u64",15]],[[],["u64",15]],[[],["u64",15]],[[],["bool",15]],[[]],[[]],[[]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[["keysource",6],["option",4,["keysource"]],["derivationpath",3]],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[["keysource",6],["option",4,["keysource"]],["derivationpath",3]],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[],[["keyerror",4],["result",4,["extendedkey","keyerror"]],["extendedkey",4]]],[[],[["keyerror",4],["result",4,["extendedkey","keyerror"]],["extendedkey",4]]],[[],[["keyerror",4],["result",4,["extendedkey","keyerror"]],["extendedkey",4]]],[[]],[[["network",4]],[["option",4,["extendedprivkey"]],["extendedprivkey",3]]],[[["network",4],["secp256k1",3]],["extendedpubkey",3]],[[],["bool",15]],[[],["bool",15]],[[],["bool",15]],[[],["bool",15]],[[],["bool",15]],[[],["bool",15]],null,null,null,[[],[["error",4],["result",4,["policy","error"]],["policy",4]]],[[],["validnetworks",6]],[[],["fingerprint",3]],[[["miniscript",3]],[["option",4,["usize"]],["usize",15]]],[[],["usize",15]],[[],["usize",15]],[[["validnetworks",6]],["validnetworks",6]],[[["sortedmultivec",3]],["bool",15]],[[["descriptorpublickey",4]],["bool",15]],[[["descriptorsinglepub",3]],["bool",15]],[[["usize",15],["vec",3,["global"]],["global",3]],[["sortedmultivec",3],["result",4,["sortedmultivec","error"]],["error",4]]],null,null,[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[["validnetworks",6]]],[[["sortedmultivec",3]],[["option",4,["ordering"]],["ordering",4]]],[[["descriptorpublickey",4]],[["option",4,["ordering"]],["ordering",4]]],[[["descriptorsinglepub",3]],[["option",4,["ordering"]],["ordering",4]]],null,[[],[["error",4],["result",4,["error"]]]],[[],[["error",4],["vec",3,["vec","global"]],["result",4,["vec","error"]]]],[[],["usize",15]],[[],["terminal",4]],[[],["validnetworks",6]],[[]],[[]],[[]],[[]],[[]],[[],["descriptorpublickey",4]],[[],["string",3]],[[],["string",3]],[[],["string",3]],[[],["string",3]],[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[["miniscript",3]],[["error",4],["result",4,["error"]]]],[[],[["result",4,["sortedmultivec"]],["sortedmultivec",3]]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[]],[[],["str",15]],[[]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],[["result",4,["vec"]],["vec",3,["u5","global"]]]],[[],["u8",15]],[[],["language",4]],[[],["mnemonic",3]],[[],["mnemonictype",4]],[[],["seed",3]],[[]],[[]],[[]],[[]],[[],["language",4]],[[],["mnemonictype",4]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[]],[[],["usize",15]],[[["language",4]],["bool",15]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["formatter",3]],[["error",3],["result",4,["error"]]]],[[["usize",15]],[["error",3],["result",4,["mnemonictype","error"]],["mnemonictype",4]]],[[["str",15]],[["error",3],["result",4,["mnemonictype","error"]],["mnemonictype",4]]],[[["usize",15]],[["error",3],["result",4,["mnemonictype","error"]],["mnemonictype",4]]],[[]],[[]],[[]],[[]],[[["language",4]],[["result",4,["mnemonic","error"]],["error",3],["mnemonic",3]]],[[["str",15]],[["option",4,["language"]],["language",4]]],[[["str",15],["language",4]],[["result",4,["mnemonic","error"]],["error",3],["mnemonic",3]]],[[],[["generatedkey",3],["result",4,["generatedkey"]]]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[["keysource",6],["option",4,["keysource"]],["derivationpath",3]],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[["keysource",6],["option",4,["keysource"]],["derivationpath",3]],[["keyerror",4],["result",4,["descriptorkey","keyerror"]],["descriptorkey",4]]],[[],[["keyerror",4],["result",4,["extendedkey","keyerror"]],["extendedkey",4]]],[[],[["keyerror",4],["result",4,["extendedkey","keyerror"]],["extendedkey",4]]],[[],["string",3]],[[],["language",4]],[[["language",4],["mnemonictype",4]],["mnemonic",3]],[[["str",15],["mnemonic",3]],["seed",3]],[[],["str",15]],[[],["string",3]],[[],["string",3]],[[]],[[]],[[]],[[]],[[],["string",3]],[[],["string",3]],[[],["usize",15]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[["str",15],["language",4]],[["error",3],["result",4,["error"]]]],[[]],[[]],[[]],[[]],[[],["usize",15]],[[],["wordlist",3]],[[],["wordmap",3]],[[],["result",4]],null,null,null,null,null,null,null,null,[[["addressvalidator",8],["arc",3,["addressvalidator"]]]],[[["arc",3,["signer"]],["signer",8],["keychainkind",4],["signerordering",3]]],null,null,[[]],[[]],[[]],[[]],[[]],[[]],[[["transaction",3]],[["result",4,["txid","error"]],["txid",3],["error",4]]],[[["txid",3]],[["result",4,["txbuilder","error"]],["txbuilder",3,["defaultcoinselectionalgorithm","bumpfee"]],["error",4]]],[[],[["defaultcoinselectionalgorithm",6],["txbuilder",3,["defaultcoinselectionalgorithm","createtx"]],["createtx",3]]],[[]],null,[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["addressinfo",3]],["bool",15]],null,[[["psbt",3],["signoptions",3]],[["error",4],["result",4,["bool","error"]],["bool",15]]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[]],[[]],[[]],[[["addressindex",4]],[["result",4,["addressinfo","error"]],["addressinfo",3],["error",4]]],[[],[["u64",15],["error",4],["result",4,["u64","error"]]]],[[["keychainkind",4]],["extendeddescriptor",6]],[[["str",15]]],[[["sighashtype",4],["bool",15],["option",4,["sighashtype"]],["localutxo",3]],[["input",3],["error",4],["result",4,["input","error"]]]],[[["outpoint",3]],[["error",4],["result",4,["option","error"]],["option",4,["localutxo"]]]],null,[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[],["bool",15]],[[["script",3]],[["error",4],["result",4,["bool","error"]],["bool",15]]],[[["bool",15]],[["vec",3,["transactiondetails"]],["error",4],["result",4,["vec","error"]]]],[[],[["vec",3,["localutxo"]],["error",4],["result",4,["vec","error"]]]],[[["addressinfo",3]],["bool",15]],[[],["network",4]],[[["option",4],["intowalletdescriptor",8],["network",4]],[["result",4,["error"]],["error",4]]],[[["option",4],["intowalletdescriptor",8],["network",4]],[["result",4,["error"]],["error",4]]],[[["keychainkind",4]],[["result",4,["option","error"]],["option",4,["policy"]],["error",4]]],[[["keychainkind",4]],[["option",4,["extendeddescriptor"]],["result",4,["option","error"]],["error",4]]],[[],["secp256k1",3]],[[["psbt",3],["signoptions",3]],[["error",4],["result",4,["bool","error"]],["bool",15]]],null,[[["progress",8],["option",4,["u32"]],["u32",15]],[["result",4,["error"]],["error",4]]],null,[[],["string",3]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],null,[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],null,null,null,null,null,null,null,null,null,[[],["fail",8]],[[]],[[]],[[],["addressvalidatorerror",4]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["addressvalidatorerror",4]],["bool",15]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[]],[[],["usize",15]],[[]],[[["addressvalidatorerror",4]],["bool",15]],[[]],[[],["string",3]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[["keychainkind",4],["hdkeypaths",6],["script",3]],[["result",4,["addressvalidatorerror"]],["addressvalidatorerror",4]]],[[]],null,null,null,null,null,null,[[]],[[]],[[]],[[]],[[]],[[]],[[],["largestfirstcoinselection",3]],[[]],[[["u64",15],["feerate",3],["weightedutxo",3],["vec",3,["weightedutxo"]]],[["result",4,["coinselectionresult","error"]],["error",4],["coinselectionresult",3]]],[[["u64",15],["feerate",3],["weightedutxo",3],["vec",3,["weightedutxo"]]],[["result",4,["coinselectionresult","error"]],["error",4],["coinselectionresult",3]]],[[["u64",15],["feerate",3],["weightedutxo",3],["vec",3,["weightedutxo"]]],[["result",4,["coinselectionresult","error"]],["error",4],["coinselectionresult",3]]],[[],["largestfirstcoinselection",3]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],null,[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[]],[[]],[[]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[],["u64",15]],[[["u64",15]]],null,[[],["u64",15]],[[]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],null,null,[[]],[[]],[[],[["option",4,["string"]],["string",3]]],[[["usize",15]]],[[["usize",15]]],[[],["string",3]],[[],["result",4]],[[["usize",15]]],[[["bool",15],["str",15],["wallet",3]],[["result",4,["str"]],["str",15]]],[[["formatter",3]],["result",6]],[[]],[[["str",15]],["result",4]],[[],["usize",15]],[[]],null,[[],["result",4]],[[],["string",3]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[]],null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[[["signerid",4],["arc",3,["signer"]],["signer",8],["signerordering",3]],[["arc",3,["signer"]],["option",4,["arc"]]]],null,[[],["fail",8]],[[["secp256k1",3]],["keymap",6]],null,[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[],["signerid",4]],[[],["signererror",4]],[[],["signerordering",3]],[[],["signerscontainer",3]],[[],["signoptions",3]],[[]],[[]],[[]],[[]],[[]],[[["signerid",4]],["ordering",4]],[[["signerordering",3]],["ordering",4]],[[]],[[],["signerscontainer",3]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[],[["descriptorsecretkey",4],["option",4,["descriptorsecretkey"]]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["signerid",4]],["bool",15]],[[["signererror",4]],["bool",15]],[[["signerordering",3]],["bool",15]],[[["signerid",4]],[["option",4,["arc"]],["arc",3]]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["hash",3]],["signerid",4]],[[["fingerprint",3]],["signerid",4]],[[]],[[]],[[]],[[]],[[["keymap",6]],["signerscontainer",3]],[[]],[[],["u64",15]],[[]],[[["secp256k1",3]],["signerid",4]],[[],[["signerid",4],["vec",3,["signerid"]]]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[["signerid",4]],["bool",15]],[[["signerordering",3]],["bool",15]],[[]],[[["signerid",4]],[["ordering",4],["option",4,["ordering"]]]],[[["signerordering",3]],[["ordering",4],["option",4,["ordering"]]]],[[["signerordering",3],["signerid",4]],[["arc",3,["signer"]],["option",4,["arc"]]]],[[["option",4,["usize"]],["usize",15],["partiallysignedtransaction",3],["secp256k1",3]],[["result",4,["signererror"]],["signererror",4]]],[[],["bool",15]],[[],[["arc",3],["vec",3,["arc"]]]],[[]],[[]],[[]],[[]],[[]],[[],["string",3]],null,[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[]],[[]],[[]],[[]],[[]],null,null,null,[[],["u64",15]],null,null,null,null,null,null,null,null,null,null,null,null,[[["usize",15],["outpoint",3],["input",3]],[["error",4],["result",4,["error"]]]],[[]],[[["u64",15],["script",3]]],[[["outpoint",3]]],[[["outpoint",3]],[["error",4],["result",4,["error"]]]],[[],[["error",4],["result",4,["error"]]]],[[["script",3]],[["error",4],["result",4,["error"]]]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[]],[[["changespendpolicy",4]]],[[],["createtx",3]],[[],["bumpfee",3]],[[]],[[],["txordering",4]],[[],["changespendpolicy",4]],[[]],[[]],[[]],[[]],[[]],[[["txordering",4]],["ordering",4]],[[["changespendpolicy",4]],["ordering",4]],[[["coinselectionalgorithm",8]],[["txbuilder",3],["coinselectionalgorithm",8]]],[[],["createtx",3]],[[],["bumpfee",3]],[[]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[]],[[["script",3]]],[[]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[["usize",15]]],[[]],[[["u32",15]]],[[["txordering",4]],["bool",15]],[[["changespendpolicy",4]],["bool",15]],[[["u64",15]]],[[["feerate",3]]],[[],[["error",4],["result",4,["error"]]]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[["formatter",3]],["result",6]],[[]],[[]],[[]],[[]],[[]],[[],["u64",15]],[[],["u64",15]],[[]],[[]],[[]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[],["usize",15]],[[]],[[]],[[]],[[]],[[]],[[]],[[["u32",15]]],[[]],[[]],[[["txordering",4]]],[[["txordering",4]],[["ordering",4],["option",4,["ordering"]]]],[[["changespendpolicy",4]],[["ordering",4],["option",4,["ordering"]]]],[[["vec",3,["usize"]],["string",3],["keychainkind",4],["btreemap",3,["string","vec"]]]],[[["vec",3]]],[[["sighashtype",4]]],[[["transaction",3]]],[[]],[[]],[[]],[[]],[[]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["result",4]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[],["typeid",3]],[[["vec",3,["outpoint"]],["outpoint",3]]],[[["i32",15]]],[[]],[[]],[[]],[[]],[[]]],"p":[[4,"Error"],[4,"KeychainKind"],[4,"Utxo"],[3,"FeeRate"],[3,"LocalUtxo"],[3,"WeightedUtxo"],[3,"TransactionDetails"],[3,"ConfirmationTime"],[6,"MnemonicWithPassphrase"],[6,"DescriptorTemplateOut"],[6,"ExtendedDescriptor"],[8,"Vbytes"],[13,"InvalidU32Bytes"],[13,"Generic"],[13,"OutputBelowDustLimit"],[13,"MissingKeyOrigin"],[13,"Key"],[13,"SpendingPolicyRequired"],[13,"InvalidPolicyPathError"],[13,"Signer"],[13,"InvalidProgressValue"],[13,"InvalidOutpoint"],[13,"Descriptor"],[13,"AddressValidator"],[13,"Encode"],[13,"Miniscript"],[13,"Bip32"],[13,"Secp256k1"],[13,"Json"],[13,"Hex"],[13,"Psbt"],[13,"PsbtParse"],[13,"Electrum"],[13,"Esplora"],[13,"CompactFilters"],[13,"Sled"],[13,"Rusqlite"],[13,"InsufficientFunds"],[13,"InvalidNetwork"],[13,"FeeRateTooLow"],[13,"FeeTooLow"],[13,"Local"],[13,"Foreign"],[4,"Capability"],[8,"ConfigurableBlockchain"],[3,"NoopProgress"],[3,"LogProgress"],[8,"Blockchain"],[8,"Progress"],[4,"AnyBlockchain"],[4,"AnyBlockchainConfig"],[13,"Electrum"],[13,"Esplora"],[13,"CompactFilters"],[13,"Electrum"],[13,"Esplora"],[13,"CompactFilters"],[4,"CompactFiltersError"],[3,"Mempool"],[3,"BitcoinPeerConfig"],[3,"Peer"],[3,"CompactFiltersBlockchain"],[3,"CompactFiltersBlockchainConfig"],[13,"Db"],[13,"Io"],[13,"Bip158"],[13,"Time"],[13,"Global"],[3,"ElectrumBlockchain"],[3,"ElectrumBlockchainConfig"],[4,"EsploraError"],[3,"EsploraBlockchainConfig"],[3,"EsploraBlockchain"],[3,"EsploraGetHistory"],[13,"Ureq"],[13,"UreqTransport"],[13,"HttpResponse"],[13,"Io"],[13,"Parsing"],[13,"BitcoinEncoding"],[13,"Hex"],[13,"TransactionNotFound"],[13,"HeaderHeightNotFound"],[13,"HeaderHashNotFound"],[8,"BatchDatabase"],[8,"ConfigurableDatabase"],[3,"SqliteDatabase"],[8,"Database"],[8,"BatchOperations"],[4,"AnyBatch"],[4,"AnyDatabase"],[4,"AnyDatabaseConfig"],[3,"SledDbConfiguration"],[3,"SqliteDbConfiguration"],[13,"Memory"],[13,"Sled"],[13,"Sqlite"],[13,"Memory"],[13,"Sled"],[13,"Sqlite"],[13,"Memory"],[13,"Sled"],[13,"Sqlite"],[3,"MemoryDatabase"],[4,"Descriptor"],[4,"Legacy"],[4,"Segwitv0"],[3,"Miniscript"],[3,"DerivedDescriptorKey"],[8,"ScriptContext"],[8,"ExtractPolicy"],[8,"IntoWalletDescriptor"],[13,"Bare"],[13,"Pkh"],[13,"Wpkh"],[13,"Sh"],[13,"Wsh"],[4,"Error"],[13,"Key"],[13,"Policy"],[13,"InvalidDescriptorCharacter"],[13,"Bip32"],[13,"Base58"],[13,"Pk"],[13,"Miniscript"],[13,"Hex"],[4,"SatisfiableItem"],[4,"PolicyError"],[4,"Satisfaction"],[4,"BuildSatisfaction"],[3,"PkOrF"],[3,"Policy"],[3,"Condition"],[13,"Psbt"],[13,"PsbtTimelocks"],[13,"NotEnoughItemsSelected"],[13,"IndexOutOfRange"],[13,"Complete"],[13,"Partial"],[13,"PartialComplete"],[13,"Signature"],[13,"SignatureKey"],[13,"Sha256Preimage"],[13,"Hash256Preimage"],[13,"Ripemd160Preimage"],[13,"Hash160Preimage"],[13,"Thresh"],[13,"Multisig"],[13,"AbsoluteTimelock"],[13,"RelativeTimelock"],[3,"P2Pkh"],[3,"P2Wpkh_P2Sh"],[3,"P2Wpkh"],[3,"Bip44"],[3,"Bip44Public"],[3,"Bip49"],[3,"Bip49Public"],[3,"Bip84"],[3,"Bip84Public"],[8,"DescriptorTemplate"],[4,"KeyError"],[8,"GeneratableKey"],[4,"ScriptContextEnum"],[4,"ExtendedKey"],[4,"DescriptorSecretKey"],[4,"DescriptorPublicKey"],[8,"ExtScriptContext"],[3,"GeneratedKey"],[4,"DescriptorKey"],[3,"PrivateKeyGenerateOptions"],[3,"SortedMultiVec"],[3,"DescriptorSinglePub"],[3,"DescriptorSinglePriv"],[8,"GeneratableDefaultOptions"],[8,"IntoDescriptorKey"],[8,"DerivableKey"],[13,"SinglePub"],[13,"XPub"],[13,"SinglePriv"],[13,"XPrv"],[13,"Private"],[13,"Public"],[13,"Message"],[13,"Bip32"],[13,"Miniscript"],[4,"Language"],[4,"MnemonicType"],[3,"Seed"],[3,"Mnemonic"],[4,"AddressIndex"],[3,"Wallet"],[3,"AddressInfo"],[8,"IsDust"],[13,"Peek"],[13,"Reset"],[4,"AddressValidatorError"],[8,"AddressValidator"],[13,"Message"],[3,"CoinSelectionResult"],[3,"LargestFirstCoinSelection"],[3,"BranchAndBoundCoinSelection"],[8,"CoinSelectionAlgorithm"],[3,"WalletExport"],[3,"SignerOrdering"],[4,"SignerId"],[4,"SignerError"],[3,"SignersContainer"],[3,"SignOptions"],[8,"Signer"],[13,"PkHash"],[13,"Fingerprint"],[13,"Dummy"],[4,"TxOrdering"],[4,"ChangeSpendPolicy"],[3,"TxBuilder"],[3,"CreateTx"],[3,"BumpFee"]]}\ -}'); -if (window.initSearch) {window.initSearch(searchIndex)}; \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/search.js b/static/docs-rs/bdk/nightly/latest/search.js deleted file mode 100644 index 91de2a155a..0000000000 --- a/static/docs-rs/bdk/nightly/latest/search.js +++ /dev/null @@ -1 +0,0 @@ -(function(){var itemTypes=["mod","externcrate","import","struct","enum","fn","type","static","trait","impl","tymethod","method","structfield","variant","macro","primitive","associatedtype","constant","associatedconstant","union","foreigntype","keyword","existential","attr","derive","traitalias"];var TY_PRIMITIVE=itemTypes.indexOf("primitive");var TY_KEYWORD=itemTypes.indexOf("keyword");function printTab(nb){if(nb===0||nb===1||nb===2){searchState.currentTab=nb}var nb_copy=nb;onEachLazy(document.getElementById("titles").childNodes,function(elem){if(nb_copy===0){addClass(elem,"selected")}else{removeClass(elem,"selected")}nb_copy-=1});onEachLazy(document.getElementById("results").childNodes,function(elem){if(nb===0){addClass(elem,"active")}else{removeClass(elem,"active")}nb-=1})}function removeEmptyStringsFromArray(x){for(var i=0,len=x.length;i-1){var obj=searchIndex[results[i].id];obj.lev=results[i].lev;var res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=obj.displayPath+obj.name;obj.fullPath+="|"+obj.ty;obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}return out}function sortResults(results,isType){var ar=[];for(var entry in results){if(hasOwnPropertyRustdoc(results,entry)){ar.push(results[entry])}}results=ar;var i,len,result;for(i=0,len=results.length;ib?+1:-1)}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}if((aaa.item.ty===TY_PRIMITIVE&&bbb.item.ty!==TY_KEYWORD)||(aaa.item.ty===TY_KEYWORD&&bbb.item.ty!==TY_PRIMITIVE)){return-1}if((bbb.item.ty===TY_PRIMITIVE&&aaa.item.ty!==TY_PRIMITIVE)||(bbb.item.ty===TY_KEYWORD&&aaa.item.ty!==TY_KEYWORD)){return 1}a=(aaa.item.desc==="");b=(bbb.item.desc==="");if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});for(i=0,len=results.length;i"));return{name:val.substring(0,val.indexOf("<")),generics:values.split(/\s*,\s*/),}}return{name:val,generics:[],}}function checkGenerics(obj,val){var tmp_lev,elem_name;if(val.generics.length>0){if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>=val.generics.length){var elems=Object.create(null);var elength=obj[GENERICS_DATA].length;for(var x=0;xGENERICS_DATA&&obj[GENERICS_DATA].length>0){var elems=Object.create(null);len=obj[GENERICS_DATA].length;for(x=0;xGENERICS_DATA&&obj[GENERICS_DATA].length!==0){var tmp_lev=checkGenerics(obj,val);if(tmp_lev<=MAX_LEV_DISTANCE){return tmp_lev}}}}else if(literalSearch){if((!val.generics||val.generics.length===0)&&obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>0){return obj[GENERICS_DATA].some(function(name){return name===val.name})}return false}lev_distance=Math.min(levenshtein(obj[NAME],val.name),lev_distance);if(lev_distance<=MAX_LEV_DISTANCE){lev_distance=Math.ceil((checkGenerics(obj,val)+lev_distance)/2)}else if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>0){var olength=obj[GENERICS_DATA].length;for(x=0;x0){var length=obj.type[INPUTS_DATA].length;for(var i=0;iOUTPUT_DATA){var ret=obj.type[OUTPUT_DATA];if(typeof ret[0]==="string"){ret=[ret]}for(var x=0,len=ret.length;xlength){return MAX_LEV_DISTANCE+1}for(var i=0;ilength){break}var lev_total=0;var aborted=false;for(var x=0;xMAX_LEV_DISTANCE){aborted=true;break}lev_total+=lev}if(!aborted){ret_lev=Math.min(ret_lev,Math.round(lev_total/clength))}}return ret_lev}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER)return true;if(filter===type)return true;var name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,desc:item.desc,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,}}function handleAliases(ret,query,filterCrates){var aliases=[];var crateAliases=[];if(filterCrates!==undefined){if(ALIASES[filterCrates]&&ALIASES[filterCrates][query.search]){var query_aliases=ALIASES[filterCrates][query.search];var len=query_aliases.length;for(var i=0;iMAX_RESULTS){ret.others.pop()}};onEach(aliases,pushFunc);onEach(crateAliases,pushFunc)}var nSearchWords=searchWords.length;var i,it;var ty;var fullId;var returned;var in_args;var len;if((val.charAt(0)==="\""||val.charAt(0)==="'")&&val.charAt(val.length-1)===val.charAt(0)){val=extractGenerics(val.substr(1,val.length-2));for(i=0;i")>-1){var trimmer=function(s){return s.trim()};var parts=val.split("->").map(trimmer);var input=parts[0];var inputs=input.split(",").map(trimmer).sort();for(i=0,len=inputs.length;i1?paths.length-1:1);var lev,j;for(j=0;j1){lev=checkPath(contains,paths[paths.length-1],ty);if(lev>MAX_LEV_DISTANCE){continue}else if(lev>0){lev_add=lev/10}}returned=MAX_LEV_DISTANCE+1;in_args=MAX_LEV_DISTANCE+1;var index=-1;lev=MAX_LEV_DISTANCE+1;fullId=ty.id;if(searchWords[j].indexOf(split[i])>-1||searchWords[j].indexOf(val)>-1||ty.normalizedName.indexOf(val)>-1){if(typePassesFilter(typeFilter,ty.ty)&&results[fullId]===undefined){index=ty.normalizedName.indexOf(val)}}if((lev=levenshtein(searchWords[j],val))<=MAX_LEV_DISTANCE){if(typePassesFilter(typeFilter,ty.ty)){lev+=1}else{lev=MAX_LEV_DISTANCE+1}}in_args=findArg(ty,valGenerics,false,typeFilter);returned=checkReturned(ty,valGenerics,false,typeFilter);lev+=lev_add;if(lev>0&&val.length>3&&searchWords[j].indexOf(val)>-1){if(val.length<6){lev-=1}else{lev=0}}if(in_args<=MAX_LEV_DISTANCE){if(results_in_args[fullId]===undefined){results_in_args[fullId]={id:j,index:index,lev:in_args,}}results_in_args[fullId].lev=Math.min(results_in_args[fullId].lev,in_args)}if(returned<=MAX_LEV_DISTANCE){if(results_returned[fullId]===undefined){results_returned[fullId]={id:j,index:index,lev:returned,}}results_returned[fullId].lev=Math.min(results_returned[fullId].lev,returned)}if(typePassesFilter(typeFilter,ty.ty)&&(index!==-1||lev<=MAX_LEV_DISTANCE)){if(index!==-1&&paths.length<2){lev=0}if(results[fullId]===undefined){results[fullId]={id:j,index:index,lev:lev,}}results[fullId].lev=Math.min(results[fullId].lev,lev)}}}var ret={"in_args":sortResults(results_in_args,true),"returned":sortResults(results_returned,true),"others":sortResults(results,false),};handleAliases(ret,query,filterCrates);return ret}function validateResult(name,path,keys,parent){for(var i=0,len=keys.length;i-1||path.indexOf(keys[i])>-1||(parent!==undefined&&parent.name!==undefined&&parent.name.toLowerCase().indexOf(keys[i])>-1)||levenshtein(name,keys[i])<=MAX_LEV_DISTANCE)){return false}}return true}function getQuery(raw){var matches,type,query;query=raw;matches=query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);if(matches){type=matches[1].replace(/^const$/,"constant");query=query.substring(matches[0].length)}return{raw:raw,query:query,type:type,id:query+type}}function nextTab(direction){var next=(searchState.currentTab+direction+3)%searchState.focusedByTab.length;searchState.focusedByTab[searchState.currentTab]=document.activeElement;printTab(next);focusSearchResult()}function focusSearchResult(){var target=searchState.focusedByTab[searchState.currentTab]||document.querySelectorAll(".search-results.active a").item(0)||document.querySelectorAll("#titles > button").item(searchState.currentTab);if(target){target.focus()}}function buildHrefAndPath(item){var displayPath;var href;var type=itemTypes[item.ty];var name=item.name;var path=item.path;if(type==="mod"){displayPath=path+"::";href=window.rootPath+path.replace(/::/g,"/")+"/"+name+"/index.html"}else if(type==="primitive"||type==="keyword"){displayPath="";href=window.rootPath+path.replace(/::/g,"/")+"/"+type+"."+name+".html"}else if(type==="externcrate"){displayPath="";href=window.rootPath+name+"/index.html"}else if(item.parent!==undefined){var myparent=item.parent;var anchor="#"+type+"."+name;var parentType=itemTypes[myparent.ty];var pageType=parentType;var pageName=myparent.name;if(parentType==="primitive"){displayPath=myparent.name+"::"}else if(type==="structfield"&&parentType==="variant"){var enumNameIdx=item.path.lastIndexOf("::");var enumName=item.path.substr(enumNameIdx+2);path=item.path.substr(0,enumNameIdx);displayPath=path+"::"+enumName+"::"+myparent.name+"::";anchor="#variant."+myparent.name+".field."+name;pageType="enum";pageName=enumName}else{displayPath=path+"::"+myparent.name+"::"}href=window.rootPath+path.replace(/::/g,"/")+"/"+pageType+"."+pageName+".html"+anchor}else{displayPath=item.path+"::";href=window.rootPath+item.path.replace(/::/g,"/")+"/"+type+"."+name+".html"}return[displayPath,href]}function escape(content){var h1=document.createElement("h1");h1.textContent=content;return h1.innerHTML}function pathSplitter(path){var tmp=""+path.replace(/::/g,"::");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}function addTab(array,query,display){var extraClass="";if(display===true){extraClass=" active"}var output=document.createElement("div");var duplicates={};var length=0;if(array.length>0){output.className="search-results "+extraClass;array.forEach(function(item){if(item.is_alias!==true){if(duplicates[item.fullPath]){return}duplicates[item.fullPath]=true}var name=item.name;var type=itemTypes[item.ty];length+=1;var extra="";if(type==="primitive"){extra=" (primitive type)"}else if(type==="keyword"){extra=" (keyword)"}var link=document.createElement("a");link.className="result-"+type;link.href=item.href;var wrapper=document.createElement("div");var resultName=document.createElement("div");resultName.className="result-name";if(item.is_alias){var alias=document.createElement("span");alias.className="alias";var bold=document.createElement("b");bold.innerText=item.alias;alias.appendChild(bold);alias.insertAdjacentHTML("beforeend"," - see ");resultName.appendChild(alias)}resultName.insertAdjacentHTML("beforeend",item.displayPath+""+name+extra+"");wrapper.appendChild(resultName);var description=document.createElement("div");description.className="desc";var spanDesc=document.createElement("span");spanDesc.insertAdjacentHTML("beforeend",item.desc);description.appendChild(spanDesc);wrapper.appendChild(description);link.appendChild(wrapper);output.appendChild(link)})}else{output.className="search-failed"+extraClass;output.innerHTML="No results :(
    "+"Try on DuckDuckGo?

    "+"Or try looking in one of these:"}return[output,length]}function makeTabHeader(tabNb,text,nbElems){if(searchState.currentTab===tabNb){return""}return""}function showResults(results,go_to_first){var search=searchState.outputElement();if(go_to_first||(results.others.length===1&&getSettingValue("go-to-only-result")==="true"&&(!search.firstChild||search.firstChild.innerText!==searchState.loadingText))){var elem=document.createElement("a");elem.href=results.others[0].href;removeClass(elem,"active");document.body.appendChild(elem);elem.click();return}var query=getQuery(searchState.input.value);currentResults=query.id;var ret_others=addTab(results.others,query);var ret_in_args=addTab(results.in_args,query,false);var ret_returned=addTab(results.returned,query,false);var currentTab=searchState.currentTab;if((currentTab===0&&ret_others[1]===0)||(currentTab===1&&ret_in_args[1]===0)||(currentTab===2&&ret_returned[1]===0)){if(ret_others[1]!==0){currentTab=0}else if(ret_in_args[1]!==0){currentTab=1}else if(ret_returned[1]!==0){currentTab=2}}var output="

    Results for "+escape(query.query)+(query.type?" (type: "+escape(query.type)+")":"")+"

    "+"
    "+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
    ";var resultsElem=document.createElement("div");resultsElem.id="results";resultsElem.appendChild(ret_others[0]);resultsElem.appendChild(ret_in_args[0]);resultsElem.appendChild(ret_returned[0]);search.innerHTML=output;search.appendChild(resultsElem);searchState.focusedByTab=[null,null,null];searchState.showResults(search);var elems=document.getElementById("titles").childNodes;elems[0].onclick=function(){printTab(0)};elems[1].onclick=function(){printTab(1)};elems[2].onclick=function(){printTab(2)};printTab(currentTab)}function execSearch(query,searchWords,filterCrates){function getSmallest(arrays,positions,notDuplicates){var start=null;for(var it=0,len=positions.length;itpositions[it]&&(start===null||start>arrays[it][positions[it]].lev)&&!notDuplicates[arrays[it][positions[it]].fullPath]){start=arrays[it][positions[it]].lev}}return start}function mergeArrays(arrays){var ret=[];var positions=[];var notDuplicates={};for(var x=0,arrays_len=arrays.length;xpositions[x]&&arrays[x][positions[x]].lev===smallest&&!notDuplicates[arrays[x][positions[x]].fullPath]){ret.push(arrays[x][positions[x]]);notDuplicates[arrays[x][positions[x]].fullPath]=true;positions[x]+=1}}}return ret}function tokenizeQuery(raw){var i,matched;var l=raw.length;var depth=0;var nextAngle=/(<|>)/g;var ret=[];var start=0;for(i=0;i'){depth+=1}break;case">":if(depth>0){depth-=1}break;case",":if(depth===0){ret.push(raw.substring(start,i));start=i+1}break}}if(start!==i){ret.push(raw.substring(start,i))}return ret}var queries=tokenizeQuery(query.raw);var results={"in_args":[],"returned":[],"others":[],};for(var i=0,len=queries.length;i1){return{"in_args":mergeArrays(results.in_args),"returned":mergeArrays(results.returned),"others":mergeArrays(results.others),}}return{"in_args":results.in_args[0],"returned":results.returned[0],"others":results.others[0],}}function getFilterCrates(){var elem=document.getElementById("crate-search");if(elem&&elem.value!=="All crates"&&hasOwnPropertyRustdoc(rawSearchIndex,elem.value)){return elem.value}return undefined}function search(e,forced){var params=searchState.getQueryStringParams();var query=getQuery(searchState.input.value.trim());if(e){e.preventDefault()}if(query.query.length===0){return}if(!forced&&query.id===currentResults){if(query.query.length>0){searchState.putBackSearch(searchState.input)}return}searchState.title="Results for "+query.query+" - Rust";if(searchState.browserSupportsHistoryApi()){var newURL=getNakedUrl()+"?search="+encodeURIComponent(query.raw)+window.location.hash;if(!history.state&&!params.search){history.pushState(query,"",newURL)}else{history.replaceState(query,"",newURL)}}var filterCrates=getFilterCrates();showResults(execSearch(query,index,filterCrates),params.go_to_first)}function buildIndex(rawSearchIndex){searchIndex=[];var searchWords=[];var i,word;var currentIndex=0;var id=0;for(var crate in rawSearchIndex){if(!hasOwnPropertyRustdoc(rawSearchIndex,crate)){continue}var crateSize=0;searchWords.push(crate);var crateRow={crate:crate,ty:1,name:crate,path:"",desc:rawSearchIndex[crate].doc,parent:undefined,type:null,id:id,normalizedName:crate.indexOf("_")===-1?crate:crate.replace(/_/g,""),};id+=1;searchIndex.push(crateRow);currentIndex+=1;var itemTypes=rawSearchIndex[crate].t;var itemNames=rawSearchIndex[crate].n;var itemPaths=rawSearchIndex[crate].q;var itemDescs=rawSearchIndex[crate].d;var itemParentIdxs=rawSearchIndex[crate].i;var itemFunctionSearchTypes=rawSearchIndex[crate].f;var paths=rawSearchIndex[crate].p;var aliases=rawSearchIndex[crate].a;var len=paths.length;for(i=0;i0?paths[itemParentIdxs[i]-1]:undefined,type:itemFunctionSearchTypes[i],id:id,normalizedName:word.indexOf("_")===-1?word:word.replace(/_/g,""),};id+=1;searchIndex.push(row);lastPath=row.path;crateSize+=1}if(aliases){ALIASES[crate]={};var j,local_aliases;for(var alias_name in aliases){if(!hasOwnPropertyRustdoc(aliases,alias_name)){continue}if(!hasOwnPropertyRustdoc(ALIASES[crate],alias_name)){ALIASES[crate][alias_name]=[]}local_aliases=aliases[alias_name];for(j=0,len=local_aliases.length;j0){searchState.input.value=params.search;search(e)}else{searchState.input.value="";searchState.hideResults()}})}window.onpageshow=function(){var qSearch=searchState.getQueryStringParams().search;if(searchState.input.value===""&&qSearch){searchState.input.value=qSearch}search()}}index=buildIndex(rawSearchIndex);registerSearchEvents();if(searchState.getQueryStringParams().search){search()}};if(window.searchIndex!==undefined){initSearch(window.searchIndex)}})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/settings.css b/static/docs-rs/bdk/nightly/latest/settings.css deleted file mode 100644 index 670986588e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/settings.css +++ /dev/null @@ -1 +0,0 @@ -.setting-line{padding:5px;position:relative;}.setting-line>div{display:inline-block;vertical-align:top;font-size:17px;padding-top:2px;}.setting-line>.title{font-size:19px;width:100%;max-width:none;border-bottom:1px solid;}.toggle{position:relative;display:inline-block;width:45px;height:27px;margin-right:20px;}.toggle input{opacity:0;position:absolute;}.select-wrapper{float:right;position:relative;height:27px;min-width:25%;}.select-wrapper select{appearance:none;-moz-appearance:none;-webkit-appearance:none;background:none;border:2px solid #ccc;padding-right:28px;width:100%;}.select-wrapper img{pointer-events:none;position:absolute;right:0;bottom:0;background:#ccc;height:100%;width:28px;padding:0px 4px;}.select-wrapper select option{color:initial;}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.3s;transition:.3s;}.slider:before{position:absolute;content:"";height:19px;width:19px;left:4px;bottom:4px;background-color:white;-webkit-transition:.3s;transition:.3s;}input:checked+.slider{background-color:#2196F3;}input:focus+.slider{box-shadow:0 0 0 2px #0a84ff,0 0 0 6px rgba(10,132,255,0.3);}input:checked+.slider:before{-webkit-transform:translateX(19px);-ms-transform:translateX(19px);transform:translateX(19px);}.setting-line>.sub-settings{padding-left:42px;width:100%;display:block;} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/settings.html b/static/docs-rs/bdk/nightly/latest/settings.html deleted file mode 100644 index e04d80ec2e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/settings.html +++ /dev/null @@ -1,4 +0,0 @@ -Rustdoc settings

    Rustdoc settings

    Theme preferences
    Use system theme
    Preferred dark theme
    Preferred light theme
    -
    Auto-hide item contents for large items.
    Auto-hide item methods' documentation
    Auto-hide trait implementation documentation
    Directly go to item in search if there is only one result
    Show line numbers on code examples
    Disable keyboard shortcuts
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/settings.js b/static/docs-rs/bdk/nightly/latest/settings.js deleted file mode 100644 index b4d6fdcd78..0000000000 --- a/static/docs-rs/bdk/nightly/latest/settings.js +++ /dev/null @@ -1 +0,0 @@ -(function(){function changeSetting(settingName,value){updateLocalStorage("rustdoc-"+settingName,value);switch(settingName){case"preferred-dark-theme":case"preferred-light-theme":case"use-system-theme":updateSystemTheme();break}}function handleKey(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey){return}switch(getVirtualKey(ev)){case"Enter":case"Return":case"Space":ev.target.checked=!ev.target.checked;ev.preventDefault();break}}function setEvents(){onEachLazy(document.getElementsByClassName("slider"),function(elem){var toggle=elem.previousElementSibling;var settingId=toggle.id;var settingValue=getSettingValue(settingId);if(settingValue!==null){toggle.checked=settingValue==="true"}toggle.onchange=function(){changeSetting(this.id,this.checked)};toggle.onkeyup=handleKey;toggle.onkeyrelease=handleKey});onEachLazy(document.getElementsByClassName("select-wrapper"),function(elem){var select=elem.getElementsByTagName("select")[0];var settingId=select.id;var settingValue=getSettingValue(settingId);if(settingValue!==null){select.value=settingValue}select.onchange=function(){changeSetting(this.id,this.value)}})}window.addEventListener("DOMContentLoaded",setEvents)})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/source-files.js b/static/docs-rs/bdk/nightly/latest/source-files.js deleted file mode 100644 index 34aad7c3a4..0000000000 --- a/static/docs-rs/bdk/nightly/latest/source-files.js +++ /dev/null @@ -1,3 +0,0 @@ -var N = null;var sourcesIndex = {}; -sourcesIndex["bdk"] = {"name":"","dirs":[{"name":"blockchain","dirs":[{"name":"compact_filters","files":["mod.rs","peer.rs","store.rs","sync.rs"]},{"name":"esplora","files":["mod.rs","ureq.rs"]}],"files":["any.rs","electrum.rs","mod.rs","utils.rs"]},{"name":"database","files":["any.rs","keyvalue.rs","memory.rs","mod.rs","sqlite.rs"]},{"name":"descriptor","files":["checksum.rs","derived.rs","dsl.rs","error.rs","mod.rs","policy.rs","template.rs"]},{"name":"keys","files":["bip39.rs","mod.rs"]},{"name":"psbt","files":["mod.rs"]},{"name":"testutils","files":["mod.rs"]},{"name":"wallet","files":["address_validator.rs","coin_selection.rs","export.rs","mod.rs","signer.rs","time.rs","tx_builder.rs","utils.rs"]}],"files":["error.rs","lib.rs","types.rs"]}; -createSourceSidebar(); diff --git a/static/docs-rs/bdk/nightly/latest/source-script.js b/static/docs-rs/bdk/nightly/latest/source-script.js deleted file mode 100644 index 5dc8fee0f2..0000000000 --- a/static/docs-rs/bdk/nightly/latest/source-script.js +++ /dev/null @@ -1 +0,0 @@ -(function(){function getCurrentFilePath(){var parts=window.location.pathname.split("/");var rootPathParts=window.rootPath.split("/");for(var i=0,len=rootPathParts.length;i"){sidebar.style.left="";this.style.left="";child.innerText="<";updateLocalStorage("rustdoc-source-sidebar-show","true")}else{sidebar.style.left="-300px";this.style.left="0";child.innerText=">";updateLocalStorage("rustdoc-source-sidebar-show","false")}}function createSidebarToggle(){var sidebarToggle=document.createElement("div");sidebarToggle.id="sidebar-toggle";sidebarToggle.onclick=toggleSidebar;var inner1=document.createElement("div");inner1.style.position="relative";var inner2=document.createElement("div");inner2.style.paddingTop="3px";if(getCurrentValue("rustdoc-source-sidebar-show")==="true"){inner2.innerText="<"}else{inner2.innerText=">";sidebarToggle.style.left="0"}inner1.appendChild(inner2);sidebarToggle.appendChild(inner1);return sidebarToggle}function createSourceSidebar(){if(!window.rootPath.endsWith("/")){window.rootPath+="/"}var main=document.getElementById("main");var sidebarToggle=createSidebarToggle();main.insertBefore(sidebarToggle,main.firstChild);var sidebar=document.createElement("div");sidebar.id="source-sidebar";if(getCurrentValue("rustdoc-source-sidebar-show")!=="true"){sidebar.style.left="-300px"}var currentFile=getCurrentFilePath();var hasFoundFile=false;var title=document.createElement("div");title.className="title";title.innerText="Files";sidebar.appendChild(title);Object.keys(sourcesIndex).forEach(function(key){sourcesIndex[key].name=key;hasFoundFile=createDirEntry(sourcesIndex[key],sidebar,"",currentFile,hasFoundFile)});main.insertBefore(sidebar,main.firstChild);var selected_elem=sidebar.getElementsByClassName("selected")[0];if(typeof selected_elem!=="undefined"){selected_elem.focus()}}var lineNumbersRegex=/^#?(\d+)(?:-(\d+))?$/;function highlightSourceLines(scrollTo,match){if(typeof match==="undefined"){match=window.location.hash.match(lineNumbersRegex)}if(!match){return}var from=parseInt(match[1],10);var to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(tocur_line_id){var tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());window.addEventListener("hashchange",function(){var match=window.location.hash.match(lineNumbersRegex);if(match){return highlightSourceLines(false,match)}});onEachLazy(document.getElementsByClassName("line-numbers"),function(el){el.addEventListener("click",handleSourceHighlight)});highlightSourceLines(true);window.createSourceSidebar=createSourceSidebar})() \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/any.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/any.rs.html deleted file mode 100644 index 977b1afcca..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/any.rs.html +++ /dev/null @@ -1,510 +0,0 @@ -any.rs - source
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Runtime-checked blockchain types
    -//!
    -//! This module provides the implementation of [`AnyBlockchain`] which allows switching the
    -//! inner [`Blockchain`] type at runtime.
    -//!
    -//! ## Example
    -//!
    -//! In this example both `wallet_electrum` and `wallet_esplora` have the same type of
    -//! `Wallet<AnyBlockchain, MemoryDatabase>`. This means that they could both, for instance, be
    -//! assigned to a struct member.
    -//!
    -//! ```no_run
    -//! # use bitcoin::Network;
    -//! # use bdk::blockchain::*;
    -//! # use bdk::database::MemoryDatabase;
    -//! # use bdk::Wallet;
    -//! # #[cfg(feature = "electrum")]
    -//! # {
    -//! let electrum_blockchain = ElectrumBlockchain::from(electrum_client::Client::new("...")?);
    -//! let wallet_electrum: Wallet<AnyBlockchain, _> = Wallet::new(
    -//!     "...",
    -//!     None,
    -//!     Network::Testnet,
    -//!     MemoryDatabase::default(),
    -//!     electrum_blockchain.into(),
    -//! )?;
    -//! # }
    -//!
    -//! # #[cfg(all(feature = "esplora", feature = "ureq"))]
    -//! # {
    -//! let esplora_blockchain = EsploraBlockchain::new("...", 20);
    -//! let wallet_esplora: Wallet<AnyBlockchain, _> = Wallet::new(
    -//!     "...",
    -//!     None,
    -//!     Network::Testnet,
    -//!     MemoryDatabase::default(),
    -//!     esplora_blockchain.into(),
    -//! )?;
    -//! # }
    -//!
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -//!
    -//! When paired with the use of [`ConfigurableBlockchain`], it allows creating wallets with any
    -//! blockchain type supported using a single line of code:
    -//!
    -//! ```no_run
    -//! # use bitcoin::Network;
    -//! # use bdk::blockchain::*;
    -//! # use bdk::database::MemoryDatabase;
    -//! # use bdk::Wallet;
    -//! # #[cfg(all(feature = "esplora", feature = "ureq"))]
    -//! # {
    -//! let config = serde_json::from_str("...")?;
    -//! let blockchain = AnyBlockchain::from_config(&config)?;
    -//! let wallet = Wallet::new(
    -//!     "...",
    -//!     None,
    -//!     Network::Testnet,
    -//!     MemoryDatabase::default(),
    -//!     blockchain,
    -//! )?;
    -//! # }
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use super::*;
    -
    -macro_rules! impl_from {
    -    ( $from:ty, $to:ty, $variant:ident, $( $cfg:tt )* ) => {
    -        $( $cfg )*
    -        impl From<$from> for $to {
    -            fn from(inner: $from) -> Self {
    -                <$to>::$variant(inner)
    -            }
    -        }
    -    };
    -}
    -
    -macro_rules! impl_inner_method {
    -    ( $self:expr, $name:ident $(, $args:expr)* ) => {
    -        match $self {
    -            #[cfg(feature = "electrum")]
    -            AnyBlockchain::Electrum(inner) => inner.$name( $($args, )* ),
    -            #[cfg(feature = "esplora")]
    -            AnyBlockchain::Esplora(inner) => inner.$name( $($args, )* ),
    -            #[cfg(feature = "compact_filters")]
    -            AnyBlockchain::CompactFilters(inner) => inner.$name( $($args, )* ),
    -            #[cfg(feature = "rpc")]
    -            AnyBlockchain::Rpc(inner) => inner.$name( $($args, )* ),
    -        }
    -    }
    -}
    -
    -/// Type that can contain any of the [`Blockchain`] types defined by the library
    -///
    -/// It allows switching backend at runtime
    -///
    -/// See [this module](crate::blockchain::any)'s documentation for a usage example.
    -pub enum AnyBlockchain {
    -    #[cfg(feature = "electrum")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
    -    /// Electrum client
    -    Electrum(electrum::ElectrumBlockchain),
    -    #[cfg(feature = "esplora")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
    -    /// Esplora client
    -    Esplora(esplora::EsploraBlockchain),
    -    #[cfg(feature = "compact_filters")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
    -    /// Compact filters client
    -    CompactFilters(compact_filters::CompactFiltersBlockchain),
    -    #[cfg(feature = "rpc")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "rpc")))]
    -    /// RPC client
    -    Rpc(rpc::RpcBlockchain),
    -}
    -
    -#[maybe_async]
    -impl Blockchain for AnyBlockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        maybe_await!(impl_inner_method!(self, get_capabilities))
    -    }
    -
    -    fn setup<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        maybe_await!(impl_inner_method!(self, setup, database, progress_update))
    -    }
    -    fn sync<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        maybe_await!(impl_inner_method!(self, sync, database, progress_update))
    -    }
    -
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        maybe_await!(impl_inner_method!(self, get_tx, txid))
    -    }
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        maybe_await!(impl_inner_method!(self, broadcast, tx))
    -    }
    -
    -    fn get_height(&self) -> Result<u32, Error> {
    -        maybe_await!(impl_inner_method!(self, get_height))
    -    }
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
    -        maybe_await!(impl_inner_method!(self, estimate_fee, target))
    -    }
    -}
    -
    -impl_from!(electrum::ElectrumBlockchain, AnyBlockchain, Electrum, #[cfg(feature = "electrum")]);
    -impl_from!(esplora::EsploraBlockchain, AnyBlockchain, Esplora, #[cfg(feature = "esplora")]);
    -impl_from!(compact_filters::CompactFiltersBlockchain, AnyBlockchain, CompactFilters, #[cfg(feature = "compact_filters")]);
    -impl_from!(rpc::RpcBlockchain, AnyBlockchain, Rpc, #[cfg(feature = "rpc")]);
    -
    -/// Type that can contain any of the blockchain configurations defined by the library
    -///
    -/// This allows storing a single configuration that can be loaded into an [`AnyBlockchain`]
    -/// instance. Wallets that plan to offer users the ability to switch blockchain backend at runtime
    -/// will find this particularly useful.
    -///
    -/// This type can be serialized from a JSON object like:
    -///
    -/// ```
    -/// # #[cfg(feature = "electrum")]
    -/// # {
    -/// use bdk::blockchain::{electrum::ElectrumBlockchainConfig, AnyBlockchainConfig};
    -/// let config: AnyBlockchainConfig = serde_json::from_str(
    -///     r#"{
    -///    "type" : "electrum",
    -///    "url" : "ssl://electrum.blockstream.info:50002",
    -///    "retry": 2,
    -///    "stop_gap": 20
    -/// }"#,
    -/// )
    -/// .unwrap();
    -/// assert_eq!(
    -///     config,
    -///     AnyBlockchainConfig::Electrum(ElectrumBlockchainConfig {
    -///         url: "ssl://electrum.blockstream.info:50002".into(),
    -///         retry: 2,
    -///         socks5: None,
    -///         timeout: None,
    -///         stop_gap: 20,
    -///     })
    -/// );
    -/// # }
    -/// ```
    -#[derive(Debug, serde::Serialize, serde::Deserialize, Clone, PartialEq)]
    -#[serde(tag = "type", rename_all = "snake_case")]
    -pub enum AnyBlockchainConfig {
    -    #[cfg(feature = "electrum")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
    -    /// Electrum client
    -    Electrum(electrum::ElectrumBlockchainConfig),
    -    #[cfg(feature = "esplora")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
    -    /// Esplora client
    -    Esplora(esplora::EsploraBlockchainConfig),
    -    #[cfg(feature = "compact_filters")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
    -    /// Compact filters client
    -    CompactFilters(compact_filters::CompactFiltersBlockchainConfig),
    -    #[cfg(feature = "rpc")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "rpc")))]
    -    /// RPC client configuration
    -    Rpc(rpc::RpcConfig),
    -}
    -
    -impl ConfigurableBlockchain for AnyBlockchain {
    -    type Config = AnyBlockchainConfig;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        Ok(match config {
    -            #[cfg(feature = "electrum")]
    -            AnyBlockchainConfig::Electrum(inner) => {
    -                AnyBlockchain::Electrum(electrum::ElectrumBlockchain::from_config(inner)?)
    -            }
    -            #[cfg(feature = "esplora")]
    -            AnyBlockchainConfig::Esplora(inner) => {
    -                AnyBlockchain::Esplora(esplora::EsploraBlockchain::from_config(inner)?)
    -            }
    -            #[cfg(feature = "compact_filters")]
    -            AnyBlockchainConfig::CompactFilters(inner) => AnyBlockchain::CompactFilters(
    -                compact_filters::CompactFiltersBlockchain::from_config(inner)?,
    -            ),
    -            #[cfg(feature = "rpc")]
    -            AnyBlockchainConfig::Rpc(inner) => {
    -                AnyBlockchain::Rpc(rpc::RpcBlockchain::from_config(inner)?)
    -            }
    -        })
    -    }
    -}
    -
    -impl_from!(electrum::ElectrumBlockchainConfig, AnyBlockchainConfig, Electrum, #[cfg(feature = "electrum")]);
    -impl_from!(esplora::EsploraBlockchainConfig, AnyBlockchainConfig, Esplora, #[cfg(feature = "esplora")]);
    -impl_from!(compact_filters::CompactFiltersBlockchainConfig, AnyBlockchainConfig, CompactFilters, #[cfg(feature = "compact_filters")]);
    -impl_from!(rpc::RpcConfig, AnyBlockchainConfig, Rpc, #[cfg(feature = "rpc")]);
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/mod.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/mod.rs.html deleted file mode 100644 index 4927399c69..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/mod.rs.html +++ /dev/null @@ -1,1140 +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
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Compact Filters
    -//!
    -//! This module contains a multithreaded implementation of an [`Blockchain`] backend that
    -//! uses BIP157 (aka "Neutrino") to populate the wallet's [database](crate::database::Database)
    -//! by downloading compact filters from the P2P network.
    -//!
    -//! Since there are currently very few peers "in the wild" that advertise the required service
    -//! flag, this implementation requires that one or more known peers are provided by the user.
    -//! No dns or other kinds of peer discovery are done internally.
    -//!
    -//! Moreover, this module doesn't currently support detecting and resolving conflicts between
    -//! messages received by different peers. Thus, it's recommended to use this module by only
    -//! connecting to a single peer at a time, optionally by opening multiple connections if it's
    -//! desirable to use multiple threads at once to sync in parallel.
    -//!
    -//! This is an **EXPERIMENTAL** feature, API and other major changes are expected.
    -//!
    -//! ## Example
    -//!
    -//! ```no_run
    -//! # use std::sync::Arc;
    -//! # use bitcoin::*;
    -//! # use bdk::*;
    -//! # use bdk::blockchain::compact_filters::*;
    -//! let num_threads = 4;
    -//!
    -//! let mempool = Arc::new(Mempool::default());
    -//! let peers = (0..num_threads)
    -//!     .map(|_| {
    -//!         Peer::connect(
    -//!             "btcd-mainnet.lightning.computer:8333",
    -//!             Arc::clone(&mempool),
    -//!             Network::Bitcoin,
    -//!         )
    -//!     })
    -//!     .collect::<Result<_, _>>()?;
    -//! let blockchain = CompactFiltersBlockchain::new(peers, "./wallet-filters", Some(500_000))?;
    -//! # Ok::<(), CompactFiltersError>(())
    -//! ```
    -
    -use std::collections::HashSet;
    -use std::fmt;
    -use std::path::Path;
    -use std::sync::atomic::{AtomicUsize, Ordering};
    -use std::sync::{Arc, Mutex};
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -use bitcoin::network::message_blockdata::Inventory;
    -use bitcoin::{Network, OutPoint, Transaction, Txid};
    -
    -use rocksdb::{Options, SliceTransform, DB};
    -
    -mod peer;
    -mod store;
    -mod sync;
    -
    -use super::{Blockchain, Capability, ConfigurableBlockchain, Progress};
    -use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
    -use crate::error::Error;
    -use crate::types::{KeychainKind, LocalUtxo, TransactionDetails};
    -use crate::{ConfirmationTime, FeeRate};
    -
    -use peer::*;
    -use store::*;
    -use sync::*;
    -
    -pub use peer::{Mempool, Peer};
    -
    -const SYNC_HEADERS_COST: f32 = 1.0;
    -const SYNC_FILTERS_COST: f32 = 11.6 * 1_000.0;
    -const PROCESS_BLOCKS_COST: f32 = 20_000.0;
    -
    -/// Structure implementing the required blockchain traits
    -///
    -/// ## Example
    -/// See the [`blockchain::compact_filters`](crate::blockchain::compact_filters) module for a usage example.
    -#[derive(Debug)]
    -pub struct CompactFiltersBlockchain {
    -    peers: Vec<Arc<Peer>>,
    -    headers: Arc<ChainStore<Full>>,
    -    skip_blocks: Option<usize>,
    -}
    -
    -impl CompactFiltersBlockchain {
    -    /// Construct a new instance given a list of peers, a path to store headers and block
    -    /// filters downloaded during the sync and optionally a number of blocks to ignore starting
    -    /// from the genesis while scanning for the wallet's outputs.
    -    ///
    -    /// For each [`Peer`] specified a new thread will be spawned to download and verify the filters
    -    /// in parallel. It's currently recommended to only connect to a single peer to avoid
    -    /// inconsistencies in the data returned, optionally with multiple connections in parallel to
    -    /// speed-up the sync process.
    -    pub fn new<P: AsRef<Path>>(
    -        peers: Vec<Peer>,
    -        storage_dir: P,
    -        skip_blocks: Option<usize>,
    -    ) -> Result<Self, CompactFiltersError> {
    -        if peers.is_empty() {
    -            return Err(CompactFiltersError::NoPeers);
    -        }
    -
    -        let mut opts = Options::default();
    -        opts.create_if_missing(true);
    -        opts.set_prefix_extractor(SliceTransform::create_fixed_prefix(16));
    -
    -        let network = peers[0].get_network();
    -
    -        let cfs = DB::list_cf(&opts, &storage_dir).unwrap_or_else(|_| vec!["default".to_string()]);
    -        let db = DB::open_cf(&opts, &storage_dir, &cfs)?;
    -        let headers = Arc::new(ChainStore::new(db, network)?);
    -
    -        // try to recover partial snapshots
    -        for cf_name in &cfs {
    -            if !cf_name.starts_with("_headers:") {
    -                continue;
    -            }
    -
    -            info!("Trying to recover: {:?}", cf_name);
    -            headers.recover_snapshot(cf_name)?;
    -        }
    -
    -        Ok(CompactFiltersBlockchain {
    -            peers: peers.into_iter().map(Arc::new).collect(),
    -            headers,
    -            skip_blocks,
    -        })
    -    }
    -
    -    /// Process a transaction by looking for inputs that spend from a UTXO in the database or
    -    /// outputs that send funds to a know script_pubkey.
    -    fn process_tx<D: BatchDatabase>(
    -        &self,
    -        database: &mut D,
    -        tx: &Transaction,
    -        height: Option<u32>,
    -        timestamp: Option<u64>,
    -        internal_max_deriv: &mut Option<u32>,
    -        external_max_deriv: &mut Option<u32>,
    -    ) -> Result<(), Error> {
    -        let mut updates = database.begin_batch();
    -
    -        let mut incoming: u64 = 0;
    -        let mut outgoing: u64 = 0;
    -
    -        let mut inputs_sum: u64 = 0;
    -        let mut outputs_sum: u64 = 0;
    -
    -        // look for our own inputs
    -        for (i, input) in tx.input.iter().enumerate() {
    -            if let Some(previous_output) = database.get_previous_output(&input.previous_output)? {
    -                inputs_sum += previous_output.value;
    -
    -                if database.is_mine(&previous_output.script_pubkey)? {
    -                    outgoing += previous_output.value;
    -
    -                    debug!("{} input #{} is mine, removing from utxo", tx.txid(), i);
    -                    updates.del_utxo(&input.previous_output)?;
    -                }
    -            }
    -        }
    -
    -        for (i, output) in tx.output.iter().enumerate() {
    -            // to compute the fees later
    -            outputs_sum += output.value;
    -
    -            // this output is ours, we have a path to derive it
    -            if let Some((keychain, child)) =
    -                database.get_path_from_script_pubkey(&output.script_pubkey)?
    -            {
    -                debug!("{} output #{} is mine, adding utxo", tx.txid(), i);
    -                updates.set_utxo(&LocalUtxo {
    -                    outpoint: OutPoint::new(tx.txid(), i as u32),
    -                    txout: output.clone(),
    -                    keychain,
    -                })?;
    -                incoming += output.value;
    -
    -                if keychain == KeychainKind::Internal
    -                    && (internal_max_deriv.is_none() || child > internal_max_deriv.unwrap_or(0))
    -                {
    -                    *internal_max_deriv = Some(child);
    -                } else if keychain == KeychainKind::External
    -                    && (external_max_deriv.is_none() || child > external_max_deriv.unwrap_or(0))
    -                {
    -                    *external_max_deriv = Some(child);
    -                }
    -            }
    -        }
    -
    -        if incoming > 0 || outgoing > 0 {
    -            let tx = TransactionDetails {
    -                txid: tx.txid(),
    -                transaction: Some(tx.clone()),
    -                received: incoming,
    -                sent: outgoing,
    -                confirmation_time: ConfirmationTime::new(height, timestamp),
    -                verified: height.is_some(),
    -                fee: Some(inputs_sum.saturating_sub(outputs_sum)),
    -            };
    -
    -            info!("Saving tx {}", tx.txid);
    -            updates.set_tx(&tx)?;
    -        }
    -
    -        database.commit_batch(updates)?;
    -
    -        Ok(())
    -    }
    -}
    -
    -impl Blockchain for CompactFiltersBlockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        vec![Capability::FullHistory].into_iter().collect()
    -    }
    -
    -    #[allow(clippy::mutex_atomic)] // Mutex is easier to understand than a CAS loop.
    -    fn setup<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        let first_peer = &self.peers[0];
    -
    -        let skip_blocks = self.skip_blocks.unwrap_or(0);
    -
    -        let cf_sync = Arc::new(CfSync::new(Arc::clone(&self.headers), skip_blocks, 0x00)?);
    -
    -        let initial_height = self.headers.get_height()?;
    -        let total_bundles = (first_peer.get_version().start_height as usize)
    -            .checked_sub(skip_blocks)
    -            .map(|x| x / 1000)
    -            .unwrap_or(0)
    -            + 1;
    -        let expected_bundles_to_sync = total_bundles.saturating_sub(cf_sync.pruned_bundles()?);
    -
    -        let headers_cost = (first_peer.get_version().start_height as usize)
    -            .saturating_sub(initial_height) as f32
    -            * SYNC_HEADERS_COST;
    -        let filters_cost = expected_bundles_to_sync as f32 * SYNC_FILTERS_COST;
    -
    -        let total_cost = headers_cost + filters_cost + PROCESS_BLOCKS_COST;
    -
    -        if let Some(snapshot) = sync::sync_headers(
    -            Arc::clone(&first_peer),
    -            Arc::clone(&self.headers),
    -            |new_height| {
    -                let local_headers_cost =
    -                    new_height.saturating_sub(initial_height) as f32 * SYNC_HEADERS_COST;
    -                progress_update.update(
    -                    local_headers_cost / total_cost * 100.0,
    -                    Some(format!("Synced headers to {}", new_height)),
    -                )
    -            },
    -        )? {
    -            if snapshot.work()? > self.headers.work()? {
    -                info!("Applying snapshot with work: {}", snapshot.work()?);
    -                self.headers.apply_snapshot(snapshot)?;
    -            }
    -        }
    -
    -        let synced_height = self.headers.get_height()?;
    -        let buried_height = synced_height.saturating_sub(sync::BURIED_CONFIRMATIONS);
    -        info!("Synced headers to height: {}", synced_height);
    -
    -        cf_sync.prepare_sync(Arc::clone(&first_peer))?;
    -
    -        let all_scripts = Arc::new(
    -            database
    -                .iter_script_pubkeys(None)?
    -                .into_iter()
    -                .map(|s| s.to_bytes())
    -                .collect::<Vec<_>>(),
    -        );
    -
    -        #[allow(clippy::mutex_atomic)]
    -        let last_synced_block = Arc::new(Mutex::new(synced_height));
    -
    -        let synced_bundles = Arc::new(AtomicUsize::new(0));
    -        let progress_update = Arc::new(Mutex::new(progress_update));
    -
    -        let mut threads = Vec::with_capacity(self.peers.len());
    -        for peer in &self.peers {
    -            let cf_sync = Arc::clone(&cf_sync);
    -            let peer = Arc::clone(&peer);
    -            let headers = Arc::clone(&self.headers);
    -            let all_scripts = Arc::clone(&all_scripts);
    -            let last_synced_block = Arc::clone(&last_synced_block);
    -            let progress_update = Arc::clone(&progress_update);
    -            let synced_bundles = Arc::clone(&synced_bundles);
    -
    -            let thread = std::thread::spawn(move || {
    -                cf_sync.capture_thread_for_sync(
    -                    peer,
    -                    |block_hash, filter| {
    -                        if !filter
    -                            .match_any(block_hash, &mut all_scripts.iter().map(AsRef::as_ref))?
    -                        {
    -                            return Ok(false);
    -                        }
    -
    -                        let block_height = headers.get_height_for(block_hash)?.unwrap_or(0);
    -                        let saved_correct_block = matches!(headers.get_full_block(block_height)?, Some(block) if &block.block_hash() == block_hash);
    -
    -                        if saved_correct_block {
    -                            Ok(false)
    -                        } else {
    -                            let mut last_synced_block = last_synced_block.lock().unwrap();
    -
    -                            // If we download a block older than `last_synced_block`, we update it so that
    -                            // we know to delete and re-process all txs starting from that height
    -                            if block_height < *last_synced_block {
    -                                *last_synced_block = block_height;
    -                            }
    -
    -                            Ok(true)
    -                        }
    -                    },
    -                    |index| {
    -                        let synced_bundles = synced_bundles.fetch_add(1, Ordering::SeqCst);
    -                        let local_filters_cost = synced_bundles as f32 * SYNC_FILTERS_COST;
    -                        progress_update.lock().unwrap().update(
    -                            (headers_cost + local_filters_cost) / total_cost * 100.0,
    -                            Some(format!(
    -                                "Synced filters {} - {}",
    -                                index * 1000 + 1,
    -                                (index + 1) * 1000
    -                            )),
    -                        )
    -                    },
    -                )
    -            });
    -
    -            threads.push(thread);
    -        }
    -
    -        for t in threads {
    -            t.join().unwrap()?;
    -        }
    -
    -        progress_update.lock().unwrap().update(
    -            (headers_cost + filters_cost) / total_cost * 100.0,
    -            Some("Processing downloaded blocks and mempool".into()),
    -        )?;
    -
    -        // delete all txs newer than last_synced_block
    -        let last_synced_block = *last_synced_block.lock().unwrap();
    -        log::debug!(
    -            "Dropping transactions newer than `last_synced_block` = {}",
    -            last_synced_block
    -        );
    -        let mut updates = database.begin_batch();
    -        for details in database.iter_txs(false)? {
    -            match details.confirmation_time {
    -                Some(c) if (c.height as usize) < last_synced_block => continue,
    -                _ => updates.del_tx(&details.txid, false)?,
    -            };
    -        }
    -        database.commit_batch(updates)?;
    -
    -        match first_peer.ask_for_mempool() {
    -            Err(CompactFiltersError::PeerBloomDisabled) => {
    -                log::warn!("Peer has BLOOM disabled, we can't ask for the mempool")
    -            }
    -            e => e?,
    -        };
    -
    -        let mut internal_max_deriv = None;
    -        let mut external_max_deriv = None;
    -
    -        for (height, block) in self.headers.iter_full_blocks()? {
    -            for tx in &block.txdata {
    -                self.process_tx(
    -                    database,
    -                    tx,
    -                    Some(height as u32),
    -                    None,
    -                    &mut internal_max_deriv,
    -                    &mut external_max_deriv,
    -                )?;
    -            }
    -        }
    -        for tx in first_peer.get_mempool().iter_txs().iter() {
    -            self.process_tx(
    -                database,
    -                tx,
    -                None,
    -                None,
    -                &mut internal_max_deriv,
    -                &mut external_max_deriv,
    -            )?;
    -        }
    -
    -        let current_ext = database
    -            .get_last_index(KeychainKind::External)?
    -            .unwrap_or(0);
    -        let first_ext_new = external_max_deriv.map(|x| x + 1).unwrap_or(0);
    -        if first_ext_new > current_ext {
    -            info!("Setting external index to {}", first_ext_new);
    -            database.set_last_index(KeychainKind::External, first_ext_new)?;
    -        }
    -
    -        let current_int = database
    -            .get_last_index(KeychainKind::Internal)?
    -            .unwrap_or(0);
    -        let first_int_new = internal_max_deriv.map(|x| x + 1).unwrap_or(0);
    -        if first_int_new > current_int {
    -            info!("Setting internal index to {}", first_int_new);
    -            database.set_last_index(KeychainKind::Internal, first_int_new)?;
    -        }
    -
    -        info!("Dropping blocks until {}", buried_height);
    -        self.headers.delete_blocks_until(buried_height)?;
    -
    -        progress_update
    -            .lock()
    -            .unwrap()
    -            .update(100.0, Some("Done".into()))?;
    -
    -        Ok(())
    -    }
    -
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        Ok(self.peers[0]
    -            .get_mempool()
    -            .get_tx(&Inventory::Transaction(*txid)))
    -    }
    -
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        self.peers[0].broadcast_tx(tx.clone())?;
    -
    -        Ok(())
    -    }
    -
    -    fn get_height(&self) -> Result<u32, Error> {
    -        Ok(self.headers.get_height()? as u32)
    -    }
    -
    -    fn estimate_fee(&self, _target: usize) -> Result<FeeRate, Error> {
    -        // TODO
    -        Ok(FeeRate::default())
    -    }
    -}
    -
    -/// Data to connect to a Bitcoin P2P peer
    -#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq)]
    -pub struct BitcoinPeerConfig {
    -    /// Peer address such as 127.0.0.1:18333
    -    pub address: String,
    -    /// Optional socks5 proxy
    -    pub socks5: Option<String>,
    -    /// Optional socks5 proxy credentials
    -    pub socks5_credentials: Option<(String, String)>,
    -}
    -
    -/// Configuration for a [`CompactFiltersBlockchain`]
    -#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq)]
    -pub struct CompactFiltersBlockchainConfig {
    -    /// List of peers to try to connect to for asking headers and filters
    -    pub peers: Vec<BitcoinPeerConfig>,
    -    /// Network used
    -    pub network: Network,
    -    /// Storage dir to save partially downloaded headers and full blocks
    -    pub storage_dir: String,
    -    /// Optionally skip initial `skip_blocks` blocks (default: 0)
    -    pub skip_blocks: Option<usize>,
    -}
    -
    -impl ConfigurableBlockchain for CompactFiltersBlockchain {
    -    type Config = CompactFiltersBlockchainConfig;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        let mempool = Arc::new(Mempool::default());
    -        let peers = config
    -            .peers
    -            .iter()
    -            .map(|peer_conf| match &peer_conf.socks5 {
    -                None => Peer::connect(&peer_conf.address, Arc::clone(&mempool), config.network),
    -                Some(proxy) => Peer::connect_proxy(
    -                    peer_conf.address.as_str(),
    -                    proxy,
    -                    peer_conf
    -                        .socks5_credentials
    -                        .as_ref()
    -                        .map(|(a, b)| (a.as_str(), b.as_str())),
    -                    Arc::clone(&mempool),
    -                    config.network,
    -                ),
    -            })
    -            .collect::<Result<_, _>>()?;
    -
    -        Ok(CompactFiltersBlockchain::new(
    -            peers,
    -            &config.storage_dir,
    -            config.skip_blocks,
    -        )?)
    -    }
    -}
    -
    -/// An error that can occur during sync with a [`CompactFiltersBlockchain`]
    -#[derive(Debug)]
    -pub enum CompactFiltersError {
    -    /// A peer sent an invalid or unexpected response
    -    InvalidResponse,
    -    /// The headers returned are invalid
    -    InvalidHeaders,
    -    /// The compact filter headers returned are invalid
    -    InvalidFilterHeader,
    -    /// The compact filter returned is invalid
    -    InvalidFilter,
    -    /// The peer is missing a block in the valid chain
    -    MissingBlock,
    -    /// The data stored in the block filters storage are corrupted
    -    DataCorruption,
    -
    -    /// A peer is not connected
    -    NotConnected,
    -    /// A peer took too long to reply to one of our messages
    -    Timeout,
    -    /// The peer doesn't advertise the [`BLOOM`](bitcoin::network::constants::ServiceFlags::BLOOM) service flag
    -    PeerBloomDisabled,
    -
    -    /// No peers have been specified
    -    NoPeers,
    -
    -    /// Internal database error
    -    Db(rocksdb::Error),
    -    /// Internal I/O error
    -    Io(std::io::Error),
    -    /// Invalid BIP158 filter
    -    Bip158(bitcoin::util::bip158::Error),
    -    /// Internal system time error
    -    Time(std::time::SystemTimeError),
    -
    -    /// Wrapper for [`crate::error::Error`]
    -    Global(Box<crate::error::Error>),
    -}
    -
    -impl fmt::Display for CompactFiltersError {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for CompactFiltersError {}
    -
    -impl_error!(rocksdb::Error, Db, CompactFiltersError);
    -impl_error!(std::io::Error, Io, CompactFiltersError);
    -impl_error!(bitcoin::util::bip158::Error, Bip158, CompactFiltersError);
    -impl_error!(std::time::SystemTimeError, Time, CompactFiltersError);
    -
    -impl From<crate::error::Error> for CompactFiltersError {
    -    fn from(err: crate::error::Error) -> Self {
    -        CompactFiltersError::Global(Box::new(err))
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/peer.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/peer.rs.html deleted file mode 100644 index c9f3b00e9c..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/peer.rs.html +++ /dev/null @@ -1,1148 +0,0 @@ -peer.rs - source
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -482
    -483
    -484
    -485
    -486
    -487
    -488
    -489
    -490
    -491
    -492
    -493
    -494
    -495
    -496
    -497
    -498
    -499
    -500
    -501
    -502
    -503
    -504
    -505
    -506
    -507
    -508
    -509
    -510
    -511
    -512
    -513
    -514
    -515
    -516
    -517
    -518
    -519
    -520
    -521
    -522
    -523
    -524
    -525
    -526
    -527
    -528
    -529
    -530
    -531
    -532
    -533
    -534
    -535
    -536
    -537
    -538
    -539
    -540
    -541
    -542
    -543
    -544
    -545
    -546
    -547
    -548
    -549
    -550
    -551
    -552
    -553
    -554
    -555
    -556
    -557
    -558
    -559
    -560
    -561
    -562
    -563
    -564
    -565
    -566
    -567
    -568
    -569
    -570
    -571
    -572
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -use std::collections::HashMap;
    -use std::net::{TcpStream, ToSocketAddrs};
    -use std::sync::{Arc, Condvar, Mutex, RwLock};
    -use std::thread;
    -use std::time::{Duration, SystemTime, UNIX_EPOCH};
    -
    -use socks::{Socks5Stream, ToTargetAddr};
    -
    -use rand::{thread_rng, Rng};
    -
    -use bitcoin::consensus::Encodable;
    -use bitcoin::hash_types::BlockHash;
    -use bitcoin::network::constants::ServiceFlags;
    -use bitcoin::network::message::{NetworkMessage, RawNetworkMessage};
    -use bitcoin::network::message_blockdata::*;
    -use bitcoin::network::message_filter::*;
    -use bitcoin::network::message_network::VersionMessage;
    -use bitcoin::network::stream_reader::StreamReader;
    -use bitcoin::network::Address;
    -use bitcoin::{Block, Network, Transaction, Txid, Wtxid};
    -
    -use super::CompactFiltersError;
    -
    -type ResponsesMap = HashMap<&'static str, Arc<(Mutex<Vec<NetworkMessage>>, Condvar)>>;
    -
    -pub(crate) const TIMEOUT_SECS: u64 = 30;
    -
    -/// Container for unconfirmed, but valid Bitcoin transactions
    -///
    -/// It is normally shared between [`Peer`]s with the use of [`Arc`], so that transactions are not
    -/// duplicated in memory.
    -#[derive(Debug, Default)]
    -pub struct Mempool(RwLock<InnerMempool>);
    -
    -#[derive(Debug, Default)]
    -struct InnerMempool {
    -    txs: HashMap<Txid, Transaction>,
    -    wtxids: HashMap<Wtxid, Txid>,
    -}
    -
    -#[derive(Debug, Clone, PartialEq, Eq)]
    -enum TxIdentifier {
    -    Wtxid(Wtxid),
    -    Txid(Txid),
    -}
    -
    -impl Mempool {
    -    /// Create a new empty mempool
    -    pub fn new() -> Self {
    -        Self::default()
    -    }
    -
    -    /// Add a transaction to the mempool
    -    ///
    -    /// Note that this doesn't propagate the transaction to other
    -    /// peers. To do that, [`broadcast`](crate::blockchain::Blockchain::broadcast) should be used.
    -    pub fn add_tx(&self, tx: Transaction) {
    -        let mut guard = self.0.write().unwrap();
    -
    -        guard.wtxids.insert(tx.wtxid(), tx.txid());
    -        guard.txs.insert(tx.txid(), tx);
    -    }
    -
    -    /// Look-up a transaction in the mempool given an [`Inventory`] request
    -    pub fn get_tx(&self, inventory: &Inventory) -> Option<Transaction> {
    -        let identifer = match inventory {
    -            Inventory::Error | Inventory::Block(_) | Inventory::WitnessBlock(_) => return None,
    -            Inventory::Transaction(txid) => TxIdentifier::Txid(*txid),
    -            Inventory::WitnessTransaction(txid) => TxIdentifier::Txid(*txid),
    -            Inventory::WTx(wtxid) => TxIdentifier::Wtxid(*wtxid),
    -            Inventory::Unknown { inv_type, hash } => {
    -                log::warn!(
    -                    "Unknown inventory request type `{}`, hash `{:?}`",
    -                    inv_type,
    -                    hash
    -                );
    -                return None;
    -            }
    -        };
    -
    -        let txid = match identifer {
    -            TxIdentifier::Txid(txid) => Some(txid),
    -            TxIdentifier::Wtxid(wtxid) => self.0.read().unwrap().wtxids.get(&wtxid).cloned(),
    -        };
    -
    -        txid.map(|txid| self.0.read().unwrap().txs.get(&txid).cloned())
    -            .flatten()
    -    }
    -
    -    /// Return whether or not the mempool contains a transaction with a given txid
    -    pub fn has_tx(&self, txid: &Txid) -> bool {
    -        self.0.read().unwrap().txs.contains_key(txid)
    -    }
    -
    -    /// Return the list of transactions contained in the mempool
    -    pub fn iter_txs(&self) -> Vec<Transaction> {
    -        self.0.read().unwrap().txs.values().cloned().collect()
    -    }
    -}
    -
    -/// A Bitcoin peer
    -#[derive(Debug)]
    -pub struct Peer {
    -    writer: Arc<Mutex<TcpStream>>,
    -    responses: Arc<RwLock<ResponsesMap>>,
    -
    -    reader_thread: thread::JoinHandle<()>,
    -    connected: Arc<RwLock<bool>>,
    -
    -    mempool: Arc<Mempool>,
    -
    -    version: VersionMessage,
    -    network: Network,
    -}
    -
    -impl Peer {
    -    /// Connect to a peer over a plaintext TCP connection
    -    ///
    -    /// This function internally spawns a new thread that will monitor incoming messages from the
    -    /// peer, and optionally reply to some of them transparently, like [pings](bitcoin::network::message::NetworkMessage::Ping)
    -    pub fn connect<A: ToSocketAddrs>(
    -        address: A,
    -        mempool: Arc<Mempool>,
    -        network: Network,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let stream = TcpStream::connect(address)?;
    -
    -        Peer::from_stream(stream, mempool, network)
    -    }
    -
    -    /// Connect to a peer through a SOCKS5 proxy, optionally by using some credentials, specified
    -    /// as a tuple of `(username, password)`
    -    ///
    -    /// This function internally spawns a new thread that will monitor incoming messages from the
    -    /// peer, and optionally reply to some of them transparently, like [pings](NetworkMessage::Ping)
    -    pub fn connect_proxy<T: ToTargetAddr, P: ToSocketAddrs>(
    -        target: T,
    -        proxy: P,
    -        credentials: Option<(&str, &str)>,
    -        mempool: Arc<Mempool>,
    -        network: Network,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let socks_stream = if let Some((username, password)) = credentials {
    -            Socks5Stream::connect_with_password(proxy, target, username, password)?
    -        } else {
    -            Socks5Stream::connect(proxy, target)?
    -        };
    -
    -        Peer::from_stream(socks_stream.into_inner(), mempool, network)
    -    }
    -
    -    /// Create a [`Peer`] from an already connected TcpStream
    -    fn from_stream(
    -        stream: TcpStream,
    -        mempool: Arc<Mempool>,
    -        network: Network,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let writer = Arc::new(Mutex::new(stream.try_clone()?));
    -        let responses: Arc<RwLock<ResponsesMap>> = Arc::new(RwLock::new(HashMap::new()));
    -        let connected = Arc::new(RwLock::new(true));
    -
    -        let mut locked_writer = writer.lock().unwrap();
    -
    -        let reader_thread_responses = Arc::clone(&responses);
    -        let reader_thread_writer = Arc::clone(&writer);
    -        let reader_thread_mempool = Arc::clone(&mempool);
    -        let reader_thread_connected = Arc::clone(&connected);
    -        let reader_thread = thread::spawn(move || {
    -            Self::reader_thread(
    -                network,
    -                stream,
    -                reader_thread_responses,
    -                reader_thread_writer,
    -                reader_thread_mempool,
    -                reader_thread_connected,
    -            )
    -        });
    -
    -        let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs() as i64;
    -        let nonce = thread_rng().gen();
    -        let receiver = Address::new(&locked_writer.peer_addr()?, ServiceFlags::NONE);
    -        let sender = Address {
    -            services: ServiceFlags::NONE,
    -            address: [0u16; 8],
    -            port: 0,
    -        };
    -
    -        Self::_send(
    -            &mut locked_writer,
    -            network.magic(),
    -            NetworkMessage::Version(VersionMessage::new(
    -                ServiceFlags::WITNESS,
    -                timestamp,
    -                receiver,
    -                sender,
    -                nonce,
    -                "MagicalBitcoinWallet".into(),
    -                0,
    -            )),
    -        )?;
    -        let version = if let NetworkMessage::Version(version) =
    -            Self::_recv(&responses, "version", None).unwrap()
    -        {
    -            version
    -        } else {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        };
    -
    -        if let NetworkMessage::Verack = Self::_recv(&responses, "verack", None).unwrap() {
    -            Self::_send(&mut locked_writer, network.magic(), NetworkMessage::Verack)?;
    -        } else {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        }
    -
    -        std::mem::drop(locked_writer);
    -
    -        Ok(Peer {
    -            writer,
    -            responses,
    -            reader_thread,
    -            connected,
    -            mempool,
    -            version,
    -            network,
    -        })
    -    }
    -
    -    /// Send a Bitcoin network message
    -    fn _send(
    -        writer: &mut TcpStream,
    -        magic: u32,
    -        payload: NetworkMessage,
    -    ) -> Result<(), CompactFiltersError> {
    -        log::trace!("==> {:?}", payload);
    -
    -        let raw_message = RawNetworkMessage { magic, payload };
    -
    -        raw_message
    -            .consensus_encode(writer)
    -            .map_err(|_| CompactFiltersError::DataCorruption)?;
    -
    -        Ok(())
    -    }
    -
    -    /// Wait for a specific incoming Bitcoin message, optionally with a timeout
    -    fn _recv(
    -        responses: &Arc<RwLock<ResponsesMap>>,
    -        wait_for: &'static str,
    -        timeout: Option<Duration>,
    -    ) -> Option<NetworkMessage> {
    -        let message_resp = {
    -            let mut lock = responses.write().unwrap();
    -            let message_resp = lock.entry(wait_for).or_default();
    -            Arc::clone(&message_resp)
    -        };
    -
    -        let (lock, cvar) = &*message_resp;
    -
    -        let mut messages = lock.lock().unwrap();
    -        while messages.is_empty() {
    -            match timeout {
    -                None => messages = cvar.wait(messages).unwrap(),
    -                Some(t) => {
    -                    let result = cvar.wait_timeout(messages, t).unwrap();
    -                    if result.1.timed_out() {
    -                        return None;
    -                    }
    -                    messages = result.0;
    -                }
    -            }
    -        }
    -
    -        messages.pop()
    -    }
    -
    -    /// Return the [`VersionMessage`] sent by the peer
    -    pub fn get_version(&self) -> &VersionMessage {
    -        &self.version
    -    }
    -
    -    /// Return the Bitcoin [`Network`] in use
    -    pub fn get_network(&self) -> Network {
    -        self.network
    -    }
    -
    -    /// Return the mempool used by this peer
    -    pub fn get_mempool(&self) -> Arc<Mempool> {
    -        Arc::clone(&self.mempool)
    -    }
    -
    -    /// Return whether or not the peer is still connected
    -    pub fn is_connected(&self) -> bool {
    -        *self.connected.read().unwrap()
    -    }
    -
    -    /// Internal function called once the `reader_thread` is spawned
    -    fn reader_thread(
    -        network: Network,
    -        connection: TcpStream,
    -        reader_thread_responses: Arc<RwLock<ResponsesMap>>,
    -        reader_thread_writer: Arc<Mutex<TcpStream>>,
    -        reader_thread_mempool: Arc<Mempool>,
    -        reader_thread_connected: Arc<RwLock<bool>>,
    -    ) {
    -        macro_rules! check_disconnect {
    -            ($call:expr) => {
    -                match $call {
    -                    Ok(good) => good,
    -                    Err(e) => {
    -                        log::debug!("Error {:?}", e);
    -                        *reader_thread_connected.write().unwrap() = false;
    -
    -                        break;
    -                    }
    -                }
    -            };
    -        }
    -
    -        let mut reader = StreamReader::new(connection, None);
    -        loop {
    -            let raw_message: RawNetworkMessage = check_disconnect!(reader.read_next());
    -
    -            let in_message = if raw_message.magic != network.magic() {
    -                continue;
    -            } else {
    -                raw_message.payload
    -            };
    -
    -            log::trace!("<== {:?}", in_message);
    -
    -            match in_message {
    -                NetworkMessage::Ping(nonce) => {
    -                    check_disconnect!(Self::_send(
    -                        &mut reader_thread_writer.lock().unwrap(),
    -                        network.magic(),
    -                        NetworkMessage::Pong(nonce),
    -                    ));
    -
    -                    continue;
    -                }
    -                NetworkMessage::Alert(_) => continue,
    -                NetworkMessage::GetData(ref inv) => {
    -                    let (found, not_found): (Vec<_>, Vec<_>) = inv
    -                        .iter()
    -                        .map(|item| (*item, reader_thread_mempool.get_tx(item)))
    -                        .partition(|(_, d)| d.is_some());
    -                    for (_, found_tx) in found {
    -                        check_disconnect!(Self::_send(
    -                            &mut reader_thread_writer.lock().unwrap(),
    -                            network.magic(),
    -                            NetworkMessage::Tx(found_tx.unwrap()),
    -                        ));
    -                    }
    -
    -                    if !not_found.is_empty() {
    -                        check_disconnect!(Self::_send(
    -                            &mut reader_thread_writer.lock().unwrap(),
    -                            network.magic(),
    -                            NetworkMessage::NotFound(
    -                                not_found.into_iter().map(|(i, _)| i).collect(),
    -                            ),
    -                        ));
    -                    }
    -                }
    -                _ => {}
    -            }
    -
    -            let message_resp = {
    -                let mut lock = reader_thread_responses.write().unwrap();
    -                let message_resp = lock.entry(in_message.cmd()).or_default();
    -                Arc::clone(&message_resp)
    -            };
    -
    -            let (lock, cvar) = &*message_resp;
    -            let mut messages = lock.lock().unwrap();
    -            messages.push(in_message);
    -            cvar.notify_all();
    -        }
    -    }
    -
    -    /// Send a raw Bitcoin message to the peer
    -    pub fn send(&self, payload: NetworkMessage) -> Result<(), CompactFiltersError> {
    -        let mut writer = self.writer.lock().unwrap();
    -        Self::_send(&mut writer, self.network.magic(), payload)
    -    }
    -
    -    /// Waits for a specific incoming Bitcoin message, optionally with a timeout
    -    pub fn recv(
    -        &self,
    -        wait_for: &'static str,
    -        timeout: Option<Duration>,
    -    ) -> Result<Option<NetworkMessage>, CompactFiltersError> {
    -        Ok(Self::_recv(&self.responses, wait_for, timeout))
    -    }
    -}
    -
    -pub trait CompactFiltersPeer {
    -    fn get_cf_checkpt(
    -        &self,
    -        filter_type: u8,
    -        stop_hash: BlockHash,
    -    ) -> Result<CFCheckpt, CompactFiltersError>;
    -    fn get_cf_headers(
    -        &self,
    -        filter_type: u8,
    -        start_height: u32,
    -        stop_hash: BlockHash,
    -    ) -> Result<CFHeaders, CompactFiltersError>;
    -    fn get_cf_filters(
    -        &self,
    -        filter_type: u8,
    -        start_height: u32,
    -        stop_hash: BlockHash,
    -    ) -> Result<(), CompactFiltersError>;
    -    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError>;
    -}
    -
    -impl CompactFiltersPeer for Peer {
    -    fn get_cf_checkpt(
    -        &self,
    -        filter_type: u8,
    -        stop_hash: BlockHash,
    -    ) -> Result<CFCheckpt, CompactFiltersError> {
    -        self.send(NetworkMessage::GetCFCheckpt(GetCFCheckpt {
    -            filter_type,
    -            stop_hash,
    -        }))?;
    -
    -        let response = self
    -            .recv("cfcheckpt", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -            .ok_or(CompactFiltersError::Timeout)?;
    -        let response = match response {
    -            NetworkMessage::CFCheckpt(response) => response,
    -            _ => return Err(CompactFiltersError::InvalidResponse),
    -        };
    -
    -        if response.filter_type != filter_type {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        }
    -
    -        Ok(response)
    -    }
    -
    -    fn get_cf_headers(
    -        &self,
    -        filter_type: u8,
    -        start_height: u32,
    -        stop_hash: BlockHash,
    -    ) -> Result<CFHeaders, CompactFiltersError> {
    -        self.send(NetworkMessage::GetCFHeaders(GetCFHeaders {
    -            filter_type,
    -            start_height,
    -            stop_hash,
    -        }))?;
    -
    -        let response = self
    -            .recv("cfheaders", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -            .ok_or(CompactFiltersError::Timeout)?;
    -        let response = match response {
    -            NetworkMessage::CFHeaders(response) => response,
    -            _ => return Err(CompactFiltersError::InvalidResponse),
    -        };
    -
    -        if response.filter_type != filter_type {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        }
    -
    -        Ok(response)
    -    }
    -
    -    fn pop_cf_filter_resp(&self) -> Result<CFilter, CompactFiltersError> {
    -        let response = self
    -            .recv("cfilter", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -            .ok_or(CompactFiltersError::Timeout)?;
    -        let response = match response {
    -            NetworkMessage::CFilter(response) => response,
    -            _ => return Err(CompactFiltersError::InvalidResponse),
    -        };
    -
    -        Ok(response)
    -    }
    -
    -    fn get_cf_filters(
    -        &self,
    -        filter_type: u8,
    -        start_height: u32,
    -        stop_hash: BlockHash,
    -    ) -> Result<(), CompactFiltersError> {
    -        self.send(NetworkMessage::GetCFilters(GetCFilters {
    -            filter_type,
    -            start_height,
    -            stop_hash,
    -        }))?;
    -
    -        Ok(())
    -    }
    -}
    -
    -pub trait InvPeer {
    -    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError>;
    -    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError>;
    -    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError>;
    -}
    -
    -impl InvPeer for Peer {
    -    fn get_block(&self, block_hash: BlockHash) -> Result<Option<Block>, CompactFiltersError> {
    -        self.send(NetworkMessage::GetData(vec![Inventory::WitnessBlock(
    -            block_hash,
    -        )]))?;
    -
    -        match self.recv("block", Some(Duration::from_secs(TIMEOUT_SECS)))? {
    -            None => Ok(None),
    -            Some(NetworkMessage::Block(response)) => Ok(Some(response)),
    -            _ => Err(CompactFiltersError::InvalidResponse),
    -        }
    -    }
    -
    -    fn ask_for_mempool(&self) -> Result<(), CompactFiltersError> {
    -        if !self.version.services.has(ServiceFlags::BLOOM) {
    -            return Err(CompactFiltersError::PeerBloomDisabled);
    -        }
    -
    -        self.send(NetworkMessage::MemPool)?;
    -        let inv = match self.recv("inv", Some(Duration::from_secs(5)))? {
    -            None => return Ok(()), // empty mempool
    -            Some(NetworkMessage::Inv(inv)) => inv,
    -            _ => return Err(CompactFiltersError::InvalidResponse),
    -        };
    -
    -        let getdata = inv
    -            .iter()
    -            .cloned()
    -            .filter(
    -                |item| matches!(item, Inventory::Transaction(txid) if !self.mempool.has_tx(txid)),
    -            )
    -            .collect::<Vec<_>>();
    -        let num_txs = getdata.len();
    -        self.send(NetworkMessage::GetData(getdata))?;
    -
    -        for _ in 0..num_txs {
    -            let tx = self
    -                .recv("tx", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -                .ok_or(CompactFiltersError::Timeout)?;
    -            let tx = match tx {
    -                NetworkMessage::Tx(tx) => tx,
    -                _ => return Err(CompactFiltersError::InvalidResponse),
    -            };
    -
    -            self.mempool.add_tx(tx);
    -        }
    -
    -        Ok(())
    -    }
    -
    -    fn broadcast_tx(&self, tx: Transaction) -> Result<(), CompactFiltersError> {
    -        self.mempool.add_tx(tx.clone());
    -        self.send(NetworkMessage::Tx(tx))?;
    -
    -        Ok(())
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/store.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/store.rs.html deleted file mode 100644 index e7ee810018..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/store.rs.html +++ /dev/null @@ -1,1704 +0,0 @@ -store.rs - source
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -482
    -483
    -484
    -485
    -486
    -487
    -488
    -489
    -490
    -491
    -492
    -493
    -494
    -495
    -496
    -497
    -498
    -499
    -500
    -501
    -502
    -503
    -504
    -505
    -506
    -507
    -508
    -509
    -510
    -511
    -512
    -513
    -514
    -515
    -516
    -517
    -518
    -519
    -520
    -521
    -522
    -523
    -524
    -525
    -526
    -527
    -528
    -529
    -530
    -531
    -532
    -533
    -534
    -535
    -536
    -537
    -538
    -539
    -540
    -541
    -542
    -543
    -544
    -545
    -546
    -547
    -548
    -549
    -550
    -551
    -552
    -553
    -554
    -555
    -556
    -557
    -558
    -559
    -560
    -561
    -562
    -563
    -564
    -565
    -566
    -567
    -568
    -569
    -570
    -571
    -572
    -573
    -574
    -575
    -576
    -577
    -578
    -579
    -580
    -581
    -582
    -583
    -584
    -585
    -586
    -587
    -588
    -589
    -590
    -591
    -592
    -593
    -594
    -595
    -596
    -597
    -598
    -599
    -600
    -601
    -602
    -603
    -604
    -605
    -606
    -607
    -608
    -609
    -610
    -611
    -612
    -613
    -614
    -615
    -616
    -617
    -618
    -619
    -620
    -621
    -622
    -623
    -624
    -625
    -626
    -627
    -628
    -629
    -630
    -631
    -632
    -633
    -634
    -635
    -636
    -637
    -638
    -639
    -640
    -641
    -642
    -643
    -644
    -645
    -646
    -647
    -648
    -649
    -650
    -651
    -652
    -653
    -654
    -655
    -656
    -657
    -658
    -659
    -660
    -661
    -662
    -663
    -664
    -665
    -666
    -667
    -668
    -669
    -670
    -671
    -672
    -673
    -674
    -675
    -676
    -677
    -678
    -679
    -680
    -681
    -682
    -683
    -684
    -685
    -686
    -687
    -688
    -689
    -690
    -691
    -692
    -693
    -694
    -695
    -696
    -697
    -698
    -699
    -700
    -701
    -702
    -703
    -704
    -705
    -706
    -707
    -708
    -709
    -710
    -711
    -712
    -713
    -714
    -715
    -716
    -717
    -718
    -719
    -720
    -721
    -722
    -723
    -724
    -725
    -726
    -727
    -728
    -729
    -730
    -731
    -732
    -733
    -734
    -735
    -736
    -737
    -738
    -739
    -740
    -741
    -742
    -743
    -744
    -745
    -746
    -747
    -748
    -749
    -750
    -751
    -752
    -753
    -754
    -755
    -756
    -757
    -758
    -759
    -760
    -761
    -762
    -763
    -764
    -765
    -766
    -767
    -768
    -769
    -770
    -771
    -772
    -773
    -774
    -775
    -776
    -777
    -778
    -779
    -780
    -781
    -782
    -783
    -784
    -785
    -786
    -787
    -788
    -789
    -790
    -791
    -792
    -793
    -794
    -795
    -796
    -797
    -798
    -799
    -800
    -801
    -802
    -803
    -804
    -805
    -806
    -807
    -808
    -809
    -810
    -811
    -812
    -813
    -814
    -815
    -816
    -817
    -818
    -819
    -820
    -821
    -822
    -823
    -824
    -825
    -826
    -827
    -828
    -829
    -830
    -831
    -832
    -833
    -834
    -835
    -836
    -837
    -838
    -839
    -840
    -841
    -842
    -843
    -844
    -845
    -846
    -847
    -848
    -849
    -850
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -use std::convert::TryInto;
    -use std::fmt;
    -use std::io::{Read, Write};
    -use std::marker::PhantomData;
    -use std::ops::Deref;
    -use std::sync::Arc;
    -use std::sync::RwLock;
    -
    -use rand::distributions::Alphanumeric;
    -use rand::{thread_rng, Rng};
    -
    -use rocksdb::{Direction, IteratorMode, ReadOptions, WriteBatch, DB};
    -
    -use bitcoin::consensus::{deserialize, encode::VarInt, serialize, Decodable, Encodable};
    -use bitcoin::hash_types::{FilterHash, FilterHeader};
    -use bitcoin::hashes::hex::FromHex;
    -use bitcoin::hashes::Hash;
    -use bitcoin::util::bip158::BlockFilter;
    -use bitcoin::util::uint::Uint256;
    -use bitcoin::Block;
    -use bitcoin::BlockHash;
    -use bitcoin::BlockHeader;
    -use bitcoin::Network;
    -
    -use lazy_static::lazy_static;
    -
    -use super::CompactFiltersError;
    -
    -lazy_static! {
    -    static ref MAINNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A29AB5F49FFFF001D1DAC2B7C0101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
    -    static ref TESTNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4ADAE5494DFFFF001D1AA4AE180101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
    -    static ref REGTEST_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4ADAE5494DFFFF7F20020000000101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
    -    static ref SIGNET_GENESIS: Block = deserialize(&Vec::<u8>::from_hex("0100000000000000000000000000000000000000000000000000000000000000000000003BA3EDFD7A7B12B27AC72C3E67768F617FC81BC3888A51323A9FB8AA4B1E5E4A008F4D5FAE77031E8AD222030101000000010000000000000000000000000000000000000000000000000000000000000000FFFFFFFF4D04FFFF001D0104455468652054696D65732030332F4A616E2F32303039204368616E63656C6C6F72206F6E206272696E6B206F66207365636F6E64206261696C6F757420666F722062616E6B73FFFFFFFF0100F2052A01000000434104678AFDB0FE5548271967F1A67130B7105CD6A828E03909A67962E0EA1F61DEB649F6BC3F4CEF38C4F35504E51EC112DE5C384DF7BA0B8D578A4C702B6BF11D5FAC00000000").unwrap()).unwrap();
    -}
    -
    -pub trait StoreType: Default + fmt::Debug {}
    -
    -#[derive(Default, Debug)]
    -pub struct Full;
    -impl StoreType for Full {}
    -#[derive(Default, Debug)]
    -pub struct Snapshot;
    -impl StoreType for Snapshot {}
    -
    -pub enum StoreEntry {
    -    BlockHeader(Option<usize>),
    -    Block(Option<usize>),
    -    BlockHeaderIndex(Option<BlockHash>),
    -    CFilterTable((u8, Option<usize>)),
    -}
    -
    -impl StoreEntry {
    -    pub fn get_prefix(&self) -> Vec<u8> {
    -        match self {
    -            StoreEntry::BlockHeader(_) => b"z",
    -            StoreEntry::Block(_) => b"x",
    -            StoreEntry::BlockHeaderIndex(_) => b"i",
    -            StoreEntry::CFilterTable(_) => b"t",
    -        }
    -        .to_vec()
    -    }
    -
    -    pub fn get_key(&self) -> Vec<u8> {
    -        let mut prefix = self.get_prefix();
    -        match self {
    -            StoreEntry::BlockHeader(Some(height)) => {
    -                prefix.extend_from_slice(&height.to_be_bytes())
    -            }
    -            StoreEntry::Block(Some(height)) => prefix.extend_from_slice(&height.to_be_bytes()),
    -            StoreEntry::BlockHeaderIndex(Some(hash)) => {
    -                prefix.extend_from_slice(&hash.into_inner())
    -            }
    -            StoreEntry::CFilterTable((filter_type, bundle_index)) => {
    -                prefix.push(*filter_type);
    -                if let Some(bundle_index) = bundle_index {
    -                    prefix.extend_from_slice(&bundle_index.to_be_bytes());
    -                }
    -            }
    -            _ => {}
    -        }
    -
    -        prefix
    -    }
    -}
    -
    -pub trait SerializeDb: Sized {
    -    fn serialize(&self) -> Vec<u8>;
    -    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError>;
    -}
    -
    -impl<T> SerializeDb for T
    -where
    -    T: Encodable + Decodable,
    -{
    -    fn serialize(&self) -> Vec<u8> {
    -        serialize(self)
    -    }
    -
    -    fn deserialize(data: &[u8]) -> Result<Self, CompactFiltersError> {
    -        deserialize(data).map_err(|_| CompactFiltersError::DataCorruption)
    -    }
    -}
    -
    -impl Encodable for BundleStatus {
    -    fn consensus_encode<W: Write>(&self, mut e: W) -> Result<usize, std::io::Error> {
    -        let mut written = 0;
    -
    -        match self {
    -            BundleStatus::Init => {
    -                written += 0x00u8.consensus_encode(&mut e)?;
    -            }
    -            BundleStatus::CfHeaders { cf_headers } => {
    -                written += 0x01u8.consensus_encode(&mut e)?;
    -                written += VarInt(cf_headers.len() as u64).consensus_encode(&mut e)?;
    -                for header in cf_headers {
    -                    written += header.consensus_encode(&mut e)?;
    -                }
    -            }
    -            BundleStatus::CFilters { cf_filters } => {
    -                written += 0x02u8.consensus_encode(&mut e)?;
    -                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
    -                for filter in cf_filters {
    -                    written += filter.consensus_encode(&mut e)?;
    -                }
    -            }
    -            BundleStatus::Processed { cf_filters } => {
    -                written += 0x03u8.consensus_encode(&mut e)?;
    -                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
    -                for filter in cf_filters {
    -                    written += filter.consensus_encode(&mut e)?;
    -                }
    -            }
    -            BundleStatus::Pruned => {
    -                written += 0x04u8.consensus_encode(&mut e)?;
    -            }
    -            BundleStatus::Tip { cf_filters } => {
    -                written += 0x05u8.consensus_encode(&mut e)?;
    -                written += VarInt(cf_filters.len() as u64).consensus_encode(&mut e)?;
    -                for filter in cf_filters {
    -                    written += filter.consensus_encode(&mut e)?;
    -                }
    -            }
    -        }
    -
    -        Ok(written)
    -    }
    -}
    -
    -impl Decodable for BundleStatus {
    -    fn consensus_decode<D: Read>(mut d: D) -> Result<Self, bitcoin::consensus::encode::Error> {
    -        let byte_type = u8::consensus_decode(&mut d)?;
    -        match byte_type {
    -            0x00 => Ok(BundleStatus::Init),
    -            0x01 => {
    -                let num = VarInt::consensus_decode(&mut d)?;
    -                let num = num.0 as usize;
    -
    -                let mut cf_headers = Vec::with_capacity(num);
    -                for _ in 0..num {
    -                    cf_headers.push(FilterHeader::consensus_decode(&mut d)?);
    -                }
    -
    -                Ok(BundleStatus::CfHeaders { cf_headers })
    -            }
    -            0x02 => {
    -                let num = VarInt::consensus_decode(&mut d)?;
    -                let num = num.0 as usize;
    -
    -                let mut cf_filters = Vec::with_capacity(num);
    -                for _ in 0..num {
    -                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
    -                }
    -
    -                Ok(BundleStatus::CFilters { cf_filters })
    -            }
    -            0x03 => {
    -                let num = VarInt::consensus_decode(&mut d)?;
    -                let num = num.0 as usize;
    -
    -                let mut cf_filters = Vec::with_capacity(num);
    -                for _ in 0..num {
    -                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
    -                }
    -
    -                Ok(BundleStatus::Processed { cf_filters })
    -            }
    -            0x04 => Ok(BundleStatus::Pruned),
    -            0x05 => {
    -                let num = VarInt::consensus_decode(&mut d)?;
    -                let num = num.0 as usize;
    -
    -                let mut cf_filters = Vec::with_capacity(num);
    -                for _ in 0..num {
    -                    cf_filters.push(Vec::<u8>::consensus_decode(&mut d)?);
    -                }
    -
    -                Ok(BundleStatus::Tip { cf_filters })
    -            }
    -            _ => Err(bitcoin::consensus::encode::Error::ParseFailed(
    -                "Invalid byte type",
    -            )),
    -        }
    -    }
    -}
    -
    -pub struct ChainStore<T: StoreType> {
    -    store: Arc<RwLock<DB>>,
    -    cf_name: String,
    -    min_height: usize,
    -    network: Network,
    -    phantom: PhantomData<T>,
    -}
    -
    -impl ChainStore<Full> {
    -    pub fn new(store: DB, network: Network) -> Result<Self, CompactFiltersError> {
    -        let genesis = match network {
    -            Network::Bitcoin => MAINNET_GENESIS.deref(),
    -            Network::Testnet => TESTNET_GENESIS.deref(),
    -            Network::Regtest => REGTEST_GENESIS.deref(),
    -            Network::Signet => SIGNET_GENESIS.deref(),
    -        };
    -
    -        let cf_name = "default".to_string();
    -        let cf_handle = store.cf_handle(&cf_name).unwrap();
    -
    -        let genesis_key = StoreEntry::BlockHeader(Some(0)).get_key();
    -
    -        if store.get_pinned_cf(cf_handle, &genesis_key)?.is_none() {
    -            let mut batch = WriteBatch::default();
    -            batch.put_cf(
    -                cf_handle,
    -                genesis_key,
    -                (genesis.header, genesis.header.work()).serialize(),
    -            );
    -            batch.put_cf(
    -                cf_handle,
    -                StoreEntry::BlockHeaderIndex(Some(genesis.block_hash())).get_key(),
    -                &0usize.to_be_bytes(),
    -            );
    -            store.write(batch)?;
    -        }
    -
    -        Ok(ChainStore {
    -            store: Arc::new(RwLock::new(store)),
    -            cf_name,
    -            min_height: 0,
    -            network,
    -            phantom: PhantomData,
    -        })
    -    }
    -
    -    pub fn get_locators(&self) -> Result<Vec<(BlockHash, usize)>, CompactFiltersError> {
    -        let mut step = 1;
    -        let mut index = self.get_height()?;
    -        let mut answer = Vec::new();
    -
    -        let store_read = self.store.read().unwrap();
    -        let cf_handle = store_read.cf_handle(&self.cf_name).unwrap();
    -
    -        loop {
    -            if answer.len() > 10 {
    -                step *= 2;
    -            }
    -
    -            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(
    -                &store_read
    -                    .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(index)).get_key())?
    -                    .unwrap(),
    -            )?;
    -            answer.push((header.block_hash(), index));
    -
    -            if let Some(new_index) = index.checked_sub(step) {
    -                index = new_index;
    -            } else {
    -                break;
    -            }
    -        }
    -
    -        Ok(answer)
    -    }
    -
    -    pub fn start_snapshot(&self, from: usize) -> Result<ChainStore<Snapshot>, CompactFiltersError> {
    -        let new_cf_name: String = thread_rng().sample_iter(&Alphanumeric).take(16).collect();
    -        let new_cf_name = format!("_headers:{}", new_cf_name);
    -
    -        let mut write_store = self.store.write().unwrap();
    -
    -        write_store.create_cf(&new_cf_name, &Default::default())?;
    -
    -        let cf_handle = write_store.cf_handle(&self.cf_name).unwrap();
    -        let new_cf_handle = write_store.cf_handle(&new_cf_name).unwrap();
    -
    -        let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(
    -            &write_store
    -                .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
    -                .ok_or(CompactFiltersError::DataCorruption)?,
    -        )?;
    -
    -        let mut batch = WriteBatch::default();
    -        batch.put_cf(
    -            new_cf_handle,
    -            StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
    -            &from.to_be_bytes(),
    -        );
    -        batch.put_cf(
    -            new_cf_handle,
    -            StoreEntry::BlockHeader(Some(from)).get_key(),
    -            (header, work).serialize(),
    -        );
    -        write_store.write(batch)?;
    -
    -        let store = Arc::clone(&self.store);
    -        Ok(ChainStore {
    -            store,
    -            cf_name: new_cf_name,
    -            min_height: from,
    -            network: self.network,
    -            phantom: PhantomData,
    -        })
    -    }
    -
    -    pub fn recover_snapshot(&self, cf_name: &str) -> Result<(), CompactFiltersError> {
    -        let mut write_store = self.store.write().unwrap();
    -        let snapshot_cf_handle = write_store.cf_handle(cf_name).unwrap();
    -
    -        let prefix = StoreEntry::BlockHeader(None).get_key();
    -        let mut iterator = write_store.prefix_iterator_cf(snapshot_cf_handle, prefix);
    -
    -        let min_height = match iterator
    -            .next()
    -            .and_then(|(k, _)| k[1..].try_into().ok())
    -            .map(usize::from_be_bytes)
    -        {
    -            None => {
    -                std::mem::drop(iterator);
    -                write_store.drop_cf(cf_name).ok();
    -
    -                return Ok(());
    -            }
    -            Some(x) => x,
    -        };
    -        std::mem::drop(iterator);
    -        std::mem::drop(write_store);
    -
    -        let snapshot = ChainStore {
    -            store: Arc::clone(&self.store),
    -            cf_name: cf_name.into(),
    -            min_height,
    -            network: self.network,
    -            phantom: PhantomData,
    -        };
    -        if snapshot.work()? > self.work()? {
    -            self.apply_snapshot(snapshot)?;
    -        }
    -
    -        Ok(())
    -    }
    -
    -    pub fn apply_snapshot(
    -        &self,
    -        snaphost: ChainStore<Snapshot>,
    -    ) -> Result<(), CompactFiltersError> {
    -        let mut batch = WriteBatch::default();
    -
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -        let snapshot_cf_handle = read_store.cf_handle(&snaphost.cf_name).unwrap();
    -
    -        let from_key = StoreEntry::BlockHeader(Some(snaphost.min_height)).get_key();
    -        let to_key = StoreEntry::BlockHeader(Some(usize::MAX)).get_key();
    -
    -        let mut opts = ReadOptions::default();
    -        opts.set_iterate_upper_bound(to_key.clone());
    -
    -        log::debug!("Removing items");
    -        batch.delete_range_cf(cf_handle, &from_key, &to_key);
    -        for (_, v) in read_store.iterator_cf_opt(
    -            cf_handle,
    -            opts,
    -            IteratorMode::From(&from_key, Direction::Forward),
    -        ) {
    -            let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
    -
    -            batch.delete_cf(
    -                cf_handle,
    -                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
    -            );
    -        }
    -
    -        // Delete full blocks overriden by snapshot
    -        let from_key = StoreEntry::Block(Some(snaphost.min_height)).get_key();
    -        let to_key = StoreEntry::Block(Some(usize::MAX)).get_key();
    -        batch.delete_range(&from_key, &to_key);
    -
    -        log::debug!("Copying over new items");
    -        for (k, v) in read_store.iterator_cf(snapshot_cf_handle, IteratorMode::Start) {
    -            batch.put_cf(cf_handle, k, v);
    -        }
    -
    -        read_store.write(batch)?;
    -        std::mem::drop(read_store);
    -
    -        self.store.write().unwrap().drop_cf(&snaphost.cf_name)?;
    -
    -        Ok(())
    -    }
    -
    -    pub fn get_height_for(
    -        &self,
    -        block_hash: &BlockHash,
    -    ) -> Result<Option<usize>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let key = StoreEntry::BlockHeaderIndex(Some(*block_hash)).get_key();
    -        let data = read_store.get_pinned_cf(cf_handle, key)?;
    -        data.map(|data| {
    -            Ok::<_, CompactFiltersError>(usize::from_be_bytes(
    -                data.as_ref()
    -                    .try_into()
    -                    .map_err(|_| CompactFiltersError::DataCorruption)?,
    -            ))
    -        })
    -        .transpose()
    -    }
    -
    -    pub fn get_block_hash(&self, height: usize) -> Result<Option<BlockHash>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let key = StoreEntry::BlockHeader(Some(height)).get_key();
    -        let data = read_store.get_pinned_cf(cf_handle, key)?;
    -        data.map(|data| {
    -            let (header, _): (BlockHeader, Uint256) =
    -                deserialize(&data).map_err(|_| CompactFiltersError::DataCorruption)?;
    -            Ok::<_, CompactFiltersError>(header.block_hash())
    -        })
    -        .transpose()
    -    }
    -
    -    pub fn save_full_block(&self, block: &Block, height: usize) -> Result<(), CompactFiltersError> {
    -        let key = StoreEntry::Block(Some(height)).get_key();
    -        self.store.read().unwrap().put(key, block.serialize())?;
    -
    -        Ok(())
    -    }
    -
    -    pub fn get_full_block(&self, height: usize) -> Result<Option<Block>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -
    -        let key = StoreEntry::Block(Some(height)).get_key();
    -        let opt_block = read_store.get_pinned(key)?;
    -
    -        opt_block
    -            .map(|data| deserialize(&data))
    -            .transpose()
    -            .map_err(|_| CompactFiltersError::DataCorruption)
    -    }
    -
    -    pub fn delete_blocks_until(&self, height: usize) -> Result<(), CompactFiltersError> {
    -        let from_key = StoreEntry::Block(Some(0)).get_key();
    -        let to_key = StoreEntry::Block(Some(height)).get_key();
    -
    -        let mut batch = WriteBatch::default();
    -        batch.delete_range(&from_key, &to_key);
    -
    -        self.store.read().unwrap().write(batch)?;
    -
    -        Ok(())
    -    }
    -
    -    pub fn iter_full_blocks(&self) -> Result<Vec<(usize, Block)>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -
    -        let prefix = StoreEntry::Block(None).get_key();
    -
    -        let iterator = read_store.prefix_iterator(&prefix);
    -        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
    -        // have the right prefix
    -        iterator
    -            .filter(|(k, _)| k.starts_with(&prefix))
    -            .map(|(k, v)| {
    -                let height: usize = usize::from_be_bytes(
    -                    k[1..]
    -                        .try_into()
    -                        .map_err(|_| CompactFiltersError::DataCorruption)?,
    -                );
    -                let block = SerializeDb::deserialize(&v)?;
    -
    -                Ok((height, block))
    -            })
    -            .collect::<Result<_, _>>()
    -    }
    -}
    -
    -impl<T: StoreType> ChainStore<T> {
    -    pub fn work(&self) -> Result<Uint256, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let prefix = StoreEntry::BlockHeader(None).get_key();
    -        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
    -
    -        Ok(iterator
    -            .last()
    -            .map(|(_, v)| -> Result<_, CompactFiltersError> {
    -                let (_, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
    -
    -                Ok(work)
    -            })
    -            .transpose()?
    -            .unwrap_or_default())
    -    }
    -
    -    pub fn get_height(&self) -> Result<usize, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let prefix = StoreEntry::BlockHeader(None).get_key();
    -        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
    -
    -        Ok(iterator
    -            .last()
    -            .map(|(k, _)| -> Result<_, CompactFiltersError> {
    -                let height = usize::from_be_bytes(
    -                    k[1..]
    -                        .try_into()
    -                        .map_err(|_| CompactFiltersError::DataCorruption)?,
    -                );
    -
    -                Ok(height)
    -            })
    -            .transpose()?
    -            .unwrap_or_default())
    -    }
    -
    -    pub fn get_tip_hash(&self) -> Result<Option<BlockHash>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let prefix = StoreEntry::BlockHeader(None).get_key();
    -        let iterator = read_store.prefix_iterator_cf(cf_handle, prefix);
    -
    -        iterator
    -            .last()
    -            .map(|(_, v)| -> Result<_, CompactFiltersError> {
    -                let (header, _): (BlockHeader, Uint256) = SerializeDb::deserialize(&v)?;
    -
    -                Ok(header.block_hash())
    -            })
    -            .transpose()
    -    }
    -
    -    pub fn apply(
    -        &mut self,
    -        from: usize,
    -        headers: Vec<BlockHeader>,
    -    ) -> Result<BlockHash, CompactFiltersError> {
    -        let mut batch = WriteBatch::default();
    -
    -        let read_store = self.store.read().unwrap();
    -        let cf_handle = read_store.cf_handle(&self.cf_name).unwrap();
    -
    -        let (mut last_hash, mut accumulated_work) = read_store
    -            .get_pinned_cf(cf_handle, StoreEntry::BlockHeader(Some(from)).get_key())?
    -            .map(|result| {
    -                let (header, work): (BlockHeader, Uint256) = SerializeDb::deserialize(&result)?;
    -                Ok::<_, CompactFiltersError>((header.block_hash(), work))
    -            })
    -            .transpose()?
    -            .ok_or(CompactFiltersError::DataCorruption)?;
    -
    -        for (index, header) in headers.into_iter().enumerate() {
    -            if header.prev_blockhash != last_hash {
    -                return Err(CompactFiltersError::InvalidHeaders);
    -            }
    -
    -            last_hash = header.block_hash();
    -            accumulated_work = accumulated_work + header.work();
    -
    -            let height = from + index + 1;
    -            batch.put_cf(
    -                cf_handle,
    -                StoreEntry::BlockHeaderIndex(Some(header.block_hash())).get_key(),
    -                &(height).to_be_bytes(),
    -            );
    -            batch.put_cf(
    -                cf_handle,
    -                StoreEntry::BlockHeader(Some(height)).get_key(),
    -                (header, accumulated_work).serialize(),
    -            );
    -        }
    -
    -        std::mem::drop(read_store);
    -
    -        self.store.write().unwrap().write(batch)?;
    -        Ok(last_hash)
    -    }
    -}
    -
    -impl<T: StoreType> fmt::Debug for ChainStore<T> {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        f.debug_struct(&format!("ChainStore<{:?}>", T::default()))
    -            .field("cf_name", &self.cf_name)
    -            .field("min_height", &self.min_height)
    -            .field("network", &self.network)
    -            .field("headers_height", &self.get_height())
    -            .field("tip_hash", &self.get_tip_hash())
    -            .finish()
    -    }
    -}
    -
    -pub enum BundleStatus {
    -    Init,
    -    CfHeaders { cf_headers: Vec<FilterHeader> },
    -    CFilters { cf_filters: Vec<Vec<u8>> },
    -    Processed { cf_filters: Vec<Vec<u8>> },
    -    Tip { cf_filters: Vec<Vec<u8>> },
    -    Pruned,
    -}
    -
    -pub struct CfStore {
    -    store: Arc<RwLock<DB>>,
    -    filter_type: u8,
    -}
    -
    -type BundleEntry = (BundleStatus, FilterHeader);
    -
    -impl CfStore {
    -    pub fn new(
    -        headers_store: &ChainStore<Full>,
    -        filter_type: u8,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let cf_store = CfStore {
    -            store: Arc::clone(&headers_store.store),
    -            filter_type,
    -        };
    -
    -        let genesis = match headers_store.network {
    -            Network::Bitcoin => MAINNET_GENESIS.deref(),
    -            Network::Testnet => TESTNET_GENESIS.deref(),
    -            Network::Regtest => REGTEST_GENESIS.deref(),
    -            Network::Signet => SIGNET_GENESIS.deref(),
    -        };
    -
    -        let filter = BlockFilter::new_script_filter(genesis, |utxo| {
    -            Err(bitcoin::util::bip158::Error::UtxoMissing(*utxo))
    -        })?;
    -        let first_key = StoreEntry::CFilterTable((filter_type, Some(0))).get_key();
    -
    -        // Add the genesis' filter
    -        {
    -            let read_store = cf_store.store.read().unwrap();
    -            if read_store.get_pinned(&first_key)?.is_none() {
    -                read_store.put(
    -                    &first_key,
    -                    (
    -                        BundleStatus::Init,
    -                        filter.filter_header(&FilterHeader::from_hash(Default::default())),
    -                    )
    -                        .serialize(),
    -                )?;
    -            }
    -        }
    -
    -        Ok(cf_store)
    -    }
    -
    -    pub fn get_filter_type(&self) -> u8 {
    -        self.filter_type
    -    }
    -
    -    pub fn get_bundles(&self) -> Result<Vec<BundleEntry>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -
    -        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
    -        let iterator = read_store.prefix_iterator(&prefix);
    -
    -        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
    -        // have the right prefix
    -        iterator
    -            .filter(|(k, _)| k.starts_with(&prefix))
    -            .map(|(_, data)| BundleEntry::deserialize(&data))
    -            .collect::<Result<_, _>>()
    -    }
    -
    -    pub fn get_checkpoints(&self) -> Result<Vec<FilterHeader>, CompactFiltersError> {
    -        let read_store = self.store.read().unwrap();
    -
    -        let prefix = StoreEntry::CFilterTable((self.filter_type, None)).get_key();
    -        let iterator = read_store.prefix_iterator(&prefix);
    -
    -        // FIXME: we have to filter manually because rocksdb sometimes returns stuff that doesn't
    -        // have the right prefix
    -        iterator
    -            .filter(|(k, _)| k.starts_with(&prefix))
    -            .skip(1)
    -            .map(|(_, data)| Ok::<_, CompactFiltersError>(BundleEntry::deserialize(&data)?.1))
    -            .collect::<Result<_, _>>()
    -    }
    -
    -    pub fn replace_checkpoints(
    -        &self,
    -        checkpoints: Vec<FilterHeader>,
    -    ) -> Result<(), CompactFiltersError> {
    -        let current_checkpoints = self.get_checkpoints()?;
    -
    -        let mut equal_bundles = 0;
    -        for (index, (our, their)) in current_checkpoints
    -            .iter()
    -            .zip(checkpoints.iter())
    -            .enumerate()
    -        {
    -            equal_bundles = index;
    -
    -            if our != their {
    -                break;
    -            }
    -        }
    -
    -        let read_store = self.store.read().unwrap();
    -        let mut batch = WriteBatch::default();
    -
    -        for (index, filter_hash) in checkpoints.iter().enumerate().skip(equal_bundles) {
    -            let key = StoreEntry::CFilterTable((self.filter_type, Some(index + 1))).get_key(); // +1 to skip the genesis' filter
    -
    -            if let Some((BundleStatus::Tip { .. }, _)) = read_store
    -                .get_pinned(&key)?
    -                .map(|data| BundleEntry::deserialize(&data))
    -                .transpose()?
    -            {
    -                println!("Keeping bundle #{} as Tip", index);
    -            } else {
    -                batch.put(&key, (BundleStatus::Init, *filter_hash).serialize());
    -            }
    -        }
    -
    -        read_store.write(batch)?;
    -
    -        Ok(())
    -    }
    -
    -    pub fn advance_to_cf_headers(
    -        &self,
    -        bundle: usize,
    -        checkpoint: FilterHeader,
    -        filter_hashes: Vec<FilterHash>,
    -    ) -> Result<BundleStatus, CompactFiltersError> {
    -        let cf_headers: Vec<FilterHeader> = filter_hashes
    -            .into_iter()
    -            .scan(checkpoint, |prev_header, filter_hash| {
    -                let filter_header = filter_hash.filter_header(&prev_header);
    -                *prev_header = filter_header;
    -
    -                Some(filter_header)
    -            })
    -            .collect();
    -
    -        let read_store = self.store.read().unwrap();
    -
    -        let next_key = StoreEntry::CFilterTable((self.filter_type, Some(bundle + 1))).get_key(); // +1 to skip the genesis' filter
    -        if let Some((_, next_checkpoint)) = read_store
    -            .get_pinned(&next_key)?
    -            .map(|data| BundleEntry::deserialize(&data))
    -            .transpose()?
    -        {
    -            // check connection with the next bundle if present
    -            if cf_headers.iter().last() != Some(&next_checkpoint) {
    -                return Err(CompactFiltersError::InvalidFilterHeader);
    -            }
    -        }
    -
    -        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
    -        let value = (BundleStatus::CfHeaders { cf_headers }, checkpoint);
    -
    -        read_store.put(key, value.serialize())?;
    -
    -        Ok(value.0)
    -    }
    -
    -    pub fn advance_to_cf_filters(
    -        &self,
    -        bundle: usize,
    -        checkpoint: FilterHeader,
    -        headers: Vec<FilterHeader>,
    -        filters: Vec<(usize, Vec<u8>)>,
    -    ) -> Result<BundleStatus, CompactFiltersError> {
    -        let cf_filters = filters
    -            .into_iter()
    -            .zip(headers.into_iter())
    -            .scan(checkpoint, |prev_header, ((_, filter_content), header)| {
    -                let filter = BlockFilter::new(&filter_content);
    -                if header != filter.filter_header(&prev_header) {
    -                    return Some(Err(CompactFiltersError::InvalidFilter));
    -                }
    -                *prev_header = header;
    -
    -                Some(Ok::<_, CompactFiltersError>(filter_content))
    -            })
    -            .collect::<Result<_, _>>()?;
    -
    -        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
    -        let value = (BundleStatus::CFilters { cf_filters }, checkpoint);
    -
    -        let read_store = self.store.read().unwrap();
    -        read_store.put(key, value.serialize())?;
    -
    -        Ok(value.0)
    -    }
    -
    -    pub fn prune_filters(
    -        &self,
    -        bundle: usize,
    -        checkpoint: FilterHeader,
    -    ) -> Result<BundleStatus, CompactFiltersError> {
    -        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
    -        let value = (BundleStatus::Pruned, checkpoint);
    -
    -        let read_store = self.store.read().unwrap();
    -        read_store.put(key, value.serialize())?;
    -
    -        Ok(value.0)
    -    }
    -
    -    pub fn mark_as_tip(
    -        &self,
    -        bundle: usize,
    -        cf_filters: Vec<Vec<u8>>,
    -        checkpoint: FilterHeader,
    -    ) -> Result<BundleStatus, CompactFiltersError> {
    -        let key = StoreEntry::CFilterTable((self.filter_type, Some(bundle))).get_key();
    -        let value = (BundleStatus::Tip { cf_filters }, checkpoint);
    -
    -        let read_store = self.store.read().unwrap();
    -        read_store.put(key, value.serialize())?;
    -
    -        Ok(value.0)
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/sync.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/sync.rs.html deleted file mode 100644 index 9e1601fadd..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/compact_filters/sync.rs.html +++ /dev/null @@ -1,596 +0,0 @@ -sync.rs - source
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -use std::collections::{BTreeMap, HashMap, VecDeque};
    -use std::sync::{Arc, Mutex};
    -use std::time::Duration;
    -
    -use bitcoin::hash_types::{BlockHash, FilterHeader};
    -use bitcoin::network::message::NetworkMessage;
    -use bitcoin::network::message_blockdata::GetHeadersMessage;
    -use bitcoin::util::bip158::BlockFilter;
    -
    -use super::peer::*;
    -use super::store::*;
    -use super::CompactFiltersError;
    -use crate::error::Error;
    -
    -pub(crate) const BURIED_CONFIRMATIONS: usize = 100;
    -
    -pub struct CfSync {
    -    headers_store: Arc<ChainStore<Full>>,
    -    cf_store: Arc<CfStore>,
    -    skip_blocks: usize,
    -    bundles: Mutex<VecDeque<(BundleStatus, FilterHeader, usize)>>,
    -}
    -
    -impl CfSync {
    -    pub fn new(
    -        headers_store: Arc<ChainStore<Full>>,
    -        skip_blocks: usize,
    -        filter_type: u8,
    -    ) -> Result<Self, CompactFiltersError> {
    -        let cf_store = Arc::new(CfStore::new(&headers_store, filter_type)?);
    -
    -        Ok(CfSync {
    -            headers_store,
    -            cf_store,
    -            skip_blocks,
    -            bundles: Mutex::new(VecDeque::new()),
    -        })
    -    }
    -
    -    pub fn pruned_bundles(&self) -> Result<usize, CompactFiltersError> {
    -        Ok(self
    -            .cf_store
    -            .get_bundles()?
    -            .into_iter()
    -            .skip(self.skip_blocks / 1000)
    -            .fold(0, |acc, (status, _)| match status {
    -                BundleStatus::Pruned => acc + 1,
    -                _ => acc,
    -            }))
    -    }
    -
    -    pub fn prepare_sync(&self, peer: Arc<Peer>) -> Result<(), CompactFiltersError> {
    -        let mut bundles_lock = self.bundles.lock().unwrap();
    -
    -        let resp = peer.get_cf_checkpt(
    -            self.cf_store.get_filter_type(),
    -            self.headers_store.get_tip_hash()?.unwrap(),
    -        )?;
    -        self.cf_store.replace_checkpoints(resp.filter_headers)?;
    -
    -        bundles_lock.clear();
    -        for (index, (status, checkpoint)) in self.cf_store.get_bundles()?.into_iter().enumerate() {
    -            bundles_lock.push_back((status, checkpoint, index));
    -        }
    -
    -        Ok(())
    -    }
    -
    -    pub fn capture_thread_for_sync<F, Q>(
    -        &self,
    -        peer: Arc<Peer>,
    -        process: F,
    -        completed_bundle: Q,
    -    ) -> Result<(), CompactFiltersError>
    -    where
    -        F: Fn(&BlockHash, &BlockFilter) -> Result<bool, CompactFiltersError>,
    -        Q: Fn(usize) -> Result<(), Error>,
    -    {
    -        let current_height = self.headers_store.get_height()?; // TODO: we should update it in case headers_store is also updated
    -
    -        loop {
    -            let (mut status, checkpoint, index) = match self.bundles.lock().unwrap().pop_front() {
    -                None => break,
    -                Some(x) => x,
    -            };
    -
    -            log::debug!(
    -                "Processing bundle #{} - height {} to {}",
    -                index,
    -                index * 1000 + 1,
    -                (index + 1) * 1000
    -            );
    -
    -            let process_received_filters =
    -                |expected_filters| -> Result<BTreeMap<usize, Vec<u8>>, CompactFiltersError> {
    -                    let mut filters_map = BTreeMap::new();
    -                    for _ in 0..expected_filters {
    -                        let filter = peer.pop_cf_filter_resp()?;
    -                        if filter.filter_type != self.cf_store.get_filter_type() {
    -                            return Err(CompactFiltersError::InvalidResponse);
    -                        }
    -
    -                        match self.headers_store.get_height_for(&filter.block_hash)? {
    -                            Some(height) => filters_map.insert(height, filter.filter),
    -                            None => return Err(CompactFiltersError::InvalidFilter),
    -                        };
    -                    }
    -
    -                    Ok(filters_map)
    -                };
    -
    -            let start_height = index * 1000 + 1;
    -            let mut already_processed = 0;
    -
    -            if start_height < self.skip_blocks {
    -                status = self.cf_store.prune_filters(index, checkpoint)?;
    -            }
    -
    -            let stop_height = std::cmp::min(current_height, start_height + 999);
    -            let stop_hash = self.headers_store.get_block_hash(stop_height)?.unwrap();
    -
    -            if let BundleStatus::Init = status {
    -                log::trace!("status: Init");
    -
    -                let resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
    -
    -                assert!(resp.previous_filter_header == checkpoint);
    -                status =
    -                    self.cf_store
    -                        .advance_to_cf_headers(index, checkpoint, resp.filter_hashes)?;
    -            }
    -            if let BundleStatus::Tip { cf_filters } = status {
    -                log::trace!("status: Tip (beginning) ");
    -
    -                already_processed = cf_filters.len();
    -                let headers_resp = peer.get_cf_headers(0x00, start_height as u32, stop_hash)?;
    -
    -                let cf_headers = match self.cf_store.advance_to_cf_headers(
    -                    index,
    -                    checkpoint,
    -                    headers_resp.filter_hashes,
    -                )? {
    -                    BundleStatus::CfHeaders { cf_headers } => cf_headers,
    -                    _ => return Err(CompactFiltersError::InvalidResponse),
    -                };
    -
    -                peer.get_cf_filters(
    -                    self.cf_store.get_filter_type(),
    -                    (start_height + cf_filters.len()) as u32,
    -                    stop_hash,
    -                )?;
    -                let expected_filters = stop_height - start_height + 1 - cf_filters.len();
    -                let filters_map = process_received_filters(expected_filters)?;
    -                let filters = cf_filters
    -                    .into_iter()
    -                    .enumerate()
    -                    .chain(filters_map.into_iter())
    -                    .collect();
    -                status = self
    -                    .cf_store
    -                    .advance_to_cf_filters(index, checkpoint, cf_headers, filters)?;
    -            }
    -            if let BundleStatus::CfHeaders { cf_headers } = status {
    -                log::trace!("status: CFHeaders");
    -
    -                peer.get_cf_filters(
    -                    self.cf_store.get_filter_type(),
    -                    start_height as u32,
    -                    stop_hash,
    -                )?;
    -                let expected_filters = stop_height - start_height + 1;
    -                let filters_map = process_received_filters(expected_filters)?;
    -                status = self.cf_store.advance_to_cf_filters(
    -                    index,
    -                    checkpoint,
    -                    cf_headers,
    -                    filters_map.into_iter().collect(),
    -                )?;
    -            }
    -            if let BundleStatus::CFilters { cf_filters } = status {
    -                log::trace!("status: CFilters");
    -
    -                let last_sync_buried_height =
    -                    (start_height + already_processed).saturating_sub(BURIED_CONFIRMATIONS);
    -
    -                for (filter_index, filter) in cf_filters.iter().enumerate() {
    -                    let height = filter_index + start_height;
    -
    -                    // do not download blocks that were already "buried" since the last sync
    -                    if height < last_sync_buried_height {
    -                        continue;
    -                    }
    -
    -                    let block_hash = self.headers_store.get_block_hash(height)?.unwrap();
    -
    -                    // TODO: also download random blocks?
    -                    if process(&block_hash, &BlockFilter::new(&filter))? {
    -                        log::debug!("Downloading block {}", block_hash);
    -
    -                        let block = peer
    -                            .get_block(block_hash)?
    -                            .ok_or(CompactFiltersError::MissingBlock)?;
    -                        self.headers_store.save_full_block(&block, height)?;
    -                    }
    -                }
    -
    -                status = BundleStatus::Processed { cf_filters };
    -            }
    -            if let BundleStatus::Processed { cf_filters } = status {
    -                log::trace!("status: Processed");
    -
    -                if current_height - stop_height > 1000 {
    -                    status = self.cf_store.prune_filters(index, checkpoint)?;
    -                } else {
    -                    status = self.cf_store.mark_as_tip(index, cf_filters, checkpoint)?;
    -                }
    -
    -                completed_bundle(index)?;
    -            }
    -            if let BundleStatus::Pruned = status {
    -                log::trace!("status: Pruned");
    -            }
    -            if let BundleStatus::Tip { .. } = status {
    -                log::trace!("status: Tip");
    -            }
    -        }
    -
    -        Ok(())
    -    }
    -}
    -
    -pub fn sync_headers<F>(
    -    peer: Arc<Peer>,
    -    store: Arc<ChainStore<Full>>,
    -    sync_fn: F,
    -) -> Result<Option<ChainStore<Snapshot>>, CompactFiltersError>
    -where
    -    F: Fn(usize) -> Result<(), Error>,
    -{
    -    let locators = store.get_locators()?;
    -    let locators_vec = locators.iter().map(|(hash, _)| hash).cloned().collect();
    -    let locators_map: HashMap<_, _> = locators.into_iter().collect();
    -
    -    peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
    -        locators_vec,
    -        Default::default(),
    -    )))?;
    -    let (mut snapshot, mut last_hash) = if let NetworkMessage::Headers(headers) = peer
    -        .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -        .ok_or(CompactFiltersError::Timeout)?
    -    {
    -        if headers.is_empty() {
    -            return Ok(None);
    -        }
    -
    -        match locators_map.get(&headers[0].prev_blockhash) {
    -            None => return Err(CompactFiltersError::InvalidHeaders),
    -            Some(from) => (store.start_snapshot(*from)?, headers[0].prev_blockhash),
    -        }
    -    } else {
    -        return Err(CompactFiltersError::InvalidResponse);
    -    };
    -
    -    let mut sync_height = store.get_height()?;
    -    while sync_height < peer.get_version().start_height as usize {
    -        peer.send(NetworkMessage::GetHeaders(GetHeadersMessage::new(
    -            vec![last_hash],
    -            Default::default(),
    -        )))?;
    -        if let NetworkMessage::Headers(headers) = peer
    -            .recv("headers", Some(Duration::from_secs(TIMEOUT_SECS)))?
    -            .ok_or(CompactFiltersError::Timeout)?
    -        {
    -            let batch_len = headers.len();
    -            last_hash = snapshot.apply(sync_height, headers)?;
    -
    -            sync_height += batch_len;
    -            sync_fn(sync_height)?;
    -        } else {
    -            return Err(CompactFiltersError::InvalidResponse);
    -        }
    -    }
    -
    -    Ok(Some(snapshot))
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/electrum.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/electrum.rs.html deleted file mode 100644 index a51f2cbb78..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/electrum.rs.html +++ /dev/null @@ -1,374 +0,0 @@ -electrum.rs - source
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Electrum
    -//!
    -//! This module defines a [`Blockchain`] struct that wraps an [`electrum_client::Client`]
    -//! and implements the logic required to populate the wallet's [database](crate::database::Database) by
    -//! querying the inner client.
    -//!
    -//! ## Example
    -//!
    -//! ```no_run
    -//! # use bdk::blockchain::electrum::ElectrumBlockchain;
    -//! let client = electrum_client::Client::new("ssl://electrum.blockstream.info:50002")?;
    -//! let blockchain = ElectrumBlockchain::from(client);
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use std::collections::HashSet;
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -use bitcoin::{BlockHeader, Script, Transaction, Txid};
    -
    -use electrum_client::{Client, ConfigBuilder, ElectrumApi, Socks5Config};
    -
    -use self::utils::{ElectrumLikeSync, ElsGetHistoryRes};
    -use super::*;
    -use crate::database::BatchDatabase;
    -use crate::error::Error;
    -use crate::FeeRate;
    -
    -/// Wrapper over an Electrum Client that implements the required blockchain traits
    -///
    -/// ## Example
    -/// See the [`blockchain::electrum`](crate::blockchain::electrum) module for a usage example.
    -pub struct ElectrumBlockchain {
    -    client: Client,
    -    stop_gap: usize,
    -}
    -
    -impl std::convert::From<Client> for ElectrumBlockchain {
    -    fn from(client: Client) -> Self {
    -        ElectrumBlockchain {
    -            client,
    -            stop_gap: 20,
    -        }
    -    }
    -}
    -
    -impl Blockchain for ElectrumBlockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        vec![
    -            Capability::FullHistory,
    -            Capability::GetAnyTx,
    -            Capability::AccurateFees,
    -        ]
    -        .into_iter()
    -        .collect()
    -    }
    -
    -    fn setup<D: BatchDatabase, P: Progress>(
    -        &self,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        self.client
    -            .electrum_like_setup(self.stop_gap, database, progress_update)
    -    }
    -
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        Ok(self.client.transaction_get(txid).map(Option::Some)?)
    -    }
    -
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        Ok(self.client.transaction_broadcast(tx).map(|_| ())?)
    -    }
    -
    -    fn get_height(&self) -> Result<u32, Error> {
    -        // TODO: unsubscribe when added to the client, or is there a better call to use here?
    -
    -        Ok(self
    -            .client
    -            .block_headers_subscribe()
    -            .map(|data| data.height as u32)?)
    -    }
    -
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
    -        Ok(FeeRate::from_btc_per_kvb(
    -            self.client.estimate_fee(target)? as f32
    -        ))
    -    }
    -}
    -
    -impl ElectrumLikeSync for Client {
    -    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script> + Clone>(
    -        &self,
    -        scripts: I,
    -    ) -> Result<Vec<Vec<ElsGetHistoryRes>>, Error> {
    -        self.batch_script_get_history(scripts)
    -            .map(|v| {
    -                v.into_iter()
    -                    .map(|v| {
    -                        v.into_iter()
    -                            .map(
    -                                |electrum_client::GetHistoryRes {
    -                                     height, tx_hash, ..
    -                                 }| ElsGetHistoryRes {
    -                                    height,
    -                                    tx_hash,
    -                                },
    -                            )
    -                            .collect()
    -                    })
    -                    .collect()
    -            })
    -            .map_err(Error::Electrum)
    -    }
    -
    -    fn els_batch_transaction_get<'s, I: IntoIterator<Item = &'s Txid> + Clone>(
    -        &self,
    -        txids: I,
    -    ) -> Result<Vec<Transaction>, Error> {
    -        self.batch_transaction_get(txids).map_err(Error::Electrum)
    -    }
    -
    -    fn els_batch_block_header<I: IntoIterator<Item = u32> + Clone>(
    -        &self,
    -        heights: I,
    -    ) -> Result<Vec<BlockHeader>, Error> {
    -        self.batch_block_header(heights).map_err(Error::Electrum)
    -    }
    -}
    -
    -/// Configuration for an [`ElectrumBlockchain`]
    -#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq)]
    -pub struct ElectrumBlockchainConfig {
    -    /// URL of the Electrum server (such as ElectrumX, Esplora, BWT) may start with `ssl://` or `tcp://` and include a port
    -    ///
    -    /// eg. `ssl://electrum.blockstream.info:60002`
    -    pub url: String,
    -    /// URL of the socks5 proxy server or a Tor service
    -    pub socks5: Option<String>,
    -    /// Request retry count
    -    pub retry: u8,
    -    /// Request timeout (seconds)
    -    pub timeout: Option<u8>,
    -    /// Stop searching addresses for transactions after finding an unused gap of this length
    -    pub stop_gap: usize,
    -}
    -
    -impl ConfigurableBlockchain for ElectrumBlockchain {
    -    type Config = ElectrumBlockchainConfig;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        let socks5 = config.socks5.as_ref().map(Socks5Config::new);
    -        let electrum_config = ConfigBuilder::new()
    -            .retry(config.retry)
    -            .timeout(config.timeout)?
    -            .socks5(socks5)?
    -            .build();
    -
    -        Ok(ElectrumBlockchain {
    -            client: Client::from_config(config.url.as_str(), electrum_config)?,
    -            stop_gap: config.stop_gap,
    -        })
    -    }
    -}
    -
    -#[cfg(test)]
    -#[cfg(feature = "test-electrum")]
    -crate::bdk_blockchain_tests! {
    -    fn test_instance(test_client: &TestClient) -> ElectrumBlockchain {
    -        ElectrumBlockchain::from(Client::new(&test_client.electrsd.electrum_url).unwrap())
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/mod.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/mod.rs.html deleted file mode 100644 index 7d87905c9b..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/mod.rs.html +++ /dev/null @@ -1,262 +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
    -
    //! Esplora
    -//!
    -//! This module defines a [`EsploraBlockchain`] struct that can query an Esplora
    -//! backend populate the wallet's [database](crate::database::Database) by:
    -//!
    -//! ## Example
    -//!
    -//! ```no_run
    -//! # use bdk::blockchain::esplora::EsploraBlockchain;
    -//! let blockchain = EsploraBlockchain::new("https://blockstream.info/testnet/api", 20);
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -//!
    -//! Esplora blockchain can use either `ureq` or `reqwest` for the HTTP client
    -//! depending on your needs (blocking or async respectively).
    -//!
    -//! Please note, to configure the Esplora HTTP client correctly use one of:
    -//! Blocking:  --features='esplora,ureq'
    -//! Async:     --features='async-interface,esplora,reqwest' --no-default-features
    -use std::collections::HashMap;
    -use std::fmt;
    -use std::io;
    -
    -use serde::Deserialize;
    -
    -use bitcoin::consensus;
    -use bitcoin::{BlockHash, Txid};
    -
    -use crate::error::Error;
    -use crate::FeeRate;
    -
    -#[cfg(feature = "reqwest")]
    -mod reqwest;
    -
    -#[cfg(feature = "reqwest")]
    -pub use self::reqwest::*;
    -
    -#[cfg(feature = "ureq")]
    -mod ureq;
    -
    -#[cfg(feature = "ureq")]
    -pub use self::ureq::*;
    -
    -fn into_fee_rate(target: usize, estimates: HashMap<String, f64>) -> Result<FeeRate, Error> {
    -    let fee_val = estimates
    -        .into_iter()
    -        .map(|(k, v)| Ok::<_, std::num::ParseIntError>((k.parse::<usize>()?, v)))
    -        .collect::<Result<Vec<_>, _>>()
    -        .map_err(|e| Error::Generic(e.to_string()))?
    -        .into_iter()
    -        .take_while(|(k, _)| k <= &target)
    -        .map(|(_, v)| v)
    -        .last()
    -        .unwrap_or(1.0);
    -
    -    Ok(FeeRate::from_sat_per_vb(fee_val as f32))
    -}
    -
    -/// Data type used when fetching transaction history from Esplora.
    -#[derive(Deserialize)]
    -pub struct EsploraGetHistory {
    -    txid: Txid,
    -    status: EsploraGetHistoryStatus,
    -}
    -
    -#[derive(Deserialize)]
    -struct EsploraGetHistoryStatus {
    -    block_height: Option<usize>,
    -}
    -
    -/// Errors that can happen during a sync with [`EsploraBlockchain`]
    -#[derive(Debug)]
    -pub enum EsploraError {
    -    /// Error during ureq HTTP request
    -    #[cfg(feature = "ureq")]
    -    Ureq(::ureq::Error),
    -    /// Transport error during the ureq HTTP call
    -    #[cfg(feature = "ureq")]
    -    UreqTransport(::ureq::Transport),
    -    /// Error during reqwest HTTP request
    -    #[cfg(feature = "reqwest")]
    -    Reqwest(::reqwest::Error),
    -    /// HTTP response error
    -    HttpResponse(u16),
    -    /// IO error during ureq response read
    -    Io(io::Error),
    -    /// No header found in ureq response
    -    NoHeader,
    -    /// Invalid number returned
    -    Parsing(std::num::ParseIntError),
    -    /// Invalid Bitcoin data returned
    -    BitcoinEncoding(bitcoin::consensus::encode::Error),
    -    /// Invalid Hex data returned
    -    Hex(bitcoin::hashes::hex::Error),
    -
    -    /// Transaction not found
    -    TransactionNotFound(Txid),
    -    /// Header height not found
    -    HeaderHeightNotFound(u32),
    -    /// Header hash not found
    -    HeaderHashNotFound(BlockHash),
    -}
    -
    -impl fmt::Display for EsploraError {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for EsploraError {}
    -
    -#[cfg(feature = "ureq")]
    -impl_error!(::ureq::Error, Ureq, EsploraError);
    -#[cfg(feature = "ureq")]
    -impl_error!(::ureq::Transport, UreqTransport, EsploraError);
    -#[cfg(feature = "reqwest")]
    -impl_error!(::reqwest::Error, Reqwest, EsploraError);
    -impl_error!(io::Error, Io, EsploraError);
    -impl_error!(std::num::ParseIntError, Parsing, EsploraError);
    -impl_error!(consensus::encode::Error, BitcoinEncoding, EsploraError);
    -impl_error!(bitcoin::hashes::hex::Error, Hex, EsploraError);
    -
    -#[cfg(test)]
    -#[cfg(feature = "test-esplora")]
    -crate::bdk_blockchain_tests! {
    -    fn test_instance(test_client: &TestClient) -> EsploraBlockchain {
    -        EsploraBlockchain::new(&format!("http://{}",test_client.electrsd.esplora_url.as_ref().unwrap()), 20)
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/ureq.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/ureq.rs.html deleted file mode 100644 index 10f92a0fea..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/esplora/ureq.rs.html +++ /dev/null @@ -1,800 +0,0 @@ -ureq.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
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Esplora by way of `ureq` HTTP client.
    -
    -use std::collections::{HashMap, HashSet};
    -use std::io;
    -use std::io::Read;
    -use std::time::Duration;
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -use ureq::{Agent, Proxy, Response};
    -
    -use bitcoin::consensus::{deserialize, serialize};
    -use bitcoin::hashes::hex::{FromHex, ToHex};
    -use bitcoin::hashes::{sha256, Hash};
    -use bitcoin::{BlockHeader, Script, Transaction, Txid};
    -
    -use crate::blockchain::esplora::{EsploraError, EsploraGetHistory};
    -use crate::blockchain::utils::{ElectrumLikeSync, ElsGetHistoryRes};
    -use crate::blockchain::*;
    -use crate::database::BatchDatabase;
    -use crate::error::Error;
    -use crate::FeeRate;
    -
    -#[derive(Debug)]
    -struct UrlClient {
    -    url: String,
    -    agent: Agent,
    -}
    -
    -/// Structure that implements the logic to sync with Esplora
    -///
    -/// ## Example
    -/// See the [`blockchain::esplora`](crate::blockchain::esplora) module for a usage example.
    -#[derive(Debug)]
    -pub struct EsploraBlockchain {
    -    url_client: UrlClient,
    -    stop_gap: usize,
    -}
    -
    -impl std::convert::From<UrlClient> for EsploraBlockchain {
    -    fn from(url_client: UrlClient) -> Self {
    -        EsploraBlockchain {
    -            url_client,
    -            stop_gap: 20,
    -        }
    -    }
    -}
    -
    -impl EsploraBlockchain {
    -    /// Create a new instance of the client from a base URL and the `stop_gap`.
    -    pub fn new(base_url: &str, stop_gap: usize) -> Self {
    -        EsploraBlockchain {
    -            url_client: UrlClient {
    -                url: base_url.to_string(),
    -                agent: Agent::new(),
    -            },
    -            stop_gap,
    -        }
    -    }
    -
    -    /// Set the inner `ureq` agent.
    -    pub fn with_agent(mut self, agent: Agent) -> Self {
    -        self.url_client.agent = agent;
    -        self
    -    }
    -}
    -
    -impl Blockchain for EsploraBlockchain {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        vec![
    -            Capability::FullHistory,
    -            Capability::GetAnyTx,
    -            Capability::AccurateFees,
    -        ]
    -        .into_iter()
    -        .collect()
    -    }
    -
    -    fn setup<D: BatchDatabase, P: Progress>(
    -        &self,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        self.url_client
    -            .electrum_like_setup(self.stop_gap, database, progress_update)
    -    }
    -
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        Ok(self.url_client._get_tx(txid)?)
    -    }
    -
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        let _txid = self.url_client._broadcast(tx)?;
    -        Ok(())
    -    }
    -
    -    fn get_height(&self) -> Result<u32, Error> {
    -        Ok(self.url_client._get_height()?)
    -    }
    -
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
    -        let estimates = self.url_client._get_fee_estimates()?;
    -        super::into_fee_rate(target, estimates)
    -    }
    -}
    -
    -impl UrlClient {
    -    fn script_to_scripthash(script: &Script) -> String {
    -        sha256::Hash::hash(script.as_bytes()).into_inner().to_hex()
    -    }
    -
    -    fn _get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, EsploraError> {
    -        let resp = self
    -            .agent
    -            .get(&format!("{}/tx/{}/raw", self.url, txid))
    -            .call();
    -
    -        match resp {
    -            Ok(resp) => Ok(Some(deserialize(&into_bytes(resp)?)?)),
    -            Err(ureq::Error::Status(code, _)) => {
    -                if is_status_not_found(code) {
    -                    return Ok(None);
    -                }
    -                Err(EsploraError::HttpResponse(code))
    -            }
    -            Err(e) => Err(EsploraError::Ureq(e)),
    -        }
    -    }
    -
    -    fn _get_tx_no_opt(&self, txid: &Txid) -> Result<Transaction, EsploraError> {
    -        match self._get_tx(txid) {
    -            Ok(Some(tx)) => Ok(tx),
    -            Ok(None) => Err(EsploraError::TransactionNotFound(*txid)),
    -            Err(e) => Err(e),
    -        }
    -    }
    -
    -    fn _get_header(&self, block_height: u32) -> Result<BlockHeader, EsploraError> {
    -        let resp = self
    -            .agent
    -            .get(&format!("{}/block-height/{}", self.url, block_height))
    -            .call();
    -
    -        let bytes = match resp {
    -            Ok(resp) => Ok(into_bytes(resp)?),
    -            Err(ureq::Error::Status(code, _)) => Err(EsploraError::HttpResponse(code)),
    -            Err(e) => Err(EsploraError::Ureq(e)),
    -        }?;
    -
    -        let hash = std::str::from_utf8(&bytes)
    -            .map_err(|_| EsploraError::HeaderHeightNotFound(block_height))?;
    -
    -        let resp = self
    -            .agent
    -            .get(&format!("{}/block/{}/header", self.url, hash))
    -            .call();
    -
    -        match resp {
    -            Ok(resp) => Ok(deserialize(&Vec::from_hex(&resp.into_string()?)?)?),
    -            Err(ureq::Error::Status(code, _)) => Err(EsploraError::HttpResponse(code)),
    -            Err(e) => Err(EsploraError::Ureq(e)),
    -        }
    -    }
    -
    -    fn _broadcast(&self, transaction: &Transaction) -> Result<(), EsploraError> {
    -        let resp = self
    -            .agent
    -            .post(&format!("{}/tx", self.url))
    -            .send_string(&serialize(transaction).to_hex());
    -
    -        match resp {
    -            Ok(_) => Ok(()), // We do not return the txid?
    -            Err(ureq::Error::Status(code, _)) => Err(EsploraError::HttpResponse(code)),
    -            Err(e) => Err(EsploraError::Ureq(e)),
    -        }
    -    }
    -
    -    fn _get_height(&self) -> Result<u32, EsploraError> {
    -        let resp = self
    -            .agent
    -            .get(&format!("{}/blocks/tip/height", self.url))
    -            .call();
    -
    -        match resp {
    -            Ok(resp) => Ok(resp.into_string()?.parse()?),
    -            Err(ureq::Error::Status(code, _)) => Err(EsploraError::HttpResponse(code)),
    -            Err(e) => Err(EsploraError::Ureq(e)),
    -        }
    -    }
    -
    -    fn _script_get_history(&self, script: &Script) -> Result<Vec<ElsGetHistoryRes>, EsploraError> {
    -        let mut result = Vec::new();
    -        let scripthash = Self::script_to_scripthash(script);
    -
    -        // Add the unconfirmed transactions first
    -
    -        let resp = self
    -            .agent
    -            .get(&format!(
    -                "{}/scripthash/{}/txs/mempool",
    -                self.url, scripthash
    -            ))
    -            .call();
    -
    -        let v = match resp {
    -            Ok(resp) => {
    -                let v: Vec<EsploraGetHistory> = resp.into_json()?;
    -                Ok(v)
    -            }
    -            Err(ureq::Error::Status(code, _)) => Err(EsploraError::HttpResponse(code)),
    -            Err(e) => Err(EsploraError::Ureq(e)),
    -        }?;
    -
    -        result.extend(v.into_iter().map(|x| ElsGetHistoryRes {
    -            tx_hash: x.txid,
    -            height: x.status.block_height.unwrap_or(0) as i32,
    -        }));
    -
    -        debug!(
    -            "Found {} mempool txs for {} - {:?}",
    -            result.len(),
    -            scripthash,
    -            script
    -        );
    -
    -        // Then go through all the pages of confirmed transactions
    -        let mut last_txid = String::new();
    -        loop {
    -            let resp = self
    -                .agent
    -                .get(&format!(
    -                    "{}/scripthash/{}/txs/chain/{}",
    -                    self.url, scripthash, last_txid
    -                ))
    -                .call();
    -
    -            let v = match resp {
    -                Ok(resp) => {
    -                    let v: Vec<EsploraGetHistory> = resp.into_json()?;
    -                    Ok(v)
    -                }
    -                Err(ureq::Error::Status(code, _)) => Err(EsploraError::HttpResponse(code)),
    -                Err(e) => Err(EsploraError::Ureq(e)),
    -            }?;
    -
    -            let len = v.len();
    -            if let Some(elem) = v.last() {
    -                last_txid = elem.txid.to_hex();
    -            }
    -
    -            debug!("... adding {} confirmed transactions", len);
    -
    -            result.extend(v.into_iter().map(|x| ElsGetHistoryRes {
    -                tx_hash: x.txid,
    -                height: x.status.block_height.unwrap_or(0) as i32,
    -            }));
    -
    -            if len < 25 {
    -                break;
    -            }
    -        }
    -
    -        Ok(result)
    -    }
    -
    -    fn _get_fee_estimates(&self) -> Result<HashMap<String, f64>, EsploraError> {
    -        let resp = self
    -            .agent
    -            .get(&format!("{}/fee-estimates", self.url,))
    -            .call();
    -
    -        let map = match resp {
    -            Ok(resp) => {
    -                let map: HashMap<String, f64> = resp.into_json()?;
    -                Ok(map)
    -            }
    -            Err(ureq::Error::Status(code, _)) => Err(EsploraError::HttpResponse(code)),
    -            Err(e) => Err(EsploraError::Ureq(e)),
    -        }?;
    -
    -        Ok(map)
    -    }
    -}
    -
    -fn is_status_not_found(status: u16) -> bool {
    -    status == 404
    -}
    -
    -fn into_bytes(resp: Response) -> Result<Vec<u8>, io::Error> {
    -    const BYTES_LIMIT: usize = 10 * 1_024 * 1_024;
    -
    -    let mut buf: Vec<u8> = vec![];
    -    resp.into_reader()
    -        .take((BYTES_LIMIT + 1) as u64)
    -        .read_to_end(&mut buf)?;
    -    if buf.len() > BYTES_LIMIT {
    -        return Err(io::Error::new(
    -            io::ErrorKind::Other,
    -            "response too big for into_bytes",
    -        ));
    -    }
    -
    -    Ok(buf)
    -}
    -
    -impl ElectrumLikeSync for UrlClient {
    -    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script>>(
    -        &self,
    -        scripts: I,
    -    ) -> Result<Vec<Vec<ElsGetHistoryRes>>, Error> {
    -        let mut results = vec![];
    -        for script in scripts.into_iter() {
    -            let v = self._script_get_history(script)?;
    -            results.push(v);
    -        }
    -        Ok(results)
    -    }
    -
    -    fn els_batch_transaction_get<'s, I: IntoIterator<Item = &'s Txid>>(
    -        &self,
    -        txids: I,
    -    ) -> Result<Vec<Transaction>, Error> {
    -        let mut results = vec![];
    -        for txid in txids.into_iter() {
    -            let tx = self._get_tx_no_opt(txid)?;
    -            results.push(tx);
    -        }
    -        Ok(results)
    -    }
    -
    -    fn els_batch_block_header<I: IntoIterator<Item = u32>>(
    -        &self,
    -        heights: I,
    -    ) -> Result<Vec<BlockHeader>, Error> {
    -        let mut results = vec![];
    -        for height in heights.into_iter() {
    -            let header = self._get_header(height)?;
    -            results.push(header);
    -        }
    -        Ok(results)
    -    }
    -}
    -
    -/// Configuration for an [`EsploraBlockchain`]
    -#[derive(Debug, serde::Deserialize, serde::Serialize, Clone, PartialEq)]
    -pub struct EsploraBlockchainConfig {
    -    /// Base URL of the esplora service eg. `https://blockstream.info/api/`
    -    pub base_url: String,
    -    /// Optional URL of the proxy to use to make requests to the Esplora server
    -    ///
    -    /// The string should be formatted as: `<protocol>://<user>:<password>@host:<port>`.
    -    ///
    -    /// Note that the format of this value and the supported protocols change slightly between the
    -    /// sync version of esplora (using `ureq`) and the async version (using `reqwest`). For more
    -    /// details check with the documentation of the two crates. Both of them are compiled with
    -    /// the `socks` feature enabled.
    -    ///
    -    /// The proxy is ignored when targeting `wasm32`.
    -    pub proxy: Option<String>,
    -    /// Socket read timeout.
    -    pub timeout_read: u64,
    -    /// Socket write timeout.
    -    pub timeout_write: u64,
    -    /// Stop searching addresses for transactions after finding an unused gap of this length.
    -    pub stop_gap: usize,
    -}
    -
    -impl ConfigurableBlockchain for EsploraBlockchain {
    -    type Config = EsploraBlockchainConfig;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        let mut agent_builder = ureq::AgentBuilder::new()
    -            .timeout_read(Duration::from_secs(config.timeout_read))
    -            .timeout_write(Duration::from_secs(config.timeout_write));
    -
    -        if let Some(proxy) = &config.proxy {
    -            agent_builder = agent_builder
    -                .proxy(Proxy::new(proxy).map_err(|e| Error::Esplora(Box::new(e.into())))?);
    -        }
    -
    -        Ok(
    -            EsploraBlockchain::new(config.base_url.as_str(), config.stop_gap)
    -                .with_agent(agent_builder.build()),
    -        )
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/mod.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/mod.rs.html deleted file mode 100644 index 6bac7fc40c..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/mod.rs.html +++ /dev/null @@ -1,516 +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
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Blockchain backends
    -//!
    -//! This module provides the implementation of a few commonly-used backends like
    -//! [Electrum](crate::blockchain::electrum), [Esplora](crate::blockchain::esplora) and
    -//! [Compact Filters/Neutrino](crate::blockchain::compact_filters), along with a generalized trait
    -//! [`Blockchain`] that can be implemented to build customized backends.
    -
    -use std::collections::HashSet;
    -use std::ops::Deref;
    -use std::sync::mpsc::{channel, Receiver, Sender};
    -use std::sync::Arc;
    -
    -use bitcoin::{Transaction, Txid};
    -
    -use crate::database::BatchDatabase;
    -use crate::error::Error;
    -use crate::FeeRate;
    -
    -#[cfg(any(feature = "electrum", feature = "esplora"))]
    -pub(crate) mod utils;
    -
    -#[cfg(any(
    -    feature = "electrum",
    -    feature = "esplora",
    -    feature = "compact_filters",
    -    feature = "rpc"
    -))]
    -pub mod any;
    -#[cfg(any(
    -    feature = "electrum",
    -    feature = "esplora",
    -    feature = "compact_filters",
    -    feature = "rpc"
    -))]
    -pub use any::{AnyBlockchain, AnyBlockchainConfig};
    -
    -#[cfg(feature = "electrum")]
    -#[cfg_attr(docsrs, doc(cfg(feature = "electrum")))]
    -pub mod electrum;
    -#[cfg(feature = "electrum")]
    -pub use self::electrum::ElectrumBlockchain;
    -#[cfg(feature = "electrum")]
    -pub use self::electrum::ElectrumBlockchainConfig;
    -
    -#[cfg(feature = "rpc")]
    -#[cfg_attr(docsrs, doc(cfg(feature = "rpc")))]
    -pub mod rpc;
    -#[cfg(feature = "rpc")]
    -pub use self::rpc::RpcBlockchain;
    -#[cfg(feature = "rpc")]
    -pub use self::rpc::RpcConfig;
    -
    -#[cfg(feature = "esplora")]
    -#[cfg_attr(docsrs, doc(cfg(feature = "esplora")))]
    -pub mod esplora;
    -#[cfg(feature = "esplora")]
    -pub use self::esplora::EsploraBlockchain;
    -
    -#[cfg(feature = "compact_filters")]
    -#[cfg_attr(docsrs, doc(cfg(feature = "compact_filters")))]
    -pub mod compact_filters;
    -
    -#[cfg(feature = "compact_filters")]
    -pub use self::compact_filters::CompactFiltersBlockchain;
    -
    -/// Capabilities that can be supported by a [`Blockchain`] backend
    -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
    -pub enum Capability {
    -    /// Can recover the full history of a wallet and not only the set of currently spendable UTXOs
    -    FullHistory,
    -    /// Can fetch any historical transaction given its txid
    -    GetAnyTx,
    -    /// Can compute accurate fees for the transactions found during sync
    -    AccurateFees,
    -}
    -
    -/// Trait that defines the actions that must be supported by a blockchain backend
    -#[maybe_async]
    -pub trait Blockchain {
    -    /// Return the set of [`Capability`] supported by this backend
    -    fn get_capabilities(&self) -> HashSet<Capability>;
    -
    -    /// Setup the backend and populate the internal database for the first time
    -    ///
    -    /// This method is the equivalent of [`Blockchain::sync`], but it's guaranteed to only be
    -    /// called once, at the first [`Wallet::sync`](crate::wallet::Wallet::sync).
    -    ///
    -    /// The rationale behind the distinction between `sync` and `setup` is that some custom backends
    -    /// might need to perform specific actions only the first time they are synced.
    -    ///
    -    /// For types that do not have that distinction, only this method can be implemented, since
    -    /// [`Blockchain::sync`] defaults to calling this internally if not overridden.
    -    fn setup<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error>;
    -    /// Populate the internal database with transactions and UTXOs
    -    ///
    -    /// If not overridden, it defaults to calling [`Blockchain::setup`] internally.
    -    ///
    -    /// This method should implement the logic required to iterate over the list of the wallet's
    -    /// script_pubkeys using [`Database::iter_script_pubkeys`] and look for relevant transactions
    -    /// in the blockchain to populate the database with [`BatchOperations::set_tx`] and
    -    /// [`BatchOperations::set_utxo`].
    -    ///
    -    /// This method should also take care of removing UTXOs that are seen as spent in the
    -    /// blockchain, using [`BatchOperations::del_utxo`].
    -    ///
    -    /// The `progress_update` object can be used to give the caller updates about the progress by using
    -    /// [`Progress::update`].
    -    ///
    -    /// [`Database::iter_script_pubkeys`]: crate::database::Database::iter_script_pubkeys
    -    /// [`BatchOperations::set_tx`]: crate::database::BatchOperations::set_tx
    -    /// [`BatchOperations::set_utxo`]: crate::database::BatchOperations::set_utxo
    -    /// [`BatchOperations::del_utxo`]: crate::database::BatchOperations::del_utxo
    -    fn sync<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        maybe_await!(self.setup(database, progress_update))
    -    }
    -
    -    /// Fetch a transaction from the blockchain given its txid
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
    -    /// Broadcast a transaction
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error>;
    -
    -    /// Return the current height
    -    fn get_height(&self) -> Result<u32, Error>;
    -    /// Estimate the fee rate required to confirm a transaction in a given `target` of blocks
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error>;
    -}
    -
    -/// Trait for [`Blockchain`] types that can be created given a configuration
    -pub trait ConfigurableBlockchain: Blockchain + Sized {
    -    /// Type that contains the configuration
    -    type Config: std::fmt::Debug;
    -
    -    /// Create a new instance given a configuration
    -    fn from_config(config: &Self::Config) -> Result<Self, Error>;
    -}
    -
    -/// Data sent with a progress update over a [`channel`]
    -pub type ProgressData = (f32, Option<String>);
    -
    -/// Trait for types that can receive and process progress updates during [`Blockchain::sync`] and
    -/// [`Blockchain::setup`]
    -pub trait Progress: Send {
    -    /// Send a new progress update
    -    ///
    -    /// The `progress` value should be in the range 0.0 - 100.0, and the `message` value is an
    -    /// optional text message that can be displayed to the user.
    -    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error>;
    -}
    -
    -/// Shortcut to create a [`channel`] (pair of [`Sender`] and [`Receiver`]) that can transport [`ProgressData`]
    -pub fn progress() -> (Sender<ProgressData>, Receiver<ProgressData>) {
    -    channel()
    -}
    -
    -impl Progress for Sender<ProgressData> {
    -    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
    -        if !(0.0..=100.0).contains(&progress) {
    -            return Err(Error::InvalidProgressValue(progress));
    -        }
    -
    -        self.send((progress, message))
    -            .map_err(|_| Error::ProgressUpdateError)
    -    }
    -}
    -
    -/// Type that implements [`Progress`] and drops every update received
    -#[derive(Clone, Copy)]
    -pub struct NoopProgress;
    -
    -/// Create a new instance of [`NoopProgress`]
    -pub fn noop_progress() -> NoopProgress {
    -    NoopProgress
    -}
    -
    -impl Progress for NoopProgress {
    -    fn update(&self, _progress: f32, _message: Option<String>) -> Result<(), Error> {
    -        Ok(())
    -    }
    -}
    -
    -/// Type that implements [`Progress`] and logs at level `INFO` every update received
    -#[derive(Clone, Copy)]
    -pub struct LogProgress;
    -
    -/// Create a new instance of [`LogProgress`]
    -pub fn log_progress() -> LogProgress {
    -    LogProgress
    -}
    -
    -impl Progress for LogProgress {
    -    fn update(&self, progress: f32, message: Option<String>) -> Result<(), Error> {
    -        log::info!(
    -            "Sync {:.3}%: `{}`",
    -            progress,
    -            message.unwrap_or_else(|| "".into())
    -        );
    -
    -        Ok(())
    -    }
    -}
    -
    -#[maybe_async]
    -impl<T: Blockchain> Blockchain for Arc<T> {
    -    fn get_capabilities(&self) -> HashSet<Capability> {
    -        maybe_await!(self.deref().get_capabilities())
    -    }
    -
    -    fn setup<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        maybe_await!(self.deref().setup(database, progress_update))
    -    }
    -
    -    fn sync<D: BatchDatabase, P: 'static + Progress>(
    -        &self,
    -        database: &mut D,
    -        progress_update: P,
    -    ) -> Result<(), Error> {
    -        maybe_await!(self.deref().sync(database, progress_update))
    -    }
    -
    -    fn get_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        maybe_await!(self.deref().get_tx(txid))
    -    }
    -    fn broadcast(&self, tx: &Transaction) -> Result<(), Error> {
    -        maybe_await!(self.deref().broadcast(tx))
    -    }
    -
    -    fn get_height(&self) -> Result<u32, Error> {
    -        maybe_await!(self.deref().get_height())
    -    }
    -    fn estimate_fee(&self, target: usize) -> Result<FeeRate, Error> {
    -        maybe_await!(self.deref().estimate_fee(target))
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/utils.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/utils.rs.html deleted file mode 100644 index c5288d5967..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/blockchain/utils.rs.html +++ /dev/null @@ -1,780 +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
    -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
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -use std::collections::{HashMap, HashSet};
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -use rand::seq::SliceRandom;
    -use rand::thread_rng;
    -
    -use bitcoin::{BlockHeader, OutPoint, Script, Transaction, Txid};
    -
    -use super::*;
    -use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
    -use crate::error::Error;
    -use crate::types::{ConfirmationTime, KeychainKind, LocalUtxo, TransactionDetails};
    -use crate::wallet::time::Instant;
    -use crate::wallet::utils::ChunksIterator;
    -
    -#[derive(Debug)]
    -pub struct ElsGetHistoryRes {
    -    pub height: i32,
    -    pub tx_hash: Txid,
    -}
    -
    -/// Implements the synchronization logic for an Electrum-like client.
    -#[maybe_async]
    -pub trait ElectrumLikeSync {
    -    fn els_batch_script_get_history<'s, I: IntoIterator<Item = &'s Script> + Clone>(
    -        &self,
    -        scripts: I,
    -    ) -> Result<Vec<Vec<ElsGetHistoryRes>>, Error>;
    -
    -    fn els_batch_transaction_get<'s, I: IntoIterator<Item = &'s Txid> + Clone>(
    -        &self,
    -        txids: I,
    -    ) -> Result<Vec<Transaction>, Error>;
    -
    -    fn els_batch_block_header<I: IntoIterator<Item = u32> + Clone>(
    -        &self,
    -        heights: I,
    -    ) -> Result<Vec<BlockHeader>, Error>;
    -
    -    // Provided methods down here...
    -
    -    fn electrum_like_setup<D: BatchDatabase, P: Progress>(
    -        &self,
    -        stop_gap: usize,
    -        db: &mut D,
    -        _progress_update: P,
    -    ) -> Result<(), Error> {
    -        // TODO: progress
    -        let start = Instant::new();
    -        debug!("start setup");
    -
    -        let chunk_size = stop_gap;
    -
    -        let mut history_txs_id = HashSet::new();
    -        let mut txid_height = HashMap::new();
    -        let mut max_indexes = HashMap::new();
    -
    -        let mut wallet_chains = vec![KeychainKind::Internal, KeychainKind::External];
    -        // shuffling improve privacy, the server doesn't know my first request is from my internal or external addresses
    -        wallet_chains.shuffle(&mut thread_rng());
    -        // download history of our internal and external script_pubkeys
    -        for keychain in wallet_chains.iter() {
    -            let script_iter = db.iter_script_pubkeys(Some(*keychain))?.into_iter();
    -
    -            for (i, chunk) in ChunksIterator::new(script_iter, stop_gap).enumerate() {
    -                // TODO if i == last, should create another chunk of addresses in db
    -                let call_result: Vec<Vec<ElsGetHistoryRes>> =
    -                    maybe_await!(self.els_batch_script_get_history(chunk.iter()))?;
    -                let max_index = call_result
    -                    .iter()
    -                    .enumerate()
    -                    .filter_map(|(i, v)| v.first().map(|_| i as u32))
    -                    .max();
    -                if let Some(max) = max_index {
    -                    max_indexes.insert(keychain, max + (i * chunk_size) as u32);
    -                }
    -                let flattened: Vec<ElsGetHistoryRes> = call_result.into_iter().flatten().collect();
    -                debug!("#{} of {:?} results:{}", i, keychain, flattened.len());
    -                if flattened.is_empty() {
    -                    // Didn't find anything in the last `stop_gap` script_pubkeys, breaking
    -                    break;
    -                }
    -
    -                for el in flattened {
    -                    // el.height = -1 means unconfirmed with unconfirmed parents
    -                    // el.height =  0 means unconfirmed with confirmed parents
    -                    // but we treat those tx the same
    -                    if el.height <= 0 {
    -                        txid_height.insert(el.tx_hash, None);
    -                    } else {
    -                        txid_height.insert(el.tx_hash, Some(el.height as u32));
    -                    }
    -                    history_txs_id.insert(el.tx_hash);
    -                }
    -            }
    -        }
    -
    -        // saving max indexes
    -        info!("max indexes are: {:?}", max_indexes);
    -        for keychain in wallet_chains.iter() {
    -            if let Some(index) = max_indexes.get(keychain) {
    -                db.set_last_index(*keychain, *index)?;
    -            }
    -        }
    -
    -        // get db status
    -        let txs_details_in_db: HashMap<Txid, TransactionDetails> = db
    -            .iter_txs(false)?
    -            .into_iter()
    -            .map(|tx| (tx.txid, tx))
    -            .collect();
    -        let txs_raw_in_db: HashMap<Txid, Transaction> = db
    -            .iter_raw_txs()?
    -            .into_iter()
    -            .map(|tx| (tx.txid(), tx))
    -            .collect();
    -        let utxos_deps = utxos_deps(db, &txs_raw_in_db)?;
    -
    -        // download new txs and headers
    -        let new_txs = maybe_await!(self.download_and_save_needed_raw_txs(
    -            &history_txs_id,
    -            &txs_raw_in_db,
    -            chunk_size,
    -            db
    -        ))?;
    -        let new_timestamps = maybe_await!(self.download_needed_headers(
    -            &txid_height,
    -            &txs_details_in_db,
    -            chunk_size
    -        ))?;
    -
    -        let mut batch = db.begin_batch();
    -
    -        // save any tx details not in db but in history_txs_id or with different height/timestamp
    -        for txid in history_txs_id.iter() {
    -            let height = txid_height.get(txid).cloned().flatten();
    -            let timestamp = new_timestamps.get(txid).cloned();
    -            if let Some(tx_details) = txs_details_in_db.get(txid) {
    -                // check if tx height matches, otherwise updates it. timestamp is not in the if clause
    -                // because we are not asking headers for confirmed tx we know about
    -                if tx_details.confirmation_time.as_ref().map(|c| c.height) != height {
    -                    let confirmation_time = ConfirmationTime::new(height, timestamp);
    -                    let mut new_tx_details = tx_details.clone();
    -                    new_tx_details.confirmation_time = confirmation_time;
    -                    batch.set_tx(&new_tx_details)?;
    -                }
    -            } else {
    -                save_transaction_details_and_utxos(
    -                    txid,
    -                    db,
    -                    timestamp,
    -                    height,
    -                    &mut batch,
    -                    &utxos_deps,
    -                )?;
    -            }
    -        }
    -
    -        // remove any tx details in db but not in history_txs_id
    -        for txid in txs_details_in_db.keys() {
    -            if !history_txs_id.contains(txid) {
    -                batch.del_tx(txid, false)?;
    -            }
    -        }
    -
    -        // remove any spent utxo
    -        for new_tx in new_txs.iter() {
    -            for input in new_tx.input.iter() {
    -                batch.del_utxo(&input.previous_output)?;
    -            }
    -        }
    -
    -        db.commit_batch(batch)?;
    -        info!("finish setup, elapsed {:?}ms", start.elapsed().as_millis());
    -
    -        Ok(())
    -    }
    -
    -    /// download txs identified by `history_txs_id` and theirs previous outputs if not already present in db
    -    fn download_and_save_needed_raw_txs<D: BatchDatabase>(
    -        &self,
    -        history_txs_id: &HashSet<Txid>,
    -        txs_raw_in_db: &HashMap<Txid, Transaction>,
    -        chunk_size: usize,
    -        db: &mut D,
    -    ) -> Result<Vec<Transaction>, Error> {
    -        let mut txs_downloaded = vec![];
    -        let txids_raw_in_db: HashSet<Txid> = txs_raw_in_db.keys().cloned().collect();
    -        let txids_to_download: Vec<&Txid> = history_txs_id.difference(&txids_raw_in_db).collect();
    -        if !txids_to_download.is_empty() {
    -            info!("got {} txs to download", txids_to_download.len());
    -            txs_downloaded.extend(maybe_await!(self.download_and_save_in_chunks(
    -                txids_to_download,
    -                chunk_size,
    -                db,
    -            ))?);
    -            let mut prev_txids = HashSet::new();
    -            let mut txids_downloaded = HashSet::new();
    -            for tx in txs_downloaded.iter() {
    -                txids_downloaded.insert(tx.txid());
    -                // add every previous input tx, but skip coinbase
    -                for input in tx.input.iter().filter(|i| !i.previous_output.is_null()) {
    -                    prev_txids.insert(input.previous_output.txid);
    -                }
    -            }
    -            let already_present: HashSet<Txid> =
    -                txids_downloaded.union(&txids_raw_in_db).cloned().collect();
    -            let prev_txs_to_download: Vec<&Txid> =
    -                prev_txids.difference(&already_present).collect();
    -            info!("{} previous txs to download", prev_txs_to_download.len());
    -            txs_downloaded.extend(maybe_await!(self.download_and_save_in_chunks(
    -                prev_txs_to_download,
    -                chunk_size,
    -                db,
    -            ))?);
    -        }
    -
    -        Ok(txs_downloaded)
    -    }
    -
    -    /// download headers at heights in `txid_height` if tx details not already present, returns a map Txid -> timestamp
    -    fn download_needed_headers(
    -        &self,
    -        txid_height: &HashMap<Txid, Option<u32>>,
    -        txs_details_in_db: &HashMap<Txid, TransactionDetails>,
    -        chunk_size: usize,
    -    ) -> Result<HashMap<Txid, u64>, Error> {
    -        let mut txid_timestamp = HashMap::new();
    -        let txid_in_db_with_conf: HashSet<_> = txs_details_in_db
    -            .values()
    -            .filter_map(|details| details.confirmation_time.as_ref().map(|_| details.txid))
    -            .collect();
    -        let needed_txid_height: HashMap<&Txid, u32> = txid_height
    -            .iter()
    -            .filter(|(t, _)| !txid_in_db_with_conf.contains(*t))
    -            .filter_map(|(t, o)| o.map(|h| (t, h)))
    -            .collect();
    -        let needed_heights: HashSet<u32> = needed_txid_height.values().cloned().collect();
    -        if !needed_heights.is_empty() {
    -            info!("{} headers to download for timestamp", needed_heights.len());
    -            let mut height_timestamp: HashMap<u32, u64> = HashMap::new();
    -            for chunk in ChunksIterator::new(needed_heights.into_iter(), chunk_size) {
    -                let call_result: Vec<BlockHeader> =
    -                    maybe_await!(self.els_batch_block_header(chunk.clone()))?;
    -                height_timestamp.extend(
    -                    chunk
    -                        .into_iter()
    -                        .zip(call_result.iter().map(|h| h.time as u64)),
    -                );
    -            }
    -            for (txid, height) in needed_txid_height {
    -                let timestamp = height_timestamp
    -                    .get(&height)
    -                    .ok_or_else(|| Error::Generic("timestamp missing".to_string()))?;
    -                txid_timestamp.insert(*txid, *timestamp);
    -            }
    -        }
    -
    -        Ok(txid_timestamp)
    -    }
    -
    -    fn download_and_save_in_chunks<D: BatchDatabase>(
    -        &self,
    -        to_download: Vec<&Txid>,
    -        chunk_size: usize,
    -        db: &mut D,
    -    ) -> Result<Vec<Transaction>, Error> {
    -        let mut txs_downloaded = vec![];
    -        for chunk in ChunksIterator::new(to_download.into_iter(), chunk_size) {
    -            let call_result: Vec<Transaction> =
    -                maybe_await!(self.els_batch_transaction_get(chunk))?;
    -            let mut batch = db.begin_batch();
    -            for new_tx in call_result.iter() {
    -                batch.set_raw_tx(new_tx)?;
    -            }
    -            db.commit_batch(batch)?;
    -            txs_downloaded.extend(call_result);
    -        }
    -
    -        Ok(txs_downloaded)
    -    }
    -}
    -
    -fn save_transaction_details_and_utxos<D: BatchDatabase>(
    -    txid: &Txid,
    -    db: &mut D,
    -    timestamp: Option<u64>,
    -    height: Option<u32>,
    -    updates: &mut dyn BatchOperations,
    -    utxo_deps: &HashMap<OutPoint, OutPoint>,
    -) -> Result<(), Error> {
    -    let tx = db.get_raw_tx(txid)?.ok_or(Error::TransactionNotFound)?;
    -
    -    let mut incoming: u64 = 0;
    -    let mut outgoing: u64 = 0;
    -
    -    let mut inputs_sum: u64 = 0;
    -    let mut outputs_sum: u64 = 0;
    -
    -    // look for our own inputs
    -    for input in tx.input.iter() {
    -        // skip coinbase inputs
    -        if input.previous_output.is_null() {
    -            continue;
    -        }
    -
    -        // We already downloaded all previous output txs in the previous step
    -        if let Some(previous_output) = db.get_previous_output(&input.previous_output)? {
    -            inputs_sum += previous_output.value;
    -
    -            if db.is_mine(&previous_output.script_pubkey)? {
    -                outgoing += previous_output.value;
    -            }
    -        } else {
    -            // The input is not ours, but we still need to count it for the fees
    -            let tx = db
    -                .get_raw_tx(&input.previous_output.txid)?
    -                .ok_or(Error::TransactionNotFound)?;
    -            inputs_sum += tx.output[input.previous_output.vout as usize].value;
    -        }
    -
    -        // removes conflicting UTXO if any (generated from same inputs, like for example RBF)
    -        if let Some(outpoint) = utxo_deps.get(&input.previous_output) {
    -            updates.del_utxo(outpoint)?;
    -        }
    -    }
    -
    -    for (i, output) in tx.output.iter().enumerate() {
    -        // to compute the fees later
    -        outputs_sum += output.value;
    -
    -        // this output is ours, we have a path to derive it
    -        if let Some((keychain, _child)) = db.get_path_from_script_pubkey(&output.script_pubkey)? {
    -            debug!("{} output #{} is mine, adding utxo", txid, i);
    -            updates.set_utxo(&LocalUtxo {
    -                outpoint: OutPoint::new(tx.txid(), i as u32),
    -                txout: output.clone(),
    -                keychain,
    -            })?;
    -
    -            incoming += output.value;
    -        }
    -    }
    -
    -    let tx_details = TransactionDetails {
    -        txid: tx.txid(),
    -        transaction: Some(tx),
    -        received: incoming,
    -        sent: outgoing,
    -        confirmation_time: ConfirmationTime::new(height, timestamp),
    -        fee: Some(inputs_sum.saturating_sub(outputs_sum)), /* if the tx is a coinbase, fees would be negative */
    -        verified: height.is_some(),
    -    };
    -    updates.set_tx(&tx_details)?;
    -
    -    Ok(())
    -}
    -
    -/// returns utxo dependency as the inputs needed for the utxo to exist
    -/// `tx_raw_in_db` must contains utxo's generating txs or errors with [crate::Error::TransactionNotFound]
    -fn utxos_deps<D: BatchDatabase>(
    -    db: &mut D,
    -    tx_raw_in_db: &HashMap<Txid, Transaction>,
    -) -> Result<HashMap<OutPoint, OutPoint>, Error> {
    -    let utxos = db.iter_utxos()?;
    -    let mut utxos_deps = HashMap::new();
    -    for utxo in utxos {
    -        let from_tx = tx_raw_in_db
    -            .get(&utxo.outpoint.txid)
    -            .ok_or(Error::TransactionNotFound)?;
    -        for input in from_tx.input.iter() {
    -            utxos_deps.insert(input.previous_output, utxo.outpoint);
    -        }
    -    }
    -    Ok(utxos_deps)
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/database/any.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/database/any.rs.html deleted file mode 100644 index a259b301c3..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/database/any.rs.html +++ /dev/null @@ -1,834 +0,0 @@ -any.rs - source
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Runtime-checked database types
    -//!
    -//! This module provides the implementation of [`AnyDatabase`] which allows switching the
    -//! inner [`Database`] type at runtime.
    -//!
    -//! ## Example
    -//!
    -//! In this example, `wallet_memory` and `wallet_sled` have the same type of `Wallet<(), AnyDatabase>`.
    -//!
    -//! ```no_run
    -//! # use bitcoin::Network;
    -//! # use bdk::database::{AnyDatabase, MemoryDatabase};
    -//! # use bdk::{Wallet};
    -//! let memory = MemoryDatabase::default();
    -//! let wallet_memory = Wallet::new_offline("...", None, Network::Testnet, memory)?;
    -//!
    -//! # #[cfg(feature = "key-value-db")]
    -//! # {
    -//! let sled = sled::open("my-database")?.open_tree("default_tree")?;
    -//! let wallet_sled = Wallet::new_offline("...", None, Network::Testnet, sled)?;
    -//! # }
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -//!
    -//! When paired with the use of [`ConfigurableDatabase`], it allows creating wallets with any
    -//! database supported using a single line of code:
    -//!
    -//! ```no_run
    -//! # use bitcoin::Network;
    -//! # use bdk::database::*;
    -//! # use bdk::{Wallet};
    -//! let config = serde_json::from_str("...")?;
    -//! let database = AnyDatabase::from_config(&config)?;
    -//! let wallet = Wallet::new_offline("...", None, Network::Testnet, database)?;
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use super::*;
    -
    -macro_rules! impl_from {
    -    ( $from:ty, $to:ty, $variant:ident, $( $cfg:tt )* ) => {
    -        $( $cfg )*
    -        impl From<$from> for $to {
    -            fn from(inner: $from) -> Self {
    -                <$to>::$variant(inner)
    -            }
    -        }
    -    };
    -}
    -
    -macro_rules! impl_inner_method {
    -    ( $enum_name:ident, $self:expr, $name:ident $(, $args:expr)* ) => {
    -        match $self {
    -            $enum_name::Memory(inner) => inner.$name( $($args, )* ),
    -            #[cfg(feature = "key-value-db")]
    -            $enum_name::Sled(inner) => inner.$name( $($args, )* ),
    -            #[cfg(feature = "sqlite")]
    -            $enum_name::Sqlite(inner) => inner.$name( $($args, )* ),
    -        }
    -    }
    -}
    -
    -/// Type that can contain any of the [`Database`] types defined by the library
    -///
    -/// It allows switching database type at runtime.
    -///
    -/// See [this module](crate::database::any)'s documentation for a usage example.
    -#[derive(Debug)]
    -pub enum AnyDatabase {
    -    /// In-memory ephemeral database
    -    Memory(memory::MemoryDatabase),
    -    #[cfg(feature = "key-value-db")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
    -    /// Simple key-value embedded database based on [`sled`]
    -    Sled(sled::Tree),
    -    #[cfg(feature = "sqlite")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
    -    /// Sqlite embedded database using [`rusqlite`]
    -    Sqlite(sqlite::SqliteDatabase),
    -}
    -
    -impl_from!(memory::MemoryDatabase, AnyDatabase, Memory,);
    -impl_from!(sled::Tree, AnyDatabase, Sled, #[cfg(feature = "key-value-db")]);
    -impl_from!(sqlite::SqliteDatabase, AnyDatabase, Sqlite, #[cfg(feature = "sqlite")]);
    -
    -/// Type that contains any of the [`BatchDatabase::Batch`] types defined by the library
    -pub enum AnyBatch {
    -    /// In-memory ephemeral database
    -    Memory(<memory::MemoryDatabase as BatchDatabase>::Batch),
    -    #[cfg(feature = "key-value-db")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
    -    /// Simple key-value embedded database based on [`sled`]
    -    Sled(<sled::Tree as BatchDatabase>::Batch),
    -    #[cfg(feature = "sqlite")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
    -    /// Sqlite embedded database using [`rusqlite`]
    -    Sqlite(<sqlite::SqliteDatabase as BatchDatabase>::Batch),
    -}
    -
    -impl_from!(
    -    <memory::MemoryDatabase as BatchDatabase>::Batch,
    -    AnyBatch,
    -    Memory,
    -);
    -impl_from!(<sled::Tree as BatchDatabase>::Batch, AnyBatch, Sled, #[cfg(feature = "key-value-db")]);
    -impl_from!(<sqlite::SqliteDatabase as BatchDatabase>::Batch, AnyBatch, Sqlite, #[cfg(feature = "sqlite")]);
    -
    -impl BatchOperations for AnyDatabase {
    -    fn set_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<(), Error> {
    -        impl_inner_method!(
    -            AnyDatabase,
    -            self,
    -            set_script_pubkey,
    -            script,
    -            keychain,
    -            child
    -        )
    -    }
    -    fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
    -        impl_inner_method!(AnyDatabase, self, set_utxo, utxo)
    -    }
    -    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
    -        impl_inner_method!(AnyDatabase, self, set_raw_tx, transaction)
    -    }
    -    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
    -        impl_inner_method!(AnyDatabase, self, set_tx, transaction)
    -    }
    -    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
    -        impl_inner_method!(AnyDatabase, self, set_last_index, keychain, value)
    -    }
    -
    -    fn del_script_pubkey_from_path(
    -        &mut self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        impl_inner_method!(
    -            AnyDatabase,
    -            self,
    -            del_script_pubkey_from_path,
    -            keychain,
    -            child
    -        )
    -    }
    -    fn del_path_from_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        impl_inner_method!(AnyDatabase, self, del_path_from_script_pubkey, script)
    -    }
    -    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        impl_inner_method!(AnyDatabase, self, del_utxo, outpoint)
    -    }
    -    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        impl_inner_method!(AnyDatabase, self, del_raw_tx, txid)
    -    }
    -    fn del_tx(
    -        &mut self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error> {
    -        impl_inner_method!(AnyDatabase, self, del_tx, txid, include_raw)
    -    }
    -    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        impl_inner_method!(AnyDatabase, self, del_last_index, keychain)
    -    }
    -}
    -
    -impl Database for AnyDatabase {
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        keychain: KeychainKind,
    -        bytes: B,
    -    ) -> Result<(), Error> {
    -        impl_inner_method!(
    -            AnyDatabase,
    -            self,
    -            check_descriptor_checksum,
    -            keychain,
    -            bytes
    -        )
    -    }
    -
    -    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
    -        impl_inner_method!(AnyDatabase, self, iter_script_pubkeys, keychain)
    -    }
    -    fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
    -        impl_inner_method!(AnyDatabase, self, iter_utxos)
    -    }
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
    -        impl_inner_method!(AnyDatabase, self, iter_raw_txs)
    -    }
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        impl_inner_method!(AnyDatabase, self, iter_txs, include_raw)
    -    }
    -
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        impl_inner_method!(
    -            AnyDatabase,
    -            self,
    -            get_script_pubkey_from_path,
    -            keychain,
    -            child
    -        )
    -    }
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        impl_inner_method!(AnyDatabase, self, get_path_from_script_pubkey, script)
    -    }
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        impl_inner_method!(AnyDatabase, self, get_utxo, outpoint)
    -    }
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        impl_inner_method!(AnyDatabase, self, get_raw_tx, txid)
    -    }
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -        impl_inner_method!(AnyDatabase, self, get_tx, txid, include_raw)
    -    }
    -    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        impl_inner_method!(AnyDatabase, self, get_last_index, keychain)
    -    }
    -
    -    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
    -        impl_inner_method!(AnyDatabase, self, increment_last_index, keychain)
    -    }
    -
    -    fn flush(&mut self) -> Result<(), Error> {
    -        impl_inner_method!(AnyDatabase, self, flush)
    -    }
    -}
    -
    -impl BatchOperations for AnyBatch {
    -    fn set_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<(), Error> {
    -        impl_inner_method!(AnyBatch, self, set_script_pubkey, script, keychain, child)
    -    }
    -    fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
    -        impl_inner_method!(AnyBatch, self, set_utxo, utxo)
    -    }
    -    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
    -        impl_inner_method!(AnyBatch, self, set_raw_tx, transaction)
    -    }
    -    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
    -        impl_inner_method!(AnyBatch, self, set_tx, transaction)
    -    }
    -    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
    -        impl_inner_method!(AnyBatch, self, set_last_index, keychain, value)
    -    }
    -
    -    fn del_script_pubkey_from_path(
    -        &mut self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_script_pubkey_from_path, keychain, child)
    -    }
    -    fn del_path_from_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_path_from_script_pubkey, script)
    -    }
    -    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_utxo, outpoint)
    -    }
    -    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_raw_tx, txid)
    -    }
    -    fn del_tx(
    -        &mut self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_tx, txid, include_raw)
    -    }
    -    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        impl_inner_method!(AnyBatch, self, del_last_index, keychain)
    -    }
    -}
    -
    -impl BatchDatabase for AnyDatabase {
    -    type Batch = AnyBatch;
    -
    -    fn begin_batch(&self) -> Self::Batch {
    -        match self {
    -            AnyDatabase::Memory(inner) => inner.begin_batch().into(),
    -            #[cfg(feature = "key-value-db")]
    -            AnyDatabase::Sled(inner) => inner.begin_batch().into(),
    -            #[cfg(feature = "sqlite")]
    -            AnyDatabase::Sqlite(inner) => inner.begin_batch().into(),
    -        }
    -    }
    -    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
    -        match self {
    -            AnyDatabase::Memory(db) => match batch {
    -                AnyBatch::Memory(batch) => db.commit_batch(batch),
    -                #[cfg(any(feature = "key-value-db", feature = "sqlite"))]
    -                _ => unimplemented!("Other batch shouldn't be used with Memory db."),
    -            },
    -            #[cfg(feature = "key-value-db")]
    -            AnyDatabase::Sled(db) => match batch {
    -                AnyBatch::Sled(batch) => db.commit_batch(batch),
    -                _ => unimplemented!("Other batch shouldn't be used with Sled db."),
    -            },
    -            #[cfg(feature = "sqlite")]
    -            AnyDatabase::Sqlite(db) => match batch {
    -                AnyBatch::Sqlite(batch) => db.commit_batch(batch),
    -                _ => unimplemented!("Other batch shouldn't be used with Sqlite db."),
    -            },
    -        }
    -    }
    -}
    -
    -/// Configuration type for a [`sled::Tree`] database
    -#[cfg(feature = "key-value-db")]
    -#[derive(Debug, serde::Serialize, serde::Deserialize)]
    -pub struct SledDbConfiguration {
    -    /// Main directory of the db
    -    pub path: String,
    -    /// Name of the database tree, a separated namespace for the data
    -    pub tree_name: String,
    -}
    -
    -#[cfg(feature = "key-value-db")]
    -impl ConfigurableDatabase for sled::Tree {
    -    type Config = SledDbConfiguration;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        Ok(sled::open(&config.path)?.open_tree(&config.tree_name)?)
    -    }
    -}
    -
    -/// Configuration type for a [`sqlite::SqliteDatabase`] database
    -#[cfg(feature = "sqlite")]
    -#[derive(Debug, serde::Serialize, serde::Deserialize)]
    -pub struct SqliteDbConfiguration {
    -    /// Main directory of the db
    -    pub path: String,
    -}
    -
    -#[cfg(feature = "sqlite")]
    -impl ConfigurableDatabase for sqlite::SqliteDatabase {
    -    type Config = SqliteDbConfiguration;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        Ok(sqlite::SqliteDatabase::new(config.path.clone()))
    -    }
    -}
    -
    -/// Type that can contain any of the database configurations defined by the library
    -///
    -/// This allows storing a single configuration that can be loaded into an [`AnyDatabase`]
    -/// instance. Wallets that plan to offer users the ability to switch blockchain backend at runtime
    -/// will find this particularly useful.
    -#[derive(Debug, serde::Serialize, serde::Deserialize)]
    -pub enum AnyDatabaseConfig {
    -    /// Memory database has no config
    -    Memory(()),
    -    #[cfg(feature = "key-value-db")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "key-value-db")))]
    -    /// Simple key-value embedded database based on [`sled`]
    -    Sled(SledDbConfiguration),
    -    #[cfg(feature = "sqlite")]
    -    #[cfg_attr(docsrs, doc(cfg(feature = "sqlite")))]
    -    /// Sqlite embedded database using [`rusqlite`]
    -    Sqlite(SqliteDbConfiguration),
    -}
    -
    -impl ConfigurableDatabase for AnyDatabase {
    -    type Config = AnyDatabaseConfig;
    -
    -    fn from_config(config: &Self::Config) -> Result<Self, Error> {
    -        Ok(match config {
    -            AnyDatabaseConfig::Memory(inner) => {
    -                AnyDatabase::Memory(memory::MemoryDatabase::from_config(inner)?)
    -            }
    -            #[cfg(feature = "key-value-db")]
    -            AnyDatabaseConfig::Sled(inner) => AnyDatabase::Sled(sled::Tree::from_config(inner)?),
    -            #[cfg(feature = "sqlite")]
    -            AnyDatabaseConfig::Sqlite(inner) => {
    -                AnyDatabase::Sqlite(sqlite::SqliteDatabase::from_config(inner)?)
    -            }
    -        })
    -    }
    -}
    -
    -impl_from!((), AnyDatabaseConfig, Memory,);
    -impl_from!(SledDbConfiguration, AnyDatabaseConfig, Sled, #[cfg(feature = "key-value-db")]);
    -impl_from!(SqliteDbConfiguration, AnyDatabaseConfig, Sqlite, #[cfg(feature = "sqlite")]);
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/database/keyvalue.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/database/keyvalue.rs.html deleted file mode 100644 index 111cc74a11..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/database/keyvalue.rs.html +++ /dev/null @@ -1,950 +0,0 @@ -keyvalue.rs - source
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -use std::convert::TryInto;
    -
    -use sled::{Batch, Tree};
    -
    -use bitcoin::consensus::encode::{deserialize, serialize};
    -use bitcoin::hash_types::Txid;
    -use bitcoin::{OutPoint, Script, Transaction};
    -
    -use crate::database::memory::MapKey;
    -use crate::database::{BatchDatabase, BatchOperations, Database};
    -use crate::error::Error;
    -use crate::types::*;
    -
    -macro_rules! impl_batch_operations {
    -    ( { $($after_insert:tt)* }, $process_delete:ident ) => {
    -        fn set_script_pubkey(&mut self, script: &Script, keychain: KeychainKind, path: u32) -> Result<(), Error> {
    -            let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -            self.insert(key, serialize(script))$($after_insert)*;
    -
    -            let key = MapKey::Script(Some(script)).as_map_key();
    -            let value = json!({
    -                "t": keychain,
    -                "p": path,
    -            });
    -            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
    -            let key = MapKey::Utxo(Some(&utxo.outpoint)).as_map_key();
    -            let value = json!({
    -                "t": utxo.txout,
    -                "i": utxo.keychain,
    -            });
    -            self.insert(key, serde_json::to_vec(&value)?)$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
    -            let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
    -            let value = serialize(transaction);
    -            self.insert(key, value)$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
    -            let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
    -
    -            // remove the raw tx from the serialized version
    -            let mut value = serde_json::to_value(transaction)?;
    -            value["transaction"] = serde_json::Value::Null;
    -            let value = serde_json::to_vec(&value)?;
    -
    -            self.insert(key, value)$($after_insert)*;
    -
    -            // insert the raw_tx if present
    -            if let Some(ref tx) = transaction.transaction {
    -                self.set_raw_tx(tx)?;
    -            }
    -
    -            Ok(())
    -        }
    -
    -        fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
    -            let key = MapKey::LastIndex(keychain).as_map_key();
    -            self.insert(key, &value.to_be_bytes())$($after_insert)*;
    -
    -            Ok(())
    -        }
    -
    -        fn del_script_pubkey_from_path(&mut self, keychain: KeychainKind, path: u32) -> Result<Option<Script>, Error> {
    -            let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
    -        }
    -
    -        fn del_path_from_script_pubkey(&mut self, script: &Script) -> Result<Option<(KeychainKind, u32)>, Error> {
    -            let key = MapKey::Script(Some(script)).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            match res {
    -                None => Ok(None),
    -                Some(b) => {
    -                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
    -                    let st = serde_json::from_value(val["t"].take())?;
    -                    let path = serde_json::from_value(val["p"].take())?;
    -
    -                    Ok(Some((st, path)))
    -                }
    -            }
    -        }
    -
    -        fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -            let key = MapKey::Utxo(Some(outpoint)).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            match res {
    -                None => Ok(None),
    -                Some(b) => {
    -                    let mut val: serde_json::Value = serde_json::from_slice(&b)?;
    -                    let txout = serde_json::from_value(val["t"].take())?;
    -                    let keychain = serde_json::from_value(val["i"].take())?;
    -
    -                    Ok(Some(LocalUtxo { outpoint: outpoint.clone(), txout, keychain }))
    -                }
    -            }
    -        }
    -
    -        fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -            let key = MapKey::RawTx(Some(txid)).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            Ok(res.map_or(Ok(None), |x| Some(deserialize(&x)).transpose())?)
    -        }
    -
    -        fn del_tx(&mut self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -            let raw_tx = if include_raw {
    -                self.del_raw_tx(txid)?
    -            } else {
    -                None
    -            };
    -
    -            let key = MapKey::Transaction(Some(txid)).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            match res {
    -                None => Ok(None),
    -                Some(b) => {
    -                    let mut val: TransactionDetails = serde_json::from_slice(&b)?;
    -                    val.transaction = raw_tx;
    -
    -                    Ok(Some(val))
    -                }
    -            }
    -        }
    -
    -        fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -            let key = MapKey::LastIndex(keychain).as_map_key();
    -            let res = self.remove(key);
    -            let res = $process_delete!(res);
    -
    -            match res {
    -                None => Ok(None),
    -                Some(b) => {
    -                    let array: [u8; 4] = b.as_ref().try_into().map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
    -                    let val = u32::from_be_bytes(array);
    -                    Ok(Some(val))
    -                }
    -            }
    -        }
    -    }
    -}
    -
    -macro_rules! process_delete_tree {
    -    ($res:expr) => {
    -        $res?
    -    };
    -}
    -impl BatchOperations for Tree {
    -    impl_batch_operations!({?}, process_delete_tree);
    -}
    -
    -macro_rules! process_delete_batch {
    -    ($res:expr) => {
    -        None as Option<sled::IVec>
    -    };
    -}
    -#[allow(unused_variables)]
    -impl BatchOperations for Batch {
    -    impl_batch_operations!({}, process_delete_batch);
    -}
    -
    -impl Database for Tree {
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        keychain: KeychainKind,
    -        bytes: B,
    -    ) -> Result<(), Error> {
    -        let key = MapKey::DescriptorChecksum(keychain).as_map_key();
    -
    -        let prev = self.get(&key)?.map(|x| x.to_vec());
    -        if let Some(val) = prev {
    -            if val == bytes.as_ref() {
    -                Ok(())
    -            } else {
    -                Err(Error::ChecksumMismatch)
    -            }
    -        } else {
    -            self.insert(&key, bytes.as_ref())?;
    -            Ok(())
    -        }
    -    }
    -
    -    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
    -        let key = MapKey::Path((keychain, None)).as_map_key();
    -        self.scan_prefix(key)
    -            .map(|x| -> Result<_, Error> {
    -                let (_, v) = x?;
    -                Ok(deserialize(&v)?)
    -            })
    -            .collect()
    -    }
    -
    -    fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
    -        let key = MapKey::Utxo(None).as_map_key();
    -        self.scan_prefix(key)
    -            .map(|x| -> Result<_, Error> {
    -                let (k, v) = x?;
    -                let outpoint = deserialize(&k[1..])?;
    -
    -                let mut val: serde_json::Value = serde_json::from_slice(&v)?;
    -                let txout = serde_json::from_value(val["t"].take())?;
    -                let keychain = serde_json::from_value(val["i"].take())?;
    -
    -                Ok(LocalUtxo {
    -                    outpoint,
    -                    txout,
    -                    keychain,
    -                })
    -            })
    -            .collect()
    -    }
    -
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
    -        let key = MapKey::RawTx(None).as_map_key();
    -        self.scan_prefix(key)
    -            .map(|x| -> Result<_, Error> {
    -                let (_, v) = x?;
    -                Ok(deserialize(&v)?)
    -            })
    -            .collect()
    -    }
    -
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        let key = MapKey::Transaction(None).as_map_key();
    -        self.scan_prefix(key)
    -            .map(|x| -> Result<_, Error> {
    -                let (k, v) = x?;
    -                let mut txdetails: TransactionDetails = serde_json::from_slice(&v)?;
    -                if include_raw {
    -                    let txid = deserialize(&k[1..])?;
    -                    txdetails.transaction = self.get_raw_tx(&txid)?;
    -                }
    -
    -                Ok(txdetails)
    -            })
    -            .collect()
    -    }
    -
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        keychain: KeychainKind,
    -        path: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
    -    }
    -
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        let key = MapKey::Script(Some(script)).as_map_key();
    -        self.get(key)?
    -            .map(|b| -> Result<_, Error> {
    -                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
    -                let st = serde_json::from_value(val["t"].take())?;
    -                let path = serde_json::from_value(val["p"].take())?;
    -
    -                Ok((st, path))
    -            })
    -            .transpose()
    -    }
    -
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        let key = MapKey::Utxo(Some(outpoint)).as_map_key();
    -        self.get(key)?
    -            .map(|b| -> Result<_, Error> {
    -                let mut val: serde_json::Value = serde_json::from_slice(&b)?;
    -                let txout = serde_json::from_value(val["t"].take())?;
    -                let keychain = serde_json::from_value(val["i"].take())?;
    -
    -                Ok(LocalUtxo {
    -                    outpoint: *outpoint,
    -                    txout,
    -                    keychain,
    -                })
    -            })
    -            .transpose()
    -    }
    -
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        let key = MapKey::RawTx(Some(txid)).as_map_key();
    -        Ok(self.get(key)?.map(|b| deserialize(&b)).transpose()?)
    -    }
    -
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -        let key = MapKey::Transaction(Some(txid)).as_map_key();
    -        self.get(key)?
    -            .map(|b| -> Result<_, Error> {
    -                let mut txdetails: TransactionDetails = serde_json::from_slice(&b)?;
    -                if include_raw {
    -                    txdetails.transaction = self.get_raw_tx(txid)?;
    -                }
    -
    -                Ok(txdetails)
    -            })
    -            .transpose()
    -    }
    -
    -    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        self.get(key)?
    -            .map(|b| -> Result<_, Error> {
    -                let array: [u8; 4] = b
    -                    .as_ref()
    -                    .try_into()
    -                    .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
    -                let val = u32::from_be_bytes(array);
    -                Ok(val)
    -            })
    -            .transpose()
    -    }
    -
    -    // inserts 0 if not present
    -    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        self.update_and_fetch(key, |prev| {
    -            let new = match prev {
    -                Some(b) => {
    -                    let array: [u8; 4] = b.try_into().unwrap_or([0; 4]);
    -                    let val = u32::from_be_bytes(array);
    -
    -                    val + 1
    -                }
    -                None => 0,
    -            };
    -
    -            Some(new.to_be_bytes().to_vec())
    -        })?
    -        .map_or(Ok(0), |b| -> Result<_, Error> {
    -            let array: [u8; 4] = b
    -                .as_ref()
    -                .try_into()
    -                .map_err(|_| Error::InvalidU32Bytes(b.to_vec()))?;
    -            let val = u32::from_be_bytes(array);
    -            Ok(val)
    -        })
    -    }
    -
    -    fn flush(&mut self) -> Result<(), Error> {
    -        Ok(Tree::flush(self).map(|_| ())?)
    -    }
    -}
    -
    -impl BatchDatabase for Tree {
    -    type Batch = sled::Batch;
    -
    -    fn begin_batch(&self) -> Self::Batch {
    -        sled::Batch::default()
    -    }
    -
    -    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
    -        Ok(self.apply_batch(batch)?)
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use lazy_static::lazy_static;
    -    use std::sync::{Arc, Condvar, Mutex, Once};
    -    use std::time::{SystemTime, UNIX_EPOCH};
    -
    -    use sled::{Db, Tree};
    -
    -    static mut COUNT: usize = 0;
    -
    -    lazy_static! {
    -        static ref DB: Arc<(Mutex<Option<Db>>, Condvar)> =
    -            Arc::new((Mutex::new(None), Condvar::new()));
    -        static ref INIT: Once = Once::new();
    -    }
    -
    -    fn get_tree() -> Tree {
    -        unsafe {
    -            let cloned = DB.clone();
    -            let (mutex, cvar) = &*cloned;
    -
    -            INIT.call_once(|| {
    -                let mut db = mutex.lock().unwrap();
    -
    -                let time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
    -                let mut dir = std::env::temp_dir();
    -                dir.push(format!("mbw_{}", time.as_nanos()));
    -
    -                *db = Some(sled::open(dir).unwrap());
    -                cvar.notify_all();
    -            });
    -
    -            let mut db = mutex.lock().unwrap();
    -            while !db.is_some() {
    -                db = cvar.wait(db).unwrap();
    -            }
    -
    -            COUNT += 1;
    -
    -            db.as_ref()
    -                .unwrap()
    -                .open_tree(format!("tree_{}", COUNT))
    -                .unwrap()
    -        }
    -    }
    -
    -    #[test]
    -    fn test_script_pubkey() {
    -        crate::database::test::test_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_batch_script_pubkey() {
    -        crate::database::test::test_batch_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_iter_script_pubkey() {
    -        crate::database::test::test_iter_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_script_pubkey() {
    -        crate::database::test::test_del_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_utxo() {
    -        crate::database::test::test_utxo(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_raw_tx() {
    -        crate::database::test::test_raw_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_tx() {
    -        crate::database::test::test_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_last_index() {
    -        crate::database::test::test_last_index(get_tree());
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/database/memory.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/database/memory.rs.html deleted file mode 100644 index 5c0d43db48..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/database/memory.rs.html +++ /dev/null @@ -1,1188 +0,0 @@ -memory.rs - source
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -482
    -483
    -484
    -485
    -486
    -487
    -488
    -489
    -490
    -491
    -492
    -493
    -494
    -495
    -496
    -497
    -498
    -499
    -500
    -501
    -502
    -503
    -504
    -505
    -506
    -507
    -508
    -509
    -510
    -511
    -512
    -513
    -514
    -515
    -516
    -517
    -518
    -519
    -520
    -521
    -522
    -523
    -524
    -525
    -526
    -527
    -528
    -529
    -530
    -531
    -532
    -533
    -534
    -535
    -536
    -537
    -538
    -539
    -540
    -541
    -542
    -543
    -544
    -545
    -546
    -547
    -548
    -549
    -550
    -551
    -552
    -553
    -554
    -555
    -556
    -557
    -558
    -559
    -560
    -561
    -562
    -563
    -564
    -565
    -566
    -567
    -568
    -569
    -570
    -571
    -572
    -573
    -574
    -575
    -576
    -577
    -578
    -579
    -580
    -581
    -582
    -583
    -584
    -585
    -586
    -587
    -588
    -589
    -590
    -591
    -592
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! In-memory ephemeral database
    -//!
    -//! This module defines an in-memory database type called [`MemoryDatabase`] that is based on a
    -//! [`BTreeMap`].
    -
    -use std::collections::BTreeMap;
    -use std::ops::Bound::{Excluded, Included};
    -
    -use bitcoin::consensus::encode::{deserialize, serialize};
    -use bitcoin::hash_types::Txid;
    -use bitcoin::{OutPoint, Script, Transaction};
    -
    -use crate::database::{BatchDatabase, BatchOperations, ConfigurableDatabase, Database};
    -use crate::error::Error;
    -use crate::types::*;
    -
    -// path -> script       p{i,e}<path> -> script
    -// script -> path       s<script> -> {i,e}<path>
    -// outpoint             u<outpoint> -> txout
    -// rawtx                r<txid> -> tx
    -// transactions         t<txid> -> tx details
    -// deriv indexes        c{i,e} -> u32
    -// descriptor checksum  d{i,e} -> vec<u8>
    -
    -pub(crate) enum MapKey<'a> {
    -    Path((Option<KeychainKind>, Option<u32>)),
    -    Script(Option<&'a Script>),
    -    Utxo(Option<&'a OutPoint>),
    -    RawTx(Option<&'a Txid>),
    -    Transaction(Option<&'a Txid>),
    -    LastIndex(KeychainKind),
    -    DescriptorChecksum(KeychainKind),
    -}
    -
    -impl MapKey<'_> {
    -    fn as_prefix(&self) -> Vec<u8> {
    -        match self {
    -            MapKey::Path((st, _)) => {
    -                let mut v = b"p".to_vec();
    -                if let Some(st) = st {
    -                    v.push(st.as_byte());
    -                }
    -                v
    -            }
    -            MapKey::Script(_) => b"s".to_vec(),
    -            MapKey::Utxo(_) => b"u".to_vec(),
    -            MapKey::RawTx(_) => b"r".to_vec(),
    -            MapKey::Transaction(_) => b"t".to_vec(),
    -            MapKey::LastIndex(st) => [b"c", st.as_ref()].concat(),
    -            MapKey::DescriptorChecksum(st) => [b"d", st.as_ref()].concat(),
    -        }
    -    }
    -
    -    fn serialize_content(&self) -> Vec<u8> {
    -        match self {
    -            MapKey::Path((_, Some(child))) => child.to_be_bytes().to_vec(),
    -            MapKey::Script(Some(s)) => serialize(*s),
    -            MapKey::Utxo(Some(s)) => serialize(*s),
    -            MapKey::RawTx(Some(s)) => serialize(*s),
    -            MapKey::Transaction(Some(s)) => serialize(*s),
    -            _ => vec![],
    -        }
    -    }
    -
    -    pub fn as_map_key(&self) -> Vec<u8> {
    -        let mut v = self.as_prefix();
    -        v.extend_from_slice(&self.serialize_content());
    -
    -        v
    -    }
    -}
    -
    -fn after(key: &[u8]) -> Vec<u8> {
    -    let mut key = key.to_owned();
    -    let mut idx = key.len();
    -    while idx > 0 {
    -        if key[idx - 1] == 0xFF {
    -            idx -= 1;
    -            continue;
    -        } else {
    -            key[idx - 1] += 1;
    -            break;
    -        }
    -    }
    -
    -    key
    -}
    -
    -/// In-memory ephemeral database
    -///
    -/// This database can be used as a temporary storage for wallets that are not kept permanently on
    -/// a device, or on platforms that don't provide a filesystem, like `wasm32`.
    -///
    -/// Once it's dropped its content will be lost.
    -///
    -/// If you are looking for a permanent storage solution, you can try with the default key-value
    -/// database called [`sled`]. See the [`database`] module documentation for more defailts.
    -///
    -/// [`database`]: crate::database
    -#[derive(Debug, Default)]
    -pub struct MemoryDatabase {
    -    map: BTreeMap<Vec<u8>, Box<dyn std::any::Any>>,
    -    deleted_keys: Vec<Vec<u8>>,
    -}
    -
    -impl MemoryDatabase {
    -    /// Create a new empty database
    -    pub fn new() -> Self {
    -        MemoryDatabase {
    -            map: BTreeMap::new(),
    -            deleted_keys: Vec::new(),
    -        }
    -    }
    -}
    -
    -impl BatchOperations for MemoryDatabase {
    -    fn set_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -        keychain: KeychainKind,
    -        path: u32,
    -    ) -> Result<(), Error> {
    -        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -        self.map.insert(key, Box::new(script.clone()));
    -
    -        let key = MapKey::Script(Some(script)).as_map_key();
    -        let value = json!({
    -            "t": keychain,
    -            "p": path,
    -        });
    -        self.map.insert(key, Box::new(value));
    -
    -        Ok(())
    -    }
    -
    -    fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
    -        let key = MapKey::Utxo(Some(&utxo.outpoint)).as_map_key();
    -        self.map
    -            .insert(key, Box::new((utxo.txout.clone(), utxo.keychain)));
    -
    -        Ok(())
    -    }
    -    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
    -        let key = MapKey::RawTx(Some(&transaction.txid())).as_map_key();
    -        self.map.insert(key, Box::new(transaction.clone()));
    -
    -        Ok(())
    -    }
    -    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
    -        let key = MapKey::Transaction(Some(&transaction.txid)).as_map_key();
    -
    -        // insert the raw_tx if present
    -        if let Some(ref tx) = transaction.transaction {
    -            self.set_raw_tx(tx)?;
    -        }
    -
    -        // remove the raw tx from the serialized version
    -        let mut transaction = transaction.clone();
    -        transaction.transaction = None;
    -
    -        self.map.insert(key, Box::new(transaction));
    -
    -        Ok(())
    -    }
    -    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        self.map.insert(key, Box::new(value));
    -
    -        Ok(())
    -    }
    -
    -    fn del_script_pubkey_from_path(
    -        &mut self,
    -        keychain: KeychainKind,
    -        path: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
    -    }
    -    fn del_path_from_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        let key = MapKey::Script(Some(script)).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        match res {
    -            None => Ok(None),
    -            Some(b) => {
    -                let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
    -                let st = serde_json::from_value(val["t"].take())?;
    -                let path = serde_json::from_value(val["p"].take())?;
    -
    -                Ok(Some((st, path)))
    -            }
    -        }
    -    }
    -    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        let key = MapKey::Utxo(Some(outpoint)).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        match res {
    -            None => Ok(None),
    -            Some(b) => {
    -                let (txout, keychain) = b.downcast_ref().cloned().unwrap();
    -                Ok(Some(LocalUtxo {
    -                    outpoint: *outpoint,
    -                    txout,
    -                    keychain,
    -                }))
    -            }
    -        }
    -    }
    -    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        let key = MapKey::RawTx(Some(txid)).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        Ok(res.map(|x| x.downcast_ref().cloned().unwrap()))
    -    }
    -    fn del_tx(
    -        &mut self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error> {
    -        let raw_tx = if include_raw {
    -            self.del_raw_tx(txid)?
    -        } else {
    -            None
    -        };
    -
    -        let key = MapKey::Transaction(Some(txid)).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        match res {
    -            None => Ok(None),
    -            Some(b) => {
    -                let mut val: TransactionDetails = b.downcast_ref().cloned().unwrap();
    -                val.transaction = raw_tx;
    -
    -                Ok(Some(val))
    -            }
    -        }
    -    }
    -    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        let res = self.map.remove(&key);
    -        self.deleted_keys.push(key);
    -
    -        match res {
    -            None => Ok(None),
    -            Some(b) => Ok(Some(*b.downcast_ref().unwrap())),
    -        }
    -    }
    -}
    -
    -impl Database for MemoryDatabase {
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        keychain: KeychainKind,
    -        bytes: B,
    -    ) -> Result<(), Error> {
    -        let key = MapKey::DescriptorChecksum(keychain).as_map_key();
    -
    -        let prev = self
    -            .map
    -            .get(&key)
    -            .map(|x| x.downcast_ref::<Vec<u8>>().unwrap());
    -        if let Some(val) = prev {
    -            if val == &bytes.as_ref().to_vec() {
    -                Ok(())
    -            } else {
    -                Err(Error::ChecksumMismatch)
    -            }
    -        } else {
    -            self.map.insert(key, Box::new(bytes.as_ref().to_vec()));
    -            Ok(())
    -        }
    -    }
    -
    -    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
    -        let key = MapKey::Path((keychain, None)).as_map_key();
    -        self.map
    -            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
    -            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
    -            .collect()
    -    }
    -
    -    fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
    -        let key = MapKey::Utxo(None).as_map_key();
    -        self.map
    -            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
    -            .map(|(k, v)| {
    -                let outpoint = deserialize(&k[1..]).unwrap();
    -                let (txout, keychain) = v.downcast_ref().cloned().unwrap();
    -                Ok(LocalUtxo {
    -                    outpoint,
    -                    txout,
    -                    keychain,
    -                })
    -            })
    -            .collect()
    -    }
    -
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
    -        let key = MapKey::RawTx(None).as_map_key();
    -        self.map
    -            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
    -            .map(|(_, v)| Ok(v.downcast_ref().cloned().unwrap()))
    -            .collect()
    -    }
    -
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        let key = MapKey::Transaction(None).as_map_key();
    -        self.map
    -            .range::<Vec<u8>, _>((Included(&key), Excluded(&after(&key))))
    -            .map(|(k, v)| {
    -                let mut txdetails: TransactionDetails = v.downcast_ref().cloned().unwrap();
    -                if include_raw {
    -                    let txid = deserialize(&k[1..])?;
    -                    txdetails.transaction = self.get_raw_tx(&txid)?;
    -                }
    -
    -                Ok(txdetails)
    -            })
    -            .collect()
    -    }
    -
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        keychain: KeychainKind,
    -        path: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let key = MapKey::Path((Some(keychain), Some(path))).as_map_key();
    -        Ok(self
    -            .map
    -            .get(&key)
    -            .map(|b| b.downcast_ref().cloned().unwrap()))
    -    }
    -
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        let key = MapKey::Script(Some(script)).as_map_key();
    -        Ok(self.map.get(&key).map(|b| {
    -            let mut val: serde_json::Value = b.downcast_ref().cloned().unwrap();
    -            let st = serde_json::from_value(val["t"].take()).unwrap();
    -            let path = serde_json::from_value(val["p"].take()).unwrap();
    -
    -            (st, path)
    -        }))
    -    }
    -
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        let key = MapKey::Utxo(Some(outpoint)).as_map_key();
    -        Ok(self.map.get(&key).map(|b| {
    -            let (txout, keychain) = b.downcast_ref().cloned().unwrap();
    -            LocalUtxo {
    -                outpoint: *outpoint,
    -                txout,
    -                keychain,
    -            }
    -        }))
    -    }
    -
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        let key = MapKey::RawTx(Some(txid)).as_map_key();
    -        Ok(self
    -            .map
    -            .get(&key)
    -            .map(|b| b.downcast_ref().cloned().unwrap()))
    -    }
    -
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -        let key = MapKey::Transaction(Some(txid)).as_map_key();
    -        Ok(self.map.get(&key).map(|b| {
    -            let mut txdetails: TransactionDetails = b.downcast_ref().cloned().unwrap();
    -            if include_raw {
    -                txdetails.transaction = self.get_raw_tx(txid).unwrap();
    -            }
    -
    -            txdetails
    -        }))
    -    }
    -
    -    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        Ok(self.map.get(&key).map(|b| *b.downcast_ref().unwrap()))
    -    }
    -
    -    // inserts 0 if not present
    -    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
    -        let key = MapKey::LastIndex(keychain).as_map_key();
    -        let value = self
    -            .map
    -            .entry(key)
    -            .and_modify(|x| *x.downcast_mut::<u32>().unwrap() += 1)
    -            .or_insert_with(|| Box::<u32>::new(0))
    -            .downcast_mut()
    -            .unwrap();
    -
    -        Ok(*value)
    -    }
    -
    -    fn flush(&mut self) -> Result<(), Error> {
    -        Ok(())
    -    }
    -}
    -
    -impl BatchDatabase for MemoryDatabase {
    -    type Batch = Self;
    -
    -    fn begin_batch(&self) -> Self::Batch {
    -        MemoryDatabase::new()
    -    }
    -
    -    fn commit_batch(&mut self, mut batch: Self::Batch) -> Result<(), Error> {
    -        for key in batch.deleted_keys.iter() {
    -            self.map.remove(key);
    -        }
    -        self.map.append(&mut batch.map);
    -        Ok(())
    -    }
    -}
    -
    -impl ConfigurableDatabase for MemoryDatabase {
    -    type Config = ();
    -
    -    fn from_config(_config: &Self::Config) -> Result<Self, Error> {
    -        Ok(MemoryDatabase::default())
    -    }
    -}
    -
    -#[macro_export]
    -#[doc(hidden)]
    -/// Artificially insert a tx in the database, as if we had found it with a `sync`. This is a hidden
    -/// macro and not a `[cfg(test)]` function so it can be called within the context of doctests which
    -/// don't have `test` set.
    -macro_rules! populate_test_db {
    -    ($db:expr, $tx_meta:expr, $current_height:expr$(,)?) => {{
    -        use std::str::FromStr;
    -        use $crate::database::BatchOperations;
    -        let mut db = $db;
    -        let tx_meta = $tx_meta;
    -        let current_height: Option<u32> = $current_height;
    -        let tx = $crate::bitcoin::Transaction {
    -            version: 1,
    -            lock_time: 0,
    -            input: vec![],
    -            output: tx_meta
    -                .output
    -                .iter()
    -                .map(|out_meta| $crate::bitcoin::TxOut {
    -                    value: out_meta.value,
    -                    script_pubkey: $crate::bitcoin::Address::from_str(&out_meta.to_address)
    -                        .unwrap()
    -                        .script_pubkey(),
    -                })
    -                .collect(),
    -        };
    -
    -        let txid = tx.txid();
    -        let confirmation_time = tx_meta
    -            .min_confirmations
    -            .map(|conf| $crate::ConfirmationTime {
    -                height: current_height.unwrap().checked_sub(conf as u32).unwrap(),
    -                timestamp: 0,
    -            });
    -
    -        let tx_details = $crate::TransactionDetails {
    -            transaction: Some(tx.clone()),
    -            txid,
    -            fee: Some(0),
    -            received: 0,
    -            sent: 0,
    -            confirmation_time,
    -            verified: current_height.is_some(),
    -        };
    -
    -        db.set_tx(&tx_details).unwrap();
    -        for (vout, out) in tx.output.iter().enumerate() {
    -            db.set_utxo(&$crate::LocalUtxo {
    -                txout: out.clone(),
    -                outpoint: $crate::bitcoin::OutPoint {
    -                    txid,
    -                    vout: vout as u32,
    -                },
    -                keychain: $crate::KeychainKind::External,
    -            })
    -            .unwrap();
    -        }
    -
    -        txid
    -    }};
    -}
    -
    -#[macro_export]
    -#[doc(hidden)]
    -/// Macro for getting a wallet for use in a doctest
    -macro_rules! doctest_wallet {
    -    () => {{
    -        use $crate::bitcoin::Network;
    -        use $crate::database::MemoryDatabase;
    -        use $crate::testutils;
    -        let descriptor = "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)";
    -        let descriptors = testutils!(@descriptors (descriptor) (descriptor));
    -
    -        let mut db = MemoryDatabase::new();
    -        let txid = populate_test_db!(
    -            &mut db,
    -            testutils! {
    -                @tx ( (@external descriptors, 0) => 500_000 ) (@confirmations 1)
    -            },
    -            Some(100),
    -        );
    -
    -        $crate::Wallet::new_offline(
    -            &descriptors.0,
    -            descriptors.1.as_ref(),
    -            Network::Regtest,
    -            db
    -        )
    -        .unwrap()
    -    }}
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use super::MemoryDatabase;
    -
    -    fn get_tree() -> MemoryDatabase {
    -        MemoryDatabase::new()
    -    }
    -
    -    #[test]
    -    fn test_script_pubkey() {
    -        crate::database::test::test_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_batch_script_pubkey() {
    -        crate::database::test::test_batch_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_iter_script_pubkey() {
    -        crate::database::test::test_iter_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_del_script_pubkey() {
    -        crate::database::test::test_del_script_pubkey(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_utxo() {
    -        crate::database::test::test_utxo(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_raw_tx() {
    -        crate::database::test::test_raw_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_tx() {
    -        crate::database::test::test_tx(get_tree());
    -    }
    -
    -    #[test]
    -    fn test_last_index() {
    -        crate::database::test::test_last_index(get_tree());
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/database/mod.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/database/mod.rs.html deleted file mode 100644 index 8dfc8a0079..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/database/mod.rs.html +++ /dev/null @@ -1,766 +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
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Database types
    -//!
    -//! This module provides the implementation of some defaults database types, along with traits that
    -//! can be implemented externally to let [`Wallet`]s use customized databases.
    -//!
    -//! It's important to note that the databases defined here only contains "blockchain-related" data.
    -//! They can be seen more as a cache than a critical piece of storage that contains secrets and
    -//! keys.
    -//!
    -//! The currently recommended database is [`sled`], which is a pretty simple key-value embedded
    -//! database written in Rust. If the `key-value-db` feature is enabled (which by default is),
    -//! this library automatically implements all the required traits for [`sled::Tree`].
    -//!
    -//! [`Wallet`]: crate::wallet::Wallet
    -
    -use bitcoin::hash_types::Txid;
    -use bitcoin::{OutPoint, Script, Transaction, TxOut};
    -
    -use crate::error::Error;
    -use crate::types::*;
    -
    -pub mod any;
    -pub use any::{AnyDatabase, AnyDatabaseConfig};
    -
    -#[cfg(feature = "key-value-db")]
    -pub(crate) mod keyvalue;
    -
    -#[cfg(feature = "sqlite")]
    -pub(crate) mod sqlite;
    -#[cfg(feature = "sqlite")]
    -pub use sqlite::SqliteDatabase;
    -
    -pub mod memory;
    -pub use memory::MemoryDatabase;
    -
    -/// Trait for operations that can be batched
    -///
    -/// This trait defines the list of operations that must be implemented on the [`Database`] type and
    -/// the [`BatchDatabase::Batch`] type.
    -pub trait BatchOperations {
    -    /// Store a script_pubkey along with its keychain and child number.
    -    fn set_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<(), Error>;
    -    /// Store a [`LocalUtxo`]
    -    fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error>;
    -    /// Store a raw transaction
    -    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error>;
    -    /// Store the metadata of a transaction
    -    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error>;
    -    /// Store the last derivation index for a given keychain.
    -    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error>;
    -
    -    /// Delete a script_pubkey given the keychain and its child number.
    -    fn del_script_pubkey_from_path(
    -        &mut self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error>;
    -    /// Delete the data related to a specific script_pubkey, meaning the keychain and the child
    -    /// number.
    -    fn del_path_from_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error>;
    -    /// Delete a [`LocalUtxo`] given its [`OutPoint`]
    -    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error>;
    -    /// Delete a raw transaction given its [`Txid`]
    -    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error>;
    -    /// Delete the metadata of a transaction and optionally the raw transaction itself
    -    fn del_tx(
    -        &mut self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error>;
    -    /// Delete the last derivation index for a keychain.
    -    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error>;
    -}
    -
    -/// Trait for reading data from a database
    -///
    -/// This traits defines the operations that can be used to read data out of a database
    -pub trait Database: BatchOperations {
    -    /// Read and checks the descriptor checksum for a given keychain.
    -    ///
    -    /// Should return [`Error::ChecksumMismatch`](crate::error::Error::ChecksumMismatch) if the
    -    /// checksum doesn't match. If there's no checksum in the database, simply store it for the
    -    /// next time.
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        keychain: KeychainKind,
    -        bytes: B,
    -    ) -> Result<(), Error>;
    -
    -    /// Return the list of script_pubkeys
    -    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error>;
    -    /// Return the list of [`LocalUtxo`]s
    -    fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error>;
    -    /// Return the list of raw transactions
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error>;
    -    /// Return the list of transactions metadata
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error>;
    -
    -    /// Fetch a script_pubkey given the child number of a keychain.
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error>;
    -    /// Fetch the keychain and child number of a given script_pubkey
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error>;
    -    /// Fetch a [`LocalUtxo`] given its [`OutPoint`]
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error>;
    -    /// Fetch a raw transaction given its [`Txid`]
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error>;
    -    /// Fetch the transaction metadata and optionally also the raw transaction
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error>;
    -    /// Return the last defivation index for a keychain.
    -    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error>;
    -
    -    /// Increment the last derivation index for a keychain and return it
    -    ///
    -    /// It should insert and return `0` if not present in the database
    -    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error>;
    -
    -    /// Force changes to be written to disk
    -    fn flush(&mut self) -> Result<(), Error>;
    -}
    -
    -/// Trait for a database that supports batch operations
    -///
    -/// This trait defines the methods to start and apply a batch of operations.
    -pub trait BatchDatabase: Database {
    -    /// Container for the operations
    -    type Batch: BatchOperations;
    -
    -    /// Create a new batch container
    -    fn begin_batch(&self) -> Self::Batch;
    -    /// Consume and apply a batch of operations
    -    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error>;
    -}
    -
    -/// Trait for [`Database`] types that can be created given a configuration
    -pub trait ConfigurableDatabase: Database + Sized {
    -    /// Type that contains the configuration
    -    type Config: std::fmt::Debug;
    -
    -    /// Create a new instance given a configuration
    -    fn from_config(config: &Self::Config) -> Result<Self, Error>;
    -}
    -
    -pub(crate) trait DatabaseUtils: Database {
    -    fn is_mine(&self, script: &Script) -> Result<bool, Error> {
    -        self.get_path_from_script_pubkey(script)
    -            .map(|o| o.is_some())
    -    }
    -
    -    fn get_raw_tx_or<D>(&self, txid: &Txid, default: D) -> Result<Option<Transaction>, Error>
    -    where
    -        D: FnOnce() -> Result<Option<Transaction>, Error>,
    -    {
    -        self.get_tx(txid, true)?
    -            .map(|t| t.transaction)
    -            .flatten()
    -            .map_or_else(default, |t| Ok(Some(t)))
    -    }
    -
    -    fn get_previous_output(&self, outpoint: &OutPoint) -> Result<Option<TxOut>, Error> {
    -        self.get_raw_tx(&outpoint.txid)?
    -            .map(|previous_tx| {
    -                if outpoint.vout as usize >= previous_tx.output.len() {
    -                    Err(Error::InvalidOutpoint(*outpoint))
    -                } else {
    -                    Ok(previous_tx.output[outpoint.vout as usize].clone())
    -                }
    -            })
    -            .transpose()
    -    }
    -}
    -
    -impl<T: Database> DatabaseUtils for T {}
    -
    -#[cfg(test)]
    -pub mod test {
    -    use std::str::FromStr;
    -
    -    use bitcoin::consensus::encode::deserialize;
    -    use bitcoin::hashes::hex::*;
    -    use bitcoin::*;
    -
    -    use super::*;
    -
    -    pub fn test_script_pubkey<D: Database>(mut tree: D) {
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let keychain = KeychainKind::External;
    -
    -        tree.set_script_pubkey(&script, keychain, path).unwrap();
    -
    -        assert_eq!(
    -            tree.get_script_pubkey_from_path(keychain, path).unwrap(),
    -            Some(script.clone())
    -        );
    -        assert_eq!(
    -            tree.get_path_from_script_pubkey(&script).unwrap(),
    -            Some((keychain, path))
    -        );
    -    }
    -
    -    pub fn test_batch_script_pubkey<D: BatchDatabase>(mut tree: D) {
    -        let mut batch = tree.begin_batch();
    -
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let keychain = KeychainKind::External;
    -
    -        batch.set_script_pubkey(&script, keychain, path).unwrap();
    -
    -        assert_eq!(
    -            tree.get_script_pubkey_from_path(keychain, path).unwrap(),
    -            None
    -        );
    -        assert_eq!(tree.get_path_from_script_pubkey(&script).unwrap(), None);
    -
    -        tree.commit_batch(batch).unwrap();
    -
    -        assert_eq!(
    -            tree.get_script_pubkey_from_path(keychain, path).unwrap(),
    -            Some(script.clone())
    -        );
    -        assert_eq!(
    -            tree.get_path_from_script_pubkey(&script).unwrap(),
    -            Some((keychain, path))
    -        );
    -    }
    -
    -    pub fn test_iter_script_pubkey<D: Database>(mut tree: D) {
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let keychain = KeychainKind::External;
    -
    -        tree.set_script_pubkey(&script, keychain, path).unwrap();
    -
    -        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 1);
    -    }
    -
    -    pub fn test_del_script_pubkey<D: Database>(mut tree: D) {
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let path = 42;
    -        let keychain = KeychainKind::External;
    -
    -        tree.set_script_pubkey(&script, keychain, path).unwrap();
    -        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 1);
    -
    -        tree.del_script_pubkey_from_path(keychain, path).unwrap();
    -        assert_eq!(tree.iter_script_pubkeys(None).unwrap().len(), 0);
    -    }
    -
    -    pub fn test_utxo<D: Database>(mut tree: D) {
    -        let outpoint = OutPoint::from_str(
    -            "5df6e0e2761359d30a8275058e299fcc0381534545f55cf43e41983f5d4c9456:0",
    -        )
    -        .unwrap();
    -        let script = Script::from(
    -            Vec::<u8>::from_hex("76a91402306a7c23f3e8010de41e9e591348bb83f11daa88ac").unwrap(),
    -        );
    -        let txout = TxOut {
    -            value: 133742,
    -            script_pubkey: script,
    -        };
    -        let utxo = LocalUtxo {
    -            txout,
    -            outpoint,
    -            keychain: KeychainKind::External,
    -        };
    -
    -        tree.set_utxo(&utxo).unwrap();
    -
    -        assert_eq!(tree.get_utxo(&outpoint).unwrap(), Some(utxo));
    -    }
    -
    -    pub fn test_raw_tx<D: Database>(mut tree: D) {
    -        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
    -        let tx: Transaction = deserialize(&hex_tx).unwrap();
    -
    -        tree.set_raw_tx(&tx).unwrap();
    -
    -        let txid = tx.txid();
    -
    -        assert_eq!(tree.get_raw_tx(&txid).unwrap(), Some(tx));
    -    }
    -
    -    pub fn test_tx<D: Database>(mut tree: D) {
    -        let hex_tx = Vec::<u8>::from_hex("0100000001a15d57094aa7a21a28cb20b59aab8fc7d1149a3bdbcddba9c622e4f5f6a99ece010000006c493046022100f93bb0e7d8db7bd46e40132d1f8242026e045f03a0efe71bbb8e3f475e970d790221009337cd7f1f929f00cc6ff01f03729b069a7c21b59b1736ddfee5db5946c5da8c0121033b9b137ee87d5a812d6f506efdd37f0affa7ffc310711c06c7f3e097c9447c52ffffffff0100e1f505000000001976a9140389035a9225b3839e2bbf32d826a1e222031fd888ac00000000").unwrap();
    -        let tx: Transaction = deserialize(&hex_tx).unwrap();
    -        let txid = tx.txid();
    -        let mut tx_details = TransactionDetails {
    -            transaction: Some(tx),
    -            txid,
    -            received: 1337,
    -            sent: 420420,
    -            fee: Some(140),
    -            confirmation_time: Some(ConfirmationTime {
    -                timestamp: 123456,
    -                height: 1000,
    -            }),
    -            verified: true,
    -        };
    -
    -        tree.set_tx(&tx_details).unwrap();
    -
    -        // get with raw tx too
    -        assert_eq!(
    -            tree.get_tx(&tx_details.txid, true).unwrap(),
    -            Some(tx_details.clone())
    -        );
    -        // get only raw_tx
    -        assert_eq!(
    -            tree.get_raw_tx(&tx_details.txid).unwrap(),
    -            tx_details.transaction
    -        );
    -
    -        // now get without raw_tx
    -        tx_details.transaction = None;
    -        assert_eq!(
    -            tree.get_tx(&tx_details.txid, false).unwrap(),
    -            Some(tx_details)
    -        );
    -    }
    -
    -    pub fn test_last_index<D: Database>(mut tree: D) {
    -        tree.set_last_index(KeychainKind::External, 1337).unwrap();
    -
    -        assert_eq!(
    -            tree.get_last_index(KeychainKind::External).unwrap(),
    -            Some(1337)
    -        );
    -        assert_eq!(tree.get_last_index(KeychainKind::Internal).unwrap(), None);
    -
    -        let res = tree.increment_last_index(KeychainKind::External).unwrap();
    -        assert_eq!(res, 1338);
    -        let res = tree.increment_last_index(KeychainKind::Internal).unwrap();
    -        assert_eq!(res, 0);
    -
    -        assert_eq!(
    -            tree.get_last_index(KeychainKind::External).unwrap(),
    -            Some(1338)
    -        );
    -        assert_eq!(
    -            tree.get_last_index(KeychainKind::Internal).unwrap(),
    -            Some(0)
    -        );
    -    }
    -
    -    // TODO: more tests...
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/database/sqlite.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/database/sqlite.rs.html deleted file mode 100644 index ff5e01c5bf..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/database/sqlite.rs.html +++ /dev/null @@ -1,1940 +0,0 @@ -sqlite.rs - source
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -191
    -192
    -193
    -194
    -195
    -196
    -197
    -198
    -199
    -200
    -201
    -202
    -203
    -204
    -205
    -206
    -207
    -208
    -209
    -210
    -211
    -212
    -213
    -214
    -215
    -216
    -217
    -218
    -219
    -220
    -221
    -222
    -223
    -224
    -225
    -226
    -227
    -228
    -229
    -230
    -231
    -232
    -233
    -234
    -235
    -236
    -237
    -238
    -239
    -240
    -241
    -242
    -243
    -244
    -245
    -246
    -247
    -248
    -249
    -250
    -251
    -252
    -253
    -254
    -255
    -256
    -257
    -258
    -259
    -260
    -261
    -262
    -263
    -264
    -265
    -266
    -267
    -268
    -269
    -270
    -271
    -272
    -273
    -274
    -275
    -276
    -277
    -278
    -279
    -280
    -281
    -282
    -283
    -284
    -285
    -286
    -287
    -288
    -289
    -290
    -291
    -292
    -293
    -294
    -295
    -296
    -297
    -298
    -299
    -300
    -301
    -302
    -303
    -304
    -305
    -306
    -307
    -308
    -309
    -310
    -311
    -312
    -313
    -314
    -315
    -316
    -317
    -318
    -319
    -320
    -321
    -322
    -323
    -324
    -325
    -326
    -327
    -328
    -329
    -330
    -331
    -332
    -333
    -334
    -335
    -336
    -337
    -338
    -339
    -340
    -341
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -352
    -353
    -354
    -355
    -356
    -357
    -358
    -359
    -360
    -361
    -362
    -363
    -364
    -365
    -366
    -367
    -368
    -369
    -370
    -371
    -372
    -373
    -374
    -375
    -376
    -377
    -378
    -379
    -380
    -381
    -382
    -383
    -384
    -385
    -386
    -387
    -388
    -389
    -390
    -391
    -392
    -393
    -394
    -395
    -396
    -397
    -398
    -399
    -400
    -401
    -402
    -403
    -404
    -405
    -406
    -407
    -408
    -409
    -410
    -411
    -412
    -413
    -414
    -415
    -416
    -417
    -418
    -419
    -420
    -421
    -422
    -423
    -424
    -425
    -426
    -427
    -428
    -429
    -430
    -431
    -432
    -433
    -434
    -435
    -436
    -437
    -438
    -439
    -440
    -441
    -442
    -443
    -444
    -445
    -446
    -447
    -448
    -449
    -450
    -451
    -452
    -453
    -454
    -455
    -456
    -457
    -458
    -459
    -460
    -461
    -462
    -463
    -464
    -465
    -466
    -467
    -468
    -469
    -470
    -471
    -472
    -473
    -474
    -475
    -476
    -477
    -478
    -479
    -480
    -481
    -482
    -483
    -484
    -485
    -486
    -487
    -488
    -489
    -490
    -491
    -492
    -493
    -494
    -495
    -496
    -497
    -498
    -499
    -500
    -501
    -502
    -503
    -504
    -505
    -506
    -507
    -508
    -509
    -510
    -511
    -512
    -513
    -514
    -515
    -516
    -517
    -518
    -519
    -520
    -521
    -522
    -523
    -524
    -525
    -526
    -527
    -528
    -529
    -530
    -531
    -532
    -533
    -534
    -535
    -536
    -537
    -538
    -539
    -540
    -541
    -542
    -543
    -544
    -545
    -546
    -547
    -548
    -549
    -550
    -551
    -552
    -553
    -554
    -555
    -556
    -557
    -558
    -559
    -560
    -561
    -562
    -563
    -564
    -565
    -566
    -567
    -568
    -569
    -570
    -571
    -572
    -573
    -574
    -575
    -576
    -577
    -578
    -579
    -580
    -581
    -582
    -583
    -584
    -585
    -586
    -587
    -588
    -589
    -590
    -591
    -592
    -593
    -594
    -595
    -596
    -597
    -598
    -599
    -600
    -601
    -602
    -603
    -604
    -605
    -606
    -607
    -608
    -609
    -610
    -611
    -612
    -613
    -614
    -615
    -616
    -617
    -618
    -619
    -620
    -621
    -622
    -623
    -624
    -625
    -626
    -627
    -628
    -629
    -630
    -631
    -632
    -633
    -634
    -635
    -636
    -637
    -638
    -639
    -640
    -641
    -642
    -643
    -644
    -645
    -646
    -647
    -648
    -649
    -650
    -651
    -652
    -653
    -654
    -655
    -656
    -657
    -658
    -659
    -660
    -661
    -662
    -663
    -664
    -665
    -666
    -667
    -668
    -669
    -670
    -671
    -672
    -673
    -674
    -675
    -676
    -677
    -678
    -679
    -680
    -681
    -682
    -683
    -684
    -685
    -686
    -687
    -688
    -689
    -690
    -691
    -692
    -693
    -694
    -695
    -696
    -697
    -698
    -699
    -700
    -701
    -702
    -703
    -704
    -705
    -706
    -707
    -708
    -709
    -710
    -711
    -712
    -713
    -714
    -715
    -716
    -717
    -718
    -719
    -720
    -721
    -722
    -723
    -724
    -725
    -726
    -727
    -728
    -729
    -730
    -731
    -732
    -733
    -734
    -735
    -736
    -737
    -738
    -739
    -740
    -741
    -742
    -743
    -744
    -745
    -746
    -747
    -748
    -749
    -750
    -751
    -752
    -753
    -754
    -755
    -756
    -757
    -758
    -759
    -760
    -761
    -762
    -763
    -764
    -765
    -766
    -767
    -768
    -769
    -770
    -771
    -772
    -773
    -774
    -775
    -776
    -777
    -778
    -779
    -780
    -781
    -782
    -783
    -784
    -785
    -786
    -787
    -788
    -789
    -790
    -791
    -792
    -793
    -794
    -795
    -796
    -797
    -798
    -799
    -800
    -801
    -802
    -803
    -804
    -805
    -806
    -807
    -808
    -809
    -810
    -811
    -812
    -813
    -814
    -815
    -816
    -817
    -818
    -819
    -820
    -821
    -822
    -823
    -824
    -825
    -826
    -827
    -828
    -829
    -830
    -831
    -832
    -833
    -834
    -835
    -836
    -837
    -838
    -839
    -840
    -841
    -842
    -843
    -844
    -845
    -846
    -847
    -848
    -849
    -850
    -851
    -852
    -853
    -854
    -855
    -856
    -857
    -858
    -859
    -860
    -861
    -862
    -863
    -864
    -865
    -866
    -867
    -868
    -869
    -870
    -871
    -872
    -873
    -874
    -875
    -876
    -877
    -878
    -879
    -880
    -881
    -882
    -883
    -884
    -885
    -886
    -887
    -888
    -889
    -890
    -891
    -892
    -893
    -894
    -895
    -896
    -897
    -898
    -899
    -900
    -901
    -902
    -903
    -904
    -905
    -906
    -907
    -908
    -909
    -910
    -911
    -912
    -913
    -914
    -915
    -916
    -917
    -918
    -919
    -920
    -921
    -922
    -923
    -924
    -925
    -926
    -927
    -928
    -929
    -930
    -931
    -932
    -933
    -934
    -935
    -936
    -937
    -938
    -939
    -940
    -941
    -942
    -943
    -944
    -945
    -946
    -947
    -948
    -949
    -950
    -951
    -952
    -953
    -954
    -955
    -956
    -957
    -958
    -959
    -960
    -961
    -962
    -963
    -964
    -965
    -966
    -967
    -968
    -
    // 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::consensus::encode::{deserialize, serialize};
    -use bitcoin::hash_types::Txid;
    -use bitcoin::{OutPoint, Script, Transaction, TxOut};
    -
    -use crate::database::{BatchDatabase, BatchOperations, Database};
    -use crate::error::Error;
    -use crate::types::*;
    -
    -use rusqlite::{named_params, Connection};
    -
    -static MIGRATIONS: &[&str] = &[
    -    "CREATE TABLE version (version INTEGER)",
    -    "INSERT INTO version VALUES (1)",
    -    "CREATE TABLE script_pubkeys (keychain TEXT, child INTEGER, script BLOB);",
    -    "CREATE INDEX idx_keychain_child ON script_pubkeys(keychain, child);",
    -    "CREATE INDEX idx_script ON script_pubkeys(script);",
    -    "CREATE TABLE utxos (value INTEGER, keychain TEXT, vout INTEGER, txid BLOB, script BLOB);",
    -    "CREATE INDEX idx_txid_vout ON utxos(txid, vout);",
    -    "CREATE TABLE transactions (txid BLOB, raw_tx BLOB);",
    -    "CREATE INDEX idx_txid ON transactions(txid);",
    -    "CREATE TABLE transaction_details (txid BLOB, timestamp INTEGER, received INTEGER, sent INTEGER, fee INTEGER, height INTEGER, verified INTEGER DEFAULT 0);",
    -    "CREATE INDEX idx_txdetails_txid ON transaction_details(txid);",
    -    "CREATE TABLE last_derivation_indices (keychain TEXT, value INTEGER);",
    -    "CREATE UNIQUE INDEX idx_indices_keychain ON last_derivation_indices(keychain);",
    -    "CREATE TABLE checksums (keychain TEXT, checksum BLOB);",
    -    "CREATE INDEX idx_checksums_keychain ON checksums(keychain);",
    -];
    -
    -/// Sqlite database stored on filesystem
    -///
    -/// This is a permanent storage solution for devices and platforms that provide a filesystem.
    -/// [`crate::database`]
    -#[derive(Debug)]
    -pub struct SqliteDatabase {
    -    /// Path on the local filesystem to store the sqlite file
    -    pub path: String,
    -    /// A rusqlite connection object to the sqlite database
    -    pub connection: Connection,
    -}
    -
    -impl SqliteDatabase {
    -    /// Instantiate a new SqliteDatabase instance by creating a connection
    -    /// to the database stored at path
    -    pub fn new(path: String) -> Self {
    -        let connection = get_connection(&path).unwrap();
    -        SqliteDatabase { path, connection }
    -    }
    -    fn insert_script_pubkey(
    -        &self,
    -        keychain: String,
    -        child: u32,
    -        script: &[u8],
    -    ) -> Result<i64, Error> {
    -        let mut statement = self.connection.prepare_cached("INSERT INTO script_pubkeys (keychain, child, script) VALUES (:keychain, :child, :script)")?;
    -        statement.execute(named_params! {
    -            ":keychain": keychain,
    -            ":child": child,
    -            ":script": script
    -        })?;
    -
    -        Ok(self.connection.last_insert_rowid())
    -    }
    -    fn insert_utxo(
    -        &self,
    -        value: u64,
    -        keychain: String,
    -        vout: u32,
    -        txid: &[u8],
    -        script: &[u8],
    -    ) -> Result<i64, Error> {
    -        let mut statement = self.connection.prepare_cached("INSERT INTO utxos (value, keychain, vout, txid, script) VALUES (:value, :keychain, :vout, :txid, :script)")?;
    -        statement.execute(named_params! {
    -            ":value": value,
    -            ":keychain": keychain,
    -            ":vout": vout,
    -            ":txid": txid,
    -            ":script": script
    -        })?;
    -
    -        Ok(self.connection.last_insert_rowid())
    -    }
    -    fn insert_transaction(&self, txid: &[u8], raw_tx: &[u8]) -> Result<i64, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("INSERT INTO transactions (txid, raw_tx) VALUES (:txid, :raw_tx)")?;
    -        statement.execute(named_params! {
    -            ":txid": txid,
    -            ":raw_tx": raw_tx,
    -        })?;
    -
    -        Ok(self.connection.last_insert_rowid())
    -    }
    -
    -    fn update_transaction(&self, txid: &[u8], raw_tx: &[u8]) -> Result<(), Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("UPDATE transactions SET raw_tx=:raw_tx WHERE txid=:txid")?;
    -
    -        statement.execute(named_params! {
    -            ":txid": txid,
    -            ":raw_tx": raw_tx,
    -        })?;
    -
    -        Ok(())
    -    }
    -
    -    fn insert_transaction_details(&self, transaction: &TransactionDetails) -> Result<i64, Error> {
    -        let (timestamp, height) = match &transaction.confirmation_time {
    -            Some(confirmation_time) => (
    -                Some(confirmation_time.timestamp),
    -                Some(confirmation_time.height),
    -            ),
    -            None => (None, None),
    -        };
    -
    -        let txid: &[u8] = &transaction.txid;
    -
    -        let mut statement = self.connection.prepare_cached("INSERT INTO transaction_details (txid, timestamp, received, sent, fee, height, verified) VALUES (:txid, :timestamp, :received, :sent, :fee, :height, :verified)")?;
    -
    -        statement.execute(named_params! {
    -            ":txid": txid,
    -            ":timestamp": timestamp,
    -            ":received": transaction.received,
    -            ":sent": transaction.sent,
    -            ":fee": transaction.fee,
    -            ":height": height,
    -            ":verified": transaction.verified
    -        })?;
    -
    -        Ok(self.connection.last_insert_rowid())
    -    }
    -
    -    fn update_transaction_details(&self, transaction: &TransactionDetails) -> Result<(), Error> {
    -        let (timestamp, height) = match &transaction.confirmation_time {
    -            Some(confirmation_time) => (
    -                Some(confirmation_time.timestamp),
    -                Some(confirmation_time.height),
    -            ),
    -            None => (None, None),
    -        };
    -
    -        let txid: &[u8] = &transaction.txid;
    -
    -        let mut statement = self.connection.prepare_cached("UPDATE transaction_details SET timestamp=:timestamp, received=:received, sent=:sent, fee=:fee, height=:height, verified=:verified WHERE txid=:txid")?;
    -
    -        statement.execute(named_params! {
    -            ":txid": txid,
    -            ":timestamp": timestamp,
    -            ":received": transaction.received,
    -            ":sent": transaction.sent,
    -            ":fee": transaction.fee,
    -            ":height": height,
    -            ":verified": transaction.verified,
    -        })?;
    -
    -        Ok(())
    -    }
    -
    -    fn insert_last_derivation_index(&self, keychain: String, value: u32) -> Result<i64, Error> {
    -        let mut statement = self.connection.prepare_cached(
    -            "INSERT INTO last_derivation_indices (keychain, value) VALUES (:keychain, :value)",
    -        )?;
    -
    -        statement.execute(named_params! {
    -            ":keychain": keychain,
    -            ":value": value,
    -        })?;
    -
    -        Ok(self.connection.last_insert_rowid())
    -    }
    -
    -    fn insert_checksum(&self, keychain: String, checksum: &[u8]) -> Result<i64, Error> {
    -        let mut statement = self.connection.prepare_cached(
    -            "INSERT INTO checksums (keychain, checksum) VALUES (:keychain, :checksum)",
    -        )?;
    -        statement.execute(named_params! {
    -            ":keychain": keychain,
    -            ":checksum": checksum,
    -        })?;
    -
    -        Ok(self.connection.last_insert_rowid())
    -    }
    -
    -    fn update_last_derivation_index(&self, keychain: String, value: u32) -> Result<(), Error> {
    -        let mut statement = self.connection.prepare_cached(
    -            "INSERT INTO last_derivation_indices (keychain, value) VALUES (:keychain, :value) ON CONFLICT(keychain) DO UPDATE SET value=:value WHERE keychain=:keychain",
    -        )?;
    -
    -        statement.execute(named_params! {
    -            ":keychain": keychain,
    -            ":value": value,
    -        })?;
    -
    -        Ok(())
    -    }
    -
    -    fn select_script_pubkeys(&self) -> Result<Vec<Script>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT script FROM script_pubkeys")?;
    -        let mut scripts: Vec<Script> = vec![];
    -        let mut rows = statement.query([])?;
    -        while let Some(row) = rows.next()? {
    -            let raw_script: Vec<u8> = row.get(0)?;
    -            scripts.push(raw_script.into());
    -        }
    -
    -        Ok(scripts)
    -    }
    -
    -    fn select_script_pubkeys_by_keychain(&self, keychain: String) -> Result<Vec<Script>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT script FROM script_pubkeys WHERE keychain=:keychain")?;
    -        let mut scripts: Vec<Script> = vec![];
    -        let mut rows = statement.query(named_params! {":keychain": keychain})?;
    -        while let Some(row) = rows.next()? {
    -            let raw_script: Vec<u8> = row.get(0)?;
    -            scripts.push(raw_script.into());
    -        }
    -
    -        Ok(scripts)
    -    }
    -
    -    fn select_script_pubkey_by_path(
    -        &self,
    -        keychain: String,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let mut statement = self.connection.prepare_cached(
    -            "SELECT script FROM script_pubkeys WHERE keychain=:keychain AND child=:child",
    -        )?;
    -        let mut rows = statement.query(named_params! {":keychain": keychain,":child": child})?;
    -
    -        match rows.next()? {
    -            Some(row) => {
    -                let script: Vec<u8> = row.get(0)?;
    -                let script: Script = script.into();
    -                Ok(Some(script))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn select_script_pubkey_by_script(
    -        &self,
    -        script: &[u8],
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT keychain, child FROM script_pubkeys WHERE script=:script")?;
    -        let mut rows = statement.query(named_params! {":script": script})?;
    -        match rows.next()? {
    -            Some(row) => {
    -                let keychain: String = row.get(0)?;
    -                let keychain: KeychainKind = serde_json::from_str(&keychain)?;
    -                let child: u32 = row.get(1)?;
    -                Ok(Some((keychain, child)))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn select_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT value, keychain, vout, txid, script FROM utxos")?;
    -        let mut utxos: Vec<LocalUtxo> = vec![];
    -        let mut rows = statement.query([])?;
    -        while let Some(row) = rows.next()? {
    -            let value = row.get(0)?;
    -            let keychain: String = row.get(1)?;
    -            let vout = row.get(2)?;
    -            let txid: Vec<u8> = row.get(3)?;
    -            let script: Vec<u8> = row.get(4)?;
    -
    -            let keychain: KeychainKind = serde_json::from_str(&keychain)?;
    -
    -            utxos.push(LocalUtxo {
    -                outpoint: OutPoint::new(deserialize(&txid)?, vout),
    -                txout: TxOut {
    -                    value,
    -                    script_pubkey: script.into(),
    -                },
    -                keychain,
    -            })
    -        }
    -
    -        Ok(utxos)
    -    }
    -
    -    fn select_utxo_by_outpoint(
    -        &self,
    -        txid: &[u8],
    -        vout: u32,
    -    ) -> Result<Option<(u64, KeychainKind, Script)>, Error> {
    -        let mut statement = self.connection.prepare_cached(
    -            "SELECT value, keychain, script FROM utxos WHERE txid=:txid AND vout=:vout",
    -        )?;
    -        let mut rows = statement.query(named_params! {":txid": txid,":vout": vout})?;
    -        match rows.next()? {
    -            Some(row) => {
    -                let value: u64 = row.get(0)?;
    -                let keychain: String = row.get(1)?;
    -                let keychain: KeychainKind = serde_json::from_str(&keychain)?;
    -                let script: Vec<u8> = row.get(2)?;
    -                let script: Script = script.into();
    -
    -                Ok(Some((value, keychain, script)))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn select_transactions(&self) -> Result<Vec<Transaction>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT raw_tx FROM transactions")?;
    -        let mut txs: Vec<Transaction> = vec![];
    -        let mut rows = statement.query([])?;
    -        while let Some(row) = rows.next()? {
    -            let raw_tx: Vec<u8> = row.get(0)?;
    -            let tx: Transaction = deserialize(&raw_tx)?;
    -            txs.push(tx);
    -        }
    -        Ok(txs)
    -    }
    -
    -    fn select_transaction_by_txid(&self, txid: &[u8]) -> Result<Option<Transaction>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT raw_tx FROM transactions WHERE txid=:txid")?;
    -        let mut rows = statement.query(named_params! {":txid": txid})?;
    -        match rows.next()? {
    -            Some(row) => {
    -                let raw_tx: Vec<u8> = row.get(0)?;
    -                let tx: Transaction = deserialize(&raw_tx)?;
    -                Ok(Some(tx))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn select_transaction_details_with_raw(&self) -> Result<Vec<TransactionDetails>, Error> {
    -        let mut statement = self.connection.prepare_cached("SELECT transaction_details.txid, transaction_details.timestamp, transaction_details.received, transaction_details.sent, transaction_details.fee, transaction_details.height, transaction_details.verified, transactions.raw_tx FROM transaction_details, transactions WHERE transaction_details.txid = transactions.txid")?;
    -        let mut transaction_details: Vec<TransactionDetails> = vec![];
    -        let mut rows = statement.query([])?;
    -        while let Some(row) = rows.next()? {
    -            let txid: Vec<u8> = row.get(0)?;
    -            let txid: Txid = deserialize(&txid)?;
    -            let timestamp: Option<u64> = row.get(1)?;
    -            let received: u64 = row.get(2)?;
    -            let sent: u64 = row.get(3)?;
    -            let fee: Option<u64> = row.get(4)?;
    -            let height: Option<u32> = row.get(5)?;
    -            let verified: bool = row.get(6)?;
    -            let raw_tx: Option<Vec<u8>> = row.get(7)?;
    -            let tx: Option<Transaction> = match raw_tx {
    -                Some(raw_tx) => {
    -                    let tx: Transaction = deserialize(&raw_tx)?;
    -                    Some(tx)
    -                }
    -                None => None,
    -            };
    -
    -            let confirmation_time = match (height, timestamp) {
    -                (Some(height), Some(timestamp)) => Some(ConfirmationTime { height, timestamp }),
    -                _ => None,
    -            };
    -
    -            transaction_details.push(TransactionDetails {
    -                transaction: tx,
    -                txid,
    -                received,
    -                sent,
    -                fee,
    -                confirmation_time,
    -                verified,
    -            });
    -        }
    -        Ok(transaction_details)
    -    }
    -
    -    fn select_transaction_details(&self) -> Result<Vec<TransactionDetails>, Error> {
    -        let mut statement = self.connection.prepare_cached(
    -            "SELECT txid, timestamp, received, sent, fee, height, verified FROM transaction_details",
    -        )?;
    -        let mut transaction_details: Vec<TransactionDetails> = vec![];
    -        let mut rows = statement.query([])?;
    -        while let Some(row) = rows.next()? {
    -            let txid: Vec<u8> = row.get(0)?;
    -            let txid: Txid = deserialize(&txid)?;
    -            let timestamp: Option<u64> = row.get(1)?;
    -            let received: u64 = row.get(2)?;
    -            let sent: u64 = row.get(3)?;
    -            let fee: Option<u64> = row.get(4)?;
    -            let height: Option<u32> = row.get(5)?;
    -            let verified: bool = row.get(6)?;
    -
    -            let confirmation_time = match (height, timestamp) {
    -                (Some(height), Some(timestamp)) => Some(ConfirmationTime { height, timestamp }),
    -                _ => None,
    -            };
    -
    -            transaction_details.push(TransactionDetails {
    -                transaction: None,
    -                txid,
    -                received,
    -                sent,
    -                fee,
    -                confirmation_time,
    -                verified,
    -            });
    -        }
    -        Ok(transaction_details)
    -    }
    -
    -    fn select_transaction_details_by_txid(
    -        &self,
    -        txid: &[u8],
    -    ) -> Result<Option<TransactionDetails>, Error> {
    -        let mut statement = self.connection.prepare_cached("SELECT transaction_details.timestamp, transaction_details.received, transaction_details.sent, transaction_details.fee, transaction_details.height, transaction_details.verified, transactions.raw_tx FROM transaction_details, transactions WHERE transaction_details.txid=transactions.txid AND transaction_details.txid=:txid")?;
    -        let mut rows = statement.query(named_params! { ":txid": txid })?;
    -
    -        match rows.next()? {
    -            Some(row) => {
    -                let timestamp: Option<u64> = row.get(0)?;
    -                let received: u64 = row.get(1)?;
    -                let sent: u64 = row.get(2)?;
    -                let fee: Option<u64> = row.get(3)?;
    -                let height: Option<u32> = row.get(4)?;
    -                let verified: bool = row.get(5)?;
    -
    -                let raw_tx: Option<Vec<u8>> = row.get(6)?;
    -                let tx: Option<Transaction> = match raw_tx {
    -                    Some(raw_tx) => {
    -                        let tx: Transaction = deserialize(&raw_tx)?;
    -                        Some(tx)
    -                    }
    -                    None => None,
    -                };
    -
    -                let confirmation_time = match (height, timestamp) {
    -                    (Some(height), Some(timestamp)) => Some(ConfirmationTime { height, timestamp }),
    -                    _ => None,
    -                };
    -
    -                Ok(Some(TransactionDetails {
    -                    transaction: tx,
    -                    txid: deserialize(txid)?,
    -                    received,
    -                    sent,
    -                    fee,
    -                    confirmation_time,
    -                    verified,
    -                }))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn select_last_derivation_index_by_keychain(
    -        &self,
    -        keychain: String,
    -    ) -> Result<Option<u32>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT value FROM last_derivation_indices WHERE keychain=:keychain")?;
    -        let mut rows = statement.query(named_params! {":keychain": keychain})?;
    -        match rows.next()? {
    -            Some(row) => {
    -                let value: u32 = row.get(0)?;
    -                Ok(Some(value))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn select_checksum_by_keychain(&self, keychain: String) -> Result<Option<Vec<u8>>, Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("SELECT checksum FROM checksums WHERE keychain=:keychain")?;
    -        let mut rows = statement.query(named_params! {":keychain": keychain})?;
    -
    -        match rows.next()? {
    -            Some(row) => {
    -                let checksum: Vec<u8> = row.get(0)?;
    -                Ok(Some(checksum))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn delete_script_pubkey_by_path(&self, keychain: String, child: u32) -> Result<(), Error> {
    -        let mut statement = self.connection.prepare_cached(
    -            "DELETE FROM script_pubkeys WHERE keychain=:keychain AND child=:child",
    -        )?;
    -        statement.execute(named_params! {
    -            ":keychain": keychain,
    -            ":child": child
    -        })?;
    -
    -        Ok(())
    -    }
    -
    -    fn delete_script_pubkey_by_script(&self, script: &[u8]) -> Result<(), Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("DELETE FROM script_pubkeys WHERE script=:script")?;
    -        statement.execute(named_params! {
    -            ":script": script
    -        })?;
    -
    -        Ok(())
    -    }
    -
    -    fn delete_utxo_by_outpoint(&self, txid: &[u8], vout: u32) -> Result<(), Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("DELETE FROM utxos WHERE txid=:txid AND vout=:vout")?;
    -        statement.execute(named_params! {
    -            ":txid": txid,
    -            ":vout": vout
    -        })?;
    -
    -        Ok(())
    -    }
    -
    -    fn delete_transaction_by_txid(&self, txid: &[u8]) -> Result<(), Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("DELETE FROM transactions WHERE txid=:txid")?;
    -        statement.execute(named_params! {":txid": txid})?;
    -        Ok(())
    -    }
    -
    -    fn delete_transaction_details_by_txid(&self, txid: &[u8]) -> Result<(), Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("DELETE FROM transaction_details WHERE txid=:txid")?;
    -        statement.execute(named_params! {":txid": txid})?;
    -        Ok(())
    -    }
    -
    -    fn delete_last_derivation_index_by_keychain(&self, keychain: String) -> Result<(), Error> {
    -        let mut statement = self
    -            .connection
    -            .prepare_cached("DELETE FROM last_derivation_indices WHERE keychain=:keychain")?;
    -        statement.execute(named_params! {
    -            ":keychain": &keychain
    -        })?;
    -
    -        Ok(())
    -    }
    -}
    -
    -impl BatchOperations for SqliteDatabase {
    -    fn set_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<(), Error> {
    -        let keychain = serde_json::to_string(&keychain)?;
    -        self.insert_script_pubkey(keychain, child, script.as_bytes())?;
    -        Ok(())
    -    }
    -
    -    fn set_utxo(&mut self, utxo: &LocalUtxo) -> Result<(), Error> {
    -        self.insert_utxo(
    -            utxo.txout.value,
    -            serde_json::to_string(&utxo.keychain)?,
    -            utxo.outpoint.vout,
    -            &utxo.outpoint.txid,
    -            utxo.txout.script_pubkey.as_bytes(),
    -        )?;
    -        Ok(())
    -    }
    -
    -    fn set_raw_tx(&mut self, transaction: &Transaction) -> Result<(), Error> {
    -        match self.select_transaction_by_txid(&transaction.txid())? {
    -            Some(_) => {
    -                self.update_transaction(&transaction.txid(), &serialize(transaction))?;
    -            }
    -            None => {
    -                self.insert_transaction(&transaction.txid(), &serialize(transaction))?;
    -            }
    -        }
    -        Ok(())
    -    }
    -
    -    fn set_tx(&mut self, transaction: &TransactionDetails) -> Result<(), Error> {
    -        match self.select_transaction_details_by_txid(&transaction.txid)? {
    -            Some(_) => {
    -                self.update_transaction_details(transaction)?;
    -            }
    -            None => {
    -                self.insert_transaction_details(transaction)?;
    -            }
    -        }
    -
    -        if let Some(tx) = &transaction.transaction {
    -            self.set_raw_tx(tx)?;
    -        }
    -
    -        Ok(())
    -    }
    -
    -    fn set_last_index(&mut self, keychain: KeychainKind, value: u32) -> Result<(), Error> {
    -        self.update_last_derivation_index(serde_json::to_string(&keychain)?, value)?;
    -        Ok(())
    -    }
    -
    -    fn del_script_pubkey_from_path(
    -        &mut self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let keychain = serde_json::to_string(&keychain)?;
    -        let script = self.select_script_pubkey_by_path(keychain.clone(), child)?;
    -        match script {
    -            Some(script) => {
    -                self.delete_script_pubkey_by_path(keychain, child)?;
    -                Ok(Some(script))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn del_path_from_script_pubkey(
    -        &mut self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        match self.select_script_pubkey_by_script(script.as_bytes())? {
    -            Some((keychain, child)) => {
    -                self.delete_script_pubkey_by_script(script.as_bytes())?;
    -                Ok(Some((keychain, child)))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn del_utxo(&mut self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        match self.select_utxo_by_outpoint(&outpoint.txid, outpoint.vout)? {
    -            Some((value, keychain, script_pubkey)) => {
    -                self.delete_utxo_by_outpoint(&outpoint.txid, outpoint.vout)?;
    -                Ok(Some(LocalUtxo {
    -                    outpoint: *outpoint,
    -                    txout: TxOut {
    -                        value,
    -                        script_pubkey,
    -                    },
    -                    keychain,
    -                }))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn del_raw_tx(&mut self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        match self.select_transaction_by_txid(txid)? {
    -            Some(tx) => {
    -                self.delete_transaction_by_txid(txid)?;
    -                Ok(Some(tx))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn del_tx(
    -        &mut self,
    -        txid: &Txid,
    -        include_raw: bool,
    -    ) -> Result<Option<TransactionDetails>, Error> {
    -        match self.select_transaction_details_by_txid(txid)? {
    -            Some(transaction_details) => {
    -                self.delete_transaction_details_by_txid(txid)?;
    -
    -                if include_raw {
    -                    self.delete_transaction_by_txid(txid)?;
    -                }
    -                Ok(Some(transaction_details))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn del_last_index(&mut self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        let keychain = serde_json::to_string(&keychain)?;
    -        match self.select_last_derivation_index_by_keychain(keychain.clone())? {
    -            Some(value) => {
    -                self.delete_last_derivation_index_by_keychain(keychain)?;
    -
    -                Ok(Some(value))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -}
    -
    -impl Database for SqliteDatabase {
    -    fn check_descriptor_checksum<B: AsRef<[u8]>>(
    -        &mut self,
    -        keychain: KeychainKind,
    -        bytes: B,
    -    ) -> Result<(), Error> {
    -        let keychain = serde_json::to_string(&keychain)?;
    -
    -        match self.select_checksum_by_keychain(keychain.clone())? {
    -            Some(checksum) => {
    -                if checksum == bytes.as_ref().to_vec() {
    -                    Ok(())
    -                } else {
    -                    Err(Error::ChecksumMismatch)
    -                }
    -            }
    -            None => {
    -                self.insert_checksum(keychain, bytes.as_ref())?;
    -                Ok(())
    -            }
    -        }
    -    }
    -
    -    fn iter_script_pubkeys(&self, keychain: Option<KeychainKind>) -> Result<Vec<Script>, Error> {
    -        match keychain {
    -            Some(keychain) => {
    -                let keychain = serde_json::to_string(&keychain)?;
    -                self.select_script_pubkeys_by_keychain(keychain)
    -            }
    -            None => self.select_script_pubkeys(),
    -        }
    -    }
    -
    -    fn iter_utxos(&self) -> Result<Vec<LocalUtxo>, Error> {
    -        self.select_utxos()
    -    }
    -
    -    fn iter_raw_txs(&self) -> Result<Vec<Transaction>, Error> {
    -        self.select_transactions()
    -    }
    -
    -    fn iter_txs(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        match include_raw {
    -            true => self.select_transaction_details_with_raw(),
    -            false => self.select_transaction_details(),
    -        }
    -    }
    -
    -    fn get_script_pubkey_from_path(
    -        &self,
    -        keychain: KeychainKind,
    -        child: u32,
    -    ) -> Result<Option<Script>, Error> {
    -        let keychain = serde_json::to_string(&keychain)?;
    -        match self.select_script_pubkey_by_path(keychain, child)? {
    -            Some(script) => Ok(Some(script)),
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn get_path_from_script_pubkey(
    -        &self,
    -        script: &Script,
    -    ) -> Result<Option<(KeychainKind, u32)>, Error> {
    -        match self.select_script_pubkey_by_script(script.as_bytes())? {
    -            Some((keychain, child)) => Ok(Some((keychain, child))),
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn get_utxo(&self, outpoint: &OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        match self.select_utxo_by_outpoint(&outpoint.txid, outpoint.vout)? {
    -            Some((value, keychain, script_pubkey)) => Ok(Some(LocalUtxo {
    -                outpoint: *outpoint,
    -                txout: TxOut {
    -                    value,
    -                    script_pubkey,
    -                },
    -                keychain,
    -            })),
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn get_raw_tx(&self, txid: &Txid) -> Result<Option<Transaction>, Error> {
    -        match self.select_transaction_by_txid(txid)? {
    -            Some(tx) => Ok(Some(tx)),
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn get_tx(&self, txid: &Txid, include_raw: bool) -> Result<Option<TransactionDetails>, Error> {
    -        match self.select_transaction_details_by_txid(txid)? {
    -            Some(mut transaction_details) => {
    -                if !include_raw {
    -                    transaction_details.transaction = None;
    -                }
    -                Ok(Some(transaction_details))
    -            }
    -            None => Ok(None),
    -        }
    -    }
    -
    -    fn get_last_index(&self, keychain: KeychainKind) -> Result<Option<u32>, Error> {
    -        let keychain = serde_json::to_string(&keychain)?;
    -        let value = self.select_last_derivation_index_by_keychain(keychain)?;
    -        Ok(value)
    -    }
    -
    -    fn increment_last_index(&mut self, keychain: KeychainKind) -> Result<u32, Error> {
    -        let keychain_string = serde_json::to_string(&keychain)?;
    -        match self.get_last_index(keychain)? {
    -            Some(value) => {
    -                self.update_last_derivation_index(keychain_string, value + 1)?;
    -                Ok(value + 1)
    -            }
    -            None => {
    -                self.insert_last_derivation_index(keychain_string, 0)?;
    -                Ok(0)
    -            }
    -        }
    -    }
    -
    -    fn flush(&mut self) -> Result<(), Error> {
    -        Ok(())
    -    }
    -}
    -
    -impl BatchDatabase for SqliteDatabase {
    -    type Batch = SqliteDatabase;
    -
    -    fn begin_batch(&self) -> Self::Batch {
    -        let db = SqliteDatabase::new(self.path.clone());
    -        db.connection.execute("BEGIN TRANSACTION", []).unwrap();
    -        db
    -    }
    -
    -    fn commit_batch(&mut self, batch: Self::Batch) -> Result<(), Error> {
    -        batch.connection.execute("COMMIT TRANSACTION", [])?;
    -        Ok(())
    -    }
    -}
    -
    -pub fn get_connection(path: &str) -> Result<Connection, Error> {
    -    let connection = Connection::open(path)?;
    -    migrate(&connection)?;
    -    Ok(connection)
    -}
    -
    -pub fn get_schema_version(conn: &Connection) -> rusqlite::Result<i32> {
    -    let statement = conn.prepare_cached("SELECT version FROM version");
    -    match statement {
    -        Err(rusqlite::Error::SqliteFailure(e, Some(msg))) => {
    -            if msg == "no such table: version" {
    -                Ok(0)
    -            } else {
    -                Err(rusqlite::Error::SqliteFailure(e, Some(msg)))
    -            }
    -        }
    -        Ok(mut stmt) => {
    -            let mut rows = stmt.query([])?;
    -            match rows.next()? {
    -                Some(row) => {
    -                    let version: i32 = row.get(0)?;
    -                    Ok(version)
    -                }
    -                None => Ok(0),
    -            }
    -        }
    -        _ => Ok(0),
    -    }
    -}
    -
    -pub fn set_schema_version(conn: &Connection, version: i32) -> rusqlite::Result<usize> {
    -    conn.execute(
    -        "UPDATE version SET version=:version",
    -        named_params! {":version": version},
    -    )
    -}
    -
    -pub fn migrate(conn: &Connection) -> rusqlite::Result<()> {
    -    let version = get_schema_version(conn)?;
    -    let stmts = &MIGRATIONS[(version as usize)..];
    -    let mut i: i32 = version;
    -
    -    if version == MIGRATIONS.len() as i32 {
    -        log::info!("db up to date, no migration needed");
    -        return Ok(());
    -    }
    -
    -    for stmt in stmts {
    -        let res = conn.execute(stmt, []);
    -        if res.is_err() {
    -            println!("migration failed on:\n{}\n{:?}", stmt, res);
    -            break;
    -        }
    -
    -        i += 1;
    -    }
    -
    -    set_schema_version(conn, i)?;
    -
    -    Ok(())
    -}
    -
    -#[cfg(test)]
    -pub mod test {
    -    use crate::database::SqliteDatabase;
    -    use std::time::{SystemTime, UNIX_EPOCH};
    -
    -    fn get_database() -> SqliteDatabase {
    -        let time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap();
    -        let mut dir = std::env::temp_dir();
    -        dir.push(format!("bdk_{}", time.as_nanos()));
    -        SqliteDatabase::new(String::from(dir.to_str().unwrap()))
    -    }
    -
    -    #[test]
    -    fn test_script_pubkey() {
    -        crate::database::test::test_script_pubkey(get_database());
    -    }
    -
    -    #[test]
    -    fn test_batch_script_pubkey() {
    -        crate::database::test::test_batch_script_pubkey(get_database());
    -    }
    -
    -    #[test]
    -    fn test_iter_script_pubkey() {
    -        crate::database::test::test_iter_script_pubkey(get_database());
    -    }
    -
    -    #[test]
    -    fn test_del_script_pubkey() {
    -        crate::database::test::test_del_script_pubkey(get_database());
    -    }
    -
    -    #[test]
    -    fn test_utxo() {
    -        crate::database::test::test_utxo(get_database());
    -    }
    -
    -    #[test]
    -    fn test_raw_tx() {
    -        crate::database::test::test_raw_tx(get_database());
    -    }
    -
    -    #[test]
    -    fn test_tx() {
    -        crate::database::test::test_tx(get_database());
    -    }
    -
    -    #[test]
    -    fn test_last_index() {
    -        crate::database::test::test_last_index(get_database());
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/checksum.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/checksum.rs.html deleted file mode 100644 index 93562a5060..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/checksum.rs.html +++ /dev/null @@ -1,230 +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
    -
    // 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 std::iter::FromIterator;
    -
    -use crate::descriptor::DescriptorError;
    -
    -const INPUT_CHARSET: &str =  "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ ";
    -const CHECKSUM_CHARSET: &str = "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 of a descriptor
    -pub fn get_checksum(desc: &str) -> Result<String, DescriptorError> {
    -    let mut c = 1;
    -    let mut cls = 0;
    -    let mut clscount = 0;
    -    for ch in desc.chars() {
    -        let pos = INPUT_CHARSET
    -            .find(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 chars = Vec::with_capacity(8);
    -    for j in 0..8 {
    -        chars.push(
    -            CHECKSUM_CHARSET
    -                .chars()
    -                .nth(((c >> (5 * (7 - j))) & 31) as usize)
    -                .unwrap(),
    -        );
    -    }
    -
    -    Ok(String::from_iter(chars))
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use super::*;
    -    use crate::descriptor::get_checksum;
    -
    -    // test get_checksum() function; it should return the same value as Bitcoin Core
    -    #[test]
    -    fn test_get_checksum() {
    -        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)";
    -        assert_eq!(get_checksum(desc).unwrap(), "tqz0nc62");
    -
    -        let desc = "pkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/44'/1'/0'/0/*)";
    -        assert_eq!(get_checksum(desc).unwrap(), "lasegmfs");
    -    }
    -
    -    #[test]
    -    fn test_get_checksum_invalid_character() {
    -        let sparkle_heart = vec![240, 159, 146, 150];
    -        let sparkle_heart = std::str::from_utf8(&sparkle_heart)
    -            .unwrap()
    -            .chars()
    -            .next()
    -            .unwrap();
    -        let invalid_desc = format!("wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcL{}fjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)", sparkle_heart);
    -
    -        assert!(matches!(
    -            get_checksum(&invalid_desc).err(),
    -            Some(DescriptorError::InvalidDescriptorCharacter(invalid_char)) if invalid_char == sparkle_heart
    -        ));
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/derived.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/derived.rs.html deleted file mode 100644 index edd1b2714d..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/derived.rs.html +++ /dev/null @@ -1,304 +0,0 @@ -derived.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
    -
    // 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.
    -
    -//! Derived descriptor keys
    -
    -use std::cmp::Ordering;
    -use std::fmt;
    -use std::hash::{Hash, Hasher};
    -use std::ops::Deref;
    -
    -use bitcoin::hashes::hash160;
    -use bitcoin::PublicKey;
    -
    -pub use miniscript::{
    -    descriptor::KeyMap, descriptor::Wildcard, Descriptor, DescriptorPublicKey, Legacy, Miniscript,
    -    ScriptContext, Segwitv0,
    -};
    -use miniscript::{MiniscriptKey, ToPublicKey, TranslatePk};
    -
    -use crate::wallet::utils::SecpCtx;
    -
    -/// Extended [`DescriptorPublicKey`] that has been derived
    -///
    -/// Derived keys are guaranteed to never contain wildcards of any kind
    -#[derive(Debug, Clone)]
    -pub struct DerivedDescriptorKey<'s>(DescriptorPublicKey, &'s SecpCtx);
    -
    -impl<'s> DerivedDescriptorKey<'s> {
    -    /// Construct a new derived key
    -    ///
    -    /// Panics if the key is wildcard
    -    pub fn new(key: DescriptorPublicKey, secp: &'s SecpCtx) -> DerivedDescriptorKey<'s> {
    -        if let DescriptorPublicKey::XPub(xpub) = &key {
    -            assert!(xpub.wildcard == Wildcard::None)
    -        }
    -
    -        DerivedDescriptorKey(key, secp)
    -    }
    -}
    -
    -impl<'s> Deref for DerivedDescriptorKey<'s> {
    -    type Target = DescriptorPublicKey;
    -
    -    fn deref(&self) -> &Self::Target {
    -        &self.0
    -    }
    -}
    -
    -impl<'s> PartialEq for DerivedDescriptorKey<'s> {
    -    fn eq(&self, other: &Self) -> bool {
    -        self.0 == other.0
    -    }
    -}
    -
    -impl<'s> Eq for DerivedDescriptorKey<'s> {}
    -
    -impl<'s> PartialOrd for DerivedDescriptorKey<'s> {
    -    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
    -        self.0.partial_cmp(&other.0)
    -    }
    -}
    -
    -impl<'s> Ord for DerivedDescriptorKey<'s> {
    -    fn cmp(&self, other: &Self) -> Ordering {
    -        self.0.cmp(&other.0)
    -    }
    -}
    -
    -impl<'s> fmt::Display for DerivedDescriptorKey<'s> {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        self.0.fmt(f)
    -    }
    -}
    -
    -impl<'s> Hash for DerivedDescriptorKey<'s> {
    -    fn hash<H: Hasher>(&self, state: &mut H) {
    -        self.0.hash(state);
    -    }
    -}
    -
    -impl<'s> MiniscriptKey for DerivedDescriptorKey<'s> {
    -    type Hash = Self;
    -
    -    fn to_pubkeyhash(&self) -> Self::Hash {
    -        DerivedDescriptorKey(self.0.to_pubkeyhash(), self.1)
    -    }
    -
    -    fn is_uncompressed(&self) -> bool {
    -        self.0.is_uncompressed()
    -    }
    -    fn serialized_len(&self) -> usize {
    -        self.0.serialized_len()
    -    }
    -}
    -
    -impl<'s> ToPublicKey for DerivedDescriptorKey<'s> {
    -    fn to_public_key(&self) -> PublicKey {
    -        match &self.0 {
    -            DescriptorPublicKey::SinglePub(ref spub) => spub.key.to_public_key(),
    -            DescriptorPublicKey::XPub(ref xpub) => {
    -                xpub.xkey
    -                    .derive_pub(self.1, &xpub.derivation_path)
    -                    .expect("Shouldn't fail, only normal derivations")
    -                    .public_key
    -            }
    -        }
    -    }
    -
    -    fn hash_to_hash160(hash: &Self::Hash) -> hash160::Hash {
    -        hash.to_public_key().to_pubkeyhash()
    -    }
    -}
    -
    -pub(crate) trait AsDerived {
    -    // Derive a descriptor and transform all of its keys to `DerivedDescriptorKey`
    -    fn as_derived<'s>(&self, index: u32, secp: &'s SecpCtx)
    -        -> Descriptor<DerivedDescriptorKey<'s>>;
    -
    -    // Transform the keys into `DerivedDescriptorKey`.
    -    //
    -    // Panics if the descriptor is not "fixed", i.e. if it's derivable
    -    fn as_derived_fixed<'s>(&self, secp: &'s SecpCtx) -> Descriptor<DerivedDescriptorKey<'s>>;
    -}
    -
    -impl AsDerived for Descriptor<DescriptorPublicKey> {
    -    fn as_derived<'s>(
    -        &self,
    -        index: u32,
    -        secp: &'s SecpCtx,
    -    ) -> Descriptor<DerivedDescriptorKey<'s>> {
    -        self.derive(index).translate_pk_infallible(
    -            |key| DerivedDescriptorKey::new(key.clone(), secp),
    -            |key| DerivedDescriptorKey::new(key.clone(), secp),
    -        )
    -    }
    -
    -    fn as_derived_fixed<'s>(&self, secp: &'s SecpCtx) -> Descriptor<DerivedDescriptorKey<'s>> {
    -        assert!(!self.is_deriveable());
    -
    -        self.as_derived(0, secp)
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/dsl.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/dsl.rs.html deleted file mode 100644 index 4914cdfc1d..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/dsl.rs.html +++ /dev/null @@ -1,2134 +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
    -
    // 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 std::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 std::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_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_minsicript()?;
    -            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_minsicript()?;
    -            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_minsicript()?;
    -            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(
    -                    std::sync::Arc::new(a_minisc),
    -                    std::sync::Arc::new(b_minisc),
    -                ))?;
    -
    -                minisc.check_minsicript()?;
    -
    -                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(
    -                    std::sync::Arc::new(a_minisc),
    -                    std::sync::Arc::new(b_minisc),
    -                    std::sync::Arc::new(c_minisc),
    -                ))?;
    -
    -                minisc.check_minsicript()?;
    -
    -                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<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! 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(
    -                        std::sync::Arc::new(minisc),
    -                    ),
    -                )?;
    -
    -                minisc.check_minsicript()?;
    -
    -                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,
    -                std::sync::Arc::new(a_minisc),
    -                std::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,
    -                std::sync::Arc::new($crate::fragment!(false).unwrap().0),
    -                std::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,
    -                std::sync::Arc::new(a_minisc),
    -                std::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(...),sdv: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: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: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>>(())
    -/// ```
    -#[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)
    -            .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?, 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?, 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 )*)
    -    });
    -}
    -
    -#[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! 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 succedes, 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, $value)
    -    });
    -    ( older ( $value:expr ) ) => ({
    -        $crate::impl_leaf_opcode_value!(Older, $value)
    -    });
    -    ( 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): (Vec<_>, Vec<_>) = $items.into_iter().map(|(a, b, c)| (a, (b, c))).unzip();
    -        let items = items.into_iter().map(std::sync::Arc::new).collect();
    -
    -        let (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<Vec<_>, _>>()
    -            .and_then(|items| $crate::fragment!(thresh_vec($thresh, items)))
    -    });
    -    ( multi_vec ( $thresh:expr, $keys:expr ) ) => ({
    -        $crate::keys::make_multi($thresh, $keys)
    -    });
    -    ( multi ( $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<Vec<_>, _>>()
    -            .map_err($crate::descriptor::DescriptorError::Key)
    -            .and_then(|keys| $crate::keys::make_multi($thresh, keys, &secp))
    -    });
    -
    -    // `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 bitcoin::hashes::hex::ToHex;
    -    use bitcoin::secp256k1::Secp256k1;
    -    use miniscript::descriptor::{DescriptorPublicKey, DescriptorTrait, KeyMap};
    -    use miniscript::{Descriptor, Legacy, Segwitv0};
    -
    -    use std::str::FromStr;
    -
    -    use crate::descriptor::{DescriptorError, DescriptorMeta};
    -    use crate::keys::{DescriptorKey, IntoDescriptorKey, ValidNetworks};
    -    use bitcoin::network::constants::Network::{Bitcoin, Regtest, Signet, Testnet};
    -    use bitcoin::util::bip32;
    -    use bitcoin::PrivateKey;
    -
    -    use crate::descriptor::derived::AsDerived;
    -
    -    // 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 secp = Secp256k1::new();
    -
    -        let (desc, _key_map, _networks) = desc.unwrap();
    -        assert_eq!(desc.is_witness(), is_witness);
    -        assert_eq!(!desc.is_deriveable(), is_fixed);
    -        for i in 0..expected.len() {
    -            let index = i as u32;
    -            let child_desc = if !desc.is_deriveable() {
    -                desc.as_derived_fixed(&secp)
    -            } else {
    -                desc.as_derived(index, &secp)
    -            };
    -            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().as_str(), *expected.get(i).unwrap());
    -            }
    -        }
    -    }
    -
    -    // - at least one of each "type" of operator; ie. 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::ExtendedPrivKey::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::ExtendedPrivKey::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::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
    -        let path_1 = bip32::DerivationPath::from_str("m/0").unwrap();
    -
    -        let key_2 = bip32::ExtendedPrivKey::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::ExtendedPrivKey::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::ExtendedPrivKey::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::ExtendedPrivKey::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::ExtendedPrivKey::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::ExtendedPrivKey::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::ExtendedPrivKey::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,d:v:older(1),s:pk(private_key),s:pk(private_key)))).unwrap();
    -
    -        assert_eq!(descriptor.to_string(), "wsh(thresh(2,dv:older(1),s:pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c),s:pk(02e96fe52ef0e22d2f131dd425ce1893073a3c6ad20e8cac36726393dfb4856a4c)))#cfdcqs3s")
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "Miniscript(ContextError(CompressedOnly))")]
    -    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();
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/error.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/error.rs.html deleted file mode 100644 index 49cea1f62b..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/error.rs.html +++ /dev/null @@ -1,142 +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
    -
    // 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
    -
    -/// 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 multiple keys with the same BIP32 fingerprint
    -    DuplicatedKeys,
    -
    -    /// Error thrown while working with [`keys`](crate::keys)
    -    Key(crate::keys::KeyError),
    -    /// Error while extracting and manipulating policies
    -    Policy(crate::descriptor::policy::PolicyError),
    -
    -    /// Invalid character found in the descriptor checksum
    -    InvalidDescriptorCharacter(char),
    -
    -    /// BIP32 error
    -    Bip32(bitcoin::util::bip32::Error),
    -    /// Error during base58 decoding
    -    Base58(bitcoin::util::base58::Error),
    -    /// Key-related error
    -    Pk(bitcoin::util::key::Error),
    -    /// Miniscript error
    -    Miniscript(miniscript::Error),
    -    /// Hex decoding error
    -    Hex(bitcoin::hashes::hex::Error),
    -}
    -
    -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 std::fmt::Display for Error {
    -    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for Error {}
    -
    -impl_error!(bitcoin::util::bip32::Error, Bip32);
    -impl_error!(bitcoin::util::base58::Error, Base58);
    -impl_error!(bitcoin::util::key::Error, Pk);
    -impl_error!(miniscript::Error, Miniscript);
    -impl_error!(bitcoin::hashes::hex::Error, Hex);
    -impl_error!(crate::descriptor::policy::PolicyError, Policy);
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/mod.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/mod.rs.html deleted file mode 100644 index 628c70d6f8..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/mod.rs.html +++ /dev/null @@ -1,1612 +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
    -
    // 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 std::collections::{BTreeMap, HashMap, HashSet};
    -use std::ops::Deref;
    -
    -use bitcoin::util::bip32::{
    -    ChildNumber, DerivationPath, ExtendedPrivKey, ExtendedPubKey, Fingerprint, KeySource,
    -};
    -use bitcoin::util::psbt;
    -use bitcoin::{Network, PublicKey, Script, TxOut};
    -
    -use miniscript::descriptor::{DescriptorPublicKey, DescriptorType, DescriptorXKey, Wildcard};
    -pub use miniscript::{descriptor::KeyMap, Descriptor, Legacy, Miniscript, ScriptContext, Segwitv0};
    -use miniscript::{DescriptorTrait, ForEachKey, TranslatePk};
    -
    -use crate::descriptor::policy::BuildSatisfaction;
    -
    -pub mod checksum;
    -pub(crate) mod derived;
    -#[doc(hidden)]
    -pub mod dsl;
    -pub mod error;
    -pub mod policy;
    -pub mod template;
    -
    -pub use self::checksum::get_checksum;
    -use self::derived::AsDerived;
    -pub use self::derived::DerivedDescriptorKey;
    -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<'s> = Descriptor<DerivedDescriptorKey<'s>>;
    -
    -/// Alias for the type of maps that represent derivation paths in a [`psbt::Input`] or
    -/// [`psbt::Output`]
    -///
    -/// [`psbt::Input`]: bitcoin::util::psbt::Input
    -/// [`psbt::Output`]: bitcoin::util::psbt::Output
    -pub type HdKeyPaths = BTreeMap<PublicKey, 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 = if self.contains('#') {
    -            let parts: Vec<&str> = self.splitn(2, '#').collect();
    -            if !get_checksum(parts[0])
    -                .ok()
    -                .map(|computed| computed == parts[1])
    -                .unwrap_or(false)
    -            {
    -                return Err(DescriptorError::InvalidDescriptorChecksum);
    -            }
    -
    -            parts[0]
    -        } else {
    -            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;
    -
    -        let check_key = |pk: &DescriptorPublicKey| {
    -            let (pk, _, networks) = if self.0.is_witness() {
    -                let desciptor_key: DescriptorKey<miniscript::Segwitv0> =
    -                    pk.clone().into_descriptor_key()?;
    -                desciptor_key.extract(secp)?
    -            } else {
    -                let desciptor_key: DescriptorKey<miniscript::Legacy> =
    -                    pk.clone().into_descriptor_key()?;
    -                desciptor_key.extract(secp)?
    -            };
    -
    -            if networks.contains(&network) {
    -                Ok(pk)
    -            } else {
    -                Err(DescriptorError::Key(KeyError::InvalidNetwork))
    -            }
    -        };
    -
    -        // check the network for the keys
    -        let translated = self.0.translate_pk(check_key, check_key)?;
    -
    -        Ok((translated, self.1))
    -    }
    -}
    -
    -impl IntoWalletDescriptor for DescriptorTemplateOut {
    -    fn into_wallet_descriptor(
    -        self,
    -        _secp: &SecpCtx,
    -        network: Network,
    -    ) -> Result<(ExtendedDescriptor, KeyMap), DescriptorError> {
    -        let valid_networks = &self.2;
    -
    -        let fix_key = |pk: &DescriptorPublicKey| {
    -            if valid_networks.contains(&network) {
    -                // 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 = network;
    -
    -                        DescriptorPublicKey::XPub(xpub)
    -                    }
    -                    other => other.clone(),
    -                };
    -
    -                Ok(pk)
    -            } else {
    -                Err(DescriptorError::Key(KeyError::InvalidNetwork))
    -            }
    -        };
    -
    -        // fixup the network for keys that need it
    -        let translated = self.0.translate_pk(fix_key, fix_key)?;
    -
    -        Ok((translated, self.1))
    -    }
    -}
    -
    -/// 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.as_key()
    -        {
    -            return *wildcard == Wildcard::Hardened
    -                || derivation_path.into_iter().any(ChildNumber::is_hardened);
    -        }
    -
    -        false
    -    });
    -    if descriptor_contains_hardened_steps {
    -        return Err(DescriptorError::HardenedDerivationXpub);
    -    }
    -
    -    // Ensure that there are no duplicated keys
    -    let mut found_keys = HashSet::new();
    -    let descriptor_contains_duplicated_keys = descriptor.for_any_key(|k| {
    -        if let DescriptorPublicKey::XPub(xkey) = k.as_key() {
    -            let fingerprint = xkey.root_fingerprint(secp);
    -            if found_keys.contains(&fingerprint) {
    -                return true;
    -            }
    -
    -            found_keys.insert(fingerprint);
    -        }
    -
    -        false
    -    });
    -    if descriptor_contains_duplicated_keys {
    -        return Err(DescriptorError::DuplicatedKeys);
    -    }
    -
    -    Ok((descriptor, keymap))
    -}
    -
    -#[doc(hidden)]
    -/// Used internally mainly by the `descriptor!()` and `fragment!()` macros
    -pub trait CheckMiniscript<Ctx: miniscript::ScriptContext> {
    -    fn check_minsicript(&self) -> Result<(), miniscript::Error>;
    -}
    -
    -impl<Ctx: miniscript::ScriptContext, Pk: miniscript::MiniscriptKey> CheckMiniscript<Ctx>
    -    for miniscript::Miniscript<Pk, Ctx>
    -{
    -    fn check_minsicript(&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 full_path(&self, append: &[ChildNumber]) -> DerivationPath;
    -    fn root_fingerprint(&self, secp: &SecpCtx) -> Fingerprint;
    -}
    -
    -// FIXME: `InnerXKey` was made private in rust-miniscript, so we have to implement this manually on
    -// both `ExtendedPubKey` and `ExtendedPrivKey`.
    -//
    -// Revert back to using the trait once https://github.com/rust-bitcoin/rust-miniscript/pull/230 is
    -// released
    -impl XKeyUtils for DescriptorXKey<ExtendedPubKey> {
    -    fn full_path(&self, append: &[ChildNumber]) -> DerivationPath {
    -        let full_path = match self.origin {
    -            Some((_, ref path)) => path
    -                .into_iter()
    -                .chain(self.derivation_path.into_iter())
    -                .cloned()
    -                .collect(),
    -            None => self.derivation_path.clone(),
    -        };
    -
    -        if self.wildcard != Wildcard::None {
    -            full_path
    -                .into_iter()
    -                .chain(append.iter())
    -                .cloned()
    -                .collect()
    -        } else {
    -            full_path
    -        }
    -    }
    -
    -    fn root_fingerprint(&self, _: &SecpCtx) -> Fingerprint {
    -        match self.origin {
    -            Some((fingerprint, _)) => fingerprint,
    -            None => self.xkey.fingerprint(),
    -        }
    -    }
    -}
    -impl XKeyUtils for DescriptorXKey<ExtendedPrivKey> {
    -    fn full_path(&self, append: &[ChildNumber]) -> DerivationPath {
    -        let full_path = match self.origin {
    -            Some((_, ref path)) => path
    -                .into_iter()
    -                .chain(self.derivation_path.into_iter())
    -                .cloned()
    -                .collect(),
    -            None => self.derivation_path.clone(),
    -        };
    -
    -        if self.wildcard != Wildcard::None {
    -            full_path
    -                .into_iter()
    -                .chain(append.iter())
    -                .cloned()
    -                .collect()
    -        } else {
    -            full_path
    -        }
    -    }
    -
    -    fn root_fingerprint(&self, secp: &SecpCtx) -> Fingerprint {
    -        match self.origin {
    -            Some((fingerprint, _)) => fingerprint,
    -            None => self.xkey.fingerprint(secp),
    -        }
    -    }
    -}
    -
    -pub(crate) trait DerivedDescriptorMeta {
    -    fn get_hd_keypaths(&self, secp: &SecpCtx) -> Result<HdKeyPaths, DescriptorError>;
    -}
    -
    -pub(crate) trait DescriptorMeta {
    -    fn is_witness(&self) -> bool;
    -    fn get_extended_keys(&self) -> Result<Vec<DescriptorXKey<ExtendedPubKey>>, DescriptorError>;
    -    fn derive_from_hd_keypaths<'s>(
    -        &self,
    -        hd_keypaths: &HdKeyPaths,
    -        secp: &'s SecpCtx,
    -    ) -> Option<DerivedDescriptor<'s>>;
    -    fn derive_from_psbt_input<'s>(
    -        &self,
    -        psbt_input: &psbt::Input,
    -        utxo: Option<TxOut>,
    -        secp: &'s SecpCtx,
    -    ) -> Option<DerivedDescriptor<'s>>;
    -}
    -
    -pub(crate) trait DescriptorScripts {
    -    fn psbt_redeem_script(&self) -> Option<Script>;
    -    fn psbt_witness_script(&self) -> Option<Script>;
    -}
    -
    -impl<'s> DescriptorScripts for DerivedDescriptor<'s> {
    -    fn psbt_redeem_script(&self) -> Option<Script> {
    -        match self.desc_type() {
    -            DescriptorType::ShWpkh => Some(self.explicit_script()),
    -            DescriptorType::ShWsh => Some(self.explicit_script().to_v0_p2wsh()),
    -            DescriptorType::Sh => Some(self.explicit_script()),
    -            DescriptorType::Bare => Some(self.explicit_script()),
    -            DescriptorType::ShSortedMulti => Some(self.explicit_script()),
    -            _ => None,
    -        }
    -    }
    -
    -    fn psbt_witness_script(&self) -> Option<Script> {
    -        match self.desc_type() {
    -            DescriptorType::Wsh => Some(self.explicit_script()),
    -            DescriptorType::ShWsh => Some(self.explicit_script()),
    -            DescriptorType::WshSortedMulti | DescriptorType::ShWshSortedMulti => {
    -                Some(self.explicit_script())
    -            }
    -            _ => None,
    -        }
    -    }
    -}
    -
    -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 get_extended_keys(&self) -> Result<Vec<DescriptorXKey<ExtendedPubKey>>, DescriptorError> {
    -        let mut answer = Vec::new();
    -
    -        self.for_each_key(|pk| {
    -            if let DescriptorPublicKey::XPub(xpub) = pk.as_key() {
    -                answer.push(xpub.clone());
    -            }
    -
    -            true
    -        });
    -
    -        Ok(answer)
    -    }
    -
    -    fn derive_from_hd_keypaths<'s>(
    -        &self,
    -        hd_keypaths: &HdKeyPaths,
    -        secp: &'s SecpCtx,
    -    ) -> Option<DerivedDescriptor<'s>> {
    -        let index: HashMap<_, _> = hd_keypaths.values().map(|(a, b)| (a, b)).collect();
    -
    -        let mut path_found = None;
    -        self.for_each_key(|key| {
    -            if path_found.is_some() {
    -                // already found a matching path, we are done
    -                return true;
    -            }
    -
    -            if let DescriptorPublicKey::XPub(xpub) = key.as_key().deref() {
    -                // Check if the key matches one entry in our `index`. If it does, `matches()` will
    -                // return the "prefix" that matched, so we remove that prefix from the full path
    -                // found in `index` 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 derivation_path: Option<Vec<ChildNumber>> = index
    -                    .get_key_value(&root_fingerprint)
    -                    .and_then(|(fingerprint, path)| {
    -                        xpub.matches(&(**fingerprint, (*path).clone()), secp)
    -                    })
    -                    .map(|prefix| {
    -                        index
    -                            .get(&xpub.root_fingerprint(secp))
    -                            .unwrap()
    -                            .into_iter()
    -                            .skip(prefix.into_iter().count())
    -                            .cloned()
    -                            .collect()
    -                    });
    -
    -                match derivation_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)
    -                        }
    -                    }
    -                    Some(path) if xpub.wildcard == Wildcard::None && path.is_empty() => {
    -                        path_found = Some(0)
    -                    }
    -                    _ => {}
    -                }
    -            }
    -
    -            true
    -        });
    -
    -        path_found.map(|path| self.as_derived(path, secp))
    -    }
    -
    -    fn derive_from_psbt_input<'s>(
    -        &self,
    -        psbt_input: &psbt::Input,
    -        utxo: Option<TxOut>,
    -        secp: &'s SecpCtx,
    -    ) -> Option<DerivedDescriptor<'s>> {
    -        if let Some(derived) = self.derive_from_hd_keypaths(&psbt_input.bip32_derivation, secp) {
    -            return Some(derived);
    -        }
    -        if self.is_deriveable() {
    -            // We can't try to bruteforce the derivation index, exit here
    -            return None;
    -        }
    -
    -        let descriptor = self.as_derived_fixed(secp);
    -        match descriptor.desc_type() {
    -            // TODO: add pk() here
    -            DescriptorType::Pkh | DescriptorType::Wpkh | DescriptorType::ShWpkh
    -                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()
    -                        == 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()
    -                        == psbt_input.witness_script.as_ref().unwrap() =>
    -            {
    -                Some(descriptor)
    -            }
    -            _ => None,
    -        }
    -    }
    -}
    -
    -impl<'s> DerivedDescriptorMeta for DerivedDescriptor<'s> {
    -    fn get_hd_keypaths(&self, secp: &SecpCtx) -> Result<HdKeyPaths, DescriptorError> {
    -        let mut answer = BTreeMap::new();
    -        self.for_each_key(|key| {
    -            if let DescriptorPublicKey::XPub(xpub) = key.as_key().deref() {
    -                let derived_pubkey = xpub
    -                    .xkey
    -                    .derive_pub(secp, &xpub.derivation_path)
    -                    .expect("Derivation can't fail");
    -
    -                answer.insert(
    -                    derived_pubkey.public_key,
    -                    (xpub.root_fingerprint(secp), xpub.full_path(&[])),
    -                );
    -            }
    -
    -            true
    -        });
    -
    -        Ok(answer)
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::str::FromStr;
    -
    -    use bitcoin::consensus::encode::deserialize;
    -    use bitcoin::hashes::hex::FromHex;
    -    use bitcoin::secp256k1::Secp256k1;
    -    use bitcoin::util::{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::PartiallySignedTransaction = 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::PartiallySignedTransaction = 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::PartiallySignedTransaction = 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::PartiallySignedTransaction = 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 xpub = bip32::ExtendedPubKey::from_str("xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL").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 = (xpub, path).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 conver the key that supports "any_network" to the right network (testnet)
    -        let (wallet_desc, _) = desc
    -            .into_wallet_descriptor(&secp, Network::Testnet)
    -            .unwrap();
    -
    -        assert_eq!(wallet_desc.to_string(), "wpkh(tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)#y8p7e8kk");
    -    }
    -
    -    // 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(),
    -            Some(DescriptorError::InvalidDescriptorChecksum)
    -        ));
    -
    -        let desc = "wpkh(tprv8ZgxMBicQKsPdpkqS7Eair4YxjcuuvDPNYmKX3sCniCf16tHEVrjjiSXEkFRnUH77yXc6ZcwHHcLNfjdi5qUvw3VDfgYiH5mNsj5izuiu2N/1/2/*)#67ju93jw"
    -            .into_wallet_descriptor(&secp, Network::Testnet);
    -        assert!(matches!(
    -            desc.err(),
    -            Some(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(),
    -            Some(DescriptorError::Key(KeyError::InvalidNetwork))
    -        ));
    -
    -        let desc = "wpkh(tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/2/*)"
    -            .into_wallet_descriptor(&secp, Network::Bitcoin);
    -        assert!(matches!(
    -            desc.err(),
    -            Some(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::ExtendedPubKey::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!(result.is_err());
    -        assert!(matches!(
    -            result.unwrap_err(),
    -            DescriptorError::HardenedDerivationXpub
    -        ));
    -
    -        let descriptor = "wsh(multi(2,tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/0/*,tpubD6NzVbkrYhZ4XHndKkuB8FifXm8r5FQHwrN6oZuWCz13qb93rtgKvD4PQsqC4HP4yhV3tA2fqr2RbY5mNXfM7RxXUoeABoDtsFUq2zJq6YK/1/*))";
    -        let result = into_wallet_descriptor_checked(descriptor, &secp, Network::Testnet);
    -
    -        assert!(result.is_err());
    -        assert!(matches!(
    -            result.unwrap_err(),
    -            DescriptorError::DuplicatedKeys
    -        ));
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/policy.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/policy.rs.html deleted file mode 100644 index 98bb3b3e19..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/policy.rs.html +++ /dev/null @@ -1,3208 +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
    -
    // 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::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(key_map.into());
    -//! let policy = extended_desc.extract_policy(&signers, BuildSatisfaction::None, &secp)?;
    -//! println!("policy: {}", serde_json::to_string(&policy)?);
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use std::cmp::max;
    -use std::collections::{BTreeMap, HashSet, VecDeque};
    -use std::fmt;
    -
    -use serde::ser::SerializeMap;
    -use serde::{Serialize, Serializer};
    -
    -use bitcoin::hashes::*;
    -use bitcoin::util::bip32::Fingerprint;
    -use bitcoin::PublicKey;
    -
    -use miniscript::descriptor::{DescriptorPublicKey, ShInner, SortedMultiVec, WshInner};
    -use miniscript::{Descriptor, Miniscript, MiniscriptKey, Satisfier, ScriptContext, Terminal};
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -use crate::descriptor::ExtractPolicy;
    -use crate::wallet::signer::{SignerId, SignersContainer};
    -use crate::wallet::utils::{self, After, Older, SecpCtx};
    -
    -use super::checksum::get_checksum;
    -use super::error::Error;
    -use super::XKeyUtils;
    -use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
    -use miniscript::psbt::PsbtInputSatisfier;
    -
    -/// Raw public key or extended key fingerprint
    -#[derive(Debug, Clone, Default, Serialize)]
    -pub struct PkOrF {
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    pubkey: Option<PublicKey>,
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    pubkey_hash: Option<hash160::Hash>,
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    fingerprint: Option<Fingerprint>,
    -}
    -
    -impl PkOrF {
    -    fn from_key(k: &DescriptorPublicKey, secp: &SecpCtx) -> Self {
    -        match k {
    -            DescriptorPublicKey::SinglePub(pubkey) => PkOrF {
    -                pubkey: Some(pubkey.key),
    -                ..Default::default()
    -            },
    -            DescriptorPublicKey::XPub(xpub) => PkOrF {
    -                fingerprint: Some(xpub.root_fingerprint(secp)),
    -                ..Default::default()
    -            },
    -        }
    -    }
    -}
    -
    -/// An item that needs to be satisfied
    -#[derive(Debug, Clone, Serialize)]
    -#[serde(tag = "type", rename_all = "UPPERCASE")]
    -pub enum SatisfiableItem {
    -    // Leaves
    -    /// Signature for a raw public key
    -    Signature(PkOrF),
    -    /// Signature for an extended key fingerprint
    -    SignatureKey(PkOrF),
    -    /// SHA256 preimage hash
    -    Sha256Preimage {
    -        /// The digest value
    -        hash: sha256::Hash,
    -    },
    -    /// Double SHA256 preimage hash
    -    Hash256Preimage {
    -        /// The digest value
    -        hash: sha256d::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 timestamp value
    -        value: u32,
    -    },
    -    /// Relative timelock locktime
    -    RelativeTimelock {
    -        /// The locktime value
    -        value: u32,
    -    },
    -    /// 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 {
    -        get_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, 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 ([choosen 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 possibile options and check whether or not they are compatible.
    -                    .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: &Vec<(Vec<usize>, Vec<Condition>)>| println!("fetch {:?}", x))
    -                    // since the previous step can turn one item of the iterator into multiple ones, we call flatten to expand them out
    -                    .flatten()
    -                    // .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, 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
    -#[derive(Hash, Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Default, Serialize)]
    -pub struct Condition {
    -    /// Optional CheckSequenceVerify condition
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    pub csv: Option<u32>,
    -    /// Optional timelock condition
    -    #[serde(skip_serializing_if = "Option::is_none")]
    -    pub timelock: Option<u32>,
    -}
    -
    -impl Condition {
    -    fn merge_nlocktime(a: u32, b: u32) -> Result<u32, PolicyError> {
    -        if (a < utils::BLOCKS_TIMELOCK_THRESHOLD) != (b < utils::BLOCKS_TIMELOCK_THRESHOLD) {
    -            Err(PolicyError::MixedTimelockUnits)
    -        } else {
    -            Ok(max(a, b))
    -        }
    -    }
    -
    -    fn merge_nsequence(a: u32, b: u32) -> Result<u32, PolicyError> {
    -        let mask = utils::SEQUENCE_LOCKTIME_TYPE_FLAG | utils::SEQUENCE_LOCKTIME_MASK;
    -
    -        let a = a & mask;
    -        let b = b & mask;
    -
    -        if (a < utils::SEQUENCE_LOCKTIME_TYPE_FLAG) != (b < utils::SEQUENCE_LOCKTIME_TYPE_FLAG) {
    -            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 {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -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(
    -        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 signature_in_psbt(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(),
    -            _ => vec![],
    -        };
    -        let selected = match path.get(&self.id) {
    -            Some(arr) => arr,
    -            _ => &default,
    -        };
    -
    -        match &self.item {
    -            SatisfiableItem::Thresh { items, threshold } => {
    -                let mapped_req = items
    -                    .iter()
    -                    .map(|i| i.get_condition(path))
    -                    .collect::<Result<Vec<_>, _>>()?;
    -
    -                // if all the requirements are null we don't care about `selected` because there
    -                // are no requirements
    -                if mapped_req.iter().all(Condition::is_null) {
    -                    return Ok(Condition::default());
    -                }
    -
    -                // 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
    -                let mut requirements = Condition::default();
    -                for item_index in selected {
    -                    requirements = requirements.merge(
    -                        mapped_req
    -                            .get(*item_index)
    -                            .ok_or(PolicyError::IndexOutOfRange(*item_index))?,
    -                    )?;
    -                }
    -
    -                Ok(requirements)
    -            }
    -            SatisfiableItem::Multisig { keys, threshold } => {
    -                if selected.len() < *threshold {
    -                    return Err(PolicyError::NotEnoughItemsSelected(self.id.clone()));
    -                }
    -                if let Some(item) = selected.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 {
    -    match key {
    -        DescriptorPublicKey::SinglePub(pubkey) => pubkey.key.to_pubkeyhash().into(),
    -        DescriptorPublicKey::XPub(xpub) => xpub.root_fingerprint(secp).into(),
    -    }
    -}
    -
    -fn signature(
    -    key: &DescriptorPublicKey,
    -    signers: &SignersContainer,
    -    build_sat: BuildSatisfaction,
    -    secp: &SecpCtx,
    -) -> Policy {
    -    let mut policy: Policy = SatisfiableItem::Signature(PkOrF::from_key(key, secp)).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 signature_in_psbt(psbt, key, secp) {
    -            Satisfaction::Complete {
    -                condition: Default::default(),
    -            }
    -        } else {
    -            Satisfaction::None
    -        };
    -    }
    -
    -    policy
    -}
    -
    -fn signature_in_psbt(psbt: &Psbt, key: &DescriptorPublicKey, secp: &SecpCtx) -> bool {
    -    //TODO check signature validity
    -    psbt.inputs.iter().all(|input| match key {
    -        DescriptorPublicKey::SinglePub(key) => input.partial_sigs.contains_key(&key.key),
    -        DescriptorPublicKey::XPub(xpub) => {
    -            let pubkey = input
    -                .bip32_derivation
    -                .iter()
    -                .find(|(_, (f, _))| *f == xpub.root_fingerprint(secp))
    -                .map(|(p, _)| p);
    -            //TODO check actual derivation matches
    -            match pubkey {
    -                Some(pubkey) => input.partial_sigs.contains_key(pubkey),
    -                None => false,
    -            }
    -        }
    -    })
    -}
    -
    -impl<Ctx: ScriptContext> 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(signature(pubkey, signers, build_sat, secp)),
    -            Terminal::PkH(pubkey_hash) => Some(signature(pubkey_hash, signers, build_sat, secp)),
    -            Terminal::After(value) => {
    -                let mut policy: Policy = SatisfiableItem::AbsoluteTimelock { value: *value }.into();
    -                policy.contribution = Satisfaction::Complete {
    -                    condition: Condition {
    -                        timelock: Some(*value),
    -                        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);
    -                    let inputs_sat = psbt_inputs_sat(psbt)
    -                        .all(|sat| Satisfier::<bitcoin::PublicKey>::check_after(&sat, *value));
    -                    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) => {
    -                Policy::make_multisig(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)?
    -            }
    -        })
    -    }
    -}
    -
    -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>(
    -            keys: &SortedMultiVec<DescriptorPublicKey, Ctx>,
    -            signers: &SignersContainer,
    -            build_sat: BuildSatisfaction,
    -            secp: &SecpCtx,
    -        ) -> Result<Option<Policy>, Error> {
    -            Ok(Policy::make_multisig(
    -                keys.pks.as_ref(),
    -                signers,
    -                build_sat,
    -                keys.k,
    -                true,
    -                secp,
    -            )?)
    -        }
    -
    -        match self {
    -            Descriptor::Pkh(pk) => Ok(Some(signature(pk.as_inner(), signers, build_sat, secp))),
    -            Descriptor::Wpkh(pk) => Ok(Some(signature(pk.as_inner(), signers, build_sat, secp))),
    -            Descriptor::Sh(sh) => match sh.as_inner() {
    -                ShInner::Wpkh(pk) => Ok(Some(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)?),
    -        }
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use crate::descriptor;
    -    use crate::descriptor::{ExtractPolicy, IntoWalletDescriptor};
    -
    -    use super::*;
    -    use crate::descriptor::derived::AsDerived;
    -    use crate::descriptor::policy::SatisfiableItem::{Multisig, Signature, Thresh};
    -    use crate::keys::{DescriptorKey, IntoDescriptorKey};
    -    use crate::wallet::signer::SignersContainer;
    -    use bitcoin::secp256k1::Secp256k1;
    -    use bitcoin::util::bip32;
    -    use bitcoin::Network;
    -    use miniscript::DescriptorTrait;
    -    use std::str::FromStr;
    -    use std::sync::Arc;
    -
    -    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::ExtendedPrivKey::from_str(tprv).unwrap();
    -        let tpub = bip32::ExtendedPubKey::from_private(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::from(keymap));
    -        let policy = wallet_desc
    -            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
    -            .unwrap()
    -            .unwrap();
    -
    -        assert!(
    -            matches!(&policy.item, Signature(pk_or_f) if pk_or_f.fingerprint.unwrap() == 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::from(keymap));
    -        let policy = wallet_desc
    -            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
    -            .unwrap()
    -            .unwrap();
    -
    -        assert!(
    -            matches!(&policy.item, Signature(pk_or_f) if pk_or_f.fingerprint.unwrap() == fingerprint)
    -        );
    -        assert!(
    -            matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == 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::from(keymap));
    -        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].fingerprint.unwrap() == fingerprint0
    -            && keys[1].fingerprint.unwrap() == 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::from(keymap));
    -        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].fingerprint.unwrap() == fingerprint0
    -            && keys[1].fingerprint.unwrap() == 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::from(keymap));
    -        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].fingerprint.unwrap() == fingerprint0
    -            && keys[1].fingerprint.unwrap() == 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::from(keymap));
    -        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].fingerprint.unwrap() == fingerprint0
    -            && keys[1].fingerprint.unwrap() == 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 single_key = wallet_desc.derive(0);
    -        let signers_container = Arc::new(SignersContainer::from(keymap));
    -        let policy = single_key
    -            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
    -            .unwrap()
    -            .unwrap();
    -
    -        assert!(
    -            matches!(&policy.item, Signature(pk_or_f) if pk_or_f.fingerprint.unwrap() == 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 single_key = wallet_desc.derive(0);
    -        let signers_container = Arc::new(SignersContainer::from(keymap));
    -        let policy = single_key
    -            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
    -            .unwrap()
    -            .unwrap();
    -
    -        assert!(
    -            matches!(&policy.item, Signature(pk_or_f) if pk_or_f.fingerprint.unwrap() == fingerprint)
    -        );
    -        assert!(
    -            matches!(&policy.contribution, Satisfaction::Complete {condition} if condition.csv == None && condition.timelock == 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 single_key = wallet_desc.derive(0);
    -        let signers_container = Arc::new(SignersContainer::from(keymap));
    -        let policy = single_key
    -            .extract_policy(&signers_container, BuildSatisfaction::None, &secp)
    -            .unwrap()
    -            .unwrap();
    -
    -        assert!(
    -            matches!(&policy.item, Multisig { keys, threshold } if threshold == &1
    -            && keys[0].fingerprint.unwrap() == fingerprint0
    -            && keys[1].fingerprint.unwrap() == 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::from(keymap));
    -        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)
    -             && conditions.get(&vec![1,2]).unwrap().iter().next().unwrap().csv == Some(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::from(keymap));
    -        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::from(keymap));
    -        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::from(keymap));
    -        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 = keymap.into();
    -
    -        let policy = wallet_desc
    -            .extract_policy(&signers, 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
    -            .as_derived(0, &secp)
    -            .address(Network::Testnet)
    -            .unwrap();
    -        assert_eq!(
    -            "tb1qg3cwv3xt50gdg875qvjjpfgaps86gtk4rz0ejvp6ttc5ldnlxuvqlcn0xk",
    -            addr.to_string()
    -        );
    -
    -        let signers_container = Arc::new(SignersContainer::from(keymap));
    -
    -        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,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::from(keymap));
    -
    -        let addr = wallet_desc
    -            .as_derived(0, &secp)
    -            .address(Network::Testnet)
    -            .unwrap();
    -        assert_eq!(
    -            "tb1qhpemaacpeu8ajlnh8k9v55ftg0px58r8630fz8t5mypxcwdk5d8sum522g",
    -            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::from(keymap));
    -
    -        let policy = wallet_desc.extract_policy(&signers_container, BuildSatisfaction::None, &secp);
    -        assert!(policy.is_ok());
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/template.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/template.rs.html deleted file mode 100644 index 31d6c7edbe..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/descriptor/template.rs.html +++ /dev/null @@ -1,1456 +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
    -
    // 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::util::bip32;
    -use bitcoin::Network;
    -
    -use miniscript::{Legacy, Segwitv0};
    -
    -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};
    -///
    -/// struct MyP2PKH<K: IntoDescriptorKey<Legacy>>(K);
    -///
    -/// impl<K: IntoDescriptorKey<Legacy>> DescriptorTemplate for MyP2PKH<K> {
    -///     fn build(self) -> Result<DescriptorTemplateOut, DescriptorError> {
    -///         Ok(bdk::descriptor!(pkh(self.0))?)
    -///     }
    -/// }
    -/// ```
    -pub trait DescriptorTemplate {
    -    /// Build the complete descriptor
    -    fn build(self) -> 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()?.into_wallet_descriptor(secp, network)
    -    }
    -}
    -
    -/// P2PKH template. Expands to a descriptor `pkh(key)`
    -///
    -/// ## Example
    -///
    -/// ```
    -/// # use bdk::bitcoin::{PrivateKey, Network};
    -/// # use bdk::{Wallet};
    -/// # use bdk::database::MemoryDatabase;
    -/// # use bdk::wallet::AddressIndex::New;
    -/// use bdk::template::P2Pkh;
    -///
    -/// let key =
    -///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
    -/// let wallet = Wallet::new_offline(
    -///     P2Pkh(key),
    -///     None,
    -///     Network::Testnet,
    -///     MemoryDatabase::default(),
    -/// )?;
    -///
    -/// assert_eq!(
    -///     wallet.get_address(New)?.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) -> 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::database::MemoryDatabase;
    -/// # use bdk::wallet::AddressIndex::New;
    -/// use bdk::template::P2Wpkh_P2Sh;
    -///
    -/// let key =
    -///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
    -/// let wallet = Wallet::new_offline(
    -///     P2Wpkh_P2Sh(key),
    -///     None,
    -///     Network::Testnet,
    -///     MemoryDatabase::default(),
    -/// )?;
    -///
    -/// assert_eq!(
    -///     wallet.get_address(New)?.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) -> 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::database::MemoryDatabase;
    -/// # use bdk::wallet::AddressIndex::New;
    -/// use bdk::template::P2Wpkh;
    -///
    -/// let key =
    -///     bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")?;
    -/// let wallet = Wallet::new_offline(
    -///     P2Wpkh(key),
    -///     None,
    -///     Network::Testnet,
    -///     MemoryDatabase::default(),
    -/// )?;
    -///
    -/// assert_eq!(
    -///     wallet.get_address(New)?.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) -> Result<DescriptorTemplateOut, DescriptorError> {
    -        descriptor!(wpkh(self.0))
    -    }
    -}
    -
    -/// BIP44 template. Expands to `pkh(key/44'/0'/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::database::MemoryDatabase;
    -/// # use bdk::wallet::AddressIndex::New;
    -/// use bdk::template::Bip44;
    -///
    -/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -/// let wallet = Wallet::new_offline(
    -///     Bip44(key.clone(), KeychainKind::External),
    -///     Some(Bip44(key, KeychainKind::Internal)),
    -///     Network::Testnet,
    -///     MemoryDatabase::default()
    -/// )?;
    -///
    -/// assert_eq!(wallet.get_address(New)?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#xgaaevjx");
    -/// # 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) -> Result<DescriptorTemplateOut, DescriptorError> {
    -        P2Pkh(legacy::make_bipxx_private(44, self.0, self.1)?).build()
    -    }
    -}
    -
    -/// BIP44 public template. Expands to `pkh(key/{0,1}/*)`
    -///
    -/// This assumes that the key used has already been derived with `m/44'/0'/0'`.
    -///
    -/// 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::database::MemoryDatabase;
    -/// # use bdk::wallet::AddressIndex::New;
    -/// use bdk::template::Bip44Public;
    -///
    -/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU")?;
    -/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
    -/// let wallet = Wallet::new_offline(
    -///     Bip44Public(key.clone(), fingerprint, KeychainKind::External),
    -///     Some(Bip44Public(key, fingerprint, KeychainKind::Internal)),
    -///     Network::Testnet,
    -///     MemoryDatabase::default()
    -/// )?;
    -///
    -/// assert_eq!(wallet.get_address(New)?.to_string(), "miNG7dJTzJqNbFS19svRdTCisC65dsubtR");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "pkh([c55b303f/44'/0'/0']tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU/0/*)#xgaaevjx");
    -/// # 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) -> Result<DescriptorTemplateOut, DescriptorError> {
    -        P2Pkh(legacy::make_bipxx_public(44, self.0, self.1, self.2)?).build()
    -    }
    -}
    -
    -/// BIP49 template. Expands to `sh(wpkh(key/49'/0'/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::database::MemoryDatabase;
    -/// # use bdk::wallet::AddressIndex::New;
    -/// use bdk::template::Bip49;
    -///
    -/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -/// let wallet = Wallet::new_offline(
    -///     Bip49(key.clone(), KeychainKind::External),
    -///     Some(Bip49(key, KeychainKind::Internal)),
    -///     Network::Testnet,
    -///     MemoryDatabase::default()
    -/// )?;
    -///
    -/// assert_eq!(wallet.get_address(New)?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))#gsmdv4xr");
    -/// # 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) -> Result<DescriptorTemplateOut, DescriptorError> {
    -        P2Wpkh_P2Sh(segwit_v0::make_bipxx_private(49, self.0, self.1)?).build()
    -    }
    -}
    -
    -/// 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'`.
    -///
    -/// 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::database::MemoryDatabase;
    -/// # use bdk::wallet::AddressIndex::New;
    -/// use bdk::template::Bip49Public;
    -///
    -/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L")?;
    -/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
    -/// let wallet = Wallet::new_offline(
    -///     Bip49Public(key.clone(), fingerprint, KeychainKind::External),
    -///     Some(Bip49Public(key, fingerprint, KeychainKind::Internal)),
    -///     Network::Testnet,
    -///     MemoryDatabase::default()
    -/// )?;
    -///
    -/// assert_eq!(wallet.get_address(New)?.to_string(), "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "sh(wpkh([c55b303f/49\'/0\'/0\']tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L/0/*))#gsmdv4xr");
    -/// # 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) -> Result<DescriptorTemplateOut, DescriptorError> {
    -        P2Wpkh_P2Sh(segwit_v0::make_bipxx_public(49, self.0, self.1, self.2)?).build()
    -    }
    -}
    -
    -/// BIP84 template. Expands to `wpkh(key/84'/0'/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::database::MemoryDatabase;
    -/// # use bdk::wallet::AddressIndex::New;
    -/// use bdk::template::Bip84;
    -///
    -/// let key = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPeZRHk4rTG6orPS2CRNFX3njhUXx5vj9qGog5ZMH4uGReDWN5kCkY3jmWEtWause41CDvBRXD1shKknAMKxT99o9qUTRVC6m")?;
    -/// let wallet = Wallet::new_offline(
    -///     Bip84(key.clone(), KeychainKind::External),
    -///     Some(Bip84(key, KeychainKind::Internal)),
    -///     Network::Testnet,
    -///     MemoryDatabase::default()
    -/// )?;
    -///
    -/// assert_eq!(wallet.get_address(New)?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#nkk5dtkg");
    -/// # 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) -> Result<DescriptorTemplateOut, DescriptorError> {
    -        P2Wpkh(segwit_v0::make_bipxx_private(84, self.0, self.1)?).build()
    -    }
    -}
    -
    -/// BIP84 public template. Expands to `wpkh(key/{0,1}/*)`
    -///
    -/// This assumes that the key used has already been derived with `m/84'/0'/0'`.
    -///
    -/// 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::database::MemoryDatabase;
    -/// # use bdk::wallet::AddressIndex::New;
    -/// use bdk::template::Bip84Public;
    -///
    -/// let key = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q")?;
    -/// let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f")?;
    -/// let wallet = Wallet::new_offline(
    -///     Bip84Public(key.clone(), fingerprint, KeychainKind::External),
    -///     Some(Bip84Public(key, fingerprint, KeychainKind::Internal)),
    -///     Network::Testnet,
    -///     MemoryDatabase::default()
    -/// )?;
    -///
    -/// assert_eq!(wallet.get_address(New)?.to_string(), "tb1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2pr6y4qc7");
    -/// assert_eq!(wallet.public_descriptor(KeychainKind::External)?.unwrap().to_string(), "wpkh([c55b303f/84\'/0\'/0\']tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q/0/*)#nkk5dtkg");
    -/// # 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) -> Result<DescriptorTemplateOut, DescriptorError> {
    -        P2Wpkh(segwit_v0::make_bipxx_public(84, self.0, self.1, self.2)?).build()
    -    }
    -}
    -
    -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,
    -            ) -> Result<impl IntoDescriptorKey<$ctx>, DescriptorError> {
    -                let mut derivation_path = Vec::with_capacity(4);
    -                derivation_path.push(bip32::ChildNumber::from_hardened_idx(bip)?);
    -                derivation_path.push(bip32::ChildNumber::from_hardened_idx(0)?);
    -                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,
    -            ) -> 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)?,
    -                    bip32::ChildNumber::from_hardened_idx(0)?,
    -                    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);
    -
    -#[cfg(test)]
    -mod test {
    -    // test existing descriptor templates, make sure they are expanded to the right descriptors
    -
    -    use std::str::FromStr;
    -
    -    use super::*;
    -    use crate::descriptor::derived::AsDerived;
    -    use crate::descriptor::{DescriptorError, DescriptorMeta};
    -    use crate::keys::ValidNetworks;
    -    use bitcoin::network::constants::Network::Regtest;
    -    use bitcoin::secp256k1::Secp256k1;
    -    use miniscript::descriptor::{DescriptorPublicKey, DescriptorTrait, KeyMap};
    -    use miniscript::Descriptor;
    -
    -    // verify template descriptor generates expected address(es)
    -    fn check(
    -        desc: Result<(Descriptor<DescriptorPublicKey>, KeyMap, ValidNetworks), DescriptorError>,
    -        is_witness: bool,
    -        is_fixed: bool,
    -        expected: &[&str],
    -    ) {
    -        let secp = Secp256k1::new();
    -
    -        let (desc, _key_map, _networks) = desc.unwrap();
    -        assert_eq!(desc.is_witness(), is_witness);
    -        assert_eq!(!desc.is_deriveable(), is_fixed);
    -        for i in 0..expected.len() {
    -            let index = i as u32;
    -            let child_desc = if !desc.is_deriveable() {
    -                desc.as_derived_fixed(&secp)
    -            } else {
    -                desc.as_derived(index, &secp)
    -            };
    -            let address = child_desc.address(Regtest).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(),
    -            false,
    -            true,
    -            &["mwJ8hxFYW19JLuc65RCTaP4v1rzVU8cVMT"],
    -        );
    -
    -        let pubkey = bitcoin::PublicKey::from_str(
    -            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
    -        )
    -        .unwrap();
    -        check(
    -            P2Pkh(pubkey).build(),
    -            false,
    -            true,
    -            &["muZpTpBYhxmRFuCjLc7C6BBDF32C8XVJUi"],
    -        );
    -    }
    -
    -    // P2WPKH-P2SH `sh(wpkh(key))`
    -    #[test]
    -    fn test_p2wphp2sh_template() {
    -        let prvkey =
    -            bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
    -                .unwrap();
    -        check(
    -            P2Wpkh_P2Sh(prvkey).build(),
    -            true,
    -            true,
    -            &["2NB4ox5VDRw1ecUv6SnT3VQHPXveYztRqk5"],
    -        );
    -
    -        let pubkey = bitcoin::PublicKey::from_str(
    -            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
    -        )
    -        .unwrap();
    -        check(
    -            P2Wpkh_P2Sh(pubkey).build(),
    -            true,
    -            true,
    -            &["2N5LiC3CqzxDamRTPG1kiNv1FpNJQ7x28sb"],
    -        );
    -    }
    -
    -    // P2WPKH `wpkh(key)`
    -    #[test]
    -    fn test_p2wph_template() {
    -        let prvkey =
    -            bitcoin::PrivateKey::from_wif("cTc4vURSzdx6QE6KVynWGomDbLaA75dNALMNyfjh3p8DRRar84Um")
    -                .unwrap();
    -        check(
    -            P2Wpkh(prvkey).build(),
    -            true,
    -            true,
    -            &["bcrt1q4525hmgw265tl3drrl8jjta7ayffu6jfcwxx9y"],
    -        );
    -
    -        let pubkey = bitcoin::PublicKey::from_str(
    -            "03a34b99f22c790c4e36b2b3c2c35a36db06226e41c692fc82b8b56ac1c540c5bd",
    -        )
    -        .unwrap();
    -        check(
    -            P2Wpkh(pubkey).build(),
    -            true,
    -            true,
    -            &["bcrt1qngw83fg8dz0k749cg7k3emc7v98wy0c7azaa6h"],
    -        );
    -    }
    -
    -    // BIP44 `pkh(key/44'/0'/0'/{0,1}/*)`
    -    #[test]
    -    fn test_bip44_template() {
    -        let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
    -        check(
    -            Bip44(prvkey, KeychainKind::External).build(),
    -            false,
    -            false,
    -            &[
    -                "n453VtnjDHPyDt2fDstKSu7A3YCJoHZ5g5",
    -                "mvfrrumXgTtwFPWDNUecBBgzuMXhYM7KRP",
    -                "mzYvhRAuQqbdSKMVVzXNYyqihgNdRadAUQ",
    -            ],
    -        );
    -        check(
    -            Bip44(prvkey, KeychainKind::Internal).build(),
    -            false,
    -            false,
    -            &[
    -                "muHF98X9KxEzdKrnFAX85KeHv96eXopaip",
    -                "n4hpyLJE5ub6B5Bymv4eqFxS5KjrewSmYR",
    -                "mgvkdv1ffmsXd2B1sRKQ5dByK3SzpG42rA",
    -            ],
    -        );
    -    }
    -
    -    // BIP44 public `pkh(key/{0,1}/*)`
    -    #[test]
    -    fn test_bip44_public_template() {
    -        let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDDDzQ31JkZB7VxUr9bjvBivDdqoFLrDPyLWtLapArAi51ftfmCb2DPxwLQzX65iNcXz1DGaVvyvo6JQ6rTU73r2gqdEo8uov9QKRb7nKCSU").unwrap();
    -        let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
    -        check(
    -            Bip44Public(pubkey, fingerprint, KeychainKind::External).build(),
    -            false,
    -            false,
    -            &[
    -                "miNG7dJTzJqNbFS19svRdTCisC65dsubtR",
    -                "n2UqaDbCjWSFJvpC84m3FjUk5UaeibCzYg",
    -                "muCPpS6Ue7nkzeJMWDViw7Lkwr92Yc4K8g",
    -            ],
    -        );
    -        check(
    -            Bip44Public(pubkey, fingerprint, KeychainKind::Internal).build(),
    -            false,
    -            false,
    -            &[
    -                "moDr3vJ8wpt5nNxSK55MPq797nXJb2Ru9H",
    -                "ms7A1Yt4uTezT2XkefW12AvLoko8WfNJMG",
    -                "mhYiyat2rtEnV77cFfQsW32y1m2ceCGHPo",
    -            ],
    -        );
    -    }
    -
    -    // BIP49 `sh(wpkh(key/49'/0'/0'/{0,1}/*))`
    -    #[test]
    -    fn test_bip49_template() {
    -        let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
    -        check(
    -            Bip49(prvkey, KeychainKind::External).build(),
    -            true,
    -            false,
    -            &[
    -                "2N9bCAJXGm168MjVwpkBdNt6ucka3PKVoUV",
    -                "2NDckYkqrYyDMtttEav5hB3Bfw9EGAW5HtS",
    -                "2NAFTVtksF9T4a97M7nyCjwUBD24QevZ5Z4",
    -            ],
    -        );
    -        check(
    -            Bip49(prvkey, KeychainKind::Internal).build(),
    -            true,
    -            false,
    -            &[
    -                "2NB3pA8PnzJLGV8YEKNDFpbViZv3Bm1K6CG",
    -                "2NBiX2Wzxngb5rPiWpUiJQ2uLVB4HBjFD4p",
    -                "2NA8ek4CdQ6aMkveYF6AYuEYNrftB47QGTn",
    -            ],
    -        );
    -    }
    -
    -    // BIP49 public `sh(wpkh(key/{0,1}/*))`
    -    #[test]
    -    fn test_bip49_public_template() {
    -        let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC49r947KGK52X5rBWS4BLs5m9SRY3pYHnvRrm7HcybZ3BfdEsGFyzCMzayi1u58eT82ZeyFZwH7DD6Q83E3fM9CpfMtmnTygnLfP59jL9L").unwrap();
    -        let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
    -        check(
    -            Bip49Public(pubkey, fingerprint, KeychainKind::External).build(),
    -            true,
    -            false,
    -            &[
    -                "2N3K4xbVAHoiTQSwxkZjWDfKoNC27pLkYnt",
    -                "2NCTQfJ1sZa3wQ3pPseYRHbaNEpC3AquEfX",
    -                "2MveFxAuC8BYPzTybx7FxSzW8HSd8ATT4z7",
    -            ],
    -        );
    -        check(
    -            Bip49Public(pubkey, fingerprint, KeychainKind::Internal).build(),
    -            true,
    -            false,
    -            &[
    -                "2NF2vttKibwyxigxtx95Zw8K7JhDbo5zPVJ",
    -                "2Mtmyd8taksxNVWCJ4wVvaiss7QPZGcAJuH",
    -                "2NBs3CTVYPr1HCzjB4YFsnWCPCtNg8uMEfp",
    -            ],
    -        );
    -    }
    -
    -    // BIP84 `wpkh(key/84'/0'/0'/{0,1}/*)`
    -    #[test]
    -    fn test_bip84_template() {
    -        let prvkey = bitcoin::util::bip32::ExtendedPrivKey::from_str("tprv8ZgxMBicQKsPcx5nBGsR63Pe8KnRUqmbJNENAfGftF3yuXoMMoVJJcYeUw5eVkm9WBPjWYt6HMWYJNesB5HaNVBaFc1M6dRjWSYnmewUMYy").unwrap();
    -        check(
    -            Bip84(prvkey, KeychainKind::External).build(),
    -            true,
    -            false,
    -            &[
    -                "bcrt1qkmvk2nadgplmd57ztld8nf8v2yxkzmdvwtjf8s",
    -                "bcrt1qx0v6zgfwe50m4kqc58cqzcyem7ay2sfl3gvqhp",
    -                "bcrt1q4h7fq9zhxst6e69p3n882nfj649l7w9g3zccfp",
    -            ],
    -        );
    -        check(
    -            Bip84(prvkey, KeychainKind::Internal).build(),
    -            true,
    -            false,
    -            &[
    -                "bcrt1qtrwtz00wxl69e5xex7amy4xzlxkaefg3gfdkxa",
    -                "bcrt1qqqasfhxpkkf7zrxqnkr2sfhn74dgsrc3e3ky45",
    -                "bcrt1qpks7n0gq74hsgsz3phn5vuazjjq0f5eqhsgyce",
    -            ],
    -        );
    -    }
    -
    -    // BIP84 public `wpkh(key/{0,1}/*)`
    -    #[test]
    -    fn test_bip84_public_template() {
    -        let pubkey = bitcoin::util::bip32::ExtendedPubKey::from_str("tpubDC2Qwo2TFsaNC4ju8nrUJ9mqVT3eSgdmy1yPqhgkjwmke3PRXutNGRYAUo6RCHTcVQaDR3ohNU9we59brGHuEKPvH1ags2nevW5opEE9Z5Q").unwrap();
    -        let fingerprint = bitcoin::util::bip32::Fingerprint::from_str("c55b303f").unwrap();
    -        check(
    -            Bip84Public(pubkey, fingerprint, KeychainKind::External).build(),
    -            true,
    -            false,
    -            &[
    -                "bcrt1qedg9fdlf8cnnqfd5mks6uz5w4kgpk2prcdvd0h",
    -                "bcrt1q3lncdlwq3lgcaaeyruynjnlccr0ve0kakh6ana",
    -                "bcrt1qt9800y6xl3922jy3uyl0z33jh5wfpycyhcylr9",
    -            ],
    -        );
    -        check(
    -            Bip84Public(pubkey, fingerprint, KeychainKind::Internal).build(),
    -            true,
    -            false,
    -            &[
    -                "bcrt1qm6wqukenh7guu792lj2njgw9n78cmwsy8xy3z2",
    -                "bcrt1q694twxtjn4nnrvnyvra769j0a23rllj5c6cgwp",
    -                "bcrt1qhlac3c5ranv5w5emlnqs7wxhkxt8maelylcarp",
    -            ],
    -        );
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/error.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/error.rs.html deleted file mode 100644 index d6c5f36fbc..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/error.rs.html +++ /dev/null @@ -1,460 +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
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -use std::fmt;
    -
    -use crate::bitcoin::Network;
    -use crate::{descriptor, wallet, wallet::address_validator};
    -use bitcoin::OutPoint;
    -
    -/// Errors that can be thrown by the [`Wallet`](crate::wallet::Wallet)
    -#[derive(Debug)]
    -pub enum Error {
    -    /// Wrong number of bytes found when trying to convert to u32
    -    InvalidU32Bytes(Vec<u8>),
    -    /// Generic error
    -    Generic(String),
    -    /// This error is thrown when trying to convert Bare and Public key script to address
    -    ScriptDoesntHaveAddressForm,
    -    /// Cannot build a tx without recipients
    -    NoRecipients,
    -    /// `manually_selected_only` option is selected but no utxo has been passed
    -    NoUtxosSelected,
    -    /// Output created is under the dust limit, 546 satoshis
    -    OutputBelowDustLimit(usize),
    -    /// 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 possible attempts with sufficiently big UTXO set could grow
    -    /// exponentially, thus a limit is set, and when hit, this error is thrown
    -    BnBTotalTriesExceeded,
    -    /// 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,
    -    /// Happens when trying to spend an UTXO that is not in the internal database
    -    UnknownUtxo,
    -    /// Thrown when a tx is not found in the internal database
    -    TransactionNotFound,
    -    /// Happens when trying to bump a transaction that is already confirmed
    -    TransactionConfirmed,
    -    /// Trying to replace a tx that has a sequence >= `0xFFFFFFFE`
    -    IrreplaceableTransaction,
    -    /// When bumping a tx the fee rate requested is lower than required
    -    FeeRateTooLow {
    -        /// Required fee rate (satoshi/vbyte)
    -        required: crate::types::FeeRate,
    -    },
    -    /// When bumping a tx the absolute fee requested is lower than replaced tx absolute fee
    -    FeeTooLow {
    -        /// Required fee absolute value (satoshi)
    -        required: u64,
    -    },
    -    /// Node doesn't have data to estimate a fee rate
    -    FeeRateUnavailable,
    -    /// 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),
    -    /// Error while working with [`keys`](crate::keys)
    -    Key(crate::keys::KeyError),
    -    /// Descriptor checksum mismatch
    -    ChecksumMismatch,
    -    /// Spending policy is not compatible with this [`KeychainKind`](crate::types::KeychainKind)
    -    SpendingPolicyRequired(crate::types::KeychainKind),
    -    /// Error while extracting and manipulating policies
    -    InvalidPolicyPathError(crate::descriptor::policy::PolicyError),
    -    /// Signing error
    -    Signer(crate::wallet::signer::SignerError),
    -    /// Invalid network
    -    InvalidNetwork {
    -        /// requested network, for example what is given as bdk-cli option
    -        requested: Network,
    -        /// found network, for example the network of the bitcoin node
    -        found: Network,
    -    },
    -    #[cfg(feature = "verify")]
    -    /// Transaction verification error
    -    Verification(crate::wallet::verify::VerifyError),
    -
    -    /// Progress value must be between `0.0` (included) and `100.0` (included)
    -    InvalidProgressValue(f32),
    -    /// Progress update error (maybe the channel has been closed)
    -    ProgressUpdateError,
    -    /// Requested outpoint doesn't exist in the tx (vout greater than available outputs)
    -    InvalidOutpoint(OutPoint),
    -
    -    /// Error related to the parsing and usage of descriptors
    -    Descriptor(crate::descriptor::error::Error),
    -    /// Error that can be returned to fail the validation of an address
    -    AddressValidator(crate::wallet::address_validator::AddressValidatorError),
    -    /// Encoding error
    -    Encode(bitcoin::consensus::encode::Error),
    -    /// Miniscript error
    -    Miniscript(miniscript::Error),
    -    /// BIP32 error
    -    Bip32(bitcoin::util::bip32::Error),
    -    /// An ECDSA error
    -    Secp256k1(bitcoin::secp256k1::Error),
    -    /// Error serializing or deserializing JSON data
    -    Json(serde_json::Error),
    -    /// Hex decoding error
    -    Hex(bitcoin::hashes::hex::Error),
    -    /// Partially signed bitcoin transaction error
    -    Psbt(bitcoin::util::psbt::Error),
    -    /// Partially signed bitcoin transaction parseerror
    -    PsbtParse(bitcoin::util::psbt::PsbtParseError),
    -
    -    //KeyMismatch(bitcoin::secp256k1::PublicKey, bitcoin::secp256k1::PublicKey),
    -    //MissingInputUTXO(usize),
    -    //InvalidAddressNetwork(Address),
    -    //DifferentTransactions,
    -    //DifferentDescriptorStructure,
    -    //Uncapable(crate::blockchain::Capability),
    -    //MissingCachedAddresses,
    -    #[cfg(feature = "electrum")]
    -    /// Electrum client error
    -    Electrum(electrum_client::Error),
    -    #[cfg(feature = "esplora")]
    -    /// Esplora client error
    -    Esplora(Box<crate::blockchain::esplora::EsploraError>),
    -    #[cfg(feature = "compact_filters")]
    -    /// Compact filters client error)
    -    CompactFilters(crate::blockchain::compact_filters::CompactFiltersError),
    -    #[cfg(feature = "key-value-db")]
    -    /// Sled database error
    -    Sled(sled::Error),
    -    #[cfg(feature = "rpc")]
    -    /// Rpc client error
    -    Rpc(core_rpc::Error),
    -    #[cfg(feature = "sqlite")]
    -    /// Rusqlite client error
    -    Rusqlite(rusqlite::Error),
    -}
    -
    -impl fmt::Display for Error {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for Error {}
    -
    -macro_rules! impl_error {
    -    ( $from:ty, $to:ident ) => {
    -        impl_error!($from, $to, Error);
    -    };
    -    ( $from:ty, $to:ident, $impl_for:ty ) => {
    -        impl std::convert::From<$from> for $impl_for {
    -            fn from(err: $from) -> Self {
    -                <$impl_for>::$to(err)
    -            }
    -        }
    -    };
    -}
    -
    -impl_error!(descriptor::error::Error, Descriptor);
    -impl_error!(address_validator::AddressValidatorError, AddressValidator);
    -impl_error!(descriptor::policy::PolicyError, InvalidPolicyPathError);
    -impl_error!(wallet::signer::SignerError, Signer);
    -
    -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),
    -            crate::keys::KeyError::InvalidChecksum => Error::ChecksumMismatch,
    -            e => Error::Key(e),
    -        }
    -    }
    -}
    -
    -impl_error!(bitcoin::consensus::encode::Error, Encode);
    -impl_error!(miniscript::Error, Miniscript);
    -impl_error!(bitcoin::util::bip32::Error, Bip32);
    -impl_error!(bitcoin::secp256k1::Error, Secp256k1);
    -impl_error!(serde_json::Error, Json);
    -impl_error!(bitcoin::hashes::hex::Error, Hex);
    -impl_error!(bitcoin::util::psbt::Error, Psbt);
    -impl_error!(bitcoin::util::psbt::PsbtParseError, PsbtParse);
    -
    -#[cfg(feature = "electrum")]
    -impl_error!(electrum_client::Error, Electrum);
    -#[cfg(feature = "key-value-db")]
    -impl_error!(sled::Error, Sled);
    -#[cfg(feature = "rpc")]
    -impl_error!(core_rpc::Error, Rpc);
    -#[cfg(feature = "sqlite")]
    -impl_error!(rusqlite::Error, Rusqlite);
    -
    -#[cfg(feature = "compact_filters")]
    -impl From<crate::blockchain::compact_filters::CompactFiltersError> for Error {
    -    fn from(other: crate::blockchain::compact_filters::CompactFiltersError) -> Self {
    -        match other {
    -            crate::blockchain::compact_filters::CompactFiltersError::Global(e) => *e,
    -            err => Error::CompactFilters(err),
    -        }
    -    }
    -}
    -
    -#[cfg(feature = "verify")]
    -impl From<crate::wallet::verify::VerifyError> for Error {
    -    fn from(other: crate::wallet::verify::VerifyError) -> Self {
    -        match other {
    -            crate::wallet::verify::VerifyError::Global(inner) => *inner,
    -            err => Error::Verification(err),
    -        }
    -    }
    -}
    -
    -#[cfg(feature = "esplora")]
    -impl From<crate::blockchain::esplora::EsploraError> for Error {
    -    fn from(other: crate::blockchain::esplora::EsploraError) -> Self {
    -        Error::Esplora(Box::new(other))
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/keys/bip39.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/keys/bip39.rs.html deleted file mode 100644 index 3cf8935dbd..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/keys/bip39.rs.html +++ /dev/null @@ -1,384 +0,0 @@ -bip39.rs - source
      1
    -  2
    -  3
    -  4
    -  5
    -  6
    -  7
    -  8
    -  9
    - 10
    - 11
    - 12
    - 13
    - 14
    - 15
    - 16
    - 17
    - 18
    - 19
    - 20
    - 21
    - 22
    - 23
    - 24
    - 25
    - 26
    - 27
    - 28
    - 29
    - 30
    - 31
    - 32
    - 33
    - 34
    - 35
    - 36
    - 37
    - 38
    - 39
    - 40
    - 41
    - 42
    - 43
    - 44
    - 45
    - 46
    - 47
    - 48
    - 49
    - 50
    - 51
    - 52
    - 53
    - 54
    - 55
    - 56
    - 57
    - 58
    - 59
    - 60
    - 61
    - 62
    - 63
    - 64
    - 65
    - 66
    - 67
    - 68
    - 69
    - 70
    - 71
    - 72
    - 73
    - 74
    - 75
    - 76
    - 77
    - 78
    - 79
    - 80
    - 81
    - 82
    - 83
    - 84
    - 85
    - 86
    - 87
    - 88
    - 89
    - 90
    - 91
    - 92
    - 93
    - 94
    - 95
    - 96
    - 97
    - 98
    - 99
    -100
    -101
    -102
    -103
    -104
    -105
    -106
    -107
    -108
    -109
    -110
    -111
    -112
    -113
    -114
    -115
    -116
    -117
    -118
    -119
    -120
    -121
    -122
    -123
    -124
    -125
    -126
    -127
    -128
    -129
    -130
    -131
    -132
    -133
    -134
    -135
    -136
    -137
    -138
    -139
    -140
    -141
    -142
    -143
    -144
    -145
    -146
    -147
    -148
    -149
    -150
    -151
    -152
    -153
    -154
    -155
    -156
    -157
    -158
    -159
    -160
    -161
    -162
    -163
    -164
    -165
    -166
    -167
    -168
    -169
    -170
    -171
    -172
    -173
    -174
    -175
    -176
    -177
    -178
    -179
    -180
    -181
    -182
    -183
    -184
    -185
    -186
    -187
    -188
    -189
    -190
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! BIP-0039
    -
    -// TODO: maybe write our own implementation of bip39? Seems stupid to have an extra dependency for
    -// something that should be fairly simple to re-implement.
    -
    -use bitcoin::util::bip32;
    -use bitcoin::Network;
    -
    -use miniscript::ScriptContext;
    -
    -pub use bip39::{Language, Mnemonic, MnemonicType, Seed};
    -
    -use super::{
    -    any_network, DerivableKey, DescriptorKey, ExtendedKey, GeneratableKey, GeneratedKey, KeyError,
    -};
    -
    -fn set_valid_on_any_network<Ctx: ScriptContext>(
    -    descriptor_key: DescriptorKey<Ctx>,
    -) -> DescriptorKey<Ctx> {
    -    // We have to pick one network to build the xprv, but since the bip39 standard doesn't
    -    // encode the network, the xprv we create is actually valid everywhere. So we override the
    -    // valid networks with `any_network()`.
    -    descriptor_key.override_valid_networks(any_network())
    -}
    -
    -/// Type for a BIP39 mnemonic with an optional passphrase
    -pub type MnemonicWithPassphrase = (Mnemonic, Option<String>);
    -
    -#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
    -impl<Ctx: ScriptContext> DerivableKey<Ctx> for Seed {
    -    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
    -        Ok(bip32::ExtendedPrivKey::new_master(Network::Bitcoin, &self.as_bytes())?.into())
    -    }
    -
    -    fn into_descriptor_key(
    -        self,
    -        source: Option<bip32::KeySource>,
    -        derivation_path: bip32::DerivationPath,
    -    ) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        let descriptor_key = self
    -            .into_extended_key()?
    -            .into_descriptor_key(source, derivation_path)?;
    -
    -        Ok(set_valid_on_any_network(descriptor_key))
    -    }
    -}
    -
    -#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
    -impl<Ctx: ScriptContext> DerivableKey<Ctx> for MnemonicWithPassphrase {
    -    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
    -        let (mnemonic, passphrase) = self;
    -        let seed = Seed::new(&mnemonic, passphrase.as_deref().unwrap_or(""));
    -
    -        seed.into_extended_key()
    -    }
    -
    -    fn into_descriptor_key(
    -        self,
    -        source: Option<bip32::KeySource>,
    -        derivation_path: bip32::DerivationPath,
    -    ) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        let descriptor_key = self
    -            .into_extended_key()?
    -            .into_descriptor_key(source, derivation_path)?;
    -
    -        Ok(set_valid_on_any_network(descriptor_key))
    -    }
    -}
    -
    -#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
    -impl<Ctx: ScriptContext> DerivableKey<Ctx> for Mnemonic {
    -    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
    -        (self, None).into_extended_key()
    -    }
    -
    -    fn into_descriptor_key(
    -        self,
    -        source: Option<bip32::KeySource>,
    -        derivation_path: bip32::DerivationPath,
    -    ) -> Result<DescriptorKey<Ctx>, KeyError> {
    -        let descriptor_key = self
    -            .into_extended_key()?
    -            .into_descriptor_key(source, derivation_path)?;
    -
    -        Ok(set_valid_on_any_network(descriptor_key))
    -    }
    -}
    -
    -#[cfg_attr(docsrs, doc(cfg(feature = "keys-bip39")))]
    -impl<Ctx: ScriptContext> GeneratableKey<Ctx> for Mnemonic {
    -    type Entropy = [u8; 32];
    -
    -    type Options = (MnemonicType, Language);
    -    type Error = Option<bip39::ErrorKind>;
    -
    -    fn generate_with_entropy(
    -        (mnemonic_type, language): Self::Options,
    -        entropy: Self::Entropy,
    -    ) -> Result<GeneratedKey<Self, Ctx>, Self::Error> {
    -        let entropy = &entropy.as_ref()[..(mnemonic_type.entropy_bits() / 8)];
    -        let mnemonic = Mnemonic::from_entropy(entropy, language).map_err(|e| e.downcast().ok())?;
    -
    -        Ok(GeneratedKey::new(mnemonic, any_network()))
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::str::FromStr;
    -
    -    use bitcoin::util::bip32;
    -
    -    use bip39::{Language, Mnemonic, MnemonicType};
    -
    -    use crate::keys::{any_network, GeneratableKey, GeneratedKey};
    -
    -    #[test]
    -    fn test_keys_bip39_mnemonic() {
    -        let mnemonic =
    -            "aim bunker wash balance finish force paper analyst cabin spoon stable organ";
    -        let mnemonic = Mnemonic::from_phrase(mnemonic, Language::English).unwrap();
    -        let path = bip32::DerivationPath::from_str("m/44'/0'/0'/0").unwrap();
    -
    -        let key = (mnemonic, path);
    -        let (desc, keys, networks) = crate::descriptor!(wpkh(key)).unwrap();
    -        assert_eq!(desc.to_string(), "wpkh([be83839f/44'/0'/0']xpub6DCQ1YcqvZtSwGWMrwHELPehjWV3f2MGZ69yBADTxFEUAoLwb5Mp5GniQK6tTp3AgbngVz9zEFbBJUPVnkG7LFYt8QMTfbrNqs6FNEwAPKA/0/*)#0r8v4nkv");
    -        assert_eq!(keys.len(), 1);
    -        assert_eq!(networks.len(), 4);
    -    }
    -
    -    #[test]
    -    fn test_keys_bip39_mnemonic_passphrase() {
    -        let mnemonic =
    -            "aim bunker wash balance finish force paper analyst cabin spoon stable organ";
    -        let mnemonic = Mnemonic::from_phrase(mnemonic, Language::English).unwrap();
    -        let path = bip32::DerivationPath::from_str("m/44'/0'/0'/0").unwrap();
    -
    -        let key = ((mnemonic, Some("passphrase".into())), path);
    -        let (desc, keys, networks) = crate::descriptor!(wpkh(key)).unwrap();
    -        assert_eq!(desc.to_string(), "wpkh([8f6cb80c/44'/0'/0']xpub6DWYS8bbihFevy29M4cbw4ZR3P5E12jB8R88gBDWCTCNpYiDHhYWNywrCF9VZQYagzPmsZpxXpytzSoxynyeFr4ZyzheVjnpLKuse4fiwZw/0/*)#h0j0tg5m");
    -        assert_eq!(keys.len(), 1);
    -        assert_eq!(networks.len(), 4);
    -    }
    -
    -    #[test]
    -    fn test_keys_generate_bip39() {
    -        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
    -            Mnemonic::generate_with_entropy(
    -                (MnemonicType::Words12, Language::English),
    -                crate::keys::test::TEST_ENTROPY,
    -            )
    -            .unwrap();
    -        assert_eq!(generated_mnemonic.valid_networks, any_network());
    -        assert_eq!(
    -            generated_mnemonic.to_string(),
    -            "primary fetch primary fetch primary fetch primary fetch primary fetch primary fever"
    -        );
    -
    -        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
    -            Mnemonic::generate_with_entropy(
    -                (MnemonicType::Words24, Language::English),
    -                crate::keys::test::TEST_ENTROPY,
    -            )
    -            .unwrap();
    -        assert_eq!(generated_mnemonic.valid_networks, any_network());
    -        assert_eq!(generated_mnemonic.to_string(), "primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary fetch primary foster");
    -    }
    -
    -    #[test]
    -    fn test_keys_generate_bip39_random() {
    -        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
    -            Mnemonic::generate((MnemonicType::Words12, Language::English)).unwrap();
    -        assert_eq!(generated_mnemonic.valid_networks, any_network());
    -
    -        let generated_mnemonic: GeneratedKey<_, miniscript::Segwitv0> =
    -            Mnemonic::generate((MnemonicType::Words24, Language::English)).unwrap();
    -        assert_eq!(generated_mnemonic.valid_networks, any_network());
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/keys/mod.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/keys/mod.rs.html deleted file mode 100644 index 7dc8e48126..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/keys/mod.rs.html +++ /dev/null @@ -1,1872 +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
    -
    // 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 std::any::TypeId;
    -use std::collections::HashSet;
    -use std::marker::PhantomData;
    -use std::ops::Deref;
    -use std::str::FromStr;
    -
    -use bitcoin::secp256k1::{self, Secp256k1, Signing};
    -
    -use bitcoin::util::bip32;
    -use bitcoin::{Network, PrivateKey, PublicKey};
    -
    -use miniscript::descriptor::{Descriptor, DescriptorXKey, Wildcard};
    -pub use miniscript::descriptor::{
    -    DescriptorPublicKey, DescriptorSecretKey, DescriptorSinglePriv, DescriptorSinglePub, KeyMap,
    -    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 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::with_capacity(1);
    -
    -                let public = secret
    -                    .as_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,
    -}
    -
    -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
    -    }
    -}
    -
    -/// 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()
    -    }
    -}
    -
    -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,
    -            _ => 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, DescriptorSinglePub,
    -///     IntoDescriptorKey, KeyError, ScriptContext,
    -/// };
    -///
    -/// 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::SinglePub(DescriptorSinglePub {
    -///                 origin: None,
    -///                 key: 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 std::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 [`ExtendedPrivKey`](bip32::ExtendedPrivKey)
    -/// or an [`ExtendedPubKey`](bip32::ExtendedPubKey) 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::ExtendedPrivKey, PhantomData<Ctx>)),
    -    /// A public extended key, aka an `xpub`
    -    Public((bip32::ExtendedPubKey, 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 [`ExtendedPrivKey`](bip32::ExtendedPrivKey) for the
    -    /// given [`Network`], if the key contains the private data
    -    pub fn into_xprv(self, network: Network) -> Option<bip32::ExtendedPrivKey> {
    -        match self {
    -            ExtendedKey::Private((mut xprv, _)) => {
    -                xprv.network = network;
    -                Some(xprv)
    -            }
    -            ExtendedKey::Public(_) => None,
    -        }
    -    }
    -
    -    /// Transform the [`ExtendedKey`] into an [`ExtendedPubKey`](bip32::ExtendedPubKey) for the
    -    /// given [`Network`]
    -    pub fn into_xpub<C: Signing>(
    -        self,
    -        network: bitcoin::Network,
    -        secp: &Secp256k1<C>,
    -    ) -> bip32::ExtendedPubKey {
    -        let mut xpub = match self {
    -            ExtendedKey::Private((xprv, _)) => bip32::ExtendedPubKey::from_private(secp, &xprv),
    -            ExtendedKey::Public((xpub, _)) => xpub,
    -        };
    -
    -        xpub.network = network;
    -        xpub
    -    }
    -}
    -
    -impl<Ctx: ScriptContext> From<bip32::ExtendedPubKey> for ExtendedKey<Ctx> {
    -    fn from(xpub: bip32::ExtendedPubKey) -> Self {
    -        ExtendedKey::Public((xpub, PhantomData))
    -    }
    -}
    -
    -impl<Ctx: ScriptContext> From<bip32::ExtendedPrivKey> for ExtendedKey<Ctx> {
    -    fn from(xprv: bip32::ExtendedPrivKey) -> Self {
    -        ExtendedKey::Private((xprv, PhantomData))
    -    }
    -}
    -
    -/// Trait for keys that can be derived.
    -///
    -/// When extra metadata are provided, a [`DerivableKey`] can be transofrmed 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 implemented 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 [`ExtendedPrivKey`] or
    -/// an [`ExtendedPubKey`] can implement only the required `into_extended_key()` method.
    -///
    -/// ```
    -/// use bdk::bitcoin;
    -/// use bdk::bitcoin::util::bip32;
    -/// use bdk::keys::{DerivableKey, ExtendedKey, KeyError, ScriptContext};
    -///
    -/// struct MyCustomKeyType {
    -///     key_data: bitcoin::PrivateKey,
    -///     chain_code: Vec<u8>,
    -///     network: bitcoin::Network,
    -/// }
    -///
    -/// impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
    -///     fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
    -///         let xprv = bip32::ExtendedPrivKey {
    -///             network: self.network,
    -///             depth: 0,
    -///             parent_fingerprint: bip32::Fingerprint::default(),
    -///             private_key: self.key_data,
    -///             chain_code: bip32::ChainCode::from(self.chain_code.as_ref()),
    -///             child_number: bip32::ChildNumber::Normal { index: 0 },
    -///         };
    -///
    -///         xprv.into_extended_key()
    -///     }
    -/// }
    -/// ```
    -///
    -/// Types that don't internally encode the [`Network`](bitcoin::Network) in which they are valid need some extra
    -/// steps to override the set of valid networks, otherwise only the network specified in the
    -/// [`ExtendedPrivKey`] or [`ExtendedPubKey`] will be considered valid.
    -///
    -/// ```
    -/// use bdk::bitcoin;
    -/// use bdk::bitcoin::util::bip32;
    -/// use bdk::keys::{
    -///     any_network, DerivableKey, DescriptorKey, ExtendedKey, KeyError, ScriptContext,
    -/// };
    -///
    -/// struct MyCustomKeyType {
    -///     key_data: bitcoin::PrivateKey,
    -///     chain_code: Vec<u8>,
    -/// }
    -///
    -/// impl<Ctx: ScriptContext> DerivableKey<Ctx> for MyCustomKeyType {
    -///     fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
    -///         let xprv = bip32::ExtendedPrivKey {
    -///             network: bitcoin::Network::Bitcoin, // pick an arbitrary network here
    -///             depth: 0,
    -///             parent_fingerprint: bip32::Fingerprint::default(),
    -///             private_key: self.key_data,
    -///             chain_code: bip32::ChainCode::from(self.chain_code.as_ref()),
    -///             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)
    -/// [`ExtendedPrivKey`]: (bip32::ExtendedPrivKey)
    -/// [`ExtendedPubKey`]: (bip32::ExtendedPubKey)
    -pub trait DerivableKey<Ctx: ScriptContext = miniscript::Legacy>: Sized {
    -    /// Consume `self` and turn it into an [`ExtendedKey`]
    -    ///
    -    /// This can be used to get direct access to `xprv`s and `xpub`s for types that implement this trait,
    -    /// like [`Mnemonic`](bip39::Mnemonic) when the `keys-bip39` feature is enabled.
    -    #[cfg_attr(
    -        feature = "keys-bip39",
    -        doc = r##"
    -```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::from_phrase(
    -        "jelly crash boy whisper mouse ecology tuna soccer memory million news short",
    -        Language::English
    -    )?
    -    .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::ExtendedPubKey {
    -    fn into_extended_key(self) -> Result<ExtendedKey<Ctx>, KeyError> {
    -        Ok(self.into())
    -    }
    -}
    -
    -impl<Ctx: ScriptContext> DerivableKey<Ctx> for bip32::ExtendedPrivKey {
    -    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
    -    }
    -}
    -
    -// 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: std::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::ExtendedPrivKey {
    -    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::ExtendedPrivKey::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 key = secp256k1::SecretKey::from_slice(&entropy)?;
    -        let private_key = PrivateKey {
    -            compressed: options.compressed,
    -            network: Network::Bitcoin,
    -            key,
    -        };
    -
    -        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.into_iter());
    -            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_minsicript()?;
    -
    -    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_minsicript()?;
    -
    -    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>(
    -    thresh: usize,
    -    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(Terminal::Multi(thresh, pks))?;
    -
    -    minisc.check_minsicript()?;
    -
    -    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::SinglePub(_) => 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::SinglePub(DescriptorSinglePub {
    -            key: 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::SinglePriv(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::SinglePriv(DescriptorSinglePriv {
    -            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::util::bip32::Error),
    -    /// Miniscript error
    -    Miniscript(miniscript::Error),
    -}
    -
    -impl_error!(miniscript::Error, Miniscript, KeyError);
    -impl_error!(bitcoin::util::bip32::Error, Bip32, KeyError);
    -
    -impl std::fmt::Display for KeyError {
    -    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for KeyError {}
    -
    -#[cfg(test)]
    -pub mod test {
    -    use bitcoin::util::bip32;
    -
    -    use super::*;
    -
    -    pub const TEST_ENTROPY: [u8; 32] = [0xAA; 32];
    -
    -    #[test]
    -    fn test_keys_generate_xprv() {
    -        let generated_xprv: GeneratedKey<_, miniscript::Segwitv0> =
    -            bip32::ExtendedPrivKey::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"
    -        );
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/lib.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/lib.rs.html deleted file mode 100644 index 5b66f7a5df..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/lib.rs.html +++ /dev/null @@ -1,570 +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
    - 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
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -// rustdoc will warn if there are missing docs
    -#![warn(missing_docs)]
    -// only enables the `doc_cfg` feature when
    -// the `docsrs` configuration attribute is defined
    -#![cfg_attr(docsrs, feature(doc_cfg))]
    -
    -//! A modern, lightweight, descriptor-based wallet library written in Rust.
    -//!
    -//! # About
    -//!
    -//! The BDK library aims to be the core building block for Bitcoin wallets of any kind.
    -//!
    -//! * It uses [Miniscript](https://github.com/rust-bitcoin/rust-miniscript) to support descriptors with generalized conditions. This exact same library can be used to build
    -//!   single-sig wallets, multisigs, timelocked contracts and more.
    -//! * It supports multiple blockchain backends and databases, allowing developers to choose exactly what's right for their projects.
    -//! * It is built to be cross-platform: the core logic works on desktop, mobile, and even WebAssembly.
    -//! * It is very easy to extend: developers can implement customized logic for blockchain backends, databases, signers, coin selection, and more, without having to fork and modify this library.
    -//!
    -//! # A Tour of BDK
    -//!
    -//! BDK consists of a number of modules that provide a range of functionality
    -//! essential for implementing descriptor based Bitcoin wallet applications in Rust. In this
    -//! section, we will take a brief tour of BDK, summarizing the major APIs and
    -//! their uses.
    -//!
    -//! The easiest way to get started is to add bdk to your dependencies with the default features.
    -//! The default features include a simple key-value database ([`sled`](sled)) to cache
    -//! blockchain data and an [electrum](https://docs.rs/electrum-client/) blockchain client to
    -//! interact with the bitcoin P2P network.
    -//!
    -//! ```toml
    -//! bdk = "0.11.0"
    -//! ```
    -#![cfg_attr(
    -    feature = "electrum",
    -    doc = r##"
    -## Sync the balance of a descriptor
    -
    -### Example
    -```no_run
    -use bdk::Wallet;
    -use bdk::database::MemoryDatabase;
    -use bdk::blockchain::{noop_progress, ElectrumBlockchain};
    -use bdk::electrum_client::Client;
    -
    -fn main() -> Result<(), bdk::Error> {
    -    let client = Client::new("ssl://electrum.blockstream.info:60002")?;
    -    let wallet = Wallet::new(
    -        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
    -        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
    -        bitcoin::Network::Testnet,
    -        MemoryDatabase::default(),
    -        ElectrumBlockchain::from(client)
    -    )?;
    -
    -    wallet.sync(noop_progress(), None)?;
    -
    -    println!("Descriptor balance: {} SAT", wallet.get_balance()?);
    -
    -    Ok(())
    -}
    -```
    -"##
    -)]
    -//!
    -//! ## Generate a few addresses
    -//!
    -//! ### Example
    -//! ```
    -//! use bdk::{Wallet};
    -//! use bdk::database::MemoryDatabase;
    -//! use bdk::wallet::AddressIndex::New;
    -//!
    -//! fn main() -> Result<(), bdk::Error> {
    -//! let wallet = Wallet::new_offline(
    -//!         "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
    -//!         Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
    -//!         bitcoin::Network::Testnet,
    -//!         MemoryDatabase::default(),
    -//!     )?;
    -//!
    -//!     println!("Address #0: {}", wallet.get_address(New)?);
    -//!     println!("Address #1: {}", wallet.get_address(New)?);
    -//!     println!("Address #2: {}", wallet.get_address(New)?);
    -//!
    -//!     Ok(())
    -//! }
    -//! ```
    -#![cfg_attr(
    -    feature = "electrum",
    -    doc = r##"
    -## Create a transaction
    -
    -### Example
    -```no_run
    -use bdk::{FeeRate, Wallet};
    -use bdk::database::MemoryDatabase;
    -use bdk::blockchain::{noop_progress, ElectrumBlockchain};
    -use bdk::electrum_client::Client;
    -
    -use bitcoin::consensus::serialize;
    -use bdk::wallet::AddressIndex::New;
    -
    -fn main() -> Result<(), bdk::Error> {
    -    let client = Client::new("ssl://electrum.blockstream.info:60002")?;
    -    let wallet = Wallet::new(
    -        "wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/0/*)",
    -        Some("wpkh([c258d2e4/84h/1h/0h]tpubDDYkZojQFQjht8Tm4jsS3iuEmKjTiEGjG6KnuFNKKJb5A6ZUCUZKdvLdSDWofKi4ToRCwb9poe1XdqfUnP4jaJjCB2Zwv11ZLgSbnZSNecE/1/*)"),
    -        bitcoin::Network::Testnet,
    -        MemoryDatabase::default(),
    -        ElectrumBlockchain::from(client)
    -    )?;
    -
    -    wallet.sync(noop_progress(), None)?;
    -
    -    let send_to = wallet.get_address(New)?;
    -    let (psbt, details) = {
    -        let mut builder =  wallet.build_tx();
    -        builder
    -            .add_recipient(send_to.script_pubkey(), 50_000)
    -            .enable_rbf()
    -            .do_not_spend_change()
    -            .fee_rate(FeeRate::from_sat_per_vb(5.0));
    -        builder.finish()?
    -    };
    -
    -    println!("Transaction details: {:#?}", details);
    -    println!("Unsigned PSBT: {}", &psbt);
    -
    -    Ok(())
    -}
    -```
    -"##
    -)]
    -//!
    -//! ## Sign a transaction
    -//!
    -//! ### Example
    -//! ```no_run
    -//! use std::str::FromStr;
    -//!
    -//! use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
    -//!
    -//! use bdk::{Wallet, SignOptions};
    -//! use bdk::database::MemoryDatabase;
    -//!
    -//! fn main() -> Result<(), bdk::Error> {
    -//!     let wallet = Wallet::new_offline(
    -//!         "wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/0/*)",
    -//!         Some("wpkh([c258d2e4/84h/1h/0h]tprv8griRPhA7342zfRyB6CqeKF8CJDXYu5pgnj1cjL1u2ngKcJha5jjTRimG82ABzJQ4MQe71CV54xfn25BbhCNfEGGJZnxvCDQCd6JkbvxW6h/1/*)"),
    -//!         bitcoin::Network::Testnet,
    -//!         MemoryDatabase::default(),
    -//!     )?;
    -//!
    -//!     let psbt = "...";
    -//!     let mut psbt = Psbt::from_str(psbt)?;
    -//!
    -//!     let finalized = wallet.sign(&mut psbt, SignOptions::default())?;
    -//!
    -//!     Ok(())
    -//! }
    -//! ```
    -//!
    -//! # Feature flags
    -//!
    -//! BDK uses a set of [feature flags](https://doc.rust-lang.org/cargo/reference/manifest.html#the-features-section)
    -//! to reduce the amount of compiled code by allowing projects to only enable the features they need.
    -//! By default, BDK enables two internal features, `key-value-db` and `electrum`.
    -//!
    -//! If you are new to BDK we recommended that you use the default features which will enable
    -//! basic descriptor wallet functionality. More advanced users can disable the `default` features
    -//! (`--no-default-features`) and build the BDK library with only the features you need.
    -
    -//! Below is a list of the available feature flags and the additional functionality they provide.
    -//!
    -//! * `all-keys`: all features for working with bitcoin keys
    -//! * `async-interface`: async functions in bdk traits
    -//! * `keys-bip39`: [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki) mnemonic codes for generating deterministic keys
    -//!
    -//! ## Internal features
    -//!
    -//! These features do not expose any new API, but influence internal implementation aspects of
    -//! BDK.
    -//!
    -//! * `compact_filters`: [`compact_filters`](crate::blockchain::compact_filters) client protocol for interacting with the bitcoin P2P network
    -//! * `electrum`: [`electrum`](crate::blockchain::electrum) client protocol for interacting with electrum servers
    -//! * `esplora`: [`esplora`](crate::blockchain::esplora) client protocol for interacting with blockstream [electrs](https://github.com/Blockstream/electrs) servers
    -//! * `key-value-db`: key value [`database`](crate::database) based on [`sled`](crate::sled) for caching blockchain data
    -
    -pub extern crate bitcoin;
    -extern crate log;
    -pub extern crate miniscript;
    -extern crate serde;
    -#[macro_use]
    -extern crate serde_json;
    -
    -#[cfg(all(feature = "reqwest", feature = "ureq"))]
    -compile_error!("Features reqwest and ureq are mutually exclusive and cannot be enabled together");
    -
    -#[cfg(all(feature = "async-interface", feature = "electrum"))]
    -compile_error!(
    -    "Features async-interface and electrum are mutually exclusive and cannot be enabled together"
    -);
    -
    -#[cfg(all(feature = "async-interface", feature = "ureq"))]
    -compile_error!(
    -    "Features async-interface and ureq are mutually exclusive and cannot be enabled together"
    -);
    -
    -#[cfg(all(feature = "async-interface", feature = "compact_filters"))]
    -compile_error!(
    -    "Features async-interface and compact_filters are mutually exclusive and cannot be enabled together"
    -);
    -
    -#[cfg(feature = "keys-bip39")]
    -extern crate bip39;
    -
    -#[cfg(any(target_arch = "wasm32", feature = "async-interface"))]
    -#[macro_use]
    -extern crate async_trait;
    -#[macro_use]
    -extern crate bdk_macros;
    -
    -#[cfg(feature = "compact_filters")]
    -extern crate lazy_static;
    -
    -#[cfg(feature = "rpc")]
    -pub extern crate core_rpc;
    -
    -#[cfg(feature = "electrum")]
    -pub extern crate electrum_client;
    -
    -#[cfg(feature = "key-value-db")]
    -pub extern crate sled;
    -
    -#[cfg(feature = "sqlite")]
    -pub extern crate rusqlite;
    -
    -#[allow(unused_imports)]
    -#[macro_use]
    -pub(crate) mod error;
    -pub mod blockchain;
    -pub mod database;
    -pub mod descriptor;
    -#[cfg(feature = "test-md-docs")]
    -mod doctest;
    -pub mod keys;
    -pub(crate) mod psbt;
    -pub(crate) mod types;
    -pub mod wallet;
    -
    -pub use descriptor::template;
    -pub use descriptor::HdKeyPaths;
    -pub use error::Error;
    -pub use types::*;
    -pub use wallet::address_validator;
    -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")
    -}
    -
    -// We should consider putting this under a feature flag but we need the macro in doctets so we need
    -// to wait until https://github.com/rust-lang/rust/issues/67295 is fixed.
    -//
    -// Stuff in here is too rough to document atm
    -#[doc(hidden)]
    -pub mod testutils;
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/psbt/mod.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/psbt/mod.rs.html deleted file mode 100644 index ca046b7b88..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/psbt/mod.rs.html +++ /dev/null @@ -1,248 +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
    -
    // 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::util::psbt::PartiallySignedTransaction as Psbt;
    -use bitcoin::TxOut;
    -
    -pub trait PsbtUtils {
    -    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut>;
    -}
    -
    -impl PsbtUtils for Psbt {
    -    #[allow(clippy::all)] // We want to allow `manual_map` but it is too new.
    -    fn get_utxo_for(&self, input_index: usize) -> Option<TxOut> {
    -        let tx = &self.global.unsigned_tx;
    -
    -        if input_index >= tx.input.len() {
    -            return None;
    -        }
    -
    -        if let Some(input) = self.inputs.get(input_index) {
    -            if let Some(wit_utxo) = &input.witness_utxo {
    -                Some(wit_utxo.clone())
    -            } else if let Some(in_tx) = &input.non_witness_utxo {
    -                Some(in_tx.output[tx.input[input_index].previous_output.vout as usize].clone())
    -            } else {
    -                None
    -            }
    -        } else {
    -            None
    -        }
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use crate::bitcoin::TxIn;
    -    use crate::psbt::Psbt;
    -    use crate::wallet::AddressIndex;
    -    use crate::wallet::{get_funded_wallet, test::get_test_wpkh};
    -    use crate::SignOptions;
    -    use std::str::FromStr;
    -
    -    // from bip 174
    -    const PSBT_STR: &str = "cHNidP8BAKACAAAAAqsJSaCMWvfEm4IS9Bfi8Vqz9cM9zxU4IagTn4d6W3vkAAAAAAD+////qwlJoIxa98SbghL0F+LxWrP1wz3PFTghqBOfh3pbe+QBAAAAAP7///8CYDvqCwAAAAAZdqkUdopAu9dAy+gdmI5x3ipNXHE5ax2IrI4kAAAAAAAAGXapFG9GILVT+glechue4O/p+gOcykWXiKwAAAAAAAEHakcwRAIgR1lmF5fAGwNrJZKJSGhiGDR9iYZLcZ4ff89X0eURZYcCIFMJ6r9Wqk2Ikf/REf3xM286KdqGbX+EhtdVRs7tr5MZASEDXNxh/HupccC1AaZGoqg7ECy0OIEhfKaC3Ibi1z+ogpIAAQEgAOH1BQAAAAAXqRQ1RebjO4MsRwUPJNPuuTycA5SLx4cBBBYAFIXRNTfy4mVAWjTbr6nj3aAfuCMIAAAA";
    -
    -    #[test]
    -    #[should_panic(expected = "InputIndexOutOfRange")]
    -    fn test_psbt_malformed_psbt_input_legacy() {
    -        let psbt_bip = Psbt::from_str(PSBT_STR).unwrap();
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let send_to = wallet.get_address(AddressIndex::New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(send_to.script_pubkey(), 10_000);
    -        let (mut psbt, _) = builder.finish().unwrap();
    -        psbt.inputs.push(psbt_bip.inputs[0].clone());
    -        let options = SignOptions {
    -            trust_witness_utxo: true,
    -            ..Default::default()
    -        };
    -        let _ = wallet.sign(&mut psbt, options).unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InputIndexOutOfRange")]
    -    fn test_psbt_malformed_psbt_input_segwit() {
    -        let psbt_bip = Psbt::from_str(PSBT_STR).unwrap();
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let send_to = wallet.get_address(AddressIndex::New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(send_to.script_pubkey(), 10_000);
    -        let (mut psbt, _) = builder.finish().unwrap();
    -        psbt.inputs.push(psbt_bip.inputs[1].clone());
    -        let options = SignOptions {
    -            trust_witness_utxo: true,
    -            ..Default::default()
    -        };
    -        let _ = wallet.sign(&mut psbt, options).unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InputIndexOutOfRange")]
    -    fn test_psbt_malformed_tx_input() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let send_to = wallet.get_address(AddressIndex::New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(send_to.script_pubkey(), 10_000);
    -        let (mut psbt, _) = builder.finish().unwrap();
    -        psbt.global.unsigned_tx.input.push(TxIn::default());
    -        let options = SignOptions {
    -            trust_witness_utxo: true,
    -            ..Default::default()
    -        };
    -        let _ = wallet.sign(&mut psbt, options).unwrap();
    -    }
    -
    -    #[test]
    -    fn test_psbt_sign_with_finalized() {
    -        let psbt_bip = Psbt::from_str(PSBT_STR).unwrap();
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let send_to = wallet.get_address(AddressIndex::New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(send_to.script_pubkey(), 10_000);
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        // add a finalized input
    -        psbt.inputs.push(psbt_bip.inputs[0].clone());
    -        psbt.global
    -            .unsigned_tx
    -            .input
    -            .push(psbt_bip.global.unsigned_tx.input[0].clone());
    -
    -        let _ = wallet.sign(&mut psbt, SignOptions::default()).unwrap();
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/testutils/mod.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/testutils/mod.rs.html deleted file mode 100644 index a673857c4e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/testutils/mod.rs.html +++ /dev/null @@ -1,466 +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
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -#![allow(missing_docs)]
    -
    -#[cfg(test)]
    -#[cfg(feature = "test-blockchains")]
    -pub mod blockchain_tests;
    -
    -use bitcoin::secp256k1::{Secp256k1, Verification};
    -use bitcoin::{Address, PublicKey};
    -
    -use miniscript::descriptor::DescriptorPublicKey;
    -use miniscript::{Descriptor, MiniscriptKey, TranslatePk};
    -
    -#[derive(Clone, Debug)]
    -pub struct TestIncomingOutput {
    -    pub value: u64,
    -    pub to_address: String,
    -}
    -
    -impl TestIncomingOutput {
    -    pub fn new(value: u64, to_address: Address) -> Self {
    -        Self {
    -            value,
    -            to_address: to_address.to_string(),
    -        }
    -    }
    -}
    -
    -#[derive(Clone, Debug)]
    -pub struct TestIncomingTx {
    -    pub output: Vec<TestIncomingOutput>,
    -    pub min_confirmations: Option<u64>,
    -    pub locktime: Option<i64>,
    -    pub replaceable: Option<bool>,
    -}
    -
    -impl TestIncomingTx {
    -    pub fn new(
    -        output: Vec<TestIncomingOutput>,
    -        min_confirmations: Option<u64>,
    -        locktime: Option<i64>,
    -        replaceable: Option<bool>,
    -    ) -> Self {
    -        Self {
    -            output,
    -            min_confirmations,
    -            locktime,
    -            replaceable,
    -        }
    -    }
    -
    -    pub fn add_output(&mut self, output: TestIncomingOutput) {
    -        self.output.push(output);
    -    }
    -}
    -
    -#[doc(hidden)]
    -pub trait TranslateDescriptor {
    -    // derive and translate a `Descriptor<DescriptorPublicKey>` into a `Descriptor<PublicKey>`
    -    fn derive_translated<C: Verification>(
    -        &self,
    -        secp: &Secp256k1<C>,
    -        index: u32,
    -    ) -> Descriptor<PublicKey>;
    -}
    -
    -impl TranslateDescriptor for Descriptor<DescriptorPublicKey> {
    -    fn derive_translated<C: Verification>(
    -        &self,
    -        secp: &Secp256k1<C>,
    -        index: u32,
    -    ) -> Descriptor<PublicKey> {
    -        let translate = |key: &DescriptorPublicKey| -> PublicKey {
    -            match key {
    -                DescriptorPublicKey::XPub(xpub) => {
    -                    xpub.xkey
    -                        .derive_pub(secp, &xpub.derivation_path)
    -                        .expect("hardened derivation steps")
    -                        .public_key
    -                }
    -                DescriptorPublicKey::SinglePub(key) => key.key,
    -            }
    -        };
    -
    -        self.derive(index)
    -            .translate_pk_infallible(|pk| translate(pk), |pkh| translate(pkh).to_pubkeyhash())
    -    }
    -}
    -
    -#[doc(hidden)]
    -#[macro_export]
    -macro_rules! testutils {
    -    ( @external $descriptors:expr, $child:expr ) => ({
    -        use $crate::bitcoin::secp256k1::Secp256k1;
    -        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey, DescriptorTrait};
    -
    -        use $crate::testutils::TranslateDescriptor;
    -
    -        let secp = Secp256k1::new();
    -
    -        let parsed = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, &$descriptors.0).expect("Failed to parse descriptor in `testutils!(@external)`").0;
    -        parsed.derive_translated(&secp, $child).address(bitcoin::Network::Regtest).expect("No address form")
    -    });
    -    ( @internal $descriptors:expr, $child:expr ) => ({
    -        use $crate::bitcoin::secp256k1::Secp256k1;
    -        use $crate::miniscript::descriptor::{Descriptor, DescriptorPublicKey, DescriptorTrait};
    -
    -        use $crate::testutils::TranslateDescriptor;
    -
    -        let secp = Secp256k1::new();
    -
    -        let parsed = Descriptor::<DescriptorPublicKey>::parse_descriptor(&secp, &$descriptors.1.expect("Missing internal descriptor")).expect("Failed to parse descriptor in `testutils!(@internal)`").0;
    -        parsed.derive_translated(&secp, $child).address($crate::bitcoin::Network::Regtest).expect("No address form")
    -    });
    -    ( @e $descriptors:expr, $child:expr ) => ({ testutils!(@external $descriptors, $child) });
    -    ( @i $descriptors:expr, $child:expr ) => ({ testutils!(@internal $descriptors, $child) });
    -
    -    ( @tx ( $( ( $( $addr:tt )* ) => $amount:expr ),+ ) $( ( @locktime $locktime:expr ) )? $( ( @confirmations $confirmations:expr ) )? $( ( @replaceable $replaceable:expr ) )? ) => ({
    -        let outs = vec![$( $crate::testutils::TestIncomingOutput::new($amount, testutils!( $($addr)* ))),+];
    -
    -        let locktime = None::<i64>$(.or(Some($locktime)))?;
    -
    -        let min_confirmations = None::<u64>$(.or(Some($confirmations)))?;
    -        let replaceable = None::<bool>$(.or(Some($replaceable)))?;
    -
    -        $crate::testutils::TestIncomingTx::new(outs, min_confirmations, locktime, replaceable)
    -    });
    -
    -    ( @literal $key:expr ) => ({
    -        let key = $key.to_string();
    -        (key, None::<String>, None::<String>)
    -    });
    -    ( @generate_xprv $( $external_path:expr )? $( ,$internal_path:expr )? ) => ({
    -        use rand::Rng;
    -
    -        let mut seed = [0u8; 32];
    -        rand::thread_rng().fill(&mut seed[..]);
    -
    -        let key = $crate::bitcoin::util::bip32::ExtendedPrivKey::new_master(
    -            $crate::bitcoin::Network::Testnet,
    -            &seed,
    -        );
    -
    -        let external_path = None::<String>$(.or(Some($external_path.to_string())))?;
    -        let internal_path = None::<String>$(.or(Some($internal_path.to_string())))?;
    -
    -        (key.unwrap().to_string(), external_path, internal_path)
    -    });
    -    ( @generate_wif ) => ({
    -        use rand::Rng;
    -
    -        let mut key = [0u8; $crate::bitcoin::secp256k1::constants::SECRET_KEY_SIZE];
    -        rand::thread_rng().fill(&mut key[..]);
    -
    -        ($crate::bitcoin::PrivateKey {
    -            compressed: true,
    -            network: $crate::bitcoin::Network::Testnet,
    -            key: $crate::bitcoin::secp256k1::SecretKey::from_slice(&key).unwrap(),
    -        }.to_string(), None::<String>, None::<String>)
    -    });
    -
    -    ( @keys ( $( $alias:expr => ( $( $key_type:tt )* ) ),+ ) ) => ({
    -        let mut map = std::collections::HashMap::new();
    -        $(
    -            let alias: &str = $alias;
    -            map.insert(alias, testutils!( $($key_type)* ));
    -        )+
    -
    -        map
    -    });
    -
    -    ( @descriptors ( $external_descriptor:expr ) $( ( $internal_descriptor:expr ) )? $( ( @keys $( $keys:tt )* ) )* ) => ({
    -        use std::str::FromStr;
    -        use std::collections::HashMap;
    -        use $crate::miniscript::descriptor::Descriptor;
    -        use $crate::miniscript::TranslatePk;
    -
    -        #[allow(unused_assignments, unused_mut)]
    -        let mut keys: HashMap<&'static str, (String, Option<String>, Option<String>)> = HashMap::new();
    -        $(
    -            keys = testutils!{ @keys $( $keys )* };
    -        )*
    -
    -        let external: Descriptor<String> = FromStr::from_str($external_descriptor).unwrap();
    -        let external: Descriptor<String> = external.translate_pk_infallible::<_, _>(|k| {
    -            if let Some((key, ext_path, _)) = keys.get(&k.as_str()) {
    -                format!("{}{}", key, ext_path.as_ref().unwrap_or(&"".into()))
    -            } else {
    -                k.clone()
    -            }
    -        }, |kh| {
    -            if let Some((key, ext_path, _)) = keys.get(&kh.as_str()) {
    -                format!("{}{}", key, ext_path.as_ref().unwrap_or(&"".into()))
    -            } else {
    -                kh.clone()
    -            }
    -
    -        });
    -        let external = external.to_string();
    -
    -        let internal = None::<String>$(.or({
    -            let string_internal: Descriptor<String> = FromStr::from_str($internal_descriptor).unwrap();
    -
    -            let string_internal: Descriptor<String> = string_internal.translate_pk_infallible::<_, _>(|k| {
    -                if let Some((key, _, int_path)) = keys.get(&k.as_str()) {
    -                    format!("{}{}", key, int_path.as_ref().unwrap_or(&"".into()))
    -                } else {
    -                    k.clone()
    -                }
    -            }, |kh| {
    -                if let Some((key, _, int_path)) = keys.get(&kh.as_str()) {
    -                    format!("{}{}", key, int_path.as_ref().unwrap_or(&"".into()))
    -                } else {
    -                    kh.clone()
    -                }
    -            });
    -            Some(string_internal.to_string())
    -        }))?;
    -
    -        (external, internal)
    -    })
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/types.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/types.rs.html deleted file mode 100644 index a5f9e76a88..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/types.rs.html +++ /dev/null @@ -1,510 +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
    -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
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -use std::convert::AsRef;
    -use std::ops::Sub;
    -
    -use bitcoin::blockdata::transaction::{OutPoint, Transaction, TxOut};
    -use bitcoin::{hash_types::Txid, util::psbt};
    -
    -use serde::{Deserialize, Serialize};
    -
    -/// Types of keychains
    -#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, Hash)]
    -pub enum KeychainKind {
    -    /// External
    -    External = 0,
    -    /// Internal, usually used for change outputs
    -    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",
    -        }
    -    }
    -}
    -
    -/// Fee rate
    -#[derive(Debug, Copy, Clone, PartialEq, PartialOrd)]
    -// Internally stored as satoshi/vbyte
    -pub struct FeeRate(f32);
    -
    -impl FeeRate {
    -    /// Create a new instance of [`FeeRate`] given a float fee rate in btc/kvbytes
    -    pub fn from_btc_per_kvb(btc_per_kvb: f32) -> Self {
    -        FeeRate(btc_per_kvb * 1e5)
    -    }
    -
    -    /// Create a new instance of [`FeeRate`] given a float fee rate in satoshi/vbyte
    -    pub const fn from_sat_per_vb(sat_per_vb: f32) -> Self {
    -        FeeRate(sat_per_vb)
    -    }
    -
    -    /// Create a new [`FeeRate`] with the default min relay fee value
    -    pub const fn default_min_relay_fee() -> Self {
    -        FeeRate(1.0)
    -    }
    -
    -    /// Calculate fee rate from `fee` and weight units (`wu`).
    -    pub fn from_wu(fee: u64, wu: usize) -> FeeRate {
    -        Self::from_vb(fee, wu.vbytes())
    -    }
    -
    -    /// Calculate fee rate from `fee` and `vbytes`.
    -    pub fn from_vb(fee: u64, vbytes: usize) -> FeeRate {
    -        let rate = fee as f32 / vbytes as f32;
    -        Self::from_sat_per_vb(rate)
    -    }
    -
    -    /// Return the value as satoshi/vbyte
    -    pub fn as_sat_vb(&self) -> f32 {
    -        self.0
    -    }
    -
    -    /// Calculate absolute fee in Satoshis using size in weight units.
    -    pub fn fee_wu(&self, wu: usize) -> u64 {
    -        self.fee_vb(wu.vbytes())
    -    }
    -
    -    /// Calculate absolute fee in Satoshis using size in virtual bytes.
    -    pub fn fee_vb(&self, vbytes: usize) -> u64 {
    -        (self.as_sat_vb() * vbytes as f32).ceil() as u64
    -    }
    -}
    -
    -impl std::default::Default for FeeRate {
    -    fn default() -> Self {
    -        FeeRate::default_min_relay_fee()
    -    }
    -}
    -
    -impl Sub for FeeRate {
    -    type Output = Self;
    -
    -    fn sub(self, other: FeeRate) -> Self::Output {
    -        FeeRate(self.0 - other.0)
    -    }
    -}
    -
    -/// Trait implemented by types that can be used to measure weight units.
    -pub trait Vbytes {
    -    /// Convert weight units to virtual bytes.
    -    fn vbytes(self) -> usize;
    -}
    -
    -impl Vbytes for usize {
    -    fn vbytes(self) -> usize {
    -        // ref: https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#transaction-size-calculations
    -        (self as f32 / 4.0).ceil() as usize
    -    }
    -}
    -
    -/// An unspent output owned by a [`Wallet`].
    -///
    -/// [`Wallet`]: crate::Wallet
    -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
    -pub struct LocalUtxo {
    -    /// Reference to a transaction output
    -    pub outpoint: OutPoint,
    -    /// Transaction output
    -    pub txout: TxOut,
    -    /// Type of keychain
    -    pub keychain: KeychainKind,
    -}
    -
    -/// A [`Utxo`] with its `satisfaction_weight`.
    -#[derive(Debug, Clone, PartialEq)]
    -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)]
    -/// An unspent transaction output (UTXO).
    -pub enum Utxo {
    -    /// A UTXO owned by the local wallet.
    -    Local(LocalUtxo),
    -    /// A UTXO owned by another wallet.
    -    Foreign {
    -        /// The location of the output.
    -        outpoint: OutPoint,
    -        /// 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")
    -            }
    -        }
    -    }
    -}
    -
    -/// A wallet transaction
    -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
    -pub struct TransactionDetails {
    -    /// Optional transaction
    -    pub transaction: Option<Transaction>,
    -    /// Transaction id
    -    pub txid: Txid,
    -
    -    /// Received value (sats)
    -    pub received: u64,
    -    /// Sent value (sats)
    -    pub sent: u64,
    -    /// Fee value (sats) if available.
    -    /// The availability of the fee depends on the backend. It's never `None` with an Electrum
    -    /// Server backend, but it could be `None` with a Bitcoin RPC node without txindex that receive
    -    /// funds while offline.
    -    pub fee: Option<u64>,
    -    /// If the transaction is confirmed, contains height and timestamp of the block containing the
    -    /// transaction, unconfirmed transaction contains `None`.
    -    pub confirmation_time: Option<ConfirmationTime>,
    -    /// Whether the tx has been verified against the consensus rules
    -    ///
    -    /// Confirmed txs are considered "verified" by default, while unconfirmed txs are checked to
    -    /// ensure an unstrusted [`Blockchain`](crate::blockchain::Blockchain) backend can't trick the
    -    /// wallet into using an invalid tx as an RBF template.
    -    ///
    -    /// The check is only perfomed when the `verify` feature is enabled.
    -    #[serde(default = "bool::default")] // default to `false` if not specified
    -    pub verified: bool,
    -}
    -
    -/// Block height and timestamp of the block containing the confirmed transaction
    -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
    -pub struct ConfirmationTime {
    -    /// confirmation block height
    -    pub height: u32,
    -    /// confirmation block timestamp
    -    pub timestamp: u64,
    -}
    -
    -impl ConfirmationTime {
    -    /// Returns `Some` `ConfirmationTime` if both `height` and `timestamp` are `Some`
    -    pub fn new(height: Option<u32>, timestamp: Option<u64>) -> Option<Self> {
    -        match (height, timestamp) {
    -            (Some(height), Some(timestamp)) => Some(ConfirmationTime { height, timestamp }),
    -            _ => None,
    -        }
    -    }
    -}
    -
    -#[cfg(test)]
    -mod tests {
    -    use super::*;
    -
    -    #[test]
    -    fn can_store_feerate_in_const() {
    -        const _MY_RATE: FeeRate = FeeRate::from_sat_per_vb(10.0);
    -        const _MIN_RELAY: FeeRate = FeeRate::default_min_relay_fee();
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/address_validator.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/address_validator.rs.html deleted file mode 100644 index b4b1b942ac..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/address_validator.rs.html +++ /dev/null @@ -1,312 +0,0 @@ -address_validator.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
    -
    // 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.
    -
    -//! Address validation callbacks
    -//!
    -//! The typical usage of those callbacks is for displaying the newly-generated address on a
    -//! hardware wallet, so that the user can cross-check its correctness.
    -//!
    -//! More generally speaking though, these callbacks can also be used to "do something" every time
    -//! an address is generated, without necessarily checking or validating it.
    -//!
    -//! An address validator can be attached to a [`Wallet`](super::Wallet) by using the
    -//! [`Wallet::add_address_validator`](super::Wallet::add_address_validator) method, and
    -//! whenever a new address is generated (either explicitly by the user with
    -//! [`Wallet::get_address`](super::Wallet::get_address) or internally to create a change
    -//! address) all the attached validators will be polled, in sequence. All of them must complete
    -//! successfully to continue.
    -//!
    -//! ## Example
    -//!
    -//! ```
    -//! # use std::sync::Arc;
    -//! # use bitcoin::*;
    -//! # use bdk::address_validator::*;
    -//! # use bdk::database::*;
    -//! # use bdk::*;
    -//! # use bdk::wallet::AddressIndex::New;
    -//! #[derive(Debug)]
    -//! struct PrintAddressAndContinue;
    -//!
    -//! impl AddressValidator for PrintAddressAndContinue {
    -//!     fn validate(
    -//!         &self,
    -//!         keychain: KeychainKind,
    -//!         hd_keypaths: &HdKeyPaths,
    -//!         script: &Script
    -//!     ) -> Result<(), AddressValidatorError> {
    -//!         let address = Address::from_script(script, Network::Testnet)
    -//!             .as_ref()
    -//!             .map(Address::to_string)
    -//!             .unwrap_or(script.to_string());
    -//!         println!("New address of type {:?}: {}", keychain, address);
    -//!         println!("HD keypaths: {:#?}", hd_keypaths);
    -//!
    -//!         Ok(())
    -//!     }
    -//! }
    -//!
    -//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -//! let mut wallet = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -//! wallet.add_address_validator(Arc::new(PrintAddressAndContinue));
    -//!
    -//! let address = wallet.get_address(New)?;
    -//! println!("Address: {}", address);
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use std::fmt;
    -
    -use bitcoin::Script;
    -
    -use crate::descriptor::HdKeyPaths;
    -use crate::types::KeychainKind;
    -
    -/// Errors that can be returned to fail the validation of an address
    -#[derive(Debug, Clone, PartialEq, Eq)]
    -pub enum AddressValidatorError {
    -    /// User rejected the address
    -    UserRejected,
    -    /// Network connection error
    -    ConnectionError,
    -    /// Network request timeout error
    -    TimeoutError,
    -    /// Invalid script
    -    InvalidScript,
    -    /// A custom error message
    -    Message(String),
    -}
    -
    -impl fmt::Display for AddressValidatorError {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for AddressValidatorError {}
    -
    -/// Trait to build address validators
    -///
    -/// All the address validators attached to a wallet with [`Wallet::add_address_validator`](super::Wallet::add_address_validator) will be polled
    -/// every time an address (external or internal) is generated by the wallet. Errors returned in the
    -/// validator will be propagated up to the original caller that triggered the address generation.
    -///
    -/// For a usage example see [this module](crate::address_validator)'s documentation.
    -pub trait AddressValidator: Send + Sync + fmt::Debug {
    -    /// Validate or inspect an address
    -    fn validate(
    -        &self,
    -        keychain: KeychainKind,
    -        hd_keypaths: &HdKeyPaths,
    -        script: &Script,
    -    ) -> Result<(), AddressValidatorError>;
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::sync::Arc;
    -
    -    use super::*;
    -    use crate::wallet::AddressIndex::New;
    -    use crate::wallet::{get_funded_wallet, test::get_test_wpkh};
    -
    -    #[derive(Debug)]
    -    struct TestValidator;
    -    impl AddressValidator for TestValidator {
    -        fn validate(
    -            &self,
    -            _keychain: KeychainKind,
    -            _hd_keypaths: &HdKeyPaths,
    -            _script: &bitcoin::Script,
    -        ) -> Result<(), AddressValidatorError> {
    -            Err(AddressValidatorError::InvalidScript)
    -        }
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InvalidScript")]
    -    fn test_address_validator_external() {
    -        let (mut wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        wallet.add_address_validator(Arc::new(TestValidator));
    -
    -        wallet.get_address(New).unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InvalidScript")]
    -    fn test_address_validator_internal() {
    -        let (mut wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        wallet.add_address_validator(Arc::new(TestValidator));
    -
    -        let addr = crate::testutils!(@external descriptors, 10);
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        builder.finish().unwrap();
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/coin_selection.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/coin_selection.rs.html deleted file mode 100644 index dc5c9f14b7..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/coin_selection.rs.html +++ /dev/null @@ -1,2122 +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
    -
    // 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, coin_selection::*};
    -//! # use bdk::database::Database;
    -//! # use bdk::*;
    -//! # const TXIN_BASE_WEIGHT: usize = (32 + 4 + 4 + 1) * 4;
    -//! #[derive(Debug)]
    -//! struct AlwaysSpendEverything;
    -//!
    -//! impl<D: Database> CoinSelectionAlgorithm<D> for AlwaysSpendEverything {
    -//!     fn coin_select(
    -//!         &self,
    -//!         database: &D,
    -//!         required_utxos: Vec<WeightedUtxo>,
    -//!         optional_utxos: Vec<WeightedUtxo>,
    -//!         fee_rate: FeeRate,
    -//!         amount_needed: u64,
    -//!         fee_amount: u64,
    -//!     ) -> Result<CoinSelectionResult, bdk::Error> {
    -//!         let mut selected_amount = 0;
    -//!         let mut additional_weight = 0;
    -//!         let all_utxos_selected = required_utxos
    -//!             .into_iter()
    -//!             .chain(optional_utxos)
    -//!             .scan(
    -//!                 (&mut selected_amount, &mut additional_weight),
    -//!                 |(selected_amount, additional_weight), weighted_utxo| {
    -//!                     **selected_amount += weighted_utxo.utxo.txout().value;
    -//!                     **additional_weight += TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight;
    -//!                     Some(weighted_utxo.utxo)
    -//!                 },
    -//!             )
    -//!             .collect::<Vec<_>>();
    -//!         let additional_fees = fee_rate.fee_wu(additional_weight);
    -//!         let amount_needed_with_fees = (fee_amount + additional_fees) + amount_needed;
    -//!         if amount_needed_with_fees > selected_amount {
    -//!             return Err(bdk::Error::InsufficientFunds {
    -//!                 needed: amount_needed_with_fees,
    -//!                 available: selected_amount,
    -//!             });
    -//!         }
    -//!
    -//!         Ok(CoinSelectionResult {
    -//!             selected: all_utxos_selected,
    -//!             fee_amount: fee_amount + additional_fees,
    -//!         })
    -//!     }
    -//! }
    -//!
    -//! # let wallet = doctest_wallet!();
    -//! // create wallet, sync, ...
    -//!
    -//! let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -//! let (psbt, details) = {
    -//!     let mut builder = wallet.build_tx().coin_selection(AlwaysSpendEverything);
    -//!     builder.add_recipient(to_address.script_pubkey(), 50_000);
    -//!     builder.finish()?
    -//! };
    -//!
    -//! // inspect, sign, broadcast, ...
    -//!
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use crate::types::FeeRate;
    -use crate::{database::Database, WeightedUtxo};
    -use crate::{error::Error, Utxo};
    -
    -use rand::seq::SliceRandom;
    -#[cfg(not(test))]
    -use rand::thread_rng;
    -#[cfg(test)]
    -use rand::{rngs::StdRng, SeedableRng};
    -use std::convert::TryInto;
    -
    -/// Default coin selection algorithm used by [`TxBuilder`](super::tx_builder::TxBuilder) if not
    -/// overridden
    -#[cfg(not(test))]
    -pub type DefaultCoinSelectionAlgorithm = BranchAndBoundCoinSelection;
    -#[cfg(test)]
    -pub type DefaultCoinSelectionAlgorithm = LargestFirstCoinSelection; // make the tests more predictable
    -
    -// Base weight of a Txin, not counting the weight needed for satisfying it.
    -// prev_txid (32 bytes) + prev_vout (4 bytes) + sequence (4 bytes) + script_len (1 bytes)
    -pub(crate) const TXIN_BASE_WEIGHT: usize = (32 + 4 + 4 + 1) * 4;
    -
    -/// 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 in satoshi
    -    pub fee_amount: u64,
    -}
    -
    -impl CoinSelectionResult {
    -    /// The total value of the inputs selected.
    -    pub fn selected_amount(&self) -> u64 {
    -        self.selected.iter().map(|u| u.txout().value).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),
    -                _ => 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<D: Database>: std::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 `amount_needed` with their
    -    ///                     weight cost
    -    /// - `optional_utxos`: the remaining available utxos to satisfy `amount_needed` with their
    -    ///                     weight cost
    -    /// - `fee_rate`: fee rate to use
    -    /// - `amount_needed`: the amount in satoshi to select
    -    /// - `fee_amount`: the amount of fees in satoshi already accumulated from adding outputs and
    -    ///                 the transaction's header
    -    fn coin_select(
    -        &self,
    -        database: &D,
    -        required_utxos: Vec<WeightedUtxo>,
    -        optional_utxos: Vec<WeightedUtxo>,
    -        fee_rate: FeeRate,
    -        amount_needed: u64,
    -        fee_amount: u64,
    -    ) -> 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<D: Database> CoinSelectionAlgorithm<D> for LargestFirstCoinSelection {
    -    fn coin_select(
    -        &self,
    -        _database: &D,
    -        required_utxos: Vec<WeightedUtxo>,
    -        mut optional_utxos: Vec<WeightedUtxo>,
    -        fee_rate: FeeRate,
    -        amount_needed: u64,
    -        mut fee_amount: u64,
    -    ) -> Result<CoinSelectionResult, Error> {
    -        log::debug!(
    -            "amount_needed = `{}`, fee_amount = `{}`, fee_rate = `{:?}`",
    -            amount_needed,
    -            fee_amount,
    -            fee_rate
    -        );
    -
    -        // 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)))
    -        };
    -
    -        // Keep including inputs until we've got enough.
    -        // Store the total input value in selected_amount and the total fee being paid in fee_amount
    -        let mut selected_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 < amount_needed + **fee_amount {
    -                        **fee_amount +=
    -                            fee_rate.fee_wu(TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight);
    -                        **selected_amount += weighted_utxo.utxo.txout().value;
    -
    -                        log::debug!(
    -                            "Selected {}, updated fee_amount = `{}`",
    -                            weighted_utxo.utxo.outpoint(),
    -                            fee_amount
    -                        );
    -
    -                        Some(weighted_utxo.utxo)
    -                    } else {
    -                        None
    -                    }
    -                },
    -            )
    -            .collect::<Vec<_>>();
    -
    -        let amount_needed_with_fees = amount_needed + fee_amount;
    -        if selected_amount < amount_needed_with_fees {
    -            return Err(Error::InsufficientFunds {
    -                needed: amount_needed_with_fees,
    -                available: selected_amount,
    -            });
    -        }
    -
    -        Ok(CoinSelectionResult {
    -            selected,
    -            fee_amount,
    -        })
    -    }
    -}
    -
    -#[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.fee_wu(TXIN_BASE_WEIGHT + weighted_utxo.satisfaction_weight);
    -        let effective_value = weighted_utxo.utxo.txout().value 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)]
    -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<D: Database> CoinSelectionAlgorithm<D> for BranchAndBoundCoinSelection {
    -    fn coin_select(
    -        &self,
    -        _database: &D,
    -        required_utxos: Vec<WeightedUtxo>,
    -        optional_utxos: Vec<WeightedUtxo>,
    -        fee_rate: FeeRate,
    -        amount_needed: u64,
    -        fee_amount: u64,
    -    ) -> 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.
    -        let optional_utxos: Vec<OutputGroup> = optional_utxos
    -            .into_iter()
    -            .map(|u| OutputGroup::new(u, fee_rate))
    -            .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 actual_target = fee_amount + amount_needed;
    -        let cost_of_change = self.size_of_change as f32 * fee_rate.as_sat_vb();
    -
    -        let expected = (curr_available_value + curr_value)
    -            .try_into()
    -            .map_err(|_| {
    -                Error::Generic("Sum of UTXO spendable values does not fit into u64".to_string())
    -            })?;
    -
    -        if expected < actual_target {
    -            return Err(Error::InsufficientFunds {
    -                needed: actual_target,
    -                available: expected,
    -            });
    -        }
    -
    -        let actual_target = actual_target
    -            .try_into()
    -            .expect("Bitcoin amount to fit into i64");
    -
    -        if curr_value > actual_target {
    -            return Ok(BranchAndBoundCoinSelection::calculate_cs_result(
    -                vec![],
    -                required_utxos,
    -                fee_amount,
    -            ));
    -        }
    -
    -        Ok(self
    -            .bnb(
    -                required_utxos.clone(),
    -                optional_utxos.clone(),
    -                curr_value,
    -                curr_available_value,
    -                actual_target,
    -                fee_amount,
    -                cost_of_change,
    -            )
    -            .unwrap_or_else(|_| {
    -                self.single_random_draw(
    -                    required_utxos,
    -                    optional_utxos,
    -                    curr_value,
    -                    actual_target,
    -                    fee_amount,
    -                )
    -            }))
    -    }
    -}
    -
    -impl BranchAndBoundCoinSelection {
    -    // TODO: make this more Rust-onic :)
    -    // (And perhpaps 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,
    -        actual_target: i64,
    -        fee_amount: u64,
    -        cost_of_change: f32,
    -    ) -> 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 < actual_target
    -                || curr_value > actual_target + cost_of_change as i64
    -            {
    -                backtrack = true;
    -            } else if curr_value >= actual_target {
    -                // 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 = current_selection.clone();
    -                    best_selection_value = Some(curr_value);
    -                }
    -
    -                // If we found a perfect match, break here
    -                if curr_value == actual_target {
    -                    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();
    -
    -        Ok(BranchAndBoundCoinSelection::calculate_cs_result(
    -            selected_utxos,
    -            required_utxos,
    -            fee_amount,
    -        ))
    -    }
    -
    -    fn single_random_draw(
    -        &self,
    -        required_utxos: Vec<OutputGroup>,
    -        mut optional_utxos: Vec<OutputGroup>,
    -        curr_value: i64,
    -        actual_target: i64,
    -        fee_amount: u64,
    -    ) -> CoinSelectionResult {
    -        #[cfg(not(test))]
    -        optional_utxos.shuffle(&mut thread_rng());
    -        #[cfg(test)]
    -        {
    -            let seed = [0; 32];
    -            let mut rng: StdRng = SeedableRng::from_seed(seed);
    -            optional_utxos.shuffle(&mut rng);
    -        }
    -
    -        let selected_utxos = optional_utxos
    -            .into_iter()
    -            .scan(curr_value, |curr_value, utxo| {
    -                if *curr_value >= actual_target {
    -                    None
    -                } else {
    -                    *curr_value += utxo.effective_value;
    -                    Some(utxo)
    -                }
    -            })
    -            .collect::<Vec<_>>();
    -
    -        BranchAndBoundCoinSelection::calculate_cs_result(selected_utxos, required_utxos, fee_amount)
    -    }
    -
    -    fn calculate_cs_result(
    -        mut selected_utxos: Vec<OutputGroup>,
    -        mut required_utxos: Vec<OutputGroup>,
    -        mut fee_amount: u64,
    -    ) -> CoinSelectionResult {
    -        selected_utxos.append(&mut required_utxos);
    -        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,
    -        }
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use std::str::FromStr;
    -
    -    use bitcoin::{OutPoint, Script, TxOut};
    -
    -    use super::*;
    -    use crate::database::MemoryDatabase;
    -    use crate::types::*;
    -    use crate::wallet::Vbytes;
    -
    -    use rand::rngs::StdRng;
    -    use rand::seq::SliceRandom;
    -    use rand::{Rng, SeedableRng};
    -
    -    const P2WPKH_WITNESS_SIZE: usize = 73 + 33 + 2;
    -
    -    const FEE_AMOUNT: u64 = 50;
    -
    -    fn utxo(value: u64, index: u32) -> WeightedUtxo {
    -        assert!(index < 10);
    -        let outpoint = OutPoint::from_str(&format!(
    -            "000000000000000000000000000000000000000000000000000000000000000{}:0",
    -            index
    -        ))
    -        .unwrap();
    -        WeightedUtxo {
    -            satisfaction_weight: P2WPKH_WITNESS_SIZE,
    -            utxo: Utxo::Local(LocalUtxo {
    -                outpoint,
    -                txout: TxOut {
    -                    value,
    -                    script_pubkey: Script::new(),
    -                },
    -                keychain: KeychainKind::External,
    -            }),
    -        }
    -    }
    -
    -    fn get_test_utxos() -> Vec<WeightedUtxo> {
    -        vec![
    -            utxo(100_000, 0),
    -            utxo(FEE_AMOUNT as u64 - 40, 1),
    -            utxo(200_000, 2),
    -        ]
    -    }
    -
    -    fn generate_random_utxos(rng: &mut StdRng, utxos_number: usize) -> Vec<WeightedUtxo> {
    -        let mut res = Vec::new();
    -        for _ in 0..utxos_number {
    -            res.push(WeightedUtxo {
    -                satisfaction_weight: P2WPKH_WITNESS_SIZE,
    -                utxo: Utxo::Local(LocalUtxo {
    -                    outpoint: OutPoint::from_str(
    -                        "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:0",
    -                    )
    -                    .unwrap(),
    -                    txout: TxOut {
    -                        value: rng.gen_range(0, 200000000),
    -                        script_pubkey: Script::new(),
    -                    },
    -                    keychain: KeychainKind::External,
    -                }),
    -            });
    -        }
    -        res
    -    }
    -
    -    fn generate_same_value_utxos(utxos_value: u64, utxos_number: usize) -> Vec<WeightedUtxo> {
    -        let utxo = WeightedUtxo {
    -            satisfaction_weight: P2WPKH_WITNESS_SIZE,
    -            utxo: Utxo::Local(LocalUtxo {
    -                outpoint: OutPoint::from_str(
    -                    "ebd9813ecebc57ff8f30797de7c205e3c7498ca950ea4341ee51a685ff2fa30a:0",
    -                )
    -                .unwrap(),
    -                txout: TxOut {
    -                    value: utxos_value,
    -                    script_pubkey: Script::new(),
    -                },
    -                keychain: KeychainKind::External,
    -            }),
    -        };
    -        vec![utxo; utxos_number]
    -    }
    -
    -    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)
    -            .sum()
    -    }
    -
    -    #[test]
    -    fn test_largest_first_coin_selection_success() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        let result = LargestFirstCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                utxos,
    -                vec![],
    -                FeeRate::from_sat_per_vb(1.0),
    -                250_000,
    -                FEE_AMOUNT,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.selected.len(), 3);
    -        assert_eq!(result.selected_amount(), 300_010);
    -        assert_eq!(result.fee_amount, 254)
    -    }
    -
    -    #[test]
    -    fn test_largest_first_coin_selection_use_all() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        let result = LargestFirstCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                utxos,
    -                vec![],
    -                FeeRate::from_sat_per_vb(1.0),
    -                20_000,
    -                FEE_AMOUNT,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.selected.len(), 3);
    -        assert_eq!(result.selected_amount(), 300_010);
    -        assert_eq!(result.fee_amount, 254);
    -    }
    -
    -    #[test]
    -    fn test_largest_first_coin_selection_use_only_necessary() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        let result = LargestFirstCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                vec![],
    -                utxos,
    -                FeeRate::from_sat_per_vb(1.0),
    -                20_000,
    -                FEE_AMOUNT,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.selected.len(), 1);
    -        assert_eq!(result.selected_amount(), 200_000);
    -        assert_eq!(result.fee_amount, 118);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_largest_first_coin_selection_insufficient_funds() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        LargestFirstCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                vec![],
    -                utxos,
    -                FeeRate::from_sat_per_vb(1.0),
    -                500_000,
    -                FEE_AMOUNT,
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_largest_first_coin_selection_insufficient_funds_high_fees() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        LargestFirstCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                vec![],
    -                utxos,
    -                FeeRate::from_sat_per_vb(1000.0),
    -                250_000,
    -                FEE_AMOUNT,
    -            )
    -            .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 database = MemoryDatabase::default();
    -
    -        let result = BranchAndBoundCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                vec![],
    -                utxos,
    -                FeeRate::from_sat_per_vb(1.0),
    -                250_000,
    -                FEE_AMOUNT,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.selected.len(), 3);
    -        assert_eq!(result.selected_amount(), 300_000);
    -        assert_eq!(result.fee_amount, 254);
    -    }
    -
    -    #[test]
    -    fn test_bnb_coin_selection_required_are_enough() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        let result = BranchAndBoundCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                utxos.clone(),
    -                utxos,
    -                FeeRate::from_sat_per_vb(1.0),
    -                20_000,
    -                FEE_AMOUNT,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.selected.len(), 3);
    -        assert_eq!(result.selected_amount(), 300_010);
    -        assert_eq!(result.fee_amount, 254);
    -    }
    -
    -    #[test]
    -    fn test_bnb_coin_selection_optional_are_enough() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        let result = BranchAndBoundCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                vec![],
    -                utxos,
    -                FeeRate::from_sat_per_vb(1.0),
    -                299756,
    -                FEE_AMOUNT,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.selected.len(), 3);
    -        assert_eq!(result.selected_amount(), 300010);
    -        assert_eq!(result.fee_amount, 254);
    -    }
    -
    -    #[test]
    -    fn test_bnb_coin_selection_required_not_enough() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        let required = vec![utxos[0].clone()];
    -        let mut optional = utxos[1..].to_vec();
    -        optional.push(utxo(500_000, 3));
    -
    -        // Defensive assertions, for sanity and in case someone changes the test utxos vector.
    -        let amount: u64 = required.iter().map(|u| u.utxo.txout().value).sum();
    -        assert_eq!(amount, 100_000);
    -        let amount: u64 = optional.iter().map(|u| u.utxo.txout().value).sum();
    -        assert!(amount > 150_000);
    -
    -        let result = BranchAndBoundCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                required,
    -                optional,
    -                FeeRate::from_sat_per_vb(1.0),
    -                150_000,
    -                FEE_AMOUNT,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.selected.len(), 3);
    -        assert_eq!(result.selected_amount(), 300_010);
    -        assert!((result.fee_amount as f32 - 254.0).abs() < f32::EPSILON);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_bnb_coin_selection_insufficient_funds() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        BranchAndBoundCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                vec![],
    -                utxos,
    -                FeeRate::from_sat_per_vb(1.0),
    -                500_000,
    -                FEE_AMOUNT,
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_bnb_coin_selection_insufficient_funds_high_fees() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        BranchAndBoundCoinSelection::default()
    -            .coin_select(
    -                &database,
    -                vec![],
    -                utxos,
    -                FeeRate::from_sat_per_vb(1000.0),
    -                250_000,
    -                FEE_AMOUNT,
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_bnb_coin_selection_check_fee_rate() {
    -        let utxos = get_test_utxos();
    -        let database = MemoryDatabase::default();
    -
    -        let result = BranchAndBoundCoinSelection::new(0)
    -            .coin_select(
    -                &database,
    -                vec![],
    -                utxos,
    -                FeeRate::from_sat_per_vb(1.0),
    -                99932, // first utxo's effective value
    -                0,
    -            )
    -            .unwrap();
    -
    -        assert_eq!(result.selected.len(), 1);
    -        assert_eq!(result.selected_amount(), 100_000);
    -        let input_size = (TXIN_BASE_WEIGHT + P2WPKH_WITNESS_SIZE).vbytes();
    -        let epsilon = 0.5;
    -        assert!((1.0 - (result.fee_amount as f32 / input_size as f32)).abs() < epsilon);
    -    }
    -
    -    #[test]
    -    fn test_bnb_coin_selection_exact_match() {
    -        let seed = [0; 32];
    -        let mut rng: StdRng = SeedableRng::from_seed(seed);
    -        let database = MemoryDatabase::default();
    -
    -        for _i in 0..200 {
    -            let mut optional_utxos = generate_random_utxos(&mut rng, 16);
    -            let target_amount = sum_random_utxos(&mut rng, &mut optional_utxos);
    -            let result = BranchAndBoundCoinSelection::new(0)
    -                .coin_select(
    -                    &database,
    -                    vec![],
    -                    optional_utxos,
    -                    FeeRate::from_sat_per_vb(0.0),
    -                    target_amount,
    -                    0,
    -                )
    -                .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(10.0);
    -        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 = size_of_change as f32 * fee_rate.as_sat_vb();
    -        BranchAndBoundCoinSelection::new(size_of_change)
    -            .bnb(
    -                vec![],
    -                utxos,
    -                0,
    -                curr_available_value,
    -                20_000,
    -                FEE_AMOUNT,
    -                cost_of_change,
    -            )
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "BnBTotalTriesExceeded")]
    -    fn test_bnb_function_tries_exceeded() {
    -        let fee_rate = FeeRate::from_sat_per_vb(10.0);
    -        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 = size_of_change as f32 * fee_rate.as_sat_vb();
    -
    -        BranchAndBoundCoinSelection::new(size_of_change)
    -            .bnb(
    -                vec![],
    -                utxos,
    -                0,
    -                curr_available_value,
    -                20_000,
    -                FEE_AMOUNT,
    -                cost_of_change,
    -            )
    -            .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(1.0);
    -        let size_of_change = 31;
    -        let cost_of_change = size_of_change as f32 * fee_rate.as_sat_vb();
    -
    -        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.ceil() as i64 + 5;
    -
    -        let result = BranchAndBoundCoinSelection::new(size_of_change)
    -            .bnb(
    -                vec![],
    -                utxos,
    -                curr_value,
    -                curr_available_value,
    -                target_amount,
    -                FEE_AMOUNT,
    -                cost_of_change,
    -            )
    -            .unwrap();
    -        assert_eq!(result.selected_amount(), 100_000);
    -        assert_eq!(result.fee_amount, 186);
    -    }
    -
    -    // 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::from_sat_per_vb(0.0);
    -
    -        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 result = BranchAndBoundCoinSelection::new(0)
    -                .bnb(
    -                    vec![],
    -                    optional_utxos,
    -                    curr_value,
    -                    curr_available_value,
    -                    target_amount,
    -                    0,
    -                    0.0,
    -                )
    -                .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);
    -
    -        let fee_rate = FeeRate::from_sat_per_vb(1.0);
    -        let utxos: Vec<OutputGroup> = utxos
    -            .into_iter()
    -            .map(|u| OutputGroup::new(u, fee_rate))
    -            .collect();
    -
    -        let result = BranchAndBoundCoinSelection::default().single_random_draw(
    -            vec![],
    -            utxos,
    -            0,
    -            target_amount as i64,
    -            FEE_AMOUNT,
    -        );
    -
    -        assert!(result.selected_amount() > target_amount);
    -        assert_eq!(result.fee_amount, (50 + result.selected.len() * 68) as u64);
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/export.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/export.rs.html deleted file mode 100644 index a78d0d922f..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/export.rs.html +++ /dev/null @@ -1,706 +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
    -342
    -343
    -344
    -345
    -346
    -347
    -348
    -349
    -350
    -351
    -
    // 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::database::*;
    -//! # use bdk::wallet::export::*;
    -//! # use bdk::*;
    -//! let import = r#"{
    -//!     "descriptor": "wpkh([c258d2e4\/84h\/1h\/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe\/0\/*)",
    -//!     "blockheight":1782088,
    -//!     "label":"testnet"
    -//! }"#;
    -//!
    -//! let import = WalletExport::from_str(import)?;
    -//! let wallet = Wallet::new_offline(
    -//!     &import.descriptor(),
    -//!     import.change_descriptor().as_ref(),
    -//!     Network::Testnet,
    -//!     MemoryDatabase::default(),
    -//! )?;
    -//! # Ok::<_, bdk::Error>(())
    -//! ```
    -//!
    -//! ### Export a `Wallet`
    -//! ```
    -//! # use bitcoin::*;
    -//! # use bdk::database::*;
    -//! # use bdk::wallet::export::*;
    -//! # use bdk::*;
    -//! let wallet = Wallet::new_offline(
    -//!     "wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/0/*)",
    -//!     Some("wpkh([c258d2e4/84h/1h/0h]tpubDD3ynpHgJQW8VvWRzQ5WFDCrs4jqVFGHB3vLC3r49XHJSqP8bHKdK4AriuUKLccK68zfzowx7YhmDN8SiSkgCDENUFx9qVw65YyqM78vyVe/1/*)"),
    -//!     Network::Testnet,
    -//!     MemoryDatabase::default()
    -//! )?;
    -//! let export = WalletExport::export_wallet(&wallet, "exported wallet", true)
    -//!     .map_err(ToString::to_string)
    -//!     .map_err(bdk::Error::Generic)?;
    -//!
    -//! println!("Exported: {}", export.to_string());
    -//! # Ok::<_, bdk::Error>(())
    -//! ```
    -
    -use std::str::FromStr;
    -
    -use serde::{Deserialize, Serialize};
    -
    -use miniscript::descriptor::{ShInner, WshInner};
    -use miniscript::{Descriptor, DescriptorPublicKey, ScriptContext, Terminal};
    -
    -use crate::database::BatchDatabase;
    -use crate::wallet::Wallet;
    -
    -/// 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 WalletExport {
    -    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 ToString for WalletExport {
    -    fn to_string(&self) -> String {
    -        serde_json::to_string(self).unwrap()
    -    }
    -}
    -
    -impl FromStr for WalletExport {
    -    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.splitn(2, '#').next().map(String::from).unwrap()
    -}
    -
    -impl WalletExport {
    -    /// 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<B, D: BatchDatabase>(
    -        wallet: &Wallet<B, D>,
    -        label: &str,
    -        include_blockheight: bool,
    -    ) -> Result<Self, &'static str> {
    -        let descriptor = wallet
    -            .descriptor
    -            .to_string_with_secret(&wallet.signers.as_key_map(wallet.secp_ctx()));
    -        let descriptor = remove_checksum(descriptor);
    -        Self::is_compatible_with_core(&descriptor)?;
    -
    -        let blockheight = match wallet.database.borrow().iter_txs(false) {
    -            _ if !include_blockheight => 0,
    -            Err(_) => 0,
    -            Ok(txs) => {
    -                let mut heights = txs
    -                    .into_iter()
    -                    .map(|tx| tx.confirmation_time.map(|c| c.height).unwrap_or(0))
    -                    .collect::<Vec<_>>();
    -                heights.sort_unstable();
    -
    -                *heights.last().unwrap_or(&0)
    -            }
    -        };
    -
    -        let export = WalletExport {
    -            descriptor,
    -            label: label.into(),
    -            blockheight,
    -        };
    -
    -        let desc_to_string = |d: &Descriptor<DescriptorPublicKey>| {
    -            let descriptor =
    -                d.to_string_with_secret(&wallet.change_signers.as_key_map(wallet.secp_ctx()));
    -            remove_checksum(descriptor)
    -        };
    -        if export.change_descriptor() != wallet.change_descriptor.as_ref().map(desc_to_string) {
    -            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 std::str::FromStr;
    -
    -    use bitcoin::{Network, Txid};
    -
    -    use super::*;
    -    use crate::database::{memory::MemoryDatabase, BatchOperations};
    -    use crate::types::TransactionDetails;
    -    use crate::wallet::Wallet;
    -    use crate::ConfirmationTime;
    -
    -    fn get_test_db() -> MemoryDatabase {
    -        let mut db = MemoryDatabase::new();
    -        db.set_tx(&TransactionDetails {
    -            transaction: None,
    -            txid: Txid::from_str(
    -                "4ddff1fa33af17f377f62b72357b43107c19110a8009b36fb832af505efed98a",
    -            )
    -            .unwrap(),
    -
    -            received: 100_000,
    -            sent: 0,
    -            fee: Some(500),
    -            confirmation_time: Some(ConfirmationTime {
    -                timestamp: 12345678,
    -                height: 5000,
    -            }),
    -            verified: true,
    -        })
    -        .unwrap();
    -
    -        db
    -    }
    -
    -    #[test]
    -    fn test_export_bip44() {
    -        let descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/0/*)";
    -        let change_descriptor = "wpkh(xprv9s21ZrQH143K4CTb63EaMxja1YiTnSEWKMbn23uoEnAzxjdUJRQkazCAtzxGm4LSoTSVTptoV9RbchnKPW9HxKtZumdyxyikZFDLhogJ5Uj/44'/0'/0'/1/*)";
    -
    -        let wallet = Wallet::new_offline(
    -            descriptor,
    -            Some(change_descriptor),
    -            Network::Bitcoin,
    -            get_test_db(),
    -        )
    -        .unwrap();
    -        let export = WalletExport::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 =
    -            Wallet::new_offline(descriptor, None, Network::Bitcoin, get_test_db()).unwrap();
    -        WalletExport::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 = Wallet::new_offline(
    -            descriptor,
    -            Some(change_descriptor),
    -            Network::Bitcoin,
    -            get_test_db(),
    -        )
    -        .unwrap();
    -        WalletExport::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 = Wallet::new_offline(
    -            descriptor,
    -            Some(change_descriptor),
    -            Network::Testnet,
    -            get_test_db(),
    -        )
    -        .unwrap();
    -        let export = WalletExport::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 = Wallet::new_offline(
    -            descriptor,
    -            Some(change_descriptor),
    -            Network::Bitcoin,
    -            get_test_db(),
    -        )
    -        .unwrap();
    -        let export = WalletExport::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 = WalletExport::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/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/mod.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/mod.rs.html deleted file mode 100644 index e4602b959b..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/mod.rs.html +++ /dev/null @@ -1,7940 +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
    -2709
    -2710
    -2711
    -2712
    -2713
    -2714
    -2715
    -2716
    -2717
    -2718
    -2719
    -2720
    -2721
    -2722
    -2723
    -2724
    -2725
    -2726
    -2727
    -2728
    -2729
    -2730
    -2731
    -2732
    -2733
    -2734
    -2735
    -2736
    -2737
    -2738
    -2739
    -2740
    -2741
    -2742
    -2743
    -2744
    -2745
    -2746
    -2747
    -2748
    -2749
    -2750
    -2751
    -2752
    -2753
    -2754
    -2755
    -2756
    -2757
    -2758
    -2759
    -2760
    -2761
    -2762
    -2763
    -2764
    -2765
    -2766
    -2767
    -2768
    -2769
    -2770
    -2771
    -2772
    -2773
    -2774
    -2775
    -2776
    -2777
    -2778
    -2779
    -2780
    -2781
    -2782
    -2783
    -2784
    -2785
    -2786
    -2787
    -2788
    -2789
    -2790
    -2791
    -2792
    -2793
    -2794
    -2795
    -2796
    -2797
    -2798
    -2799
    -2800
    -2801
    -2802
    -2803
    -2804
    -2805
    -2806
    -2807
    -2808
    -2809
    -2810
    -2811
    -2812
    -2813
    -2814
    -2815
    -2816
    -2817
    -2818
    -2819
    -2820
    -2821
    -2822
    -2823
    -2824
    -2825
    -2826
    -2827
    -2828
    -2829
    -2830
    -2831
    -2832
    -2833
    -2834
    -2835
    -2836
    -2837
    -2838
    -2839
    -2840
    -2841
    -2842
    -2843
    -2844
    -2845
    -2846
    -2847
    -2848
    -2849
    -2850
    -2851
    -2852
    -2853
    -2854
    -2855
    -2856
    -2857
    -2858
    -2859
    -2860
    -2861
    -2862
    -2863
    -2864
    -2865
    -2866
    -2867
    -2868
    -2869
    -2870
    -2871
    -2872
    -2873
    -2874
    -2875
    -2876
    -2877
    -2878
    -2879
    -2880
    -2881
    -2882
    -2883
    -2884
    -2885
    -2886
    -2887
    -2888
    -2889
    -2890
    -2891
    -2892
    -2893
    -2894
    -2895
    -2896
    -2897
    -2898
    -2899
    -2900
    -2901
    -2902
    -2903
    -2904
    -2905
    -2906
    -2907
    -2908
    -2909
    -2910
    -2911
    -2912
    -2913
    -2914
    -2915
    -2916
    -2917
    -2918
    -2919
    -2920
    -2921
    -2922
    -2923
    -2924
    -2925
    -2926
    -2927
    -2928
    -2929
    -2930
    -2931
    -2932
    -2933
    -2934
    -2935
    -2936
    -2937
    -2938
    -2939
    -2940
    -2941
    -2942
    -2943
    -2944
    -2945
    -2946
    -2947
    -2948
    -2949
    -2950
    -2951
    -2952
    -2953
    -2954
    -2955
    -2956
    -2957
    -2958
    -2959
    -2960
    -2961
    -2962
    -2963
    -2964
    -2965
    -2966
    -2967
    -2968
    -2969
    -2970
    -2971
    -2972
    -2973
    -2974
    -2975
    -2976
    -2977
    -2978
    -2979
    -2980
    -2981
    -2982
    -2983
    -2984
    -2985
    -2986
    -2987
    -2988
    -2989
    -2990
    -2991
    -2992
    -2993
    -2994
    -2995
    -2996
    -2997
    -2998
    -2999
    -3000
    -3001
    -3002
    -3003
    -3004
    -3005
    -3006
    -3007
    -3008
    -3009
    -3010
    -3011
    -3012
    -3013
    -3014
    -3015
    -3016
    -3017
    -3018
    -3019
    -3020
    -3021
    -3022
    -3023
    -3024
    -3025
    -3026
    -3027
    -3028
    -3029
    -3030
    -3031
    -3032
    -3033
    -3034
    -3035
    -3036
    -3037
    -3038
    -3039
    -3040
    -3041
    -3042
    -3043
    -3044
    -3045
    -3046
    -3047
    -3048
    -3049
    -3050
    -3051
    -3052
    -3053
    -3054
    -3055
    -3056
    -3057
    -3058
    -3059
    -3060
    -3061
    -3062
    -3063
    -3064
    -3065
    -3066
    -3067
    -3068
    -3069
    -3070
    -3071
    -3072
    -3073
    -3074
    -3075
    -3076
    -3077
    -3078
    -3079
    -3080
    -3081
    -3082
    -3083
    -3084
    -3085
    -3086
    -3087
    -3088
    -3089
    -3090
    -3091
    -3092
    -3093
    -3094
    -3095
    -3096
    -3097
    -3098
    -3099
    -3100
    -3101
    -3102
    -3103
    -3104
    -3105
    -3106
    -3107
    -3108
    -3109
    -3110
    -3111
    -3112
    -3113
    -3114
    -3115
    -3116
    -3117
    -3118
    -3119
    -3120
    -3121
    -3122
    -3123
    -3124
    -3125
    -3126
    -3127
    -3128
    -3129
    -3130
    -3131
    -3132
    -3133
    -3134
    -3135
    -3136
    -3137
    -3138
    -3139
    -3140
    -3141
    -3142
    -3143
    -3144
    -3145
    -3146
    -3147
    -3148
    -3149
    -3150
    -3151
    -3152
    -3153
    -3154
    -3155
    -3156
    -3157
    -3158
    -3159
    -3160
    -3161
    -3162
    -3163
    -3164
    -3165
    -3166
    -3167
    -3168
    -3169
    -3170
    -3171
    -3172
    -3173
    -3174
    -3175
    -3176
    -3177
    -3178
    -3179
    -3180
    -3181
    -3182
    -3183
    -3184
    -3185
    -3186
    -3187
    -3188
    -3189
    -3190
    -3191
    -3192
    -3193
    -3194
    -3195
    -3196
    -3197
    -3198
    -3199
    -3200
    -3201
    -3202
    -3203
    -3204
    -3205
    -3206
    -3207
    -3208
    -3209
    -3210
    -3211
    -3212
    -3213
    -3214
    -3215
    -3216
    -3217
    -3218
    -3219
    -3220
    -3221
    -3222
    -3223
    -3224
    -3225
    -3226
    -3227
    -3228
    -3229
    -3230
    -3231
    -3232
    -3233
    -3234
    -3235
    -3236
    -3237
    -3238
    -3239
    -3240
    -3241
    -3242
    -3243
    -3244
    -3245
    -3246
    -3247
    -3248
    -3249
    -3250
    -3251
    -3252
    -3253
    -3254
    -3255
    -3256
    -3257
    -3258
    -3259
    -3260
    -3261
    -3262
    -3263
    -3264
    -3265
    -3266
    -3267
    -3268
    -3269
    -3270
    -3271
    -3272
    -3273
    -3274
    -3275
    -3276
    -3277
    -3278
    -3279
    -3280
    -3281
    -3282
    -3283
    -3284
    -3285
    -3286
    -3287
    -3288
    -3289
    -3290
    -3291
    -3292
    -3293
    -3294
    -3295
    -3296
    -3297
    -3298
    -3299
    -3300
    -3301
    -3302
    -3303
    -3304
    -3305
    -3306
    -3307
    -3308
    -3309
    -3310
    -3311
    -3312
    -3313
    -3314
    -3315
    -3316
    -3317
    -3318
    -3319
    -3320
    -3321
    -3322
    -3323
    -3324
    -3325
    -3326
    -3327
    -3328
    -3329
    -3330
    -3331
    -3332
    -3333
    -3334
    -3335
    -3336
    -3337
    -3338
    -3339
    -3340
    -3341
    -3342
    -3343
    -3344
    -3345
    -3346
    -3347
    -3348
    -3349
    -3350
    -3351
    -3352
    -3353
    -3354
    -3355
    -3356
    -3357
    -3358
    -3359
    -3360
    -3361
    -3362
    -3363
    -3364
    -3365
    -3366
    -3367
    -3368
    -3369
    -3370
    -3371
    -3372
    -3373
    -3374
    -3375
    -3376
    -3377
    -3378
    -3379
    -3380
    -3381
    -3382
    -3383
    -3384
    -3385
    -3386
    -3387
    -3388
    -3389
    -3390
    -3391
    -3392
    -3393
    -3394
    -3395
    -3396
    -3397
    -3398
    -3399
    -3400
    -3401
    -3402
    -3403
    -3404
    -3405
    -3406
    -3407
    -3408
    -3409
    -3410
    -3411
    -3412
    -3413
    -3414
    -3415
    -3416
    -3417
    -3418
    -3419
    -3420
    -3421
    -3422
    -3423
    -3424
    -3425
    -3426
    -3427
    -3428
    -3429
    -3430
    -3431
    -3432
    -3433
    -3434
    -3435
    -3436
    -3437
    -3438
    -3439
    -3440
    -3441
    -3442
    -3443
    -3444
    -3445
    -3446
    -3447
    -3448
    -3449
    -3450
    -3451
    -3452
    -3453
    -3454
    -3455
    -3456
    -3457
    -3458
    -3459
    -3460
    -3461
    -3462
    -3463
    -3464
    -3465
    -3466
    -3467
    -3468
    -3469
    -3470
    -3471
    -3472
    -3473
    -3474
    -3475
    -3476
    -3477
    -3478
    -3479
    -3480
    -3481
    -3482
    -3483
    -3484
    -3485
    -3486
    -3487
    -3488
    -3489
    -3490
    -3491
    -3492
    -3493
    -3494
    -3495
    -3496
    -3497
    -3498
    -3499
    -3500
    -3501
    -3502
    -3503
    -3504
    -3505
    -3506
    -3507
    -3508
    -3509
    -3510
    -3511
    -3512
    -3513
    -3514
    -3515
    -3516
    -3517
    -3518
    -3519
    -3520
    -3521
    -3522
    -3523
    -3524
    -3525
    -3526
    -3527
    -3528
    -3529
    -3530
    -3531
    -3532
    -3533
    -3534
    -3535
    -3536
    -3537
    -3538
    -3539
    -3540
    -3541
    -3542
    -3543
    -3544
    -3545
    -3546
    -3547
    -3548
    -3549
    -3550
    -3551
    -3552
    -3553
    -3554
    -3555
    -3556
    -3557
    -3558
    -3559
    -3560
    -3561
    -3562
    -3563
    -3564
    -3565
    -3566
    -3567
    -3568
    -3569
    -3570
    -3571
    -3572
    -3573
    -3574
    -3575
    -3576
    -3577
    -3578
    -3579
    -3580
    -3581
    -3582
    -3583
    -3584
    -3585
    -3586
    -3587
    -3588
    -3589
    -3590
    -3591
    -3592
    -3593
    -3594
    -3595
    -3596
    -3597
    -3598
    -3599
    -3600
    -3601
    -3602
    -3603
    -3604
    -3605
    -3606
    -3607
    -3608
    -3609
    -3610
    -3611
    -3612
    -3613
    -3614
    -3615
    -3616
    -3617
    -3618
    -3619
    -3620
    -3621
    -3622
    -3623
    -3624
    -3625
    -3626
    -3627
    -3628
    -3629
    -3630
    -3631
    -3632
    -3633
    -3634
    -3635
    -3636
    -3637
    -3638
    -3639
    -3640
    -3641
    -3642
    -3643
    -3644
    -3645
    -3646
    -3647
    -3648
    -3649
    -3650
    -3651
    -3652
    -3653
    -3654
    -3655
    -3656
    -3657
    -3658
    -3659
    -3660
    -3661
    -3662
    -3663
    -3664
    -3665
    -3666
    -3667
    -3668
    -3669
    -3670
    -3671
    -3672
    -3673
    -3674
    -3675
    -3676
    -3677
    -3678
    -3679
    -3680
    -3681
    -3682
    -3683
    -3684
    -3685
    -3686
    -3687
    -3688
    -3689
    -3690
    -3691
    -3692
    -3693
    -3694
    -3695
    -3696
    -3697
    -3698
    -3699
    -3700
    -3701
    -3702
    -3703
    -3704
    -3705
    -3706
    -3707
    -3708
    -3709
    -3710
    -3711
    -3712
    -3713
    -3714
    -3715
    -3716
    -3717
    -3718
    -3719
    -3720
    -3721
    -3722
    -3723
    -3724
    -3725
    -3726
    -3727
    -3728
    -3729
    -3730
    -3731
    -3732
    -3733
    -3734
    -3735
    -3736
    -3737
    -3738
    -3739
    -3740
    -3741
    -3742
    -3743
    -3744
    -3745
    -3746
    -3747
    -3748
    -3749
    -3750
    -3751
    -3752
    -3753
    -3754
    -3755
    -3756
    -3757
    -3758
    -3759
    -3760
    -3761
    -3762
    -3763
    -3764
    -3765
    -3766
    -3767
    -3768
    -3769
    -3770
    -3771
    -3772
    -3773
    -3774
    -3775
    -3776
    -3777
    -3778
    -3779
    -3780
    -3781
    -3782
    -3783
    -3784
    -3785
    -3786
    -3787
    -3788
    -3789
    -3790
    -3791
    -3792
    -3793
    -3794
    -3795
    -3796
    -3797
    -3798
    -3799
    -3800
    -3801
    -3802
    -3803
    -3804
    -3805
    -3806
    -3807
    -3808
    -3809
    -3810
    -3811
    -3812
    -3813
    -3814
    -3815
    -3816
    -3817
    -3818
    -3819
    -3820
    -3821
    -3822
    -3823
    -3824
    -3825
    -3826
    -3827
    -3828
    -3829
    -3830
    -3831
    -3832
    -3833
    -3834
    -3835
    -3836
    -3837
    -3838
    -3839
    -3840
    -3841
    -3842
    -3843
    -3844
    -3845
    -3846
    -3847
    -3848
    -3849
    -3850
    -3851
    -3852
    -3853
    -3854
    -3855
    -3856
    -3857
    -3858
    -3859
    -3860
    -3861
    -3862
    -3863
    -3864
    -3865
    -3866
    -3867
    -3868
    -3869
    -3870
    -3871
    -3872
    -3873
    -3874
    -3875
    -3876
    -3877
    -3878
    -3879
    -3880
    -3881
    -3882
    -3883
    -3884
    -3885
    -3886
    -3887
    -3888
    -3889
    -3890
    -3891
    -3892
    -3893
    -3894
    -3895
    -3896
    -3897
    -3898
    -3899
    -3900
    -3901
    -3902
    -3903
    -3904
    -3905
    -3906
    -3907
    -3908
    -3909
    -3910
    -3911
    -3912
    -3913
    -3914
    -3915
    -3916
    -3917
    -3918
    -3919
    -3920
    -3921
    -3922
    -3923
    -3924
    -3925
    -3926
    -3927
    -3928
    -3929
    -3930
    -3931
    -3932
    -3933
    -3934
    -3935
    -3936
    -3937
    -3938
    -3939
    -3940
    -3941
    -3942
    -3943
    -3944
    -3945
    -3946
    -3947
    -3948
    -3949
    -3950
    -3951
    -3952
    -3953
    -3954
    -3955
    -3956
    -3957
    -3958
    -3959
    -3960
    -3961
    -3962
    -3963
    -3964
    -3965
    -3966
    -3967
    -3968
    -
    // 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`] structure.
    -
    -use std::cell::RefCell;
    -use std::collections::HashMap;
    -use std::collections::{BTreeMap, HashSet};
    -use std::fmt;
    -use std::ops::{Deref, DerefMut};
    -use std::str::FromStr;
    -use std::sync::Arc;
    -
    -use bitcoin::secp256k1::Secp256k1;
    -
    -use bitcoin::consensus::encode::serialize;
    -use bitcoin::util::base58;
    -use bitcoin::util::psbt::raw::Key as PsbtKey;
    -use bitcoin::util::psbt::Input;
    -use bitcoin::util::psbt::PartiallySignedTransaction as Psbt;
    -use bitcoin::{Address, Network, OutPoint, Script, SigHashType, Transaction, TxOut, Txid};
    -
    -use miniscript::descriptor::DescriptorTrait;
    -use miniscript::psbt::PsbtInputSatisfier;
    -
    -#[allow(unused_imports)]
    -use log::{debug, error, info, trace};
    -
    -pub mod address_validator;
    -pub mod coin_selection;
    -pub mod export;
    -pub mod signer;
    -pub mod time;
    -pub mod tx_builder;
    -pub(crate) mod utils;
    -#[cfg(feature = "verify")]
    -#[cfg_attr(docsrs, doc(cfg(feature = "verify")))]
    -pub mod verify;
    -
    -pub use utils::IsDust;
    -
    -use address_validator::AddressValidator;
    -use coin_selection::DefaultCoinSelectionAlgorithm;
    -use signer::{SignOptions, Signer, SignerOrdering, SignersContainer};
    -use tx_builder::{BumpFee, CreateTx, FeePolicy, TxBuilder, TxParams};
    -use utils::{check_nlocktime, check_nsequence_rbf, After, Older, SecpCtx, DUST_LIMIT_SATOSHI};
    -
    -use crate::blockchain::{Blockchain, Progress};
    -use crate::database::memory::MemoryDatabase;
    -use crate::database::{BatchDatabase, BatchOperations, DatabaseUtils};
    -use crate::descriptor::derived::AsDerived;
    -use crate::descriptor::policy::BuildSatisfaction;
    -use crate::descriptor::{
    -    get_checksum, into_wallet_descriptor_checked, DerivedDescriptor, DerivedDescriptorMeta,
    -    DescriptorMeta, DescriptorScripts, ExtendedDescriptor, ExtractPolicy, IntoWalletDescriptor,
    -    Policy, XKeyUtils,
    -};
    -use crate::error::Error;
    -use crate::psbt::PsbtUtils;
    -use crate::signer::SignerError;
    -use crate::testutils;
    -use crate::types::*;
    -
    -const CACHE_ADDR_BATCH_SIZE: u32 = 100;
    -
    -/// A Bitcoin wallet
    -///
    -/// A wallet takes descriptors, a [`database`](trait@crate::database::Database) and a
    -/// [`blockchain`](trait@crate::blockchain::Blockchain) and implements the basic functions that a Bitcoin wallets
    -/// needs to operate, like [generating addresses](Wallet::get_address), [returning the balance](Wallet::get_balance),
    -/// [creating transactions](Wallet::build_tx), etc.
    -///
    -/// A wallet can be either "online" if the [`blockchain`](crate::blockchain) type provided
    -/// implements [`Blockchain`], or "offline" if it is the unit type `()`. Offline wallets only expose
    -/// methods that don't need any interaction with the blockchain to work.
    -#[derive(Debug)]
    -pub struct Wallet<B, D> {
    -    descriptor: ExtendedDescriptor,
    -    change_descriptor: Option<ExtendedDescriptor>,
    -
    -    signers: Arc<SignersContainer>,
    -    change_signers: Arc<SignersContainer>,
    -
    -    address_validators: Vec<Arc<dyn AddressValidator>>,
    -
    -    network: Network,
    -
    -    current_height: Option<u32>,
    -
    -    client: B,
    -    database: RefCell<D>,
    -
    -    secp: SecpCtx,
    -}
    -
    -impl<D> Wallet<(), D>
    -where
    -    D: BatchDatabase,
    -{
    -    /// Create a new "offline" wallet
    -    pub fn new_offline<E: IntoWalletDescriptor>(
    -        descriptor: E,
    -        change_descriptor: Option<E>,
    -        network: Network,
    -        database: D,
    -    ) -> Result<Self, Error> {
    -        Self::_new(descriptor, change_descriptor, network, database, (), None)
    -    }
    -}
    -
    -impl<B, D> Wallet<B, D>
    -where
    -    D: BatchDatabase,
    -{
    -    fn _new<E: IntoWalletDescriptor>(
    -        descriptor: E,
    -        change_descriptor: Option<E>,
    -        network: Network,
    -        mut database: D,
    -        client: B,
    -        current_height: Option<u32>,
    -    ) -> Result<Self, Error> {
    -        let secp = Secp256k1::new();
    -
    -        let (descriptor, keymap) = into_wallet_descriptor_checked(descriptor, &secp, network)?;
    -        database.check_descriptor_checksum(
    -            KeychainKind::External,
    -            get_checksum(&descriptor.to_string())?.as_bytes(),
    -        )?;
    -        let signers = Arc::new(SignersContainer::from(keymap));
    -        let (change_descriptor, change_signers) = match change_descriptor {
    -            Some(desc) => {
    -                let (change_descriptor, change_keymap) =
    -                    into_wallet_descriptor_checked(desc, &secp, network)?;
    -                database.check_descriptor_checksum(
    -                    KeychainKind::Internal,
    -                    get_checksum(&change_descriptor.to_string())?.as_bytes(),
    -                )?;
    -
    -                let change_signers = Arc::new(SignersContainer::from(change_keymap));
    -                // if !parsed.same_structure(descriptor.as_ref()) {
    -                //     return Err(Error::DifferentDescriptorStructure);
    -                // }
    -
    -                (Some(change_descriptor), change_signers)
    -            }
    -            None => (None, Arc::new(SignersContainer::new())),
    -        };
    -
    -        Ok(Wallet {
    -            descriptor,
    -            change_descriptor,
    -            signers,
    -            change_signers,
    -            address_validators: Vec::new(),
    -            network,
    -            current_height,
    -            client,
    -            database: RefCell::new(database),
    -            secp,
    -        })
    -    }
    -
    -    /// Get the Bitcoin network the wallet is using.
    -    pub fn network(&self) -> Network {
    -        self.network
    -    }
    -}
    -
    -/// The address index selection strategy to use to derived an address from the wallet's external
    -/// descriptor. See [`Wallet::get_address`]. If you're unsure which one to use use `WalletIndex::New`.
    -#[derive(Debug)]
    -pub enum AddressIndex {
    -    /// Return a new address after incrementing the current descriptor index.
    -    New,
    -    /// Return the address for the current descriptor index if it has not been used in a received
    -    /// transaction. Otherwise return a new address as with [`AddressIndex::New`].
    -    ///
    -    /// Use with caution, if the wallet has not yet detected an address has been used it could
    -    /// return an already used address. This function is primarily meant for situations where the
    -    /// caller is untrusted; for example when deriving donation addresses on-demand for a public
    -    /// web page.
    -    LastUnused,
    -    /// Return the address for a specific descriptor index. Does not change the current descriptor
    -    /// index used by `AddressIndex::New` and `AddressIndex::LastUsed`.
    -    ///
    -    /// Use with caution, if an index is given that is less than the current descriptor index
    -    /// then the returned address may have already been used.
    -    Peek(u32),
    -    /// Return the address for a specific descriptor index and reset the current descriptor index
    -    /// used by `AddressIndex::New` and `AddressIndex::LastUsed` to this value.
    -    ///
    -    /// Use with caution, if an index is given that is less than the current descriptor index
    -    /// then the returned address and subsequent addresses returned by calls to `AddressIndex::New`
    -    /// and `AddressIndex::LastUsed` may have already been used. Also if the index is reset to a
    -    /// value earlier than the [`crate::blockchain::Blockchain`] stop_gap (default is 20) then a
    -    /// larger stop_gap should be used to monitor for all possibly used addresses.
    -    Reset(u32),
    -}
    -
    -/// A derived address and the index it was found at
    -/// For convenience this automatically derefs to `Address`
    -#[derive(Debug, PartialEq)]
    -pub struct AddressInfo {
    -    /// Child index of this address
    -    pub index: u32,
    -    /// Address
    -    pub address: Address,
    -}
    -
    -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)
    -    }
    -}
    -
    -// offline actions, always available
    -impl<B, D> Wallet<B, D>
    -where
    -    D: BatchDatabase,
    -{
    -    // Return a newly derived address using the external descriptor
    -    fn get_new_address(&self) -> Result<AddressInfo, Error> {
    -        let incremented_index = self.fetch_and_increment_index(KeychainKind::External)?;
    -
    -        let address_result = self
    -            .descriptor
    -            .as_derived(incremented_index, &self.secp)
    -            .address(self.network);
    -
    -        address_result
    -            .map(|address| AddressInfo {
    -                address,
    -                index: incremented_index,
    -            })
    -            .map_err(|_| Error::ScriptDoesntHaveAddressForm)
    -    }
    -
    -    // Return the the last previously derived address if it has not been used in a received
    -    // transaction. Otherwise return a new address using [`Wallet::get_new_address`].
    -    fn get_unused_address(&self) -> Result<AddressInfo, Error> {
    -        let current_index = self.fetch_index(KeychainKind::External)?;
    -
    -        let derived_key = self.descriptor.as_derived(current_index, &self.secp);
    -
    -        let script_pubkey = derived_key.script_pubkey();
    -
    -        let found_used = self
    -            .list_transactions(true)?
    -            .iter()
    -            .flat_map(|tx_details| tx_details.transaction.as_ref())
    -            .flat_map(|tx| tx.output.iter())
    -            .any(|o| o.script_pubkey == script_pubkey);
    -
    -        if found_used {
    -            self.get_new_address()
    -        } else {
    -            derived_key
    -                .address(self.network)
    -                .map(|address| AddressInfo {
    -                    address,
    -                    index: current_index,
    -                })
    -                .map_err(|_| Error::ScriptDoesntHaveAddressForm)
    -        }
    -    }
    -
    -    // Return derived address for the external descriptor at a specific index
    -    fn peek_address(&self, index: u32) -> Result<AddressInfo, Error> {
    -        self.descriptor
    -            .as_derived(index, &self.secp)
    -            .address(self.network)
    -            .map(|address| AddressInfo { index, address })
    -            .map_err(|_| Error::ScriptDoesntHaveAddressForm)
    -    }
    -
    -    // Return derived address for the external descriptor at a specific index and reset current
    -    // address index
    -    fn reset_address(&self, index: u32) -> Result<AddressInfo, Error> {
    -        self.set_index(KeychainKind::External, index)?;
    -
    -        self.descriptor
    -            .as_derived(index, &self.secp)
    -            .address(self.network)
    -            .map(|address| AddressInfo { index, address })
    -            .map_err(|_| Error::ScriptDoesntHaveAddressForm)
    -    }
    -
    -    /// Return a derived address using the external descriptor, see [`AddressIndex`] for
    -    /// available address index selection strategies. If none of the keys in the descriptor are derivable
    -    /// (ie. does not end with /*) then the same address will always be returned for any [`AddressIndex`].
    -    pub fn get_address(&self, address_index: AddressIndex) -> Result<AddressInfo, Error> {
    -        match address_index {
    -            AddressIndex::New => self.get_new_address(),
    -            AddressIndex::LastUnused => self.get_unused_address(),
    -            AddressIndex::Peek(index) => self.peek_address(index),
    -            AddressIndex::Reset(index) => self.reset_address(index),
    -        }
    -    }
    -
    -    /// Return whether or not a `script` is part of this wallet (either internal or external)
    -    pub fn is_mine(&self, script: &Script) -> Result<bool, Error> {
    -        self.database.borrow().is_mine(script)
    -    }
    -
    -    /// Return the list of unspent outputs of this wallet
    -    ///
    -    /// Note that this methods only operate on the internal database, which first needs to be
    -    /// [`Wallet::sync`] manually.
    -    pub fn list_unspent(&self) -> Result<Vec<LocalUtxo>, Error> {
    -        self.database.borrow().iter_utxos()
    -    }
    -
    -    /// Returns the `UTXO` owned by this wallet corresponding to `outpoint` if it exists in the
    -    /// wallet's database.
    -    pub fn get_utxo(&self, outpoint: OutPoint) -> Result<Option<LocalUtxo>, Error> {
    -        self.database.borrow().get_utxo(&outpoint)
    -    }
    -
    -    /// Return the list of transactions made and received by the wallet
    -    ///
    -    /// Optionally fill the [`TransactionDetails::transaction`] field with the raw transaction if
    -    /// `include_raw` is `true`.
    -    ///
    -    /// Note that this methods only operate on the internal database, which first needs to be
    -    /// [`Wallet::sync`] manually.
    -    pub fn list_transactions(&self, include_raw: bool) -> Result<Vec<TransactionDetails>, Error> {
    -        self.database.borrow().iter_txs(include_raw)
    -    }
    -
    -    /// Return the balance, meaning the sum of this wallet's unspent outputs' values
    -    ///
    -    /// Note that this methods only operate on the internal database, which first needs to be
    -    /// [`Wallet::sync`] manually.
    -    pub fn get_balance(&self) -> Result<u64, Error> {
    -        Ok(self
    -            .list_unspent()?
    -            .iter()
    -            .fold(0, |sum, i| sum + i.txout.value))
    -    }
    -
    -    /// 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 Signer>,
    -    ) {
    -        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);
    -    }
    -
    -    /// Add an address validator
    -    ///
    -    /// See [the `address_validator` module](address_validator) for an example.
    -    pub fn add_address_validator(&mut self, validator: Arc<dyn AddressValidator>) {
    -        self.address_validators.push(validator);
    -    }
    -
    -    /// 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::database::*;
    -    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -    /// # let wallet = doctest_wallet!();
    -    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -    /// let (psbt, details) = {
    -    ///    let mut builder =  wallet.build_tx();
    -    ///    builder
    -    ///        .add_recipient(to_address.script_pubkey(), 50_000);
    -    ///    builder.finish()?
    -    /// };
    -    ///
    -    /// // sign and broadcast ...
    -    /// # Ok::<(), bdk::Error>(())
    -    /// ```
    -    ///
    -    /// [`TxBuilder`]: crate::TxBuilder
    -    pub fn build_tx(&self) -> TxBuilder<'_, B, D, DefaultCoinSelectionAlgorithm, CreateTx> {
    -        TxBuilder {
    -            wallet: self,
    -            params: TxParams::default(),
    -            coin_selection: DefaultCoinSelectionAlgorithm::default(),
    -            phantom: core::marker::PhantomData,
    -        }
    -    }
    -
    -    pub(crate) fn create_tx<Cs: coin_selection::CoinSelectionAlgorithm<D>>(
    -        &self,
    -        coin_selection: Cs,
    -        params: TxParams,
    -    ) -> Result<(Psbt, TransactionDetails), Error> {
    -        let external_policy = self
    -            .descriptor
    -            .extract_policy(&self.signers, BuildSatisfaction::None, &self.secp)?
    -            .unwrap();
    -        let internal_policy = self
    -            .change_descriptor
    -            .as_ref()
    -            .map(|desc| {
    -                Ok::<_, Error>(
    -                    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(Error::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(Error::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::<_, Error>(
    -                    policy.get_condition(
    -                        params
    -                            .internal_policy_path
    -                            .as_ref()
    -                            .unwrap_or(&BTreeMap::new()),
    -                    )?,
    -                )
    -            })
    -            .transpose()?;
    -
    -        let requirements =
    -            external_requirements.merge(&internal_requirements.unwrap_or_default())?;
    -        debug!("Policy requirements: {:?}", requirements);
    -
    -        let version = match params.version {
    -            Some(tx_builder::Version(0)) => {
    -                return Err(Error::Generic("Invalid version `0`".into()))
    -            }
    -            Some(tx_builder::Version(1)) if requirements.csv.is_some() => {
    -                return Err(Error::Generic(
    -                    "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
    -                        .into(),
    -                ))
    -            }
    -            Some(tx_builder::Version(x)) => x,
    -            None if requirements.csv.is_some() => 2,
    -            _ => 1,
    -        };
    -
    -        let lock_time = match params.locktime {
    -            // No nLockTime, default to 0
    -            None => requirements.timelock.unwrap_or(0),
    -            // 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 check_nlocktime(x, requirements.timelock.unwrap()) => x,
    -            // Invalid nLockTime required
    -            Some(x) => return Err(Error::Generic(format!("TxBuilder requested timelock of `{}`, but at least `{}` is required to spend from this script", x, requirements.timelock.unwrap())))
    -        };
    -
    -        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 != 0 => 0xFFFFFFFE,
    -            // No RBF, CSV or nLockTime, make the transaction final
    -            (None, None) => 0xFFFFFFFF,
    -
    -            // 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 >= 0xFFFFFFFE => {
    -                return Err(Error::Generic(
    -                    "Cannot enable RBF with a nSequence >= 0xFFFFFFFE".into(),
    -                ))
    -            }
    -            // 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(Error::Generic(format!(
    -                    "Cannot enable RBF with nSequence `{}` given a required OP_CSV of `{}`",
    -                    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
    -            .as_ref()
    -            .unwrap_or(&FeePolicy::FeeRate(FeeRate::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(Error::FeeTooLow {
    -                            required: previous_fee.absolute,
    -                        });
    -                    }
    -                }
    -                (FeeRate::from_sat_per_vb(0.0), *fee)
    -            }
    -            FeePolicy::FeeRate(rate) => {
    -                if let Some(previous_fee) = params.bumping_fee {
    -                    let required_feerate = FeeRate::from_sat_per_vb(previous_fee.rate + 1.0);
    -                    if *rate < required_feerate {
    -                        return Err(Error::FeeRateTooLow {
    -                            required: required_feerate,
    -                        });
    -                    }
    -                }
    -                (*rate, 0)
    -            }
    -        };
    -
    -        let mut tx = Transaction {
    -            version,
    -            lock_time,
    -            input: vec![],
    -            output: vec![],
    -        };
    -
    -        if params.manually_selected_only && params.utxos.is_empty() {
    -            return Err(Error::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;
    -
    -        fee_amount += fee_rate.fee_wu(tx.get_weight());
    -
    -        let recipients = params.recipients.iter().map(|(r, v)| (r, *v));
    -
    -        for (index, (script_pubkey, value)) in recipients.enumerate() {
    -            if value.is_dust() {
    -                return Err(Error::OutputBelowDustLimit(index));
    -            }
    -
    -            if self.is_mine(script_pubkey)? {
    -                received += value;
    -            }
    -
    -            let new_out = TxOut {
    -                script_pubkey: script_pubkey.clone(),
    -                value,
    -            };
    -            fee_amount += fee_rate.fee_vb(serialize(&new_out).len());
    -
    -            tx.output.push(new_out);
    -
    -            outgoing += value;
    -        }
    -
    -        if params.change_policy != tx_builder::ChangeSpendPolicy::ChangeAllowed
    -            && self.change_descriptor.is_none()
    -        {
    -            return Err(Error::Generic(
    -                "The `change_policy` can be set only if the wallet has a change_descriptor".into(),
    -            ));
    -        }
    -
    -        let (required_utxos, optional_utxos) = self.preselect_utxos(
    -            params.change_policy,
    -            &params.unspendable,
    -            params.utxos.clone(),
    -            params.drain_wallet,
    -            params.manually_selected_only,
    -            params.bumping_fee.is_some(), // we mandate confirmed transactions if we're bumping the fee
    -        )?;
    -
    -        let coin_selection = coin_selection.coin_select(
    -            self.database.borrow().deref(),
    -            required_utxos,
    -            optional_utxos,
    -            fee_rate,
    -            outgoing,
    -            fee_amount,
    -        )?;
    -        let mut fee_amount = coin_selection.fee_amount;
    -
    -        tx.input = coin_selection
    -            .selected
    -            .iter()
    -            .map(|u| bitcoin::TxIn {
    -                previous_output: u.outpoint(),
    -                script_sig: Script::default(),
    -                sequence: n_sequence,
    -                witness: vec![],
    -            })
    -            .collect();
    -
    -        // prepare the drain output
    -        let mut drain_output = {
    -            let script_pubkey = match params.drain_to {
    -                Some(ref drain_recipient) => drain_recipient.clone(),
    -                None => self.get_change_address()?,
    -            };
    -
    -            TxOut {
    -                script_pubkey,
    -                value: 0,
    -            }
    -        };
    -
    -        fee_amount += fee_rate.fee_vb(serialize(&drain_output).len());
    -
    -        let drain_val = (coin_selection.selected_amount() - outgoing).saturating_sub(fee_amount);
    -
    -        if tx.output.is_empty() {
    -            if params.drain_to.is_some() {
    -                if drain_val.is_dust() {
    -                    return Err(Error::InsufficientFunds {
    -                        needed: DUST_LIMIT_SATOSHI,
    -                        available: drain_val,
    -                    });
    -                }
    -            } else {
    -                return Err(Error::NoRecipients);
    -            }
    -        }
    -
    -        if drain_val.is_dust() {
    -            fee_amount += drain_val;
    -        } else {
    -            drain_output.value = drain_val;
    -            if self.is_mine(&drain_output.script_pubkey)? {
    -                received += drain_val;
    -            }
    -            tx.output.push(drain_output);
    -        }
    -
    -        // sort input/outputs according to the chosen algorithm
    -        params.ordering.sort_tx(&mut tx);
    -
    -        let txid = tx.txid();
    -        let sent = coin_selection.local_selected_amount();
    -        let psbt = self.complete_transaction(tx, coin_selection.selected, params)?;
    -
    -        let transaction_details = TransactionDetails {
    -            transaction: None,
    -            txid,
    -            confirmation_time: None,
    -            received,
    -            sent,
    -            fee: Some(fee_amount),
    -            verified: true,
    -        };
    -
    -        Ok((psbt, transaction_details))
    -    }
    -
    -    /// 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
    -    /// *repalce 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::database::*;
    -    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -    /// # let wallet = doctest_wallet!();
    -    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -    /// let (mut psbt, _) = {
    -    ///     let mut builder = wallet.build_tx();
    -    ///     builder
    -    ///         .add_recipient(to_address.script_pubkey(), 50_000)
    -    ///         .enable_rbf();
    -    ///     builder.finish()?
    -    /// };
    -    /// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
    -    /// let tx = psbt.extract_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.0));
    -    ///     builder.finish()?
    -    /// };
    -    ///
    -    /// let _ = wallet.sign(&mut psbt, SignOptions::default())?;
    -    /// let fee_bumped_tx = psbt.extract_tx();
    -    /// // broadcast fee_bumped_tx to replace original
    -    /// # Ok::<(), bdk::Error>(())
    -    /// ```
    -    // TODO: support for merging multiple transactions while bumping the fees
    -    // TODO: option to force addition of an extra output? seems bad for privacy to update the
    -    // change
    -    pub fn build_fee_bump(
    -        &self,
    -        txid: Txid,
    -    ) -> Result<TxBuilder<'_, B, D, DefaultCoinSelectionAlgorithm, BumpFee>, Error> {
    -        let mut details = match self.database.borrow().get_tx(&txid, true)? {
    -            None => return Err(Error::TransactionNotFound),
    -            Some(tx) if tx.transaction.is_none() => return Err(Error::TransactionNotFound),
    -            Some(tx) if tx.confirmation_time.is_some() => return Err(Error::TransactionConfirmed),
    -            Some(tx) => tx,
    -        };
    -        let mut tx = details.transaction.take().unwrap();
    -        if !tx.input.iter().any(|txin| txin.sequence <= 0xFFFFFFFD) {
    -            return Err(Error::IrreplaceableTransaction);
    -        }
    -
    -        let feerate = FeeRate::from_wu(
    -            details.fee.ok_or(Error::FeeRateUnavailable)?,
    -            tx.get_weight(),
    -        );
    -
    -        // remove the inputs from the tx and process them
    -        let original_txin = tx.input.drain(..).collect::<Vec<_>>();
    -        let original_utxos = original_txin
    -            .iter()
    -            .map(|txin| -> Result<_, Error> {
    -                let txout = self
    -                    .database
    -                    .borrow()
    -                    .get_previous_output(&txin.previous_output)?
    -                    .ok_or(Error::UnknownUtxo)?;
    -
    -                let (weight, keychain) = match self
    -                    .database
    -                    .borrow()
    -                    .get_path_from_script_pubkey(&txout.script_pubkey)?
    -                {
    -                    Some((keychain, _)) => (
    -                        self._get_descriptor_for_keychain(keychain)
    -                            .0
    -                            .max_satisfaction_weight()
    -                            .unwrap(),
    -                        keychain,
    -                    ),
    -                    None => {
    -                        // estimate the weight based on the scriptsig/witness size present in the
    -                        // original transaction
    -                        let weight =
    -                            serialize(&txin.script_sig).len() * 4 + serialize(&txin.witness).len();
    -                        (weight, KeychainKind::External)
    -                    }
    -                };
    -
    -                let utxo = LocalUtxo {
    -                    outpoint: txin.previous_output,
    -                    txout,
    -                    keychain,
    -                };
    -
    -                Ok(WeightedUtxo {
    -                    satisfaction_weight: weight,
    -                    utxo: Utxo::Local(utxo),
    -                })
    -            })
    -            .collect::<Result<Vec<_>, _>>()?;
    -
    -        if tx.output.len() > 1 {
    -            let mut change_index = None;
    -            for (index, txout) in tx.output.iter().enumerate() {
    -                let (_, change_type) = self._get_descriptor_for_keychain(KeychainKind::Internal);
    -                match self
    -                    .database
    -                    .borrow()
    -                    .get_path_from_script_pubkey(&txout.script_pubkey)?
    -                {
    -                    Some((keychain, _)) if keychain == change_type => change_index = Some(index),
    -                    _ => {}
    -                }
    -            }
    -
    -            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)),
    -            recipients: tx
    -                .output
    -                .into_iter()
    -                .map(|txout| (txout.script_pubkey, txout.value))
    -                .collect(),
    -            utxos: original_utxos,
    -            bumping_fee: Some(tx_builder::PreviousFee {
    -                absolute: details.fee.ok_or(Error::FeeRateUnavailable)?,
    -                rate: feerate.as_sat_vb(),
    -            }),
    -            ..Default::default()
    -        };
    -
    -        Ok(TxBuilder {
    -            wallet: 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`]
    -    ///
    -    /// 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::database::*;
    -    /// # let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -    /// # let wallet = doctest_wallet!();
    -    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -    /// let (mut psbt, _) = {
    -    ///     let mut builder = wallet.build_tx();
    -    ///     builder.add_recipient(to_address.script_pubkey(), 50_000);
    -    ///     builder.finish()?
    -    /// };
    -    /// let  finalized = wallet.sign(&mut psbt, SignOptions::default())?;
    -    /// assert!(finalized, "we should have signed all the inputs");
    -    /// # Ok::<(), bdk::Error>(())
    -    pub fn sign(&self, psbt: &mut Psbt, sign_options: SignOptions) -> Result<bool, Error> {
    -        // this helps us doing our job later
    -        self.add_input_hd_keypaths(psbt)?;
    -
    -        // If we aren't allowed to use `witness_utxo`, ensure that every input but finalized one
    -        // 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())
    -                .any(|i| i.non_witness_utxo.is_none())
    -        {
    -            return Err(Error::Signer(signer::SignerError::MissingNonWitnessUtxo));
    -        }
    -
    -        // If the user hasn't explicitly opted-in, refuse to sign the transaction unless every input
    -        // is using `SIGHASH_ALL`
    -        if !sign_options.allow_all_sighashes
    -            && !psbt
    -                .inputs
    -                .iter()
    -                .all(|i| i.sighash_type.is_none() || i.sighash_type == Some(SigHashType::All))
    -        {
    -            return Err(Error::Signer(signer::SignerError::NonStandardSighash));
    -        }
    -
    -        for signer in self
    -            .signers
    -            .signers()
    -            .iter()
    -            .chain(self.change_signers.signers().iter())
    -        {
    -            if signer.sign_whole_tx() {
    -                signer.sign(psbt, None, &self.secp)?;
    -            } else {
    -                for index in 0..psbt.inputs.len() {
    -                    signer.sign(psbt, Some(index), &self.secp)?;
    -                }
    -            }
    -        }
    -
    -        // attempt to finalize
    -        self.finalize_psbt(psbt, sign_options)
    -    }
    -
    -    /// Return the spending policies for the wallet's descriptor
    -    pub fn policies(&self, keychain: KeychainKind) -> Result<Option<Policy>, Error> {
    -        match (keychain, self.change_descriptor.as_ref()) {
    -            (KeychainKind::External, _) => Ok(self.descriptor.extract_policy(
    -                &self.signers,
    -                BuildSatisfaction::None,
    -                &self.secp,
    -            )?),
    -            (KeychainKind::Internal, None) => Ok(None),
    -            (KeychainKind::Internal, Some(desc)) => Ok(desc.extract_policy(
    -                &self.change_signers,
    -                BuildSatisfaction::None,
    -                &self.secp,
    -            )?),
    -        }
    -    }
    -
    -    /// 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,
    -    ) -> Result<Option<ExtendedDescriptor>, Error> {
    -        match (keychain, self.change_descriptor.as_ref()) {
    -            (KeychainKind::External, _) => Ok(Some(self.descriptor.clone())),
    -            (KeychainKind::Internal, None) => Ok(None),
    -            (KeychainKind::Internal, Some(desc)) => Ok(Some(desc.clone())),
    -        }
    -    }
    -
    -    /// Try to finalize a PSBT
    -    ///
    -    /// 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, Error> {
    -        let tx = &psbt.global.unsigned_tx;
    -        let mut finished = true;
    -
    -        for (n, input) in tx.input.iter().enumerate() {
    -            let psbt_input = &psbt
    -                .inputs
    -                .get(n)
    -                .ok_or(Error::Signer(SignerError::InputIndexOutOfRange))?;
    -            if psbt_input.final_script_sig.is_some() || psbt_input.final_script_witness.is_some() {
    -                continue;
    -            }
    -            // if the height is None in the database it means it's still unconfirmed, so consider
    -            // that as a very high value
    -            let create_height = self
    -                .database
    -                .borrow()
    -                .get_tx(&input.previous_output.txid, false)?
    -                .map(|tx| tx.confirmation_time.map(|c| c.height).unwrap_or(u32::MAX));
    -            let current_height = sign_options.assume_height.or(self.current_height);
    -
    -            debug!(
    -                "Input #{} - {}, using `create_height` = {:?}, `current_height` = {:?}",
    -                n, input.previous_output, create_height, current_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)
    -                .map(|txout| self.get_descriptor_for_txout(&txout))
    -                .transpose()?
    -                .flatten()
    -                .or_else(|| {
    -                    self.descriptor.derive_from_psbt_input(
    -                        psbt_input,
    -                        psbt.get_utxo_for(n),
    -                        &self.secp,
    -                    )
    -                })
    -                .or_else(|| {
    -                    self.change_descriptor.as_ref().and_then(|desc| {
    -                        desc.derive_from_psbt_input(psbt_input, psbt.get_utxo_for(n), &self.secp)
    -                    })
    -                });
    -
    -            match desc {
    -                Some(desc) => {
    -                    let mut tmp_input = bitcoin::TxIn::default();
    -                    match desc.satisfy(
    -                        &mut tmp_input,
    -                        (
    -                            PsbtInputSatisfier::new(psbt, n),
    -                            After::new(current_height, false),
    -                            Older::new(current_height, create_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);
    -                        }
    -                        Err(e) => {
    -                            debug!("satisfy error {:?} for input {}", e, n);
    -                            finished = false
    -                        }
    -                    }
    -                }
    -                None => finished = false,
    -            }
    -        }
    -
    -        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 adddresses for a particular `keychain`.
    -    pub fn get_descriptor_for_keychain(&self, keychain: KeychainKind) -> &ExtendedDescriptor {
    -        let (descriptor, _) = self._get_descriptor_for_keychain(keychain);
    -        descriptor
    -    }
    -
    -    // Internals
    -
    -    fn _get_descriptor_for_keychain(
    -        &self,
    -        keychain: KeychainKind,
    -    ) -> (&ExtendedDescriptor, KeychainKind) {
    -        match keychain {
    -            KeychainKind::Internal if self.change_descriptor.is_some() => (
    -                self.change_descriptor.as_ref().unwrap(),
    -                KeychainKind::Internal,
    -            ),
    -            _ => (&self.descriptor, KeychainKind::External),
    -        }
    -    }
    -
    -    fn get_descriptor_for_txout(
    -        &self,
    -        txout: &TxOut,
    -    ) -> Result<Option<DerivedDescriptor<'_>>, Error> {
    -        Ok(self
    -            .database
    -            .borrow()
    -            .get_path_from_script_pubkey(&txout.script_pubkey)?
    -            .map(|(keychain, child)| (self.get_descriptor_for_keychain(keychain), child))
    -            .map(|(desc, child)| desc.as_derived(child, &self.secp)))
    -    }
    -
    -    fn get_change_address(&self) -> Result<Script, Error> {
    -        let (desc, keychain) = self._get_descriptor_for_keychain(KeychainKind::Internal);
    -        let index = self.fetch_and_increment_index(keychain)?;
    -
    -        Ok(desc.as_derived(index, &self.secp).script_pubkey())
    -    }
    -
    -    fn fetch_and_increment_index(&self, keychain: KeychainKind) -> Result<u32, Error> {
    -        let (descriptor, keychain) = self._get_descriptor_for_keychain(keychain);
    -        let index = match descriptor.is_deriveable() {
    -            false => 0,
    -            true => self.database.borrow_mut().increment_last_index(keychain)?,
    -        };
    -
    -        if self
    -            .database
    -            .borrow()
    -            .get_script_pubkey_from_path(keychain, index)?
    -            .is_none()
    -        {
    -            self.cache_addresses(keychain, index, CACHE_ADDR_BATCH_SIZE)?;
    -        }
    -
    -        let derived_descriptor = descriptor.as_derived(index, &self.secp);
    -
    -        let hd_keypaths = derived_descriptor.get_hd_keypaths(&self.secp)?;
    -        let script = derived_descriptor.script_pubkey();
    -
    -        for validator in &self.address_validators {
    -            validator.validate(keychain, &hd_keypaths, &script)?;
    -        }
    -
    -        Ok(index)
    -    }
    -
    -    fn fetch_index(&self, keychain: KeychainKind) -> Result<u32, Error> {
    -        let (descriptor, keychain) = self._get_descriptor_for_keychain(keychain);
    -        let index = match descriptor.is_deriveable() {
    -            false => Some(0),
    -            true => self.database.borrow_mut().get_last_index(keychain)?,
    -        };
    -
    -        if let Some(i) = index {
    -            Ok(i)
    -        } else {
    -            self.fetch_and_increment_index(keychain)
    -        }
    -    }
    -
    -    fn set_index(&self, keychain: KeychainKind, index: u32) -> Result<(), Error> {
    -        self.database.borrow_mut().set_last_index(keychain, index)?;
    -        Ok(())
    -    }
    -
    -    fn cache_addresses(
    -        &self,
    -        keychain: KeychainKind,
    -        from: u32,
    -        mut count: u32,
    -    ) -> Result<(), Error> {
    -        let (descriptor, keychain) = self._get_descriptor_for_keychain(keychain);
    -        if !descriptor.is_deriveable() {
    -            if from > 0 {
    -                return Ok(());
    -            }
    -
    -            count = 1;
    -        }
    -
    -        let mut address_batch = self.database.borrow().begin_batch();
    -
    -        let start_time = time::Instant::new();
    -        for i in from..(from + count) {
    -            address_batch.set_script_pubkey(
    -                &descriptor.as_derived(i, &self.secp).script_pubkey(),
    -                keychain,
    -                i,
    -            )?;
    -        }
    -
    -        info!(
    -            "Derivation of {} addresses from {} took {} ms",
    -            count,
    -            from,
    -            start_time.elapsed().as_millis()
    -        );
    -
    -        self.database.borrow_mut().commit_batch(address_batch)?;
    -
    -        Ok(())
    -    }
    -
    -    fn get_available_utxos(&self) -> Result<Vec<(LocalUtxo, usize)>, Error> {
    -        Ok(self
    -            .list_unspent()?
    -            .into_iter()
    -            .map(|utxo| {
    -                let keychain = utxo.keychain;
    -                (
    -                    utxo,
    -                    self.get_descriptor_for_keychain(keychain)
    -                        .max_satisfaction_weight()
    -                        .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.
    -    #[allow(clippy::type_complexity)]
    -    fn preselect_utxos(
    -        &self,
    -        change_policy: tx_builder::ChangeSpendPolicy,
    -        unspendable: &HashSet<OutPoint>,
    -        manually_selected: Vec<WeightedUtxo>,
    -        must_use_all_available: bool,
    -        manual_only: bool,
    -        must_only_use_confirmed_tx: bool,
    -    ) -> Result<(Vec<WeightedUtxo>, Vec<WeightedUtxo>), Error> {
    -        //    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 manual_only {
    -            return Ok((must_spend, vec![]));
    -        }
    -
    -        let satisfies_confirmed = match must_only_use_confirmed_tx {
    -            true => {
    -                let database = self.database.borrow();
    -                may_spend
    -                    .iter()
    -                    .map(|u| {
    -                        database
    -                            .get_tx(&u.0.outpoint.txid, true)
    -                            .map(|tx| match tx {
    -                                None => false,
    -                                Some(tx) => tx.confirmation_time.is_some(),
    -                            })
    -                    })
    -                    .collect::<Result<Vec<_>, _>>()?
    -            }
    -            false => vec![true; may_spend.len()],
    -        };
    -
    -        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);
    -        }
    -
    -        Ok((must_spend, may_spend))
    -    }
    -
    -    fn complete_transaction(
    -        &self,
    -        tx: Transaction,
    -        selected: Vec<Utxo>,
    -        params: TxParams,
    -    ) -> Result<Psbt, Error> {
    -        use bitcoin::util::psbt::serialize::Serialize;
    -
    -        let mut psbt = Psbt::from_unsigned_tx(tx)?;
    -
    -        if params.add_global_xpubs {
    -            let mut all_xpubs = self.descriptor.get_extended_keys()?;
    -            if let Some(change_descriptor) = &self.change_descriptor {
    -                all_xpubs.extend(change_descriptor.get_extended_keys()?);
    -            }
    -
    -            for xpub in all_xpubs {
    -                let serialized_xpub = base58::from_check(&xpub.xkey.to_string())
    -                    .expect("Internal serialization error");
    -                let key = PsbtKey {
    -                    type_value: 0x01,
    -                    key: serialized_xpub,
    -                };
    -
    -                let origin = match xpub.origin {
    -                    Some(origin) => origin,
    -                    None if xpub.xkey.depth == 0 => {
    -                        (xpub.root_fingerprint(&self.secp), vec![].into())
    -                    }
    -                    _ => return Err(Error::MissingKeyOrigin(xpub.xkey.to_string())),
    -                };
    -
    -                psbt.global.unknown.insert(key, origin.serialize());
    -            }
    -        }
    -
    -        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.global.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 {
    -                                Error::UnknownUtxo => Input {
    -                                    sighash_type: params.sighash,
    -                                    ..Input::default()
    -                                },
    -                                _ => return Err(e),
    -                            },
    -                        }
    -                }
    -                Utxo::Foreign {
    -                    psbt_input: foreign_psbt_input,
    -                    outpoint,
    -                } => {
    -                    if !params.only_witness_utxo && foreign_psbt_input.non_witness_utxo.is_none() {
    -                        return Err(Error::Generic(format!(
    -                            "Missing non_witness_utxo on foreign utxo {}",
    -                            outpoint
    -                        )));
    -                    }
    -                    *psbt_input = *foreign_psbt_input;
    -                }
    -            }
    -        }
    -
    -        // probably redundant but it doesn't hurt...
    -        self.add_input_hd_keypaths(&mut psbt)?;
    -
    -        // add metadata for the outputs
    -        for (psbt_output, tx_output) in psbt
    -            .outputs
    -            .iter_mut()
    -            .zip(psbt.global.unsigned_tx.output.iter())
    -        {
    -            if let Some((keychain, child)) = self
    -                .database
    -                .borrow()
    -                .get_path_from_script_pubkey(&tx_output.script_pubkey)?
    -            {
    -                let (desc, _) = self._get_descriptor_for_keychain(keychain);
    -                let derived_descriptor = desc.as_derived(child, &self.secp);
    -
    -                psbt_output.bip32_derivation = derived_descriptor.get_hd_keypaths(&self.secp)?;
    -                if params.include_output_redeem_witness_script {
    -                    psbt_output.witness_script = derived_descriptor.psbt_witness_script();
    -                    psbt_output.redeem_script = derived_descriptor.psbt_redeem_script();
    -                };
    -            }
    -        }
    -
    -        Ok(psbt)
    -    }
    -
    -    /// get the corresponding PSBT Input for a LocalUtxo
    -    pub fn get_psbt_input(
    -        &self,
    -        utxo: LocalUtxo,
    -        sighash_type: Option<SigHashType>,
    -        only_witness_utxo: bool,
    -    ) -> Result<Input, Error> {
    -        // Try to find the prev_script in our db to figure out if this is internal or external,
    -        // and the derivation index
    -        let (keychain, child) = self
    -            .database
    -            .borrow()
    -            .get_path_from_script_pubkey(&utxo.txout.script_pubkey)?
    -            .ok_or(Error::UnknownUtxo)?;
    -
    -        let mut psbt_input = Input {
    -            sighash_type,
    -            ..Input::default()
    -        };
    -
    -        let desc = self.get_descriptor_for_keychain(keychain);
    -        let derived_descriptor = desc.as_derived(child, &self.secp);
    -        psbt_input.bip32_derivation = derived_descriptor.get_hd_keypaths(&self.secp)?;
    -
    -        psbt_input.redeem_script = derived_descriptor.psbt_redeem_script();
    -        psbt_input.witness_script = derived_descriptor.psbt_witness_script();
    -
    -        let prev_output = utxo.outpoint;
    -        if let Some(prev_tx) = self.database.borrow().get_raw_tx(&prev_output.txid)? {
    -            if desc.is_witness() {
    -                psbt_input.witness_utxo = Some(prev_tx.output[prev_output.vout as usize].clone());
    -            }
    -            if !desc.is_witness() || !only_witness_utxo {
    -                psbt_input.non_witness_utxo = Some(prev_tx);
    -            }
    -        }
    -        Ok(psbt_input)
    -    }
    -
    -    fn add_input_hd_keypaths(&self, psbt: &mut Psbt) -> Result<(), Error> {
    -        let mut input_utxos = Vec::with_capacity(psbt.inputs.len());
    -        for n in 0..psbt.inputs.len() {
    -            input_utxos.push(psbt.get_utxo_for(n).clone());
    -        }
    -
    -        // try to add hd_keypaths if we've already seen the output
    -        for (psbt_input, out) in psbt.inputs.iter_mut().zip(input_utxos.iter()) {
    -            if let Some(out) = out {
    -                if let Some((keychain, child)) = self
    -                    .database
    -                    .borrow()
    -                    .get_path_from_script_pubkey(&out.script_pubkey)?
    -                {
    -                    debug!("Found descriptor {:?}/{}", keychain, child);
    -
    -                    // merge hd_keypaths
    -                    let desc = self.get_descriptor_for_keychain(keychain);
    -                    let mut hd_keypaths = desc
    -                        .as_derived(child, &self.secp)
    -                        .get_hd_keypaths(&self.secp)?;
    -                    psbt_input.bip32_derivation.append(&mut hd_keypaths);
    -                }
    -            }
    -        }
    -
    -        Ok(())
    -    }
    -}
    -
    -impl<B, D> Wallet<B, D>
    -where
    -    B: Blockchain,
    -    D: BatchDatabase,
    -{
    -    /// Create a new "online" wallet
    -    #[maybe_async]
    -    pub fn new<E: IntoWalletDescriptor>(
    -        descriptor: E,
    -        change_descriptor: Option<E>,
    -        network: Network,
    -        database: D,
    -        client: B,
    -    ) -> Result<Self, Error> {
    -        let current_height = Some(maybe_await!(client.get_height())? as u32);
    -        Self::_new(
    -            descriptor,
    -            change_descriptor,
    -            network,
    -            database,
    -            client,
    -            current_height,
    -        )
    -    }
    -
    -    /// Sync the internal database with the blockchain
    -    #[maybe_async]
    -    pub fn sync<P: 'static + Progress>(
    -        &self,
    -        progress_update: P,
    -        max_address_param: Option<u32>,
    -    ) -> Result<(), Error> {
    -        debug!("Begin sync...");
    -
    -        let mut run_setup = false;
    -
    -        let max_address = match self.descriptor.is_deriveable() {
    -            false => 0,
    -            true => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
    -        };
    -        debug!("max_address {}", max_address);
    -        if self
    -            .database
    -            .borrow()
    -            .get_script_pubkey_from_path(KeychainKind::External, max_address.saturating_sub(1))?
    -            .is_none()
    -        {
    -            debug!("caching external addresses");
    -            run_setup = true;
    -            self.cache_addresses(KeychainKind::External, 0, max_address)?;
    -        }
    -
    -        if let Some(change_descriptor) = &self.change_descriptor {
    -            let max_address = match change_descriptor.is_deriveable() {
    -                false => 0,
    -                true => max_address_param.unwrap_or(CACHE_ADDR_BATCH_SIZE),
    -            };
    -
    -            if self
    -                .database
    -                .borrow()
    -                .get_script_pubkey_from_path(KeychainKind::Internal, max_address.saturating_sub(1))?
    -                .is_none()
    -            {
    -                debug!("caching internal addresses");
    -                run_setup = true;
    -                self.cache_addresses(KeychainKind::Internal, 0, max_address)?;
    -            }
    -        }
    -
    -        debug!("run_setup: {}", run_setup);
    -        // TODO: what if i generate an address first and cache some addresses?
    -        // TODO: we should sync if generating an address triggers a new batch to be stored
    -        if run_setup {
    -            maybe_await!(self
    -                .client
    -                .setup(self.database.borrow_mut().deref_mut(), progress_update,))?;
    -        } else {
    -            maybe_await!(self
    -                .client
    -                .sync(self.database.borrow_mut().deref_mut(), progress_update,))?;
    -        }
    -
    -        #[cfg(feature = "verify")]
    -        {
    -            debug!("Verifying transactions...");
    -            for mut tx in self.database.borrow().iter_txs(true)? {
    -                if !tx.verified {
    -                    verify::verify_tx(
    -                        tx.transaction.as_ref().ok_or(Error::TransactionNotFound)?,
    -                        self.database.borrow().deref(),
    -                        &self.client,
    -                    )?;
    -
    -                    tx.verified = true;
    -                    self.database.borrow_mut().set_tx(&tx)?;
    -                }
    -            }
    -        }
    -
    -        Ok(())
    -    }
    -
    -    /// Return a reference to the internal blockchain client
    -    pub fn client(&self) -> &B {
    -        &self.client
    -    }
    -
    -    /// Broadcast a transaction to the network
    -    #[maybe_async]
    -    pub fn broadcast(&self, tx: Transaction) -> Result<Txid, Error> {
    -        maybe_await!(self.client.broadcast(&tx))?;
    -
    -        Ok(tx.txid())
    -    }
    -}
    -
    -/// Return a fake wallet that appears to be funded for testing.
    -pub fn get_funded_wallet(
    -    descriptor: &str,
    -) -> (
    -    Wallet<(), MemoryDatabase>,
    -    (String, Option<String>),
    -    bitcoin::Txid,
    -) {
    -    let descriptors = testutils!(@descriptors (descriptor));
    -    let wallet = Wallet::new_offline(
    -        &descriptors.0,
    -        None,
    -        Network::Regtest,
    -        MemoryDatabase::new(),
    -    )
    -    .unwrap();
    -
    -    let funding_address_kix = 0;
    -
    -    let tx_meta = testutils! {
    -            @tx ( (@external descriptors, funding_address_kix) => 50_000 ) (@confirmations 1)
    -    };
    -
    -    wallet
    -        .database
    -        .borrow_mut()
    -        .set_script_pubkey(
    -            &bitcoin::Address::from_str(&tx_meta.output.get(0).unwrap().to_address)
    -                .unwrap()
    -                .script_pubkey(),
    -            KeychainKind::External,
    -            funding_address_kix,
    -        )
    -        .unwrap();
    -    wallet
    -        .database
    -        .borrow_mut()
    -        .set_last_index(KeychainKind::External, funding_address_kix)
    -        .unwrap();
    -
    -    let txid = crate::populate_test_db!(wallet.database.borrow_mut(), tx_meta, Some(100));
    -
    -    (wallet, descriptors, txid)
    -}
    -
    -#[cfg(test)]
    -pub(crate) mod test {
    -    use bitcoin::{util::psbt, Network};
    -
    -    use crate::database::Database;
    -    use crate::types::KeychainKind;
    -
    -    use super::*;
    -    use crate::signer::{SignOptions, SignerError};
    -    use crate::wallet::AddressIndex::{LastUnused, New, Peek, Reset};
    -
    -    #[test]
    -    fn test_cache_addresses_fixed() {
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new_offline(
    -            "wpkh(L5EZftvrYaSudiozVRzTqLcHLNDoVn7H5HSfM9BAN6tMJX8oTWz6)",
    -            None,
    -            Network::Testnet,
    -            db,
    -        )
    -        .unwrap();
    -
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
    -        );
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1qj08ys4ct2hzzc2hcz6h2hgrvlmsjynaw43s835"
    -        );
    -
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::External, 0)
    -            .unwrap()
    -            .is_some());
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::Internal, 0)
    -            .unwrap()
    -            .is_none());
    -    }
    -
    -    #[test]
    -    fn test_cache_addresses() {
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
    -
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE - 1)
    -            .unwrap()
    -            .is_some());
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE)
    -            .unwrap()
    -            .is_none());
    -    }
    -
    -    #[test]
    -    fn test_cache_addresses_refill() {
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)", None, Network::Testnet, db).unwrap();
    -
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE - 1)
    -            .unwrap()
    -            .is_some());
    -
    -        for _ in 0..CACHE_ADDR_BATCH_SIZE {
    -            wallet.get_address(New).unwrap();
    -        }
    -
    -        assert!(wallet
    -            .database
    -            .borrow_mut()
    -            .get_script_pubkey_from_path(KeychainKind::External, CACHE_ADDR_BATCH_SIZE * 2 - 1)
    -            .unwrap()
    -            .is_some());
    -    }
    -
    -    pub(crate) fn get_test_wpkh() -> &'static str {
    -        "wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)"
    -    }
    -
    -    pub(crate) fn get_test_single_sig_csv() -> &'static str {
    -        // and(pk(Alice),older(6))
    -        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),older(6)))"
    -    }
    -
    -    pub(crate) fn get_test_a_or_b_plus_csv() -> &'static str {
    -        // or(pk(Alice),and(pk(Bob),older(144)))
    -        "wsh(or_d(pk(cRjo6jqfVNP33HhSS76UhXETZsGTZYx8FMFvR9kpbtCSV1PmdZdu),and_v(v:pk(cMnkdebixpXMPfkcNEjjGin7s94hiehAH4mLbYkZoh9KSiNNmqC8),older(144))))"
    -    }
    -
    -    pub(crate) fn get_test_single_sig_cltv() -> &'static str {
    -        // and(pk(Alice),after(100000))
    -        "wsh(and_v(v:pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW),after(100000)))"
    -    }
    -
    -    macro_rules! assert_fee_rate {
    -        ($tx:expr, $fees:expr, $fee_rate:expr $( ,@dust_change $( $dust_change:expr )* )* $( ,@add_signature $( $add_signature:expr )* )* ) => ({
    -            let mut tx = $tx.clone();
    -            $(
    -                $( $add_signature )*
    -                for txin in &mut tx.input {
    -                    txin.witness.push([0x00; 108].to_vec()); // fake signature
    -                }
    -            )*
    -
    -            #[allow(unused_mut)]
    -            #[allow(unused_assignments)]
    -            let mut dust_change = false;
    -            $(
    -                $( $dust_change )*
    -                dust_change = true;
    -            )*
    -
    -            let tx_fee_rate = FeeRate::from_wu($fees, tx.get_weight());
    -            let fee_rate = $fee_rate;
    -
    -            if !dust_change {
    -                assert!((tx_fee_rate - fee_rate).as_sat_vb().abs() < 0.5, "Expected fee rate of {:?}, the tx has {:?}", fee_rate, tx_fee_rate);
    -            } else {
    -                assert!(tx_fee_rate >= fee_rate, "Expected fee rate of at least {:?}, the tx has {:?}", fee_rate, tx_fee_rate);
    -            }
    -        });
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "NoRecipients")]
    -    fn test_create_tx_empty_recipients() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        wallet.build_tx().finish().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "NoUtxosSelected")]
    -    fn test_create_tx_manually_selected_empty_utxos() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .manually_selected_only();
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "Invalid version `0`")]
    -    fn test_create_tx_version_0() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .version(0);
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "TxBuilder requested version `1`, but at least `2` is needed to use OP_CSV"
    -    )]
    -    fn test_create_tx_version_1_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .version(1);
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_version() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .version(42);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.version, 42);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_locktime() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.lock_time, 0);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_locktime_cltv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.lock_time, 100_000);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_locktime() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .nlocktime(630_000);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_locktime_compatible_with_cltv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .nlocktime(630_000);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.lock_time, 630_000);
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "TxBuilder requested timelock of `50000`, but at least `100000` is required to spend from this script"
    -    )]
    -    fn test_create_tx_custom_locktime_incompatible_with_cltv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .nlocktime(50000);
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_no_rbf_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 6);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_with_default_rbf_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf();
    -        let (psbt, _) = builder.finish().unwrap();
    -        // When CSV is enabled it takes precedence over the rbf value (unless forced by the user).
    -        // It will be set to the OP_CSV value, in this case 6
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 6);
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "Cannot enable RBF with nSequence `3` given a required OP_CSV of `6`"
    -    )]
    -    fn test_create_tx_with_custom_rbf_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_csv());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf_with_sequence(3);
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_no_rbf_cltv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_single_sig_cltv());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFE);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "Cannot enable RBF with a nSequence >= 0xFFFFFFFE")]
    -    fn test_create_tx_invalid_rbf_sequence() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf_with_sequence(0xFFFFFFFE);
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_rbf_sequence() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf_with_sequence(0xDEADBEEF);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xDEADBEEF);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_sequence() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFF);
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "The `change_policy` can be set only if the wallet has a change_descriptor"
    -    )]
    -    fn test_create_tx_change_policy_no_internal() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .do_not_spend_change();
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_drain_wallet_and_drain_to() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
    -        assert_eq!(
    -            psbt.global.unsigned_tx.output[0].value,
    -            50_000 - details.fee.unwrap_or(0)
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_drain_wallet_and_drain_to_and_with_recipient() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -        let drain_addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 20_000)
    -            .drain_to(drain_addr.script_pubkey())
    -            .drain_wallet();
    -        let (psbt, details) = builder.finish().unwrap();
    -        dbg!(&psbt);
    -        let outputs = psbt.global.unsigned_tx.output;
    -
    -        assert_eq!(outputs.len(), 2);
    -        let main_output = outputs
    -            .iter()
    -            .find(|x| x.script_pubkey == addr.script_pubkey())
    -            .unwrap();
    -        let drain_output = outputs
    -            .iter()
    -            .find(|x| x.script_pubkey == drain_addr.script_pubkey())
    -            .unwrap();
    -        assert_eq!(main_output.value, 20_000,);
    -        assert_eq!(drain_output.value, 30_000 - details.fee.unwrap_or(0));
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_fee_rate() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::default(), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_fee_rate() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .fee_rate(FeeRate::from_sat_per_vb(5.0));
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(5.0), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_absolute_fee() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .drain_wallet()
    -            .fee_absolute(100);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.fee.unwrap_or(0), 100);
    -        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
    -        assert_eq!(
    -            psbt.global.unsigned_tx.output[0].value,
    -            50_000 - details.fee.unwrap_or(0)
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_absolute_zero_fee() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .drain_wallet()
    -            .fee_absolute(0);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.fee.unwrap_or(0), 0);
    -        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
    -        assert_eq!(
    -            psbt.global.unsigned_tx.output[0].value,
    -            50_000 - details.fee.unwrap_or(0)
    -        );
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_create_tx_absolute_high_fee() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .drain_wallet()
    -            .fee_absolute(60_000);
    -        let (_psbt, _details) = builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_add_change() {
    -        use super::tx_builder::TxOrdering;
    -
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .ordering(TxOrdering::Untouched);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.output.len(), 2);
    -        assert_eq!(psbt.global.unsigned_tx.output[0].value, 25_000);
    -        assert_eq!(
    -            psbt.global.unsigned_tx.output[1].value,
    -            25_000 - details.fee.unwrap_or(0)
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_skip_change_dust() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 49_800);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.output.len(), 1);
    -        assert_eq!(psbt.global.unsigned_tx.output[0].value, 49_800);
    -        assert_eq!(details.fee.unwrap_or(0), 200);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_create_tx_drain_to_dust_amount() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        // very high fee rate, so that the only output would be below dust
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .drain_wallet()
    -            .fee_rate(FeeRate::from_sat_per_vb(453.0));
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_ordering_respected() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 30_000)
    -            .add_recipient(addr.script_pubkey(), 10_000)
    -            .ordering(super::tx_builder::TxOrdering::Bip69Lexicographic);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.output.len(), 3);
    -        assert_eq!(
    -            psbt.global.unsigned_tx.output[0].value,
    -            10_000 - details.fee.unwrap_or(0)
    -        );
    -        assert_eq!(psbt.global.unsigned_tx.output[1].value, 10_000);
    -        assert_eq!(psbt.global.unsigned_tx.output[2].value, 30_000);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_default_sighash() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 30_000);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.inputs[0].sighash_type, None);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_custom_sighash() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 30_000)
    -            .sighash(bitcoin::SigHashType::Single);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(
    -            psbt.inputs[0].sighash_type,
    -            Some(bitcoin::SigHashType::Single)
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_input_hd_keypaths() {
    -        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
    -        use std::str::FromStr;
    -
    -        let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.inputs[0].bip32_derivation.len(), 1);
    -        assert_eq!(
    -            psbt.inputs[0].bip32_derivation.values().next().unwrap(),
    -            &(
    -                Fingerprint::from_str("d34db33f").unwrap(),
    -                DerivationPath::from_str("m/44'/0'/0'/0/0").unwrap()
    -            )
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_output_hd_keypaths() {
    -        use bitcoin::util::bip32::{DerivationPath, Fingerprint};
    -        use std::str::FromStr;
    -
    -        let (wallet, descriptors, _) = get_funded_wallet("wpkh([d34db33f/44'/0'/0']tpubDEnoLuPdBep9bzw5LoGYpsxUQYheRQ9gcgrJhJEcdKFB9cWQRyYmkCyRoTqeD4tJYiVVgt6A3rN6rWn9RYhR9sBsGxji29LYWHuKKbdb1ev/0/*)");
    -        // cache some addresses
    -        wallet.get_address(New).unwrap();
    -
    -        let addr = testutils!(@external descriptors, 5);
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.outputs[0].bip32_derivation.len(), 1);
    -        assert_eq!(
    -            psbt.outputs[0].bip32_derivation.values().next().unwrap(),
    -            &(
    -                Fingerprint::from_str("d34db33f").unwrap(),
    -                DerivationPath::from_str("m/44'/0'/0'/0/5").unwrap()
    -            )
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_set_redeem_script_p2sh() {
    -        use bitcoin::hashes::hex::FromHex;
    -
    -        let (wallet, _, _) =
    -            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(
    -            psbt.inputs[0].redeem_script,
    -            Some(Script::from(
    -                Vec::<u8>::from_hex(
    -                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
    -                )
    -                .unwrap()
    -            ))
    -        );
    -        assert_eq!(psbt.inputs[0].witness_script, None);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_set_witness_script_p2wsh() {
    -        use bitcoin::hashes::hex::FromHex;
    -
    -        let (wallet, _, _) =
    -            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.inputs[0].redeem_script, None);
    -        assert_eq!(
    -            psbt.inputs[0].witness_script,
    -            Some(Script::from(
    -                Vec::<u8>::from_hex(
    -                    "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac"
    -                )
    -                .unwrap()
    -            ))
    -        );
    -    }
    -
    -    #[test]
    -    fn test_create_tx_set_redeem_witness_script_p2wsh_p2sh() {
    -        use bitcoin::hashes::hex::FromHex;
    -
    -        let (wallet, _, _) =
    -            get_funded_wallet("sh(wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)))");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        let script = Script::from(
    -            Vec::<u8>::from_hex(
    -                "21032b0558078bec38694a84933d659303e2575dae7e91685911454115bfd64487e3ac",
    -            )
    -            .unwrap(),
    -        );
    -
    -        assert_eq!(psbt.inputs[0].redeem_script, Some(script.to_v0_p2wsh()));
    -        assert_eq!(psbt.inputs[0].witness_script, Some(script));
    -    }
    -
    -    #[test]
    -    fn test_create_tx_non_witness_utxo() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("sh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert!(psbt.inputs[0].non_witness_utxo.is_some());
    -        assert!(psbt.inputs[0].witness_utxo.is_none());
    -    }
    -
    -    #[test]
    -    fn test_create_tx_only_witness_utxo() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .only_witness_utxo()
    -            .drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert!(psbt.inputs[0].non_witness_utxo.is_none());
    -        assert!(psbt.inputs[0].witness_utxo.is_some());
    -    }
    -
    -    #[test]
    -    fn test_create_tx_shwpkh_has_witness_utxo() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("sh(wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert!(psbt.inputs[0].witness_utxo.is_some());
    -    }
    -
    -    #[test]
    -    fn test_create_tx_both_non_witness_utxo_and_witness_utxo_default() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("wsh(pk(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW))");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert!(psbt.inputs[0].non_witness_utxo.is_some());
    -        assert!(psbt.inputs[0].witness_utxo.is_some());
    -    }
    -
    -    #[test]
    -    fn test_create_tx_add_utxo() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let small_output_txid = crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 30_000)
    -            .add_utxo(OutPoint {
    -                txid: small_output_txid,
    -                vout: 0,
    -            })
    -            .unwrap();
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(
    -            psbt.global.unsigned_tx.input.len(),
    -            2,
    -            "should add an additional input since 25_000 < 30_000"
    -        );
    -        assert_eq!(details.sent, 75_000, "total should be sum of both inputs");
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_create_tx_manually_selected_insufficient() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let small_output_txid = crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 30_000)
    -            .add_utxo(OutPoint {
    -                txid: small_output_txid,
    -                vout: 0,
    -            })
    -            .unwrap()
    -            .manually_selected_only();
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "SpendingPolicyRequired(External)")]
    -    fn test_create_tx_policy_path_required() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_a_or_b_plus_csv());
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 30_000);
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_policy_path_no_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_a_or_b_plus_csv());
    -
    -        let external_policy = wallet.policies(KeychainKind::External).unwrap().unwrap();
    -        let root_id = external_policy.id;
    -        // child #0 is just the key "A"
    -        let path = vec![(root_id, vec![0])].into_iter().collect();
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 30_000)
    -            .policy_path(path, KeychainKind::External);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 0xFFFFFFFF);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_policy_path_use_csv() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_a_or_b_plus_csv());
    -
    -        let external_policy = wallet.policies(KeychainKind::External).unwrap().unwrap();
    -        let root_id = external_policy.id;
    -        // child #1 is or(pk(B),older(144))
    -        let path = vec![(root_id, vec![1])].into_iter().collect();
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 30_000)
    -            .policy_path(path, KeychainKind::External);
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        assert_eq!(psbt.global.unsigned_tx.input[0].sequence, 144);
    -    }
    -
    -    #[test]
    -    fn test_create_tx_global_xpubs_with_origin() {
    -        use bitcoin::hashes::hex::FromHex;
    -        use bitcoin::util::base58;
    -        use bitcoin::util::psbt::raw::Key;
    -
    -        let (wallet, _, _) = get_funded_wallet("wpkh([73756c7f/48'/0'/0'/2']tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .add_global_xpubs();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        let type_value = 0x01;
    -        let key = base58::from_check("tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3").unwrap();
    -
    -        let psbt_key = Key { type_value, key };
    -
    -        // This key has an explicit origin, so it will be encoded here
    -        let value_bytes = Vec::<u8>::from_hex("73756c7f30000080000000800000008002000080").unwrap();
    -
    -        assert_eq!(psbt.global.unknown.len(), 1);
    -        assert_eq!(psbt.global.unknown.get(&psbt_key), Some(&value_bytes));
    -    }
    -
    -    #[test]
    -    fn test_add_foreign_utxo() {
    -        let (wallet1, _, _) = get_funded_wallet(get_test_wpkh());
    -        let (wallet2, _, _) =
    -            get_funded_wallet("wpkh(cVbZ8ovhye9AoAHFsqobCf7LxbXDAECy9Kb8TZdfsDYMZGBUyCnm)");
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let utxo = wallet2.list_unspent().unwrap().remove(0);
    -        let foreign_utxo_satisfaction = wallet2
    -            .get_descriptor_for_keychain(KeychainKind::External)
    -            .max_satisfaction_weight()
    -            .unwrap();
    -
    -        let psbt_input = psbt::Input {
    -            witness_utxo: Some(utxo.txout.clone()),
    -            ..Default::default()
    -        };
    -
    -        let mut builder = wallet1.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 60_000)
    -            .only_witness_utxo()
    -            .add_foreign_utxo(utxo.outpoint, psbt_input, foreign_utxo_satisfaction)
    -            .unwrap();
    -        let (mut psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(
    -            details.sent - details.received,
    -            10_000 + details.fee.unwrap_or(0),
    -            "we should have only net spent ~10_000"
    -        );
    -
    -        assert!(
    -            psbt.global
    -                .unsigned_tx
    -                .input
    -                .iter()
    -                .any(|input| input.previous_output == utxo.outpoint),
    -            "foreign_utxo should be in there"
    -        );
    -
    -        let finished = wallet1
    -            .sign(
    -                &mut psbt,
    -                SignOptions {
    -                    trust_witness_utxo: true,
    -                    ..Default::default()
    -                },
    -            )
    -            .unwrap();
    -
    -        assert!(
    -            !finished,
    -            "only one of the inputs should have been signed so far"
    -        );
    -
    -        let finished = wallet2
    -            .sign(
    -                &mut psbt,
    -                SignOptions {
    -                    trust_witness_utxo: true,
    -                    ..Default::default()
    -                },
    -            )
    -            .unwrap();
    -        assert!(finished, "all the inputs should have been signed now");
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "Generic(\"Foreign utxo missing witness_utxo or non_witness_utxo\")")]
    -    fn test_add_foreign_utxo_invalid_psbt_input() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let mut builder = wallet.build_tx();
    -        let outpoint = wallet.list_unspent().unwrap()[0].outpoint;
    -        let foreign_utxo_satisfaction = wallet
    -            .get_descriptor_for_keychain(KeychainKind::External)
    -            .max_satisfaction_weight()
    -            .unwrap();
    -        builder
    -            .add_foreign_utxo(outpoint, psbt::Input::default(), foreign_utxo_satisfaction)
    -            .unwrap();
    -    }
    -
    -    #[test]
    -    fn test_add_foreign_utxo_where_outpoint_doesnt_match_psbt_input() {
    -        let (wallet1, _, txid1) = get_funded_wallet(get_test_wpkh());
    -        let (wallet2, _, txid2) =
    -            get_funded_wallet("wpkh(cVbZ8ovhye9AoAHFsqobCf7LxbXDAECy9Kb8TZdfsDYMZGBUyCnm)");
    -
    -        let utxo2 = wallet2.list_unspent().unwrap().remove(0);
    -        let tx1 = wallet1
    -            .database
    -            .borrow()
    -            .get_tx(&txid1, true)
    -            .unwrap()
    -            .unwrap()
    -            .transaction
    -            .unwrap();
    -        let tx2 = wallet2
    -            .database
    -            .borrow()
    -            .get_tx(&txid2, true)
    -            .unwrap()
    -            .unwrap()
    -            .transaction
    -            .unwrap();
    -
    -        let satisfaction_weight = wallet2
    -            .get_descriptor_for_keychain(KeychainKind::External)
    -            .max_satisfaction_weight()
    -            .unwrap();
    -
    -        let mut builder = wallet1.build_tx();
    -        assert!(
    -            builder
    -                .add_foreign_utxo(
    -                    utxo2.outpoint,
    -                    psbt::Input {
    -                        non_witness_utxo: Some(tx1),
    -                        ..Default::default()
    -                    },
    -                    satisfaction_weight
    -                )
    -                .is_err(),
    -            "should fail when outpoint doesn't match psbt_input"
    -        );
    -        assert!(
    -            builder
    -                .add_foreign_utxo(
    -                    utxo2.outpoint,
    -                    psbt::Input {
    -                        non_witness_utxo: Some(tx2),
    -                        ..Default::default()
    -                    },
    -                    satisfaction_weight
    -                )
    -                .is_ok(),
    -            "shoulld be ok when outpoint does match psbt_input"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_add_foreign_utxo_only_witness_utxo() {
    -        let (wallet1, _, _) = get_funded_wallet(get_test_wpkh());
    -        let (wallet2, _, txid2) =
    -            get_funded_wallet("wpkh(cVbZ8ovhye9AoAHFsqobCf7LxbXDAECy9Kb8TZdfsDYMZGBUyCnm)");
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let utxo2 = wallet2.list_unspent().unwrap().remove(0);
    -
    -        let satisfaction_weight = wallet2
    -            .get_descriptor_for_keychain(KeychainKind::External)
    -            .max_satisfaction_weight()
    -            .unwrap();
    -
    -        let mut builder = wallet1.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 60_000);
    -
    -        {
    -            let mut builder = builder.clone();
    -            let psbt_input = psbt::Input {
    -                witness_utxo: Some(utxo2.txout.clone()),
    -                ..Default::default()
    -            };
    -            builder
    -                .add_foreign_utxo(utxo2.outpoint, psbt_input, satisfaction_weight)
    -                .unwrap();
    -            assert!(
    -                builder.finish().is_err(),
    -                "psbt_input with witness_utxo should fail with only witness_utxo"
    -            );
    -        }
    -
    -        {
    -            let mut builder = builder.clone();
    -            let psbt_input = psbt::Input {
    -                witness_utxo: Some(utxo2.txout.clone()),
    -                ..Default::default()
    -            };
    -            builder
    -                .only_witness_utxo()
    -                .add_foreign_utxo(utxo2.outpoint, psbt_input, satisfaction_weight)
    -                .unwrap();
    -            assert!(
    -                builder.finish().is_ok(),
    -                "psbt_input with just witness_utxo should succeed when `only_witness_utxo` is enabled"
    -            );
    -        }
    -
    -        {
    -            let mut builder = builder.clone();
    -            let tx2 = wallet2
    -                .database
    -                .borrow()
    -                .get_tx(&txid2, true)
    -                .unwrap()
    -                .unwrap()
    -                .transaction
    -                .unwrap();
    -            let psbt_input = psbt::Input {
    -                non_witness_utxo: Some(tx2),
    -                ..Default::default()
    -            };
    -            builder
    -                .add_foreign_utxo(utxo2.outpoint, psbt_input, satisfaction_weight)
    -                .unwrap();
    -            assert!(
    -                builder.finish().is_ok(),
    -                "psbt_input with non_witness_utxo should succeed by default"
    -            );
    -        }
    -    }
    -
    -    #[test]
    -    fn test_get_psbt_input() {
    -        // this should grab a known good utxo and set the input
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        for utxo in wallet.list_unspent().unwrap() {
    -            let psbt_input = wallet.get_psbt_input(utxo, None, false).unwrap();
    -            assert!(psbt_input.witness_utxo.is_some() || psbt_input.non_witness_utxo.is_some());
    -        }
    -    }
    -
    -    #[test]
    -    #[should_panic(
    -        expected = "MissingKeyOrigin(\"tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3\")"
    -    )]
    -    fn test_create_tx_global_xpubs_origin_missing() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tpubDCKxNyM3bLgbEX13Mcd8mYxbVg9ajDkWXMh29hMWBurKfVmBfWAM96QVP3zaUcN51HvkZ3ar4VwP82kC8JZhhux8vFQoJintSpVBwpFvyU3/0/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .add_global_xpubs();
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_create_tx_global_xpubs_master_without_origin() {
    -        use bitcoin::hashes::hex::FromHex;
    -        use bitcoin::util::base58;
    -        use bitcoin::util::psbt::raw::Key;
    -
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL/0/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .add_global_xpubs();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        let type_value = 0x01;
    -        let key = base58::from_check("tpubD6NzVbkrYhZ4Y55A58Gv9RSNF5hy84b5AJqYy7sCcjFrkcLpPre8kmgfit6kY1Zs3BLgeypTDBZJM222guPpdz7Cup5yzaMu62u7mYGbwFL").unwrap();
    -
    -        let psbt_key = Key { type_value, key };
    -
    -        // This key doesn't have an explicit origin, but it's a master key (depth = 0). So we encode
    -        // its fingerprint directly and an empty path
    -        let value_bytes = Vec::<u8>::from_hex("997a323b").unwrap();
    -
    -        assert_eq!(psbt.global.unknown.len(), 1);
    -        assert_eq!(psbt.global.unknown.get(&psbt_key), Some(&value_bytes));
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "IrreplaceableTransaction")]
    -    fn test_bump_fee_irreplaceable_tx() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, mut details) = builder.finish().unwrap();
    -
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        wallet.build_fee_bump(txid).unwrap().finish().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "TransactionConfirmed")]
    -    fn test_bump_fee_confirmed_tx() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.add_recipient(addr.script_pubkey(), 25_000);
    -        let (psbt, mut details) = builder.finish().unwrap();
    -
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        details.confirmation_time = Some(ConfirmationTime {
    -            timestamp: 12345678,
    -            height: 42,
    -        });
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        wallet.build_fee_bump(txid).unwrap().finish().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "FeeRateTooLow")]
    -    fn test_bump_fee_low_fee_rate() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf();
    -        let (psbt, mut details) = builder.finish().unwrap();
    -
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_rate(FeeRate::from_sat_per_vb(1.0));
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "FeeTooLow")]
    -    fn test_bump_fee_low_abs() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf();
    -        let (psbt, mut details) = builder.finish().unwrap();
    -
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_absolute(10);
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "FeeTooLow")]
    -    fn test_bump_fee_zero_abs() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf();
    -        let (psbt, mut details) = builder.finish().unwrap();
    -
    -        let tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the utxos, we know they can't be used anyways
    -        details.transaction = Some(tx);
    -        wallet.database.borrow_mut().set_tx(&details).unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_absolute(0);
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_reduce_change() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_rate(FeeRate::from_sat_per_vb(2.5)).enable_rbf();
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent);
    -        assert_eq!(
    -            details.received + details.fee.unwrap_or(0),
    -            original_details.received + original_details.fee.unwrap_or(0)
    -        );
    -        assert!(details.fee.unwrap_or(0) > original_details.fee.unwrap_or(0));
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            25_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(2.5), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_absolute_reduce_change() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 25_000)
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_absolute(200);
    -        builder.enable_rbf();
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent);
    -        assert_eq!(
    -            details.received + details.fee.unwrap_or(0),
    -            original_details.received + original_details.fee.unwrap_or(0)
    -        );
    -        assert!(
    -            details.fee.unwrap_or(0) > original_details.fee.unwrap_or(0),
    -            "{} > {}",
    -            details.fee.unwrap_or(0),
    -            original_details.fee.unwrap_or(0)
    -        );
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            25_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_eq!(details.fee.unwrap_or(0), 200);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_reduce_single_recipient() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .drain_wallet()
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder
    -            .fee_rate(FeeRate::from_sat_per_vb(2.5))
    -            .allow_shrinking(addr.script_pubkey())
    -            .unwrap();
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent);
    -        assert!(details.fee.unwrap_or(0) > original_details.fee.unwrap_or(0));
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.output.len(), 1);
    -        assert_eq!(tx.output[0].value + details.fee.unwrap_or(0), details.sent);
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(2.5), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_absolute_reduce_single_recipient() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .drain_wallet()
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder
    -            .allow_shrinking(addr.script_pubkey())
    -            .unwrap()
    -            .fee_absolute(300);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent);
    -        assert!(details.fee.unwrap_or(0) > original_details.fee.unwrap_or(0));
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.output.len(), 1);
    -        assert_eq!(tx.output[0].value + details.fee.unwrap_or(0), details.sent);
    -
    -        assert_eq!(details.fee.unwrap_or(0), 300);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_drain_wallet() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        // receive an extra tx so that our wallet has two utxos.
    -        let incoming_txid = crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -        let outpoint = OutPoint {
    -            txid: incoming_txid,
    -            vout: 0,
    -        };
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .add_utxo(outpoint)
    -            .unwrap()
    -            .manually_selected_only()
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -        assert_eq!(original_details.sent, 25_000);
    -
    -        // for the new feerate, it should be enough to reduce the output, but since we specify
    -        // `drain_wallet` we expect to spend everything
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder
    -            .drain_wallet()
    -            .allow_shrinking(addr.script_pubkey())
    -            .unwrap()
    -            .fee_rate(FeeRate::from_sat_per_vb(5.0));
    -        let (_, details) = builder.finish().unwrap();
    -        assert_eq!(details.sent, 75_000);
    -    }
    -
    -    #[test]
    -    #[should_panic(expected = "InsufficientFunds")]
    -    fn test_bump_fee_remove_output_manually_selected_only() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        // receive an extra tx so that our wallet has two utxos. then we manually pick only one of
    -        // them, and make sure that `bump_fee` doesn't try to add more. This fails because we've
    -        // told the wallet it's not allowed to add more inputs AND it can't reduce the value of the
    -        // existing output. In other words, bump_fee + manually_selected_only is always an error
    -        // unless you've also set "allow_shrinking" OR there is a change output.
    -        let incoming_txid = crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -        let outpoint = OutPoint {
    -            txid: incoming_txid,
    -            vout: 0,
    -        };
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .add_utxo(outpoint)
    -            .unwrap()
    -            .manually_selected_only()
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -        assert_eq!(original_details.sent, 25_000);
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder
    -            .manually_selected_only()
    -            .fee_rate(FeeRate::from_sat_per_vb(255.0));
    -        builder.finish().unwrap();
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_add_input() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 45_000)
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_rate(FeeRate::from_sat_per_vb(50.0));
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fee.unwrap_or(0) + details.received, 30_000);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(50.0), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_absolute_add_input() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 45_000)
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_absolute(6_000);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fee.unwrap_or(0) + details.received, 30_000);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_eq!(details.fee.unwrap_or(0), 6_000);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_no_change_add_input_and_change() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let incoming_txid = crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        // initially make a tx without change by using `drain_to`
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .add_utxo(OutPoint {
    -                txid: incoming_txid,
    -                vout: 0,
    -            })
    -            .unwrap()
    -            .manually_selected_only()
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        // now bump the fees without using `allow_shrinking`. the wallet should add an
    -        // extra input and a change output, and leave the original output untouched
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_rate(FeeRate::from_sat_per_vb(50.0));
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        let original_send_all_amount = original_details.sent - original_details.fee.unwrap_or(0);
    -        assert_eq!(details.sent, original_details.sent + 50_000);
    -        assert_eq!(
    -            details.received,
    -            75_000 - original_send_all_amount - details.fee.unwrap_or(0)
    -        );
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            original_send_all_amount
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            75_000 - original_send_all_amount - details.fee.unwrap_or(0)
    -        );
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(50.0), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_add_input_change_dust() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 45_000)
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        assert_eq!(tx.input.len(), 1);
    -        assert_eq!(tx.output.len(), 2);
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder.fee_rate(FeeRate::from_sat_per_vb(140.0));
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(
    -            original_details.received,
    -            5_000 - original_details.fee.unwrap_or(0)
    -        );
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fee.unwrap_or(0), 30_000);
    -        assert_eq!(details.received, 0);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 1);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(140.0), @dust_change, @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_force_add_input() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let incoming_txid = crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 45_000)
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        // the new fee_rate is low enough that just reducing the change would be fine, but we force
    -        // the addition of an extra input with `add_utxo()`
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder
    -            .add_utxo(OutPoint {
    -                txid: incoming_txid,
    -                vout: 0,
    -            })
    -            .unwrap()
    -            .fee_rate(FeeRate::from_sat_per_vb(5.0));
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fee.unwrap_or(0) + details.received, 30_000);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_fee_rate!(psbt.extract_tx(), details.fee.unwrap_or(0), FeeRate::from_sat_per_vb(5.0), @add_signature);
    -    }
    -
    -    #[test]
    -    fn test_bump_fee_absolute_force_add_input() {
    -        let (wallet, descriptors, _) = get_funded_wallet(get_test_wpkh());
    -        let incoming_txid = crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 45_000)
    -            .enable_rbf();
    -        let (psbt, mut original_details) = builder.finish().unwrap();
    -        let mut tx = psbt.extract_tx();
    -        let txid = tx.txid();
    -        // skip saving the new utxos, we know they can't be used anyways
    -        for txin in &mut tx.input {
    -            txin.witness.push([0x00; 108].to_vec()); // fake signature
    -            wallet
    -                .database
    -                .borrow_mut()
    -                .del_utxo(&txin.previous_output)
    -                .unwrap();
    -        }
    -        original_details.transaction = Some(tx);
    -        wallet
    -            .database
    -            .borrow_mut()
    -            .set_tx(&original_details)
    -            .unwrap();
    -
    -        // the new fee_rate is low enough that just reducing the change would be fine, but we force
    -        // the addition of an extra input with `add_utxo()`
    -        let mut builder = wallet.build_fee_bump(txid).unwrap();
    -        builder
    -            .add_utxo(OutPoint {
    -                txid: incoming_txid,
    -                vout: 0,
    -            })
    -            .unwrap()
    -            .fee_absolute(250);
    -        let (psbt, details) = builder.finish().unwrap();
    -
    -        assert_eq!(details.sent, original_details.sent + 25_000);
    -        assert_eq!(details.fee.unwrap_or(0) + details.received, 30_000);
    -
    -        let tx = &psbt.global.unsigned_tx;
    -        assert_eq!(tx.input.len(), 2);
    -        assert_eq!(tx.output.len(), 2);
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey == addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            45_000
    -        );
    -        assert_eq!(
    -            tx.output
    -                .iter()
    -                .find(|txout| txout.script_pubkey != addr.script_pubkey())
    -                .unwrap()
    -                .value,
    -            details.received
    -        );
    -
    -        assert_eq!(details.fee.unwrap_or(0), 250);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_xprv() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
    -        assert!(finalized);
    -
    -        let extracted = psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_xprv_with_master_fingerprint_and_path() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh([d34db33f/84h/1h/0h]tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
    -        assert!(finalized);
    -
    -        let extracted = psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_xprv_bip44_path() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/44'/0'/0'/0/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
    -        assert!(finalized);
    -
    -        let extracted = psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_xprv_sh_wpkh() {
    -        let (wallet, _, _) = get_funded_wallet("sh(wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*))");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
    -        assert!(finalized);
    -
    -        let extracted = psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_wif() {
    -        let (wallet, _, _) =
    -            get_funded_wallet("wpkh(cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
    -        assert!(finalized);
    -
    -        let extracted = psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_sign_single_xprv_no_hd_keypaths() {
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder.drain_to(addr.script_pubkey()).drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        psbt.inputs[0].bip32_derivation.clear();
    -        assert_eq!(psbt.inputs[0].bip32_derivation.len(), 0);
    -
    -        let finalized = wallet.sign(&mut psbt, Default::default()).unwrap();
    -        assert!(finalized);
    -
    -        let extracted = psbt.extract_tx();
    -        assert_eq!(extracted.input[0].witness.len(), 2);
    -    }
    -
    -    #[test]
    -    fn test_include_output_redeem_witness_script() {
    -        let (wallet, _, _) = get_funded_wallet("sh(wsh(multi(1,cVpPVruEDdmutPzisEsYvtST1usBR3ntr8pXSyt6D2YYqXRyPcFW,cRjo6jqfVNP33HhSS76UhXETZsGTZYx8FMFvR9kpbtCSV1PmdZdu)))");
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 45_000)
    -            .include_output_redeem_witness_script();
    -        let (psbt, _) = builder.finish().unwrap();
    -
    -        // p2sh-p2wsh transaction should contain both witness and redeem scripts
    -        assert!(psbt
    -            .outputs
    -            .iter()
    -            .any(|output| output.redeem_script.is_some() && output.witness_script.is_some()));
    -    }
    -
    -    #[test]
    -    fn test_signing_only_one_of_multiple_inputs() {
    -        let (wallet, _, _) = get_funded_wallet(get_test_wpkh());
    -        let addr = Address::from_str("2N1Ffz3WaNzbeLFBb51xyFMHYSEUXcbiSoX").unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .add_recipient(addr.script_pubkey(), 45_000)
    -            .include_output_redeem_witness_script();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        // add another input to the psbt that is at least passable.
    -        let dud_input = bitcoin::util::psbt::Input {
    -            witness_utxo: Some(TxOut {
    -                value: 100_000,
    -                script_pubkey: miniscript::Descriptor::<bitcoin::PublicKey>::from_str(
    -                    "wpkh(025476c2e83188368da1ff3e292e7acafcdb3566bb0ad253f62fc70f07aeee6357)",
    -                )
    -                .unwrap()
    -                .script_pubkey(),
    -            }),
    -            ..Default::default()
    -        };
    -
    -        psbt.inputs.push(dud_input);
    -        psbt.global.unsigned_tx.input.push(bitcoin::TxIn::default());
    -        let is_final = wallet
    -            .sign(
    -                &mut psbt,
    -                SignOptions {
    -                    trust_witness_utxo: true,
    -                    ..Default::default()
    -                },
    -            )
    -            .unwrap();
    -        assert!(
    -            !is_final,
    -            "shouldn't be final since we can't sign one of the inputs"
    -        );
    -        assert!(
    -            psbt.inputs[0].final_script_witness.is_some(),
    -            "should finalized input it signed"
    -        )
    -    }
    -
    -    #[test]
    -    fn test_sign_nonstandard_sighash() {
    -        let sighash = SigHashType::NonePlusAnyoneCanPay;
    -
    -        let (wallet, _, _) = get_funded_wallet("wpkh(tprv8ZgxMBicQKsPd3EupYiPRhaMooHKUHJxNsTfYuScep13go8QFfHdtkG9nRkFGb7busX4isf6X9dURGCoKgitaApQ6MupRhZMcELAxTBRJgS/*)");
    -        let addr = wallet.get_address(New).unwrap();
    -        let mut builder = wallet.build_tx();
    -        builder
    -            .drain_to(addr.script_pubkey())
    -            .sighash(sighash)
    -            .drain_wallet();
    -        let (mut psbt, _) = builder.finish().unwrap();
    -
    -        let result = wallet.sign(&mut psbt, Default::default());
    -        assert!(
    -            result.is_err(),
    -            "Signing should have failed because the TX uses non-standard sighashes"
    -        );
    -        assert!(
    -            matches!(
    -                result.unwrap_err(),
    -                Error::Signer(SignerError::NonStandardSighash)
    -            ),
    -            "Signing failed with the wrong error type"
    -        );
    -
    -        // try again after opting-in
    -        let result = wallet.sign(
    -            &mut psbt,
    -            SignOptions {
    -                allow_all_sighashes: true,
    -                ..Default::default()
    -            },
    -        );
    -        assert!(result.is_ok(), "Signing should have worked");
    -        assert!(
    -            result.unwrap(),
    -            "Should finalize the input since we can produce signatures"
    -        );
    -
    -        let extracted = psbt.extract_tx();
    -        assert_eq!(
    -            *extracted.input[0].witness[0].last().unwrap(),
    -            sighash.as_u32() as u8,
    -            "The signature should have been made with the right sighash"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_unused_address() {
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)",
    -                                         None, Network::Testnet, db).unwrap();
    -
    -        assert_eq!(
    -            wallet.get_address(LastUnused).unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -        assert_eq!(
    -            wallet.get_address(LastUnused).unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_next_unused_address() {
    -        let descriptor = "wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)";
    -        let descriptors = testutils!(@descriptors (descriptor));
    -        let wallet = Wallet::new_offline(
    -            &descriptors.0,
    -            None,
    -            Network::Testnet,
    -            MemoryDatabase::new(),
    -        )
    -        .unwrap();
    -
    -        assert_eq!(
    -            wallet.get_address(LastUnused).unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -
    -        // use the above address
    -        crate::populate_test_db!(
    -            wallet.database.borrow_mut(),
    -            testutils! (@tx ( (@external descriptors, 0) => 25_000 ) (@confirmations 1)),
    -            Some(100),
    -        );
    -
    -        assert_eq!(
    -            wallet.get_address(LastUnused).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_peek_address_at_index() {
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)",
    -                                         None, Network::Testnet, db).unwrap();
    -
    -        assert_eq!(
    -            wallet.get_address(Peek(1)).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -
    -        assert_eq!(
    -            wallet.get_address(Peek(0)).unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -
    -        assert_eq!(
    -            wallet.get_address(Peek(2)).unwrap().to_string(),
    -            "tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2"
    -        );
    -
    -        // current new address is not affected
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_peek_address_at_index_not_derivable() {
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/1)",
    -                                         None, Network::Testnet, db).unwrap();
    -
    -        assert_eq!(
    -            wallet.get_address(Peek(1)).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -
    -        assert_eq!(
    -            wallet.get_address(Peek(0)).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -
    -        assert_eq!(
    -            wallet.get_address(Peek(2)).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_reset_address_index() {
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)",
    -                                         None, Network::Testnet, db).unwrap();
    -
    -        // new index 0
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a"
    -        );
    -
    -        // new index 1
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -
    -        // new index 2
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2"
    -        );
    -
    -        //  reset index 1 again
    -        assert_eq!(
    -            wallet.get_address(Reset(1)).unwrap().to_string(),
    -            "tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7"
    -        );
    -
    -        // new index 2 again
    -        assert_eq!(
    -            wallet.get_address(New).unwrap().to_string(),
    -            "tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2"
    -        );
    -    }
    -
    -    #[test]
    -    fn test_returns_index_and_address() {
    -        let db = MemoryDatabase::new();
    -        let wallet = Wallet::new_offline("wpkh(tpubEBr4i6yk5nf5DAaJpsi9N2pPYBeJ7fZ5Z9rmN4977iYLCGco1VyjB9tvvuvYtfZzjD5A8igzgw3HeWeeKFmanHYqksqZXYXGsw5zjnj7KM9/*)",
    -                                         None, Network::Testnet, db).unwrap();
    -
    -        // new index 0
    -        assert_eq!(
    -            wallet.get_address(New).unwrap(),
    -            AddressInfo {
    -                index: 0,
    -                address: Address::from_str("tb1q6yn66vajcctph75pvylgkksgpp6nq04ppwct9a").unwrap(),
    -            }
    -        );
    -
    -        // new index 1
    -        assert_eq!(
    -            wallet.get_address(New).unwrap(),
    -            AddressInfo {
    -                index: 1,
    -                address: Address::from_str("tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7").unwrap()
    -            }
    -        );
    -
    -        // peek index 25
    -        assert_eq!(
    -            wallet.get_address(Peek(25)).unwrap(),
    -            AddressInfo {
    -                index: 25,
    -                address: Address::from_str("tb1qsp7qu0knx3sl6536dzs0703u2w2ag6ppl9d0c2").unwrap()
    -            }
    -        );
    -
    -        // new index 2
    -        assert_eq!(
    -            wallet.get_address(New).unwrap(),
    -            AddressInfo {
    -                index: 2,
    -                address: Address::from_str("tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2").unwrap()
    -            }
    -        );
    -
    -        //  reset index 1 again
    -        assert_eq!(
    -            wallet.get_address(Reset(1)).unwrap(),
    -            AddressInfo {
    -                index: 1,
    -                address: Address::from_str("tb1q4er7kxx6sssz3q7qp7zsqsdx4erceahhax77d7").unwrap()
    -            }
    -        );
    -
    -        // new index 2 again
    -        assert_eq!(
    -            wallet.get_address(New).unwrap(),
    -            AddressInfo {
    -                index: 2,
    -                address: Address::from_str("tb1qzntf2mqex4ehwkjlfdyy3ewdlk08qkvkvrz7x2").unwrap()
    -            }
    -        );
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/signer.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/signer.rs.html deleted file mode 100644 index 77838e7d8e..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/signer.rs.html +++ /dev/null @@ -1,1536 +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
    -
    // 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 std::sync::Arc;
    -//! # use std::str::FromStr;
    -//! # use bitcoin::secp256k1::{Secp256k1, All};
    -//! # use bitcoin::*;
    -//! # use bitcoin::util::psbt;
    -//! # use bdk::signer::*;
    -//! # use bdk::database::*;
    -//! # use bdk::*;
    -//! # #[derive(Debug)]
    -//! # struct CustomHSM;
    -//! # impl CustomHSM {
    -//! #     fn sign_input(&self, _psbt: &mut psbt::PartiallySignedTransaction, _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 Signer for CustomSigner {
    -//!     fn sign(
    -//!         &self,
    -//!         psbt: &mut psbt::PartiallySignedTransaction,
    -//!         input_index: Option<usize>,
    -//!         _secp: &Secp256k1<All>,
    -//!     ) -> Result<(), SignerError> {
    -//!         let input_index = input_index.ok_or(SignerError::InputIndexOutOfRange)?;
    -//!         self.device.sign_input(psbt, input_index)?;
    -//!
    -//!         Ok(())
    -//!     }
    -//!
    -//!     fn id(&self, _secp: &Secp256k1<All>) -> SignerId {
    -//!         self.device.get_id()
    -//!     }
    -//!
    -//!     fn sign_whole_tx(&self) -> bool {
    -//!         false
    -//!     }
    -//! }
    -//!
    -//! let custom_signer = CustomSigner::connect();
    -//!
    -//! let descriptor = "wpkh(tpubD6NzVbkrYhZ4Xferm7Pz4VnjdcDPFyjVu5K4iZXQ4pVN8Cks4pHVowTBXBKRhX64pkRyJZJN5xAKj4UDNnLPb5p2sSKXhewoYx5GbTdUFWq/*)";
    -//! let mut wallet = Wallet::new_offline(descriptor, None, Network::Testnet, MemoryDatabase::default())?;
    -//! wallet.add_signer(
    -//!     KeychainKind::External,
    -//!     SignerOrdering(200),
    -//!     Arc::new(custom_signer)
    -//! );
    -//!
    -//! # Ok::<_, bdk::Error>(())
    -//! ```
    -
    -use std::cmp::Ordering;
    -use std::collections::BTreeMap;
    -use std::fmt;
    -use std::ops::Bound::Included;
    -use std::sync::Arc;
    -
    -use bitcoin::blockdata::opcodes;
    -use bitcoin::blockdata::script::Builder as ScriptBuilder;
    -use bitcoin::hashes::{hash160, Hash};
    -use bitcoin::secp256k1::{Message, Secp256k1};
    -use bitcoin::util::bip32::{ChildNumber, DerivationPath, ExtendedPrivKey, Fingerprint};
    -use bitcoin::util::{bip143, psbt};
    -use bitcoin::{PrivateKey, Script, SigHash, SigHashType};
    -
    -use miniscript::descriptor::{DescriptorSecretKey, DescriptorSinglePriv, DescriptorXKey, KeyMap};
    -use miniscript::{Legacy, MiniscriptKey, Segwitv0};
    -
    -use super::utils::SecpCtx;
    -use crate::descriptor::XKeyUtils;
    -
    -/// 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, PartialEq, Eq, Clone)]
    -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 requied 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,
    -}
    -
    -impl fmt::Display for SignerError {
    -    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
    -        write!(f, "{:?}", self)
    -    }
    -}
    -
    -impl std::error::Error for SignerError {}
    -
    -/// Trait for signers
    -///
    -/// This trait can be implemented to provide customized signers to the wallet. For an example see
    -/// [`this module`](crate::wallet::signer)'s documentation.
    -pub trait Signer: fmt::Debug + Send + Sync {
    -    /// Sign a PSBT
    -    ///
    -    /// The `input_index` argument is only provided if the wallet doesn't declare to sign the whole
    -    /// transaction in one go (see [`Signer::sign_whole_tx`]). Otherwise its value is `None` and
    -    /// can be ignored.
    -    fn sign(
    -        &self,
    -        psbt: &mut psbt::PartiallySignedTransaction,
    -        input_index: Option<usize>,
    -        secp: &SecpCtx,
    -    ) -> Result<(), SignerError>;
    -
    -    /// Return whether or not the signer signs the whole transaction in one go instead of every
    -    /// input individually
    -    fn sign_whole_tx(&self) -> bool;
    -
    -    /// 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
    -    }
    -}
    -
    -impl Signer for DescriptorXKey<ExtendedPrivKey> {
    -    fn sign(
    -        &self,
    -        psbt: &mut psbt::PartiallySignedTransaction,
    -        input_index: Option<usize>,
    -        secp: &SecpCtx,
    -    ) -> Result<(), SignerError> {
    -        let input_index = input_index.unwrap();
    -        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 (public_key, full_path) = match psbt.inputs[input_index]
    -            .bip32_derivation
    -            .iter()
    -            .filter_map(|(pk, &(fingerprint, ref path))| {
    -                if self.matches(&(fingerprint, path.clone()), secp).is_some() {
    -                    Some((pk, path))
    -                } else {
    -                    None
    -                }
    -            })
    -            .next()
    -        {
    -            Some((pk, full_path)) => (pk, full_path.clone()),
    -            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(),
    -        };
    -
    -        if &derived_key.private_key.public_key(secp) != public_key {
    -            Err(SignerError::InvalidKey)
    -        } else {
    -            derived_key.private_key.sign(psbt, Some(input_index), secp)
    -        }
    -    }
    -
    -    fn sign_whole_tx(&self) -> bool {
    -        false
    -    }
    -
    -    fn id(&self, secp: &SecpCtx) -> SignerId {
    -        SignerId::from(self.root_fingerprint(secp))
    -    }
    -
    -    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
    -        Some(DescriptorSecretKey::XPrv(self.clone()))
    -    }
    -}
    -
    -impl Signer for PrivateKey {
    -    fn sign(
    -        &self,
    -        psbt: &mut psbt::PartiallySignedTransaction,
    -        input_index: Option<usize>,
    -        secp: &SecpCtx,
    -    ) -> Result<(), SignerError> {
    -        let input_index = input_index.unwrap();
    -        if input_index >= psbt.inputs.len() || input_index >= psbt.global.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 = self.public_key(secp);
    -        if psbt.inputs[input_index].partial_sigs.contains_key(&pubkey) {
    -            return Ok(());
    -        }
    -
    -        // FIXME: use the presence of `witness_utxo` as an indication that we should make a bip143
    -        // sig. Does this make sense? Should we add an extra argument to explicitly swith between
    -        // these? The original idea was to declare sign() as sign<Ctx: ScriptContex>() and use Ctx,
    -        // but that violates the rules for trait-objects, so we can't do it.
    -        let (hash, sighash) = match psbt.inputs[input_index].witness_utxo {
    -            Some(_) => Segwitv0::sighash(psbt, input_index)?,
    -            None => Legacy::sighash(psbt, input_index)?,
    -        };
    -
    -        let signature = secp.sign(
    -            &Message::from_slice(&hash.into_inner()[..]).unwrap(),
    -            &self.key,
    -        );
    -
    -        let mut final_signature = Vec::with_capacity(75);
    -        final_signature.extend_from_slice(&signature.serialize_der());
    -        final_signature.push(sighash.as_u32() as u8);
    -
    -        psbt.inputs[input_index]
    -            .partial_sigs
    -            .insert(pubkey, final_signature);
    -
    -        Ok(())
    -    }
    -
    -    fn sign_whole_tx(&self) -> bool {
    -        false
    -    }
    -
    -    fn id(&self, secp: &SecpCtx) -> SignerId {
    -        SignerId::from(self.public_key(secp).to_pubkeyhash())
    -    }
    -
    -    fn descriptor_secret_key(&self) -> Option<DescriptorSecretKey> {
    -        Some(DescriptorSecretKey::SinglePriv(DescriptorSinglePriv {
    -            key: *self,
    -            origin: None,
    -        }))
    -    }
    -}
    -
    -/// 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 std::default::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 Signer>>);
    -
    -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.as_public(secp).ok().map(|public| (public, secret)))
    -            .collect()
    -    }
    -}
    -
    -impl From<KeyMap> for SignersContainer {
    -    fn from(keymap: KeyMap) -> SignersContainer {
    -        let secp = Secp256k1::new();
    -        let mut container = SignersContainer::new();
    -
    -        for (_, secret) in keymap {
    -            match secret {
    -                DescriptorSecretKey::SinglePriv(private_key) => container.add_external(
    -                    SignerId::from(private_key.key.public_key(&secp).to_pubkeyhash()),
    -                    SignerOrdering::default(),
    -                    Arc::new(private_key.key),
    -                ),
    -                DescriptorSecretKey::XPrv(xprv) => container.add_external(
    -                    SignerId::from(xprv.root_fingerprint(&secp)),
    -                    SignerOrdering::default(),
    -                    Arc::new(xprv),
    -                ),
    -            };
    -        }
    -
    -        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 Signer>,
    -    ) -> Option<Arc<dyn Signer>> {
    -        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 Signer>> {
    -        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 Signer>> {
    -        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 Signer>> {
    -        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 chould 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,
    -}
    -
    -impl Default for SignOptions {
    -    fn default() -> Self {
    -        SignOptions {
    -            trust_witness_utxo: false,
    -            assume_height: None,
    -            allow_all_sighashes: false,
    -        }
    -    }
    -}
    -
    -pub(crate) trait ComputeSighash {
    -    fn sighash(
    -        psbt: &psbt::PartiallySignedTransaction,
    -        input_index: usize,
    -    ) -> Result<(SigHash, SigHashType), SignerError>;
    -}
    -
    -impl ComputeSighash for Legacy {
    -    fn sighash(
    -        psbt: &psbt::PartiallySignedTransaction,
    -        input_index: usize,
    -    ) -> Result<(SigHash, SigHashType), SignerError> {
    -        if input_index >= psbt.inputs.len() || input_index >= psbt.global.unsigned_tx.input.len() {
    -            return Err(SignerError::InputIndexOutOfRange);
    -        }
    -
    -        let psbt_input = &psbt.inputs[input_index];
    -        let tx_input = &psbt.global.unsigned_tx.input[input_index];
    -
    -        let sighash = psbt_input.sighash_type.unwrap_or(SigHashType::All);
    -        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((
    -            psbt.global
    -                .unsigned_tx
    -                .signature_hash(input_index, &script, sighash.as_u32()),
    -            sighash,
    -        ))
    -    }
    -}
    -
    -fn p2wpkh_script_code(script: &Script) -> Script {
    -    ScriptBuilder::new()
    -        .push_opcode(opcodes::all::OP_DUP)
    -        .push_opcode(opcodes::all::OP_HASH160)
    -        .push_slice(&script[2..])
    -        .push_opcode(opcodes::all::OP_EQUALVERIFY)
    -        .push_opcode(opcodes::all::OP_CHECKSIG)
    -        .into_script()
    -}
    -
    -impl ComputeSighash for Segwitv0 {
    -    fn sighash(
    -        psbt: &psbt::PartiallySignedTransaction,
    -        input_index: usize,
    -    ) -> Result<(SigHash, SigHashType), SignerError> {
    -        if input_index >= psbt.inputs.len() || input_index >= psbt.global.unsigned_tx.input.len() {
    -            return Err(SignerError::InputIndexOutOfRange);
    -        }
    -
    -        let psbt_input = &psbt.inputs[input_index];
    -        let tx_input = &psbt.global.unsigned_tx.input[input_index];
    -
    -        let sighash = psbt_input.sighash_type.unwrap_or(SigHashType::All);
    -
    -        // 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 script = match psbt_input.witness_script {
    -            Some(ref witness_script) => witness_script.clone(),
    -            None => {
    -                if utxo.script_pubkey.is_v0_p2wpkh() {
    -                    p2wpkh_script_code(&utxo.script_pubkey)
    -                } else if psbt_input
    -                    .redeem_script
    -                    .as_ref()
    -                    .map(Script::is_v0_p2wpkh)
    -                    .unwrap_or(false)
    -                {
    -                    p2wpkh_script_code(psbt_input.redeem_script.as_ref().unwrap())
    -                } else {
    -                    return Err(SignerError::MissingWitnessScript);
    -                }
    -            }
    -        };
    -
    -        Ok((
    -            bip143::SigHashCache::new(&psbt.global.unsigned_tx).signature_hash(
    -                input_index,
    -                &script,
    -                value,
    -                sighash,
    -            ),
    -            sighash,
    -        ))
    -    }
    -}
    -
    -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 bitcoin::secp256k1::{All, Secp256k1};
    -    use bitcoin::util::bip32;
    -    use bitcoin::util::psbt::PartiallySignedTransaction;
    -    use bitcoin::Network;
    -    use miniscript::ScriptContext;
    -    use std::str::FromStr;
    -
    -    fn is_equal(this: &Arc<dyn Signer>, 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 (_, keymap) = desc
    -            .into_wallet_descriptor(&secp, Network::Testnet)
    -            .unwrap();
    -
    -        let signers = SignersContainer::from(keymap);
    -        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 Signer for DummySigner {
    -        fn sign(
    -            &self,
    -            _psbt: &mut PartiallySignedTransaction,
    -            _input_index: Option<usize>,
    -            _secp: &SecpCtx,
    -        ) -> Result<(), SignerError> {
    -            Ok(())
    -        }
    -
    -        fn id(&self, _secp: &SecpCtx) -> SignerId {
    -            SignerId::Dummy(self.number)
    -        }
    -
    -        fn sign_whole_tx(&self) -> bool {
    -            true
    -        }
    -    }
    -
    -    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::ExtendedPrivKey::from_str(tprv).unwrap();
    -        let tpub = bip32::ExtendedPubKey::from_private(&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/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/time.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/time.rs.html deleted file mode 100644 index 48832d0f43..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/time.rs.html +++ /dev/null @@ -1,150 +0,0 @@ -time.rs - source
     1
    - 2
    - 3
    - 4
    - 5
    - 6
    - 7
    - 8
    - 9
    -10
    -11
    -12
    -13
    -14
    -15
    -16
    -17
    -18
    -19
    -20
    -21
    -22
    -23
    -24
    -25
    -26
    -27
    -28
    -29
    -30
    -31
    -32
    -33
    -34
    -35
    -36
    -37
    -38
    -39
    -40
    -41
    -42
    -43
    -44
    -45
    -46
    -47
    -48
    -49
    -50
    -51
    -52
    -53
    -54
    -55
    -56
    -57
    -58
    -59
    -60
    -61
    -62
    -63
    -64
    -65
    -66
    -67
    -68
    -69
    -70
    -71
    -72
    -73
    -
    // Bitcoin Dev Kit
    -// Written in 2020 by Alekos Filini <alekos.filini@gmail.com>
    -//
    -// Copyright (c) 2020-2021 Bitcoin Dev Kit Developers
    -//
    -// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
    -// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
    -// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
    -// You may not use this file except in accordance with one or both of these
    -// licenses.
    -
    -//! Cross-platform time
    -//!
    -//! This module provides a function to get the current timestamp that works on all the platforms
    -//! supported by the library.
    -//!
    -//! It can be useful to compare it with the timestamps found in
    -//! [`TransactionDetails`](crate::types::TransactionDetails).
    -
    -use std::time::Duration;
    -
    -#[cfg(target_arch = "wasm32")]
    -use js_sys::Date;
    -#[cfg(not(target_arch = "wasm32"))]
    -use std::time::{Instant as SystemInstant, SystemTime, UNIX_EPOCH};
    -
    -/// Return the current timestamp in seconds
    -#[cfg(not(target_arch = "wasm32"))]
    -pub fn get_timestamp() -> u64 {
    -    SystemTime::now()
    -        .duration_since(UNIX_EPOCH)
    -        .unwrap()
    -        .as_secs()
    -}
    -/// Return the current timestamp in seconds
    -#[cfg(target_arch = "wasm32")]
    -pub fn get_timestamp() -> u64 {
    -    let millis = Date::now();
    -
    -    (millis / 1000.0) as u64
    -}
    -
    -#[cfg(not(target_arch = "wasm32"))]
    -pub(crate) struct Instant(SystemInstant);
    -#[cfg(target_arch = "wasm32")]
    -pub(crate) struct Instant(Duration);
    -
    -impl Instant {
    -    #[cfg(not(target_arch = "wasm32"))]
    -    pub fn new() -> Self {
    -        Instant(SystemInstant::now())
    -    }
    -    #[cfg(target_arch = "wasm32")]
    -    pub fn new() -> Self {
    -        let millis = Date::now();
    -
    -        let secs = millis / 1000.0;
    -        let nanos = (millis % 1000.0) * 1e6;
    -
    -        Instant(Duration::new(secs as u64, nanos as u32))
    -    }
    -
    -    #[cfg(not(target_arch = "wasm32"))]
    -    pub fn elapsed(&self) -> Duration {
    -        self.0.elapsed()
    -    }
    -    #[cfg(target_arch = "wasm32")]
    -    pub fn elapsed(&self) -> Duration {
    -        let now = Instant::new();
    -
    -        now.0.checked_sub(self.0).unwrap_or(Duration::new(0, 0))
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/tx_builder.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/tx_builder.rs.html deleted file mode 100644 index 732238dba1..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/tx_builder.rs.html +++ /dev/null @@ -1,1776 +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
    -
    // 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::tx_builder::CreateTx;
    -//! # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -//! # let 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(), 50_000)
    -//!     // With a custom fee rate of 5.0 satoshi/vbyte
    -//!     .fee_rate(FeeRate::from_sat_per_vb(5.0))
    -//!     // Only spend non-change outputs
    -//!     .do_not_spend_change()
    -//!     // Turn on RBF signaling
    -//!     .enable_rbf();
    -//! let (psbt, tx_details) = tx_builder.finish()?;
    -//! # Ok::<(), bdk::Error>(())
    -//! ```
    -
    -use std::collections::BTreeMap;
    -use std::collections::HashSet;
    -use std::default::Default;
    -use std::marker::PhantomData;
    -
    -use bitcoin::util::psbt::{self, PartiallySignedTransaction as Psbt};
    -use bitcoin::{OutPoint, Script, SigHashType, Transaction};
    -
    -use miniscript::descriptor::DescriptorTrait;
    -
    -use super::coin_selection::{CoinSelectionAlgorithm, DefaultCoinSelectionAlgorithm};
    -use crate::{database::BatchDatabase, Error, Utxo, Wallet};
    -use crate::{
    -    types::{FeeRate, KeychainKind, LocalUtxo, WeightedUtxo},
    -    TransactionDetails,
    -};
    -/// Context in which the [`TxBuilder`] is valid
    -pub trait TxBuilderContext: std::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;
    -/// # let wallet = doctest_wallet!();
    -/// # let addr1 = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -/// # let addr2 = addr1.clone();
    -/// // chaining
    -/// let (psbt1, details) = {
    -///     let mut builder = wallet.build_tx();
    -///     builder
    -///         .ordering(TxOrdering::Untouched)
    -///         .add_recipient(addr1.script_pubkey(), 50_000)
    -///         .add_recipient(addr2.script_pubkey(), 50_000);
    -///     builder.finish()?
    -/// };
    -///
    -/// // non-chaining
    -/// let (psbt2, details) = {
    -///     let mut builder = wallet.build_tx();
    -///     builder.ordering(TxOrdering::Untouched);
    -///     for addr in &[addr1, addr2] {
    -///         builder.add_recipient(addr.script_pubkey(), 50_000);
    -///     }
    -///     builder.finish()?
    -/// };
    -///
    -/// assert_eq!(
    -///     psbt1.global.unsigned_tx.output[..2],
    -///     psbt2.global.unsigned_tx.output[..2]
    -/// );
    -/// # Ok::<(), bdk::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, B, D, Cs, Ctx> {
    -    pub(crate) wallet: &'a Wallet<B, D>,
    -    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<(Script, u64)>,
    -    pub(crate) drain_wallet: bool,
    -    pub(crate) drain_to: Option<Script>,
    -    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<SigHashType>,
    -    pub(crate) ordering: TxOrdering,
    -    pub(crate) locktime: Option<u32>,
    -    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>,
    -}
    -
    -#[derive(Clone, Copy, Debug)]
    -pub(crate) struct PreviousFee {
    -    pub absolute: u64,
    -    pub rate: f32,
    -}
    -
    -#[derive(Debug, Clone, Copy)]
    -pub(crate) enum FeePolicy {
    -    FeeRate(FeeRate),
    -    FeeAmount(u64),
    -}
    -
    -impl std::default::Default for FeePolicy {
    -    fn default() -> Self {
    -        FeePolicy::FeeRate(FeeRate::default_min_relay_fee())
    -    }
    -}
    -
    -impl<'a, Cs: Clone, Ctx, B, D> Clone for TxBuilder<'a, B, D, Cs, Ctx> {
    -    fn clone(&self) -> Self {
    -        TxBuilder {
    -            wallet: self.wallet,
    -            params: self.params.clone(),
    -            coin_selection: self.coin_selection.clone(),
    -            phantom: PhantomData,
    -        }
    -    }
    -}
    -
    -// methods supported by both contexts, for any CoinSelectionAlgorithm
    -impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>, Ctx: TxBuilderContext>
    -    TxBuilder<'a, B, D, Cs, Ctx>
    -{
    -    /// Set a custom fee rate
    -    pub fn fee_rate(&mut self, fee_rate: FeeRate) -> &mut Self {
    -        self.params.fee_policy = Some(FeePolicy::FeeRate(fee_rate));
    -        self
    -    }
    -
    -    /// Set an absolute fee
    -    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();
    -    /// # let 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(), 50_000)
    -    ///     .policy_path(path, KeychainKind::External);
    -    ///
    -    /// # Ok::<(), bdk::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, Error> {
    -        let utxos = outpoints
    -            .iter()
    -            .map(|outpoint| self.wallet.get_utxo(*outpoint)?.ok_or(Error::UnknownUtxo))
    -            .collect::<Result<Vec<_>, _>>()?;
    -
    -        for utxo in utxos {
    -            let descriptor = self.wallet.get_descriptor_for_keychain(utxo.keychain);
    -            let satisfaction_weight = descriptor.max_satisfaction_weight().unwrap();
    -            self.params.utxos.push(WeightedUtxo {
    -                satisfaction_weight,
    -                utxo: Utxo::Local(utxo),
    -            });
    -        }
    -
    -        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, Error> {
    -        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 foregin 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 `satisfaction_weight` 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_satisfaction_weight`].
    -    ///
    -    /// This is an **EXPERIMENTAL** feature, API and other major changes are expected.
    -    ///
    -    /// # 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 `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_satisfaction_weight`]: miniscript::Descriptor::max_satisfaction_weight
    -    pub fn add_foreign_utxo(
    -        &mut self,
    -        outpoint: OutPoint,
    -        psbt_input: psbt::Input,
    -        satisfaction_weight: usize,
    -    ) -> Result<&mut Self, Error> {
    -        if psbt_input.witness_utxo.is_none() {
    -            match psbt_input.non_witness_utxo.as_ref() {
    -                Some(tx) => {
    -                    if tx.txid() != outpoint.txid {
    -                        return Err(Error::Generic(
    -                            "Foreign utxo outpoint does not match PSBT input".into(),
    -                        ));
    -                    }
    -                    if tx.output.len() <= outpoint.vout as usize {
    -                        return Err(Error::InvalidOutpoint(outpoint));
    -                    }
    -                }
    -                None => {
    -                    return Err(Error::Generic(
    -                        "Foreign utxo missing witness_utxo or non_witness_utxo".into(),
    -                    ))
    -                }
    -            }
    -        }
    -
    -        self.params.utxos.push(WeightedUtxo {
    -            satisfaction_weight,
    -            utxo: Utxo::Foreign {
    -                outpoint,
    -                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: SigHashType) -> &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: u32) -> &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::util::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::util::psbt::Output::redeem_script) and
    -    /// [`psbt::Output::witness_script`](bitcoin::util::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`](super::coin_selection::DefaultCoinSelectionAlgorithm).
    -    ///
    -    /// Note that this function consumes the builder and returns it so it is usually best to put this as the first call on the builder.
    -    pub fn coin_selection<P: CoinSelectionAlgorithm<D>>(
    -        self,
    -        coin_selection: P,
    -    ) -> TxBuilder<'a, B, D, P, Ctx> {
    -        TxBuilder {
    -            wallet: self.wallet,
    -            params: self.params,
    -            coin_selection,
    -            phantom: PhantomData,
    -        }
    -    }
    -
    -    /// Finish the building the transaction.
    -    ///
    -    /// Returns the [`BIP174`] "PSBT" and summary details about the transaction.
    -    ///
    -    /// [`BIP174`]: https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki
    -    pub fn finish(self) -> Result<(Psbt, TransactionDetails), Error> {
    -        self.wallet.create_tx(self.coin_selection, self.params)
    -    }
    -
    -    /// 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: u32) -> &mut Self {
    -        self.params.rbf = Some(RbfValue::Value(nsequence));
    -        self
    -    }
    -}
    -
    -impl<'a, B, D: BatchDatabase, Cs: CoinSelectionAlgorithm<D>> TxBuilder<'a, B, D, Cs, CreateTx> {
    -    /// Replace the recipients already added with a new list
    -    pub fn set_recipients(&mut self, recipients: Vec<(Script, u64)>) -> &mut Self {
    -        self.params.recipients = recipients;
    -        self
    -    }
    -
    -    /// Add a recipient to the internal list
    -    pub fn add_recipient(&mut self, script_pubkey: Script, amount: u64) -> &mut Self {
    -        self.params.recipients.push((script_pubkey, amount));
    -        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).
    -    ///
    -    /// 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::tx_builder::CreateTx;
    -    /// # let to_address = Address::from_str("2N4eQYCbKUHCCTUjBJeHcJp9ok6J2GZsTDt").unwrap();
    -    /// # let 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.0))
    -    ///     .enable_rbf();
    -    /// let (psbt, tx_details) = tx_builder.finish()?;
    -    /// # Ok::<(), bdk::Error>(())
    -    /// ```
    -    ///
    -    /// [`allow_shrinking`]: Self::allow_shrinking
    -    /// [`add_recipient`]: Self::add_recipient
    -    /// [`drain_wallet`]: Self::drain_wallet
    -    pub fn drain_to(&mut self, script_pubkey: Script) -> &mut Self {
    -        self.params.drain_to = Some(script_pubkey);
    -        self
    -    }
    -}
    -
    -// methods supported only by bump_fee
    -impl<'a, B, D: BatchDatabase> TxBuilder<'a, B, D, DefaultCoinSelectionAlgorithm, BumpFee> {
    -    /// Explicitly tells the wallet that it is allowed to reduce the fee 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: Script) -> Result<&mut Self, Error> {
    -        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(Error::Generic(format!(
    -                "{} was not in the original transaction",
    -                script_pubkey
    -            ))),
    -        }
    -    }
    -}
    -
    -/// Ordering of the transaction's inputs and outputs
    -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
    -pub enum TxOrdering {
    -    /// Randomized (default)
    -    Shuffle,
    -    /// Unchanged
    -    Untouched,
    -    /// BIP69 / Lexicographic
    -    Bip69Lexicographic,
    -}
    -
    -impl Default for TxOrdering {
    -    fn default() -> Self {
    -        TxOrdering::Shuffle
    -    }
    -}
    -
    -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;
    -                #[cfg(test)]
    -                use rand::SeedableRng;
    -
    -                #[cfg(not(test))]
    -                let mut rng = rand::thread_rng();
    -                #[cfg(test)]
    -                let mut rng = rand::rngs::StdRng::seed_from_u64(0);
    -
    -                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(u32),
    -}
    -
    -impl RbfValue {
    -    pub(crate) fn get_value(&self) -> u32 {
    -        match self {
    -            RbfValue::Default => 0xFFFFFFFD,
    -            RbfValue::Value(v) => *v,
    -        }
    -    }
    -}
    -
    -/// Policy regarding the use of change outputs when creating a transaction
    -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq, Hash, Clone, Copy)]
    -pub enum ChangeSpendPolicy {
    -    /// Use both change and non-change outputs (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 Default for ChangeSpendPolicy {
    -    fn default() -> Self {
    -        ChangeSpendPolicy::ChangeAllowed
    -    }
    -}
    -
    -impl ChangeSpendPolicy {
    -    pub(crate) fn is_satisfied_by(&self, utxo: &LocalUtxo) -> 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 bitcoin::consensus::deserialize;
    -    use bitcoin::hashes::hex::FromHex;
    -
    -    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();
    -
    -        TxOrdering::Shuffle.sort_tx(&mut tx);
    -
    -        assert_eq!(original_tx.input, tx.input);
    -        assert_ne!(original_tx.output, tx.output);
    -    }
    -
    -    #[test]
    -    fn test_output_ordering_bip69() {
    -        use std::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, 800);
    -        assert_eq!(tx.output[1].script_pubkey, From::from(vec![0xAA]));
    -        assert_eq!(tx.output[2].script_pubkey, From::from(vec![0xAA, 0xEE]));
    -    }
    -
    -    fn get_test_utxos() -> Vec<LocalUtxo> {
    -        vec![
    -            LocalUtxo {
    -                outpoint: OutPoint {
    -                    txid: Default::default(),
    -                    vout: 0,
    -                },
    -                txout: Default::default(),
    -                keychain: KeychainKind::External,
    -            },
    -            LocalUtxo {
    -                outpoint: OutPoint {
    -                    txid: Default::default(),
    -                    vout: 1,
    -                },
    -                txout: Default::default(),
    -                keychain: KeychainKind::Internal,
    -            },
    -        ]
    -    }
    -
    -    #[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/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/utils.rs.html b/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/utils.rs.html deleted file mode 100644 index 5154e583bb..0000000000 --- a/static/docs-rs/bdk/nightly/latest/src/bdk/wallet/utils.rs.html +++ /dev/null @@ -1,536 +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
    -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
    -
    // 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 miniscript::{MiniscriptKey, Satisfier, ToPublicKey};
    -
    -// De-facto standard "dust limit" (even though it should change based on the output type)
    -pub const DUST_LIMIT_SATOSHI: u64 = 546;
    -
    -// MSB of the nSequence. If set there's no consensus-constraint, so it must be disabled when
    -// spending using CSV in order to enforce CSV rules
    -pub(crate) const SEQUENCE_LOCKTIME_DISABLE_FLAG: u32 = 1 << 31;
    -// 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;
    -// Mask for the bits used to express the timelock
    -pub(crate) const SEQUENCE_LOCKTIME_MASK: u32 = 0x0000FFFF;
    -
    -// Threshold for nLockTime to be considered a block-height-based timelock rather than time-based
    -pub(crate) const BLOCKS_TIMELOCK_THRESHOLD: u32 = 500000000;
    -
    -/// Trait to check if a value is below the dust limit
    -// we implement this trait to make sure we don't mess up the comparison with off-by-one like a <
    -// instead of a <= etc. The constant value for the dust limit is not public on purpose, to
    -// encourage the usage of this trait.
    -pub trait IsDust {
    -    /// Check whether or not a value is below dust limit
    -    fn is_dust(&self) -> bool;
    -}
    -
    -impl IsDust for u64 {
    -    fn is_dust(&self) -> bool {
    -        *self <= DUST_LIMIT_SATOSHI
    -    }
    -}
    -
    -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: u32, csv: u32) -> bool {
    -    // This flag cannot be set in the nSequence when spending using OP_CSV
    -    if rbf & SEQUENCE_LOCKTIME_DISABLE_FLAG != 0 {
    -        return false;
    -    }
    -
    -    let mask = SEQUENCE_LOCKTIME_TYPE_FLAG | SEQUENCE_LOCKTIME_MASK;
    -    let rbf = rbf & mask;
    -    let csv = csv & mask;
    -
    -    // Both values should be represented in the same unit (either time-based or
    -    // block-height based)
    -    if (rbf < SEQUENCE_LOCKTIME_TYPE_FLAG) != (csv < SEQUENCE_LOCKTIME_TYPE_FLAG) {
    -        return false;
    -    }
    -
    -    // The value should be at least `csv`
    -    if rbf < csv {
    -        return false;
    -    }
    -
    -    true
    -}
    -
    -pub(crate) fn check_nlocktime(nlocktime: u32, required: u32) -> bool {
    -    // Both values should be expressed in the same unit
    -    if (nlocktime < BLOCKS_TIMELOCK_THRESHOLD) != (required < BLOCKS_TIMELOCK_THRESHOLD) {
    -        return false;
    -    }
    -
    -    // The value should be at least `required`
    -    if nlocktime < required {
    -        return false;
    -    }
    -
    -    true
    -}
    -
    -impl<Pk: MiniscriptKey + ToPublicKey> Satisfier<Pk> for After {
    -    fn check_after(&self, n: u32) -> bool {
    -        if let Some(current_height) = self.current_height {
    -            current_height >= n
    -        } 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: u32) -> bool {
    -        if let Some(current_height) = self.current_height {
    -            // TODO: test >= / >
    -            current_height as u64 >= self.create_height.unwrap_or(0) as u64 + n as u64
    -        } else {
    -            self.assume_height_reached
    -        }
    -    }
    -}
    -
    -pub(crate) type SecpCtx = Secp256k1<All>;
    -
    -pub struct ChunksIterator<I: Iterator> {
    -    iter: I,
    -    size: usize,
    -}
    -
    -#[cfg(any(feature = "electrum", feature = "esplora"))]
    -impl<I: Iterator> ChunksIterator<I> {
    -    pub fn new(iter: I, size: usize) -> Self {
    -        ChunksIterator { iter, size }
    -    }
    -}
    -
    -impl<I: Iterator> Iterator for ChunksIterator<I> {
    -    type Item = Vec<<I as std::iter::Iterator>::Item>;
    -
    -    fn next(&mut self) -> Option<Self::Item> {
    -        let mut v = Vec::new();
    -        for _ in 0..self.size {
    -            let e = self.iter.next();
    -
    -            match e {
    -                None => break,
    -                Some(val) => v.push(val),
    -            }
    -        }
    -
    -        if v.is_empty() {
    -            return None;
    -        }
    -
    -        Some(v)
    -    }
    -}
    -
    -#[cfg(test)]
    -mod test {
    -    use super::{
    -        check_nlocktime, check_nsequence_rbf, BLOCKS_TIMELOCK_THRESHOLD,
    -        SEQUENCE_LOCKTIME_TYPE_FLAG,
    -    };
    -    use crate::types::FeeRate;
    -
    -    #[test]
    -    fn test_fee_from_btc_per_kb() {
    -        let fee = FeeRate::from_btc_per_kvb(1e-5);
    -        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
    -    }
    -
    -    #[test]
    -    fn test_fee_from_sats_vbyte() {
    -        let fee = FeeRate::from_sat_per_vb(1.0);
    -        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
    -    }
    -
    -    #[test]
    -    fn test_fee_default_min_relay_fee() {
    -        let fee = FeeRate::default_min_relay_fee();
    -        assert!((fee.as_sat_vb() - 1.0).abs() < 0.0001);
    -    }
    -
    -    #[test]
    -    fn test_check_nsequence_rbf_msb_set() {
    -        let result = check_nsequence_rbf(0x80000000, 5000);
    -        assert!(!result);
    -    }
    -
    -    #[test]
    -    fn test_check_nsequence_rbf_lt_csv() {
    -        let result = check_nsequence_rbf(4000, 5000);
    -        assert!(!result);
    -    }
    -
    -    #[test]
    -    fn test_check_nsequence_rbf_different_unit() {
    -        let result = check_nsequence_rbf(SEQUENCE_LOCKTIME_TYPE_FLAG + 5000, 5000);
    -        assert!(!result);
    -    }
    -
    -    #[test]
    -    fn test_check_nsequence_rbf_mask() {
    -        let result = check_nsequence_rbf(0x3f + 10_000, 5000);
    -        assert!(result);
    -    }
    -
    -    #[test]
    -    fn test_check_nsequence_rbf_same_unit_blocks() {
    -        let result = check_nsequence_rbf(10_000, 5000);
    -        assert!(result);
    -    }
    -
    -    #[test]
    -    fn test_check_nsequence_rbf_same_unit_time() {
    -        let result = check_nsequence_rbf(
    -            SEQUENCE_LOCKTIME_TYPE_FLAG + 10_000,
    -            SEQUENCE_LOCKTIME_TYPE_FLAG + 5000,
    -        );
    -        assert!(result);
    -    }
    -
    -    #[test]
    -    fn test_check_nlocktime_lt_cltv() {
    -        let result = check_nlocktime(4000, 5000);
    -        assert!(!result);
    -    }
    -
    -    #[test]
    -    fn test_check_nlocktime_different_unit() {
    -        let result = check_nlocktime(BLOCKS_TIMELOCK_THRESHOLD + 5000, 5000);
    -        assert!(!result);
    -    }
    -
    -    #[test]
    -    fn test_check_nlocktime_same_unit_blocks() {
    -        let result = check_nlocktime(10_000, 5000);
    -        assert!(result);
    -    }
    -
    -    #[test]
    -    fn test_check_nlocktime_same_unit_time() {
    -        let result = check_nlocktime(
    -            BLOCKS_TIMELOCK_THRESHOLD + 10_000,
    -            BLOCKS_TIMELOCK_THRESHOLD + 5000,
    -        );
    -        assert!(result);
    -    }
    -}
    -
    -
    - - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/storage.js b/static/docs-rs/bdk/nightly/latest/storage.js deleted file mode 100644 index 6b16cbd83c..0000000000 --- a/static/docs-rs/bdk/nightly/latest/storage.js +++ /dev/null @@ -1 +0,0 @@ -var resourcesSuffix="";var darkThemes=["dark","ayu"];window.currentTheme=document.getElementById("themeStyle");window.mainTheme=document.getElementById("mainThemeStyle");var settingsDataset=(function(){var settingsElement=document.getElementById("default-settings");if(settingsElement===null){return null}var dataset=settingsElement.dataset;if(dataset===undefined){return null}return dataset})();function getSettingValue(settingName){var current=getCurrentValue('rustdoc-'+settingName);if(current!==null){return current}if(settingsDataset!==null){var def=settingsDataset[settingName.replace(/-/g,'_')];if(def!==undefined){return def}}return null}var localStoredTheme=getSettingValue("theme");var savedHref=[];function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(!elem||!elem.classList){return}elem.classList.add(className)}function removeClass(elem,className){if(!elem||!elem.classList){return}elem.classList.remove(className)}function onEach(arr,func,reversed){if(arr&&arr.length>0&&func){var length=arr.length;var i;if(reversed){for(i=length-1;i>=0;--i){if(func(arr[i])){return true}}}else{for(i=0;i=0){updateLocalStorage("rustdoc-preferred-dark-theme",localStoredTheme)}updateSystemTheme()}else{switchTheme(window.currentTheme,window.mainTheme,getSettingValue("theme")||"light",false)} \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/toggle-minus.svg b/static/docs-rs/bdk/nightly/latest/toggle-minus.svg deleted file mode 100644 index 73154788a0..0000000000 --- a/static/docs-rs/bdk/nightly/latest/toggle-minus.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/toggle-plus.svg b/static/docs-rs/bdk/nightly/latest/toggle-plus.svg deleted file mode 100644 index 08b17033e1..0000000000 --- a/static/docs-rs/bdk/nightly/latest/toggle-plus.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/static/docs-rs/bdk/nightly/latest/wheel.svg b/static/docs-rs/bdk/nightly/latest/wheel.svg deleted file mode 100644 index 01da3b24c7..0000000000 --- a/static/docs-rs/bdk/nightly/latest/wheel.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/static/icons/android-chrome-192x192.png b/static/icons/android-chrome-192x192.png deleted file mode 100644 index 15dcea39a2..0000000000 Binary files a/static/icons/android-chrome-192x192.png and /dev/null differ diff --git a/static/icons/android-chrome-512x512.png b/static/icons/android-chrome-512x512.png deleted file mode 100644 index be05e1a937..0000000000 Binary files a/static/icons/android-chrome-512x512.png and /dev/null differ diff --git a/static/icons/apple-touch-icon.png b/static/icons/apple-touch-icon.png deleted file mode 100644 index 605cd0509a..0000000000 Binary files a/static/icons/apple-touch-icon.png and /dev/null differ diff --git a/static/icons/browserconfig.xml b/static/icons/browserconfig.xml deleted file mode 100644 index b3930d0f04..0000000000 --- a/static/icons/browserconfig.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - #da532c - - - diff --git a/static/icons/favicon-16x16.png b/static/icons/favicon-16x16.png deleted file mode 100644 index 2f4bc6f184..0000000000 Binary files a/static/icons/favicon-16x16.png and /dev/null differ diff --git a/static/icons/favicon-32x32.png b/static/icons/favicon-32x32.png deleted file mode 100644 index 4beecf7e44..0000000000 Binary files a/static/icons/favicon-32x32.png and /dev/null differ diff --git a/static/icons/favicon.ico b/static/icons/favicon.ico deleted file mode 100644 index 33555bf2da..0000000000 Binary files a/static/icons/favicon.ico and /dev/null differ diff --git a/static/icons/mstile-150x150.png b/static/icons/mstile-150x150.png deleted file mode 100644 index b7f7b57ead..0000000000 Binary files a/static/icons/mstile-150x150.png and /dev/null differ diff --git a/static/icons/safari-pinned-tab.svg b/static/icons/safari-pinned-tab.svg deleted file mode 100644 index 84c1abbfc2..0000000000 --- a/static/icons/safari-pinned-tab.svg +++ /dev/null @@ -1,20 +0,0 @@ - - - - safari-pinned-tab - Created with Sketch. - - - - - - - \ No newline at end of file diff --git a/static/icons/site.webmanifest b/static/icons/site.webmanifest deleted file mode 100644 index 4d0a2f6570..0000000000 --- a/static/icons/site.webmanifest +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "Bitcoin Dev Kit Docs", - "short_name": "Bitcoin Dev Kit Docs", - "icons": [ - { - "src": "/android-chrome-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "/android-chrome-512x512.png", - "sizes": "512x512", - "type": "image/png" - } - ], - "theme_color": "#ffffff", - "background_color": "#ffffff", - "display": "standalone" -} diff --git a/static/images/bitfinex.svg b/static/images/bitfinex.svg deleted file mode 100644 index 8d7c3b1eb8..0000000000 --- a/static/images/bitfinex.svg +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - -]> - - - - - - - - - - - - - - - - - diff --git a/static/images/brink.png b/static/images/brink.png deleted file mode 100644 index b8ff73d673..0000000000 Binary files a/static/images/brink.png and /dev/null differ diff --git a/static/images/descriptor-based-paper-wallets/Bitcoin_Paper_Wallet.html b/static/images/descriptor-based-paper-wallets/Bitcoin_Paper_Wallet.html deleted file mode 100644 index bc68433046..0000000000 --- a/static/images/descriptor-based-paper-wallets/Bitcoin_Paper_Wallet.html +++ /dev/null @@ -1,2 +0,0 @@ - -Bitcoin Paper Wallet
    Alice
    tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw
    wsh(multi(2,Grandma,Alice,Barbara))#em3q73l5
    Alice: cSSKRHDmQEEutp5LD14tAcixu2ehSNPDTqNek1zMa9Pet98qxHq3
    Barbara: 02a3f3f2658b9812ddeabfbde2fde03f8a65369e4ed621f29fa8ba0cc519b789fb
    Grandma: 03f1bd2bff8e9c61f58a8d46d18fd8f3149b1f2d76b3c423a7874a5d5811d67cee
    Barbara
    tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw
    wsh(multi(2,Grandma,Alice,Barbara))#nxfa5n0z
    Alice: 02e486e32f0f87136fa042cb53219ace8537ea1d036deb2f4293570b94325d11cb
    Barbara: cSfMLzSZ9NjWUTqL3sFpgWJssnu2qgmE2cm5N1jPDRRJuDcrsPEB
    Grandma: 03f1bd2bff8e9c61f58a8d46d18fd8f3149b1f2d76b3c423a7874a5d5811d67cee
    Grandma
    tb1qu6lcua9w2zkarjj5xwxh3l3qtcxh84hsra3jrvpszh69j2e54x7q3thycw
    wsh(multi(2,Grandma,Alice,Barbara))#5m0qdehe
    Alice: 02e486e32f0f87136fa042cb53219ace8537ea1d036deb2f4293570b94325d11cb
    Barbara: 02a3f3f2658b9812ddeabfbde2fde03f8a65369e4ed621f29fa8ba0cc519b789fb
    Grandma: cS2XH31JtmbxXUxt1yxVgFzy69zq4b5jx6zFok3B4HzBEwQ5D2Kq
    diff --git a/static/images/descriptor-based-paper-wallets/data-url.txt b/static/images/descriptor-based-paper-wallets/data-url.txt deleted file mode 100644 index 4eb7f23658..0000000000 --- a/static/images/descriptor-based-paper-wallets/data-url.txt +++ /dev/null @@ -1 +0,0 @@ -data:text/html;base64,PCFET0NUWVBFIGh0bWw+PGh0bWw+PGhlYWQ+PG1ldGEgY2hhcnNldD0iVVRGLTgiPjwvbWV0YT48dGl0bGU+Qml0Y29pbiBQYXBlciBXYWxsZXQ8L3RpdGxlPjxzdHlsZT46cm9vdCB7IC0td2FsbGV0LXdpZHRoOiAyMDBweDsgLS1wYWdlLW1hcmdpbjogMWVtO31odG1sLCBib2R5IHsgaGVpZ2h0OiAxMDAlOyB3aWR0aDogMTAwJTsgbWFyZ2luOiAwOyBhbGlnbi1pdGVtczogY2VudGVyOyBmb250LWZhbWlseTogbW9ub3NwYWNlOyBkaXNwbGF5OiBmbGV4OyBmbGV4LXdyYXA6IHdyYXA7IGp1c3RpZnktY29udGVudDogc3BhY2UtZXZlbmx5O30uc2luZ2xlIHsgd2lkdGg6IDIwMHB4OyB3aWR0aDogdmFyKC0td2FsbGV0LXdpZHRoKTsgYm9yZGVyOiBkYXNoZWQ7IGJvcmRlci13aWR0aDogdGhpbjsgZGlzcGxheTogZmxleDsgZmxleC1kaXJlY3Rpb246IGNvbHVtbjsganVzdGlmeS1jb250ZW50OiBzcGFjZS1iZXR3ZWVuOyBoZWlnaHQ6IGNhbGMoMTAwJSAtIDIgKiB2YXIoLS1wYWdlLW1hcmdpbikpOyBtYXJnaW46IHZhcigtLXBhZ2UtbWFyZ2luKSAwOyBwb3NpdGlvbjogcmVsYXRpdmU7fS5zaW5nbGU6YWZ0ZXIgeyBjb250ZW50OiB1cmwoJ2RhdGE6aW1hZ2Uvc3ZnK3htbDtiYXNlNjQsUEQ5NGJXd2dkbVZ5YzJsdmJqMGlNUzR3SWlCbGJtTnZaR2x1WnowaVZWUkdMVGdpUHo0OGMzWm5JSFpsY25OcGIyNDlJakV1TVNJZ2RtbGxkMEp2ZUQwaU1DQXdJREV3TUNBMk1DSWdlRzFzYm5NOUltaDBkSEE2THk5M2QzY3Vkek11YjNKbkx6SXdNREF2YzNabklqNDhaeUIwY21GdWMyWnZjbTA5SW5SeVlXNXpiR0YwWlNnd0lDMDVPVEl1TXpZcElqNDhaeUIwY21GdWMyWnZjbTA5SW0xaGRISnBlQ2cwTGpJMk1URWdMVEV1TWpNMU1TQXhMakl6TlRFZ05DNHlOakV4SUMweE16TTNMamdnTFRJNU9UVXBJajQ4Y0dGMGFDQm1hV3hzUFNJalpETmtNMlF6SWlCa1BTSnROVGt1TnpNeUlEazFOaTQwWXkwd0xqWXdPVGM0TFRFdU16a3lPUzB5TGpNd016VXRNUzQ0TXpVMkxUTXVOams0T1MweExqY3hNak5zTFRndU56UXlOaUF3TGpZNU5UWTJZeTB4TGprek5UY3RNUzQ1TVRReUxUUXVNekEzTlMweUxqSXdORGt0TkM0eE16SXhMVEl1T0RFMk5TQXdMakV6TnpBMExUQXVORGM0TURZZ01DNDFORFU1T1Mwd0xqSTBOelExSURBdU9ETTNNUzB4TGpVeE1TQXdMakkzT1RVeExURXVNakV6TWkwd0xqY3hORGN4TFRJdU5EVTFNUzB4TGpreE5qVXRNaTQzTVRRNUxURXVNVGMzTnkwd0xqTTBOVEkyTFRJdU5qVTVPQ0F3TGpJd09ESTNMVE11TURJM055QXhMalExTWkwd0xqUTBOemc0SURFdU1qTXdOaUF3TGpJM016ZzNJREl1TmprNU55QXhMalE1T1RVZ015NHhOQ0F4TGpRd01Ea2dNQzQyTXpjMElEUXVNalEyTmlBd0xqUTVNemM1SURRdU9ETTNPQ0F6TGpBeU1TMHhMak00TkRnZ01TNDBNVEV6TFRJdU9Ua3pNU0F3TGprMU5USTFMVFF1TkRJeU1TQXdMalExTlRFdE1TNHhPRFkwTFRBdU5ERTFNalF0TWk0M016UXpMVEF1TkRnME9EY3RNeTQyTkRrMklEQXVOVE0xT0RrdE1DNDRPREUzTWlBd0xqazNOamswTFRBdU9EQXdNVFlnTWk0M05UQTJJREF1TXpjMk5qZ2dNeTQwTmpReklERXVNVFV5T0NBd0xqZzBNakVnTXk0d09UTXpJREF1TnpVeE9DQXpMamd5TkRNdE1DNDJOREUzTWlBd0xqVTJNelEzTFRFdU1EYzBNUzB3TGpBNU1URTVMVEV1T0RReU5DQXdMak16T0MweUxqRTJPQ0F3TGpNeU16ZzBMVEF1TWpRMU5qTWdNUzQzTlRreUlEQXVNell4T1RRZ05DNDNORGs1TFRBdU1EWTRObXczTGpZNE5EY2dOUzQwTmpSak1DNDVPVE0zTWlBd0xqWXhNVEU1SURJdU16RTJOU0F3TGprM09UUTNJRE11TlRjM09DQXdMakU1TVRZMGJDMDNMamt3TWpjdE5TNDRPVEE1SURrdU56WTJOUzB3TGpnNU5UYzBlbTB0TVRjdU1EYzFMVFl1T0RjeE9XTXhMakEwTlRNZ01TNHdOVEUySURBdU5EQXpNekVnTWk0NU1EY3pMVEF1T1RrME5URWdNaTQ1TURFMkxURXVNamcyTWlBd0xqQTNNaTB5TGpRMU5EWXRNUzQwT1RNeUxURXVOekU0TkMweUxqWTFNemdnTUM0MU1UWTBPQzB3TGprM056TTNJREV1T1RrM05DMHdMamsyTnpZNUlESXVOekV5T1Mwd0xqSTBOemd5ZW0wdE1pNHhOVFV5SURjdU56SXlOR014TGpFMk1URWdNQzQ0TlRFM09TQXdMak14TURjeUlESXVPVGcxTnkweExqQTVORFFnTWk0NU1ESTBMVEF1T1RZeU9UWWdNQzR3TlRNdE1pNHdPRGsyTFRBdU56UXpOQzB4TGpnNE1qUXRNUzQ0TURBMklEQXVNVGc0T1MweExqTXdNelVnTVM0NU9EZ3hMVEl1TURFME15QXlMamszTmpndE1TNHhNREU0ZWlJdlBqd3ZaejQ4TDJjK1BDOXpkbWMrQ2c9PScpOyB3aWR0aDogM2VtOyBwb3NpdGlvbjogYWJzb2x1dGU7IGJvdHRvbTogLTFlbTsgcmlnaHQ6IC0xLjY2ZW07IHRyYW5zZm9ybTogcm90YXRlKC05MGRlZyk7fS5icmVhay13b3JkIHsgd29yZC1icmVhazogYnJlYWstYWxsOyBwYWRkaW5nOiAwLjM1ZW07IC13ZWJraXQtcHJpbnQtY29sb3ItYWRqdXN0OiBleGFjdDsgcG9zaXRpb246IHJlbGF0aXZlOyBvdmVyZmxvdzogaGlkZGVuO30uYnJlYWstd29yZDo6YmVmb3JlIHsgY29udGVudDogJyc7IGJvcmRlcjogMTAwMDBweCBzb2xpZCBsaWdodGdyYXk7IHBvc2l0aW9uOiBhYnNvbHV0ZTsgdG9wOiAwOyBsZWZ0OiAwOyB6LWluZGV4OiAtMTsgYm94LXNpemluZzogYm9yZGVyLWJveDt9LnBhZCB7IHBhZGRpbmctdG9wOiAwLjFlbTsgcGFkZGluZy1ib3R0b206IDAuMWVtOyBmb250LXNpemU6IHgtc21hbGw7fS5jZW50ZXIgeyB0ZXh0LWFsaWduOiBjZW50ZXI7IGhlaWdodDogMjAwcHg7IGhlaWdodDogdmFyKC0td2FsbGV0LXdpZHRoKTt9LmJsYWNrIHsgcG9zaXRpb246IHJlbGF0aXZlOyBvdmVyZmxvdzogaGlkZGVuOyBmbGV4LWdyb3c6IDI7fS5ibGFjazo6YmVmb3JlIHsgY29udGVudDogJyc7IGJvcmRlcjogMTAwMDBweCBzb2xpZCBibGFjazsgcG9zaXRpb246IGFic29sdXRlOyB6LWluZGV4OiAtMTsgYm94LXNpemluZzogYm9yZGVyLWJveDt9LnFyIHsgaGVpZ2h0OiA4MCU7IG1hcmdpbjogMTAlOyBpbWFnZS1yZW5kZXJpbmc6IHBpeGVsYXRlZDsgaW1hZ2UtcmVuZGVyaW5nOiBjcmlzcC1lZGdlczt9LmJvbGQgeyB3aWR0aDogMTAwJTsgZGlzcGxheTogaW5saW5lLWJsb2NrOyB0ZXh0LWFsaWduOiBjZW50ZXI7IGZvbnQtd2VpZ2h0OiA4MDA7fUBtZWRpYSBwcmludCB7IEBwYWdlIHsgbWFyZ2luOiAwOyB9IDpyb290IHsgIC0td2FsbGV0LXdpZHRoOiA1Y207ICAtLXBhZ2UtbWFyZ2luOiAxY207IH19PC9zdHlsZT48L2hlYWQ+PGJvZHk+PGRpdiBjbGFzcz0ic2luZ2xlIj48ZGl2PjxkaXYgY2xhc3M9ImJyZWFrLXdvcmQiPjxzcGFuIGNsYXNzPSJib2xkIj5BbGljZTwvc3Bhbj48YnI+dGIxcXU2bGN1YTl3MnprYXJqajV4d3hoM2wzcXRjeGg4NGhzcmEzanJ2cHN6aDY5ajJlNTR4N3EzdGh5Y3c8L2Rpdj48ZGl2IGNsYXNzPSJjZW50ZXIiPjxpbWcgY2xhc3M9InFyIiBzcmM9ImRhdGE6aW1hZ2UvYm1wO2Jhc2U2NCxRazF1QmdBQUFBQUFBRDRBQUFBb0FBQUFZd0FBQUdNQUFBQUJBQUVBQUFBQUFEQUdBQUFBQWdBQUFBSUFBQUlBQUFBQ0FBQUEvLy8vQUFBQUFBRC8vL2pnQWNELzhBY0FmOGZnQUFBQS8vLzQ0QUhBLy9BSEFIL0g0QUFBQVAvLytPQUJ3UC93QndCL3grQUFBQURnQURnQUFjZi9nRC9nRDhEZ0FBQUE0QUE0QUFISC80QS80QS9BNEFBQUFPQUFPQUFCeC8rQVArQVB3T0FBQUFEai9qZ0FELzhBRC9nZmdmZ0FBQUFBNC80NEFBLy9BQS80SDRINEFBQUFBT1ArT0FBUC93QVArQitCK0FBQUFBRGovamdjY0FBRC9nZmdEL2pnQUFBQTQvNDRISEFBQS80SDRBLzQ0QUFBQU9QK09CeHdBQVArQitBUCtPQUFBQURqL2pqOGNEamdBRC8vLy84QUFBQUE0LzQ0L0hBNDRBQS8vLy8vQUFBQUFPUCtPUHh3T09BQVAvLy8vd0FBQUFEZ0FEZ2ZnZmpnRGpqZ0Q4QUFBQUFBNEFBNEg0SDQ0QTQ0NEEvQUFBQUFBT0FBT0IrQitPQU9PT0FQd0FBQUFBRC8vL2pqZ2YvamdBZmpqai9nQUFBQS8vLzQ0NEgvNDRBSDQ0NC80QUFBQVAvLytPT0IvK09BQitPT1ArQUFBQUFBQUFEOERnRDhmL2pnRGo4QUFBQUFBQUFBL0E0QS9ILzQ0QTQvQUFBQUFBQUFBUHdPQVB4LytPQU9Qd0FBQUFEL2dmZ2NEOGNmZ2YvLy84QUFBQUFBLzRINEhBL0hINEgvLy8vQUFBQUFBUCtCK0J3UHh4K0IvLy8vd0FBQUFBQUQ4Y0FjZmdBY2ZqOGNEai9nQUFBQUEvSEFISDRBSEg0L0hBNC80QUFBQUFQeHdCeCtBQngrUHh3T1ArQUFBQUFEOGYvZ0Q4RGo4QUFBRDhjQUFBQUFBL0gvNEEvQTQvQUFBQS9IQUFBQUFBUHgvK0FQd09Qd0FBQVB4d0FBQUFELy9nRGpnY0RnY2Y4Y2NmamdBQUFBLy80QTQ0SEE0SEgvSEhINDRBQUFBUC8rQU9PQndPQngveHh4K09BQUFBRGo4RDhjZmdBRC9nQURnZi9nQUFBQTQvQS9ISDRBQS80QUE0SC80QUFBQU9Qd1B4eCtBQVArQUFPQi8rQUFBQUQvajhjZjhBY2ZqOERnQUFBQUFBQUEvNC9ISC9BSEg0L0E0QUFBQUFBQUFQK1B4eC93QngrUHdPQUFBQUFBQUFEOEFEZ0FBQUQ4QWYvOERqamdBQUFBL0FBNEFBQUEvQUgvL0E0NDRBQUFBUHdBT0FBQUFQd0IvL3dPT09BQUFBQWNBY0RnRGdEampnQWNjY2ZnQUFBQUhBSEE0QTRBNDQ0QUhISEg0QUFBQUJ3QndPQU9BT09PQUJ4eHgrQUFBQURnQUQ4QUFjRGdjZmo4Y2YvZ0FBQUE0QUEvQUFIQTRISDQvSEgvNEFBQUFPQUFQd0FCd09CeCtQeHgvK0FBQUFBY2Y4Y2YvOGZnQWNjRDhmamdBQUFBSEgvSEgvL0g0QUhIQS9INDRBQUFBQngveHgvL3grQUJ4d1B4K09BQUFBQURqL2dBZmdjRGpqOGNjQWNBQUFBQUE0LzRBSDRIQTQ0L0hIQUhBQUFBQUFPUCtBQitCd09PUHh4d0J3QUFBQUQ4Y0FELzhmZ0QvOEQ4RC8vZ0FBQUEvSEFBLy9INEEvL0EvQS8vNEFBQUFQeHdBUC94K0FQL3dQd1AvK0FBQUFBRGpqLy9qOERnY0QvOERqOEFBQUFBQTQ0Ly80L0E0SEEvL0E0L0FBQUFBQU9PUC8rUHdPQndQL3dPUHdBQUFBRC8vZ0QvOGNjQURqL2dmLy9nQUFBQS8vNEEvL0hIQUE0LzRILy80QUFBQVAvK0FQL3h4d0FPUCtCLy8rQUFBQUQ4ZmpnZjhmamo4QWZqLzhEZ0FBQUEvSDQ0SC9INDQvQUg0Ly9BNEFBQUFQeCtPQi94K09Qd0IrUC93T0FBQUFELy84RDhEZ0Q4Zi8vZ0FEZ0FBQUFBLy8vQS9BNEEvSC8vNEFBNEFBQUFBUC8vd1B3T0FQeC8vK0FBT0FBQUFBRGdEai9nY0QvamdmLy8vOERnQUFBQTRBNC80SEEvNDRILy8vL0E0QUFBQU9BT1ArQndQK09CLy8vL3dPQUFBQUFBQUFEZ0FBQWYvOERnQUFBQUFBQUFBQUFBNEFBQUgvL0E0QUFBQUFBQUFBQUFBT0FBQUIvL3dPQUFBQUFBQUFELy8vampqampqampqai8vL2dBQUFBLy8vNDQ0NDQ0NDQ0NC8vLzRBQUFBUC8vK09PT09PT09PT1AvLytBQUFBRGdBRGovai84Y0RnZmpnQURnQUFBQTRBQTQvNC8vSEE0SDQ0QUE0QUFBQU9BQU9QK1AveHdPQitPQUFPQUFBQURqL2pqLzhjRDhjZmdEai9qZ0FBQUE0LzQ0Ly9IQS9ISDRBNC80NEFBQUFPUCtPUC94d1B4eCtBT1ArT0FBQUFEai9qai84QUQ4QWY4RGovamdBQUFBNC80NC8vQUEvQUgvQTQvNDRBQUFBT1ArT1Avd0FQd0Ivd09QK09BQUFBRGovamdEL2pnZi84RGpqL2pnQUFBQTQvNDRBLzQ0SC8vQTQ0LzQ0QUFBQU9QK09BUCtPQi8vd09PUCtPQUFBQURnQURnRC8vOERqZ2ZqZ0FEZ0FBQUE0QUE0QS8vL0E0NEg0NEFBNEFBQUFPQUFPQVAvL3dPT0IrT0FBT0FBQUFELy8vamdEOEFEZ0Qvai8vL2dBQUFBLy8vNDRBL0FBNEEvNC8vLzRBQUFBUC8vK09BUHdBT0FQK1AvLytBQUFBQT0iPjwvaW1nPjwvZGl2PjwvZGl2PjxkaXYgY2xhc3M9ImJsYWNrIj48L2Rpdj48ZGl2PjxkaXYgY2xhc3M9ImJyZWFrLXdvcmQiPjxkaXYgY2xhc3M9InBhZCI+d3NoKG11bHRpKDIsR3JhbmRtYSxBbGljZSxCYXJiYXJhKSkjZW0zcTczbDU8L2Rpdj48ZGl2IGNsYXNzPSJwYWQiPkFsaWNlOiBjU1NLUkhEbVFFRXV0cDVMRDE0dEFjaXh1MmVoU05QRFRxTmVrMXpNYTlQZXQ5OHF4SHEzPC9kaXY+PGRpdiBjbGFzcz0icGFkIj5CYXJiYXJhOiAwMmEzZjNmMjY1OGI5ODEyZGRlYWJmYmRlMmZkZTAzZjhhNjUzNjllNGVkNjIxZjI5ZmE4YmEwY2M1MTliNzg5ZmI8L2Rpdj48ZGl2IGNsYXNzPSJwYWQiPkdyYW5kbWE6IDAzZjFiZDJiZmY4ZTljNjFmNThhOGQ0NmQxOGZkOGYzMTQ5YjFmMmQ3NmIzYzQyM2E3ODc0YTVkNTgxMWQ2N2NlZTwvZGl2PjwvZGl2PjxkaXYgY2xhc3M9ImNlbnRlciI+PGltZyBjbGFzcz0icXIiIHNyYz0iZGF0YTppbWFnZS9ibXA7YmFzZTY0LFFrMW1FUUFBQUFBQUFENEFBQUFvQUFBQXR3QUFBTGNBQUFBQkFBRUFBQUFBQUNnUkFBQUFBZ0FBQUFJQUFBSUFBQUFDQUFBQS8vLy9BQUFBQUFELy8vamdEL2dEZ0FmZ2Zqai8vLy84Y0Q4ZmdmZ2NEZ0QvLy9qZ0QvZ0RnQWZnZmpqLy8vLzhjRDhmZ2ZnY0RnRC8vL2pnRC9nRGdBZmdmamovLy8vOGNEOGZnZmdjRGdEZ0FEZ2NjRGovOGZqamdjRGdmai9nY0FEai84QUQvZ0RnQURnY2NEai84ZmpqZ2NEZ2ZqL2djQURqLzhBRC9nRGdBRGdjY0RqLzhmampnY0RnZmovZ2NBRGovOEFEL2dEai9qZ0FBY0Q4Y0FEOEFBY2NBQURnQWNjQWYvZ2NmZ0RqL2pnQUFjRDhjQUQ4QUFjY0FBRGdBY2NBZi9nY2ZnRGovamdBQWNEOGNBRDhBQWNjQUFEZ0FjY0FmL2djZmdEai9qai8vOERnRGdEampqZ2NBY0FEajhBQUFBZmdEZ0RqL2pqLy84RGdEZ0RqampnY0FjQURqOEFBQUFmZ0RnRGovamovLzhEZ0RnRGpqamdjQWNBRGo4QUFBQWZnRGdEai9qajhEamovLy9qamovLy84Y0FmZ0Q4QWYvLy9qZ0RqL2pqOERqai8vL2pqai8vLzhjQWZnRDhBZi8vL2pnRGovamo4RGpqLy8vampqLy8vOGNBZmdEOEFmLy8vamdEZ0FEamdjY0FBQUFmLy9nRDhEL2dBY0Fmai9nRC9qZ0RnQURqZ2NjQUFBQWYvL2dEOEQvZ0FjQWZqL2dEL2pnRGdBRGpnY2NBQUFBZi8vZ0Q4RC9nQWNBZmovZ0QvamdELy8vampnZmpqLzhEai9qai84RDhmLy8vai9qajhmZ0QvLy9qamdmamovOERqL2pqLzhEOGYvLy9qL2pqOGZnRC8vL2pqZ2Zqai84RGovamovOEQ4Zi8vL2ovamo4ZmdBQUFBRGpqamovai9nY0RnRGdmLy9qamovL2pnRGovZ0FBQUFEampqai9qL2djRGdEZ2YvL2pqai8vamdEai9nQUFBQURqampqL2ovZ2NEZ0RnZi8vampqLy9qZ0RqL2dELzhEZ2YvamdBY0FEai8vL2dEamdmLzhmamovLzhmZ0QvOERnZi9qZ0FjQURqLy8vZ0RqZ2YvOGZqai8vOGZnRC84RGdmL2pnQWNBRGovLy9nRGpnZi84ZmpqLy84ZmdEL2pnZi9qOERqampqamdEOERnRGdEZ0Q4Y0Q4ZmovZ0QvamdmL2o4RGpqampqZ0Q4RGdEZ0RnRDhjRDhmai9nRC9qZ2YvajhEampqampnRDhEZ0RnRGdEOGNEOGZqL2dBRC8vOEFmOEFEajhmOGYvOGNBRDhjY0FBRGdmOGY4QUFELy84QWY4QURqOGY4Zi84Y0FEOGNjQUFEZ2Y4ZjhBQUQvLzhBZjhBRGo4ZjhmLzhjQUQ4Y2NBQURnZjhmOEFEOGNBZmpnZmdjRGpqai9qajhELzhEL2dEL2pqZ0FEZ0Q4Y0FmamdmZ2NEampqL2pqOEQvOEQvZ0QvampnQURnRDhjQWZqZ2ZnY0Rqamovamo4RC84RC9nRC9qamdBRGdBQURqOGNmZ0FEajhmLzhBZjhBRC9qLy9qL2pnRC9qZ0FBRGo4Y2ZnQURqOGYvOEFmOEFEL2ovL2ovamdEL2pnQUFEajhjZmdBRGo4Zi84QWY4QUQvai8vai9qZ0QvamdBRC9nRDhEL2dBZmdmOEQ4QWZqOGZqLy8vL2dmOGNmZ0FEL2dEOEQvZ0FmZ2Y4RDhBZmo4ZmovLy8vZ2Y4Y2ZnQUQvZ0Q4RC9nQWZnZjhEOEFmajhmai8vLy9nZjhjZmdEajhmOGNBY0FEamo4Zi9nY0FEL2dEL2dmajhBRDhmZ0RqOGY4Y0FjQURqajhmL2djQUQvZ0QvZ2ZqOEFEOGZnRGo4ZjhjQWNBRGpqOGYvZ2NBRC9nRC9nZmo4QUQ4ZmdBY2NjRGpnY2Y4Y2NmZ0RnY0Rqai9qLzhmOEFBY0RqZ0FjY2NEamdjZjhjY2ZnRGdjRGpqL2ovOGY4QUFjRGpnQWNjY0RqZ2NmOGNjZmdEZ2NEamovai84ZjhBQWNEamdBRGpqLy9nQUFjQUFBZmdmZ0Q4QWNmOGNmLy9qai8vZ0FEamovL2dBQWNBQUFmZ2ZnRDhBY2Y4Y2YvL2pqLy9nQURqai8vZ0FBY0FBQWZnZmdEOEFjZjhjZi8vamovL2dBY2NBY0FBZmo4QWZqOEFEamdBZmdEZ2NEai9qampnQUFjY0FjQUFmajhBZmo4QURqZ0FmZ0RnY0RqL2pqamdBQWNjQWNBQWZqOEFmajhBRGpnQWZnRGdjRGovampqZ0FBQUQvOEFmOGNjZmpqZ2ZnZi8vOGNmOEQ4RGovL2pnQUFBRC84QWY4Y2NmampnZmdmLy84Y2Y4RDhEai8vamdBQUFELzhBZjhjY2ZqamdmZ2YvLzhjZjhEOERqLy9qZ0FBY2NjRDhmZ2Y4Y2NmOGNmLzhmamo4Y0FEOEFmOEFmZ0FjY2NEOGZnZjhjY2Y4Y2YvOGZqajhjQUQ4QWY4QWZnQWNjY0Q4ZmdmOGNjZjhjZi84ZmpqOGNBRDhBZjhBZmdBY0RqL2pqLy9nZmdEajhjRC9qamdEajhjRGdmZ2YvZ0FjRGovamovL2dmZ0RqOGNEL2pqZ0RqOGNEZ2ZnZi9nQWNEai9qai8vZ2ZnRGo4Y0QvampnRGo4Y0RnZmdmL2dBZmo4Zmo4Y0RqZ2YvL2ovZ0FEZ0RnZjhmZ0FEZ2ZqZ0FmajhmajhjRGpnZi8vai9nQURnRGdmOGZnQURnZmpnQWZqOGZqOGNEamdmLy9qL2dBRGdEZ2Y4ZmdBRGdmamdBZmdmOGNjQURnRC8vOGNBRC9qZ2ZnZmpnQWNBY0FEZ0FmZ2Y4Y2NBRGdELy84Y0FEL2pnZmdmamdBY0FjQURnQWZnZjhjY0FEZ0QvLzhjQUQvamdmZ2ZqZ0FjQWNBRGdEZ2NBY0FEZ2NBY2NjZmdEZ2YvZ2NjY2NBY0QvamdBQURnY0FjQURnY0FjY2NmZ0RnZi9nY2NjY0FjRC9qZ0FBRGdjQWNBRGdjQWNjY2ZnRGdmL2djY2NjQWNEL2pnQUFBY2ZqamdELy9qOERqZ0FEL2ovai9qL2pqamdEOEFmZ0FjZmpqZ0QvL2o4RGpnQUQvai9qL2ovampqZ0Q4QWZnQWNmampnRC8vajhEamdBRC9qL2ovai9qampnRDhBZmdEai9nRGdjQURqamo4QUFEOERqOGZqZ0Q4RDhEai9nQURqL2dEZ2NBRGpqajhBQUQ4RGo4ZmpnRDhEOERqL2dBRGovZ0RnY0FEampqOEFBRDhEajhmamdEOEQ4RGovZ0FEOGZqOEFEamdmampqampnQUQvLzhmajhmamdjZi84QUQ4Zmo4QURqZ2ZqampqamdBRC8vOGZqOGZqZ2NmLzhBRDhmajhBRGpnZmpqampqZ0FELy84Zmo4ZmpnY2YvOEFEL2djQWYvOGZnRGdBRGpnRGdmZ2NEZ2Y4QUQvamovZ0QvZ2NBZi84ZmdEZ0FEamdEZ2ZnY0RnZjhBRC9qai9nRC9nY0FmLzhmZ0RnQURqZ0RnZmdjRGdmOEFEL2pqL2dBQUQvLy8vZ2NmOGZqZ0QvLy9qZ2YvZ2YvOEQvL2pqZ0FBRC8vLy9nY2Y4ZmpnRC8vL2pnZi9nZi84RC8vampnQUFELy8vL2djZjhmamdELy8vamdmL2dmLzhELy9qamdBQURnRGdmZ0FBZi9qL2pnRDhjQWZqOGNBQURnRGdEZ0FBRGdEZ2ZnQUFmL2ovamdEOGNBZmo4Y0FBRGdEZ0RnQUFEZ0RnZmdBQWYvai9qZ0Q4Y0FmajhjQUFEZ0RnRGdEZ0RqamdjQWNEL2ovOGZqamdBQUQ4RDhEOGZqajhBQURnRGpqZ2NBY0Qvai84ZmpqZ0FBRDhEOEQ4ZmpqOEFBRGdEampnY0FjRC9qLzhmampnQUFEOEQ4RDhmamo4QUFEZ2ZnRC84ZmovL2pnY2ZnRGpqZ0Rqai8vZ0RnRGpqZ0RnZmdELzhmai8vamdjZmdEampnRGpqLy9nRGdEampnRGdmZ0QvOGZqLy9qZ2NmZ0RqamdEamovL2dEZ0RqamdEOGYvL2o4RDhmamovai8vLzhjQUFmai8vZ0QvL2dmZ0Q4Zi8vajhEOGZqai9qLy8vOGNBQWZqLy9nRC8vZ2ZnRDhmLy9qOEQ4ZmpqL2ovLy84Y0FBZmovL2dELy9nZmdBRC84QWNEZ0QvamdjZjhmLy9qLy9nZmpqai84RGpqZ0FELzhBY0RnRC9qZ2NmOGYvL2ovL2dmampqLzhEampnQUQvOEFjRGdEL2pnY2Y4Zi8vai8vZ2ZqamovOERqamdEOGYvOGNBQUFjY2ZnQWZnY2ZqOERqLzhjY2ZnY0RqZ0Q4Zi84Y0FBQWNjZmdBZmdjZmo4RGovOGNjZmdjRGpnRDhmLzhjQUFBY2NmZ0FmZ2NmajhEai84Y2NmZ2NEamdEZ2Y4RGdjY0FBZi84Zi8vai8vZ0FjRDhmajhmamdEZ0RnZjhEZ2NjQUFmLzhmLy9qLy9nQWNEOGZqOGZqZ0RnRGdmOERnY2NBQWYvOGYvL2ovL2dBY0Q4Zmo4ZmpnRGdEai9qLy8vLzhmL2dmajhELzhBY0FjY2NmOERqZ0RqZ0RqL2ovLy8vOGYvZ2ZqOEQvOEFjQWNjY2Y4RGpnRGpnRGovai8vLy84Zi9nZmo4RC84QWNBY2NjZjhEamdEamdBY0Q4Y0FEZ0RqOEQ4QWNmOGNmL2dBY2NBQUFEOGY4QUFjRDhjQURnRGo4RDhBY2Y4Y2YvZ0FjY0FBQUQ4ZjhBQWNEOGNBRGdEajhEOEFjZjhjZi9nQWNjQUFBRDhmOEFEamovZ0RnQUQvL2djZjhEajhBZmdEZ2NjZmdBZjhEZ0Rqai9nRGdBRC8vZ2NmOERqOEFmZ0RnY2NmZ0FmOERnRGpqL2dEZ0FELy9nY2Y4RGo4QWZnRGdjY2ZnQWY4RGdEOEFjQWNBY2NmOEQ4RC9qOGNEOEQ4Zi9qL2ovLzhBQUQ4QWNBY0FjY2Y4RDhEL2o4Y0Q4RDhmL2ovai8vOEFBRDhBY0FjQWNjZjhEOEQvajhjRDhEOGYvai9qLy84QUFEajhmOEFEai8vZ2YvajhEai84Y2ZqZ0RnQWNEZ0FBQURqOGY4QURqLy9nZi9qOERqLzhjZmpnRGdBY0RnQUFBRGo4ZjhBRGovL2dmL2o4RGovOGNmamdEZ0FjRGdBQUFEamdjY0Q4RC84RGpqOEFjRGpqOEFjZmovOERqLzhjQURqZ2NjRDhELzhEamo4QWNEamo4QWNmai84RGovOGNBRGpnY2NEOEQvOERqajhBY0RqajhBY2ZqLzhEai84Y0FELzhmLzhmL2dEamovZ0Q4RDhBRGdmZ0RqLy8vZ0FEZ0QvOGYvOGYvZ0Rqai9nRDhEOEFEZ2ZnRGovLy9nQURnRC84Zi84Zi9nRGpqL2dEOEQ4QURnZmdEai8vL2dBRGdBQUFjZmo4QUFBQUFmL2ovZ0Q4RGdBRGo4Zjhmai9nQUFBQWNmajhBQUFBQWYvai9nRDhEZ0FEajhmOGZqL2dBQUFBY2ZqOEFBQUFBZi9qL2dEOERnQURqOGY4ZmovZ0FBY2YvamdEZ2NjZi9qL2dmamdBZmovOEFBRDhELy84QUFjZi9qZ0RnY2NmL2ovZ2ZqZ0Fmai84QUFEOEQvLzhBQWNmL2pnRGdjY2Yvai9nZmpnQWZqLzhBQUQ4RC8vOEFBQWNjQURqai9qL2pnQUFjRGpqamo4RGpnZmpnY2ZqZ0FBY2NBRGpqL2ovamdBQWNEampqajhEamdmamdjZmpnQUFjY0FEamovai9qZ0FBY0RqampqOERqZ2ZqZ2NmamdBZmdEOERnQUQ4ZmdBY0FEampnY0RqZ0FmOERqajhBQUFmZ0Q4RGdBRDhmZ0FjQURqamdjRGpnQWY4RGpqOEFBQWZnRDhEZ0FEOGZnQWNBRGpqZ2NEamdBZjhEamo4QUFBQUQ4QUFjQWNmL2dmampqL2pqL2ovOEFBZi9qampqZ0FBRDhBQWNBY2YvZ2Zqamovamovai84QUFmL2pqampnQUFEOEFBY0FjZi9nZmpqai9qai9qLzhBQWYvampqamdBQWNmOERnY0FjQUFEOGY4RGpqai84RGovampqajhEZ0FBY2Y4RGdjQWNBQUQ4ZjhEampqLzhEai9qampqOERnQUFjZjhEZ2NBY0FBRDhmOERqamovOERqL2pqamo4RGdBY0Q4Y2NEamdEampnY2NmZ2Y4QWNEampnZmdmLy9qZ0FjRDhjY0RqZ0RqamdjY2ZnZjhBY0RqamdmZ2YvL2pnQWNEOGNjRGpnRGpqZ2NjZmdmOEFjRGpqZ2ZnZi8vamdBRC9qZ2NjRGdmL2djY2NEL2pnQWNBRC8vOEFmOEFmZ0FEL2pnY2NEZ2YvZ2NjY0QvamdBY0FELy84QWY4QWZnQUQvamdjY0RnZi9nY2NjRC9qZ0FjQUQvLzhBZjhBZmdBQURnRGdmOERnRGdmajhjQUQvL2pqOGYvamo4Zmo4QUFBRGdEZ2Y4RGdEZ2ZqOGNBRC8vamo4Zi9qajhmajhBQUFEZ0RnZjhEZ0RnZmo4Y0FELy9qajhmL2pqOGZqOEFEZ2YvL2djQWZnRGpqZ2YvLy9nQWZnQURqOEQ4RGovZ0RnZi8vZ2NBZmdEampnZi8vL2dBZmdBRGo4RDhEai9nRGdmLy9nY0FmZ0RqamdmLy8vZ0FmZ0FEajhEOERqL2dBQUFBQUQ4Zi9nY0FjRGpnRDhmL2dmamdjY0FBQUFBQUFBQUFBRDhmL2djQWNEamdEOGYvZ2ZqZ2NjQUFBQUFBQUFBQUFEOGYvZ2NBY0RqZ0Q4Zi9nZmpnY2NBQUFBQUFELy8vampqampqampqampqampqampqampqampqLy8vZ0QvLy9qampqampqampqampqampqampqampqamovLy9nRC8vL2pqampqampqampqampqampqampqampqai8vL2dEZ0FEZ0FBQUQvai9nY2ZnRC9qOGZqOEFjZmdEZ0FEZ0RnQURnQUFBRC9qL2djZmdEL2o4Zmo4QWNmZ0RnQURnRGdBRGdBQUFEL2ovZ2NmZ0QvajhmajhBY2ZnRGdBRGdEai9qamdmZ2ZqOEFjRGovLzhEamdmL2dEajhEai9qZ0RqL2pqZ2ZnZmo4QWNEai8vOERqZ2YvZ0RqOERqL2pnRGovampnZmdmajhBY0RqLy84RGpnZi9nRGo4RGovamdEai9qZ2NBRDhjZmo4RGpnY2Y4Zi8vZ0FmL2pqai9qZ0RqL2pnY0FEOGNmajhEamdjZjhmLy9nQWYvampqL2pnRGovamdjQUQ4Y2ZqOERqZ2NmOGYvL2dBZi9qamovamdEai9qamo4QURnZi9qOGYvLy9nY2ZqLy9qLy9qai9qZ0RqL2pqajhBRGdmL2o4Zi8vL2djZmovL2ovL2pqL2pnRGovampqOEFEZ2YvajhmLy8vZ2Nmai8vai8vamovamdEZ0FEai84RDhEZ2NELzhEZ0RnY0FEZ2NBY2ZqZ0FEZ0RnQURqLzhEOERnY0QvOERnRGdjQURnY0FjZmpnQURnRGdBRGovOEQ4RGdjRC84RGdEZ2NBRGdjQWNmamdBRGdELy8vai84Y2NmOEFmai84Zmo4RGovLy9qZ2ZqLy8vZ0QvLy9qLzhjY2Y4QWZqLzhmajhEai8vL2pnZmovLy9nRC8vL2ovOGNjZjhBZmovOGZqOERqLy8vamdmai8vL2dBPSI+PC9pbWc+PC9kaXY+PC9kaXY+PC9kaXY+PGRpdiBjbGFzcz0ic2luZ2xlIj48ZGl2PjxkaXYgY2xhc3M9ImJyZWFrLXdvcmQiPjxzcGFuIGNsYXNzPSJib2xkIj5CYXJiYXJhPC9zcGFuPjxicj50YjFxdTZsY3VhOXcyemthcmpqNXh3eGgzbDNxdGN4aDg0aHNyYTNqcnZwc3poNjlqMmU1NHg3cTN0aHljdzwvZGl2PjxkaXYgY2xhc3M9ImNlbnRlciI+PGltZyBjbGFzcz0icXIiIHNyYz0iZGF0YTppbWFnZS9ibXA7YmFzZTY0LFFrMXVCZ0FBQUFBQUFENEFBQUFvQUFBQVl3QUFBR01BQUFBQkFBRUFBQUFBQURBR0FBQUFBZ0FBQUFJQUFBSUFBQUFDQUFBQS8vLy9BQUFBQUFELy8vamdBY0QvOEFjQWY4ZmdBQUFBLy8vNDRBSEEvL0FIQUgvSDRBQUFBUC8vK09BQndQL3dCd0IveCtBQUFBRGdBRGdBQWNmL2dEL2dEOERnQUFBQTRBQTRBQUhILzRBLzRBL0E0QUFBQU9BQU9BQUJ4LytBUCtBUHdPQUFBQURqL2pnQUQvOEFEL2dmZ2ZnQUFBQUE0LzQ0QUEvL0FBLzRINEg0QUFBQUFPUCtPQUFQL3dBUCtCK0IrQUFBQUFEai9qZ2NjQUFEL2dmZ0QvamdBQUFBNC80NEhIQUFBLzRINEEvNDRBQUFBT1ArT0J4d0FBUCtCK0FQK09BQUFBRGovamo4Y0RqZ0FELy8vLzhBQUFBQTQvNDQvSEE0NEFBLy8vLy9BQUFBQU9QK09QeHdPT0FBUC8vLy93QUFBQURnQURnZmdmamdEampnRDhBQUFBQUE0QUE0SDRINDRBNDQ0QS9BQUFBQUFPQUFPQitCK09BT09PQVB3QUFBQUFELy8vampnZi9qZ0FmampqL2dBQUFBLy8vNDQ0SC80NEFINDQ0LzRBQUFBUC8vK09PQi8rT0FCK09PUCtBQUFBQUFBQUQ4RGdEOGYvamdEajhBQUFBQUFBQUEvQTRBL0gvNDRBNC9BQUFBQUFBQUFQd09BUHgvK09BT1B3QUFBQUQvZ2ZnY0Q4Y2ZnZi8vLzhBQUFBQUEvNEg0SEEvSEg0SC8vLy9BQUFBQUFQK0IrQndQeHgrQi8vLy93QUFBQUFBRDhjQWNmZ0FjZmo4Y0RqL2dBQUFBQS9IQUhINEFISDQvSEE0LzRBQUFBQVB4d0J4K0FCeCtQeHdPUCtBQUFBQUQ4Zi9nRDhEajhBQUFEOGNBQUFBQUEvSC80QS9BNC9BQUFBL0hBQUFBQUFQeC8rQVB3T1B3QUFBUHh3QUFBQUQvL2dEamdjRGdjZjhjY2ZqZ0FBQUEvLzRBNDRIQTRISC9ISEg0NEFBQUFQLytBT09Cd09CeC94eHgrT0FBQUFEajhEOGNmZ0FEL2dBRGdmL2dBQUFBNC9BL0hINEFBLzRBQTRILzRBQUFBT1B3UHh4K0FBUCtBQU9CLytBQUFBRC9qOGNmOEFjZmo4RGdBQUFBQUFBQS80L0hIL0FISDQvQTRBQUFBQUFBQVArUHh4L3dCeCtQd09BQUFBQUFBQUQ4QURnQUFBRDhBZi84RGpqZ0FBQUEvQUE0QUFBQS9BSC8vQTQ0NEFBQUFQd0FPQUFBQVB3Qi8vd09PT0FBQUFBY0FjRGdEZ0RqamdBY2NjZmdBQUFBSEFIQTRBNEE0NDRBSEhISDRBQUFBQndCd09BT0FPT09BQnh4eCtBQUFBRGdBRDhBQWNEZ2NmajhjZi9nQUFBQTRBQS9BQUhBNEhINC9ISC80QUFBQU9BQVB3QUJ3T0J4K1B4eC8rQUFBQUFjZjhjZi84ZmdBY2NEOGZqZ0FBQUFISC9ISC8vSDRBSEhBL0g0NEFBQUFCeC94eC8veCtBQnh3UHgrT0FBQUFBRGovZ0FmZ2NEamo4Y2NBY0FBQUFBQTQvNEFINEhBNDQvSEhBSEFBQUFBQU9QK0FCK0J3T09QeHh3QndBQUFBRDhjQUQvOGZnRC84RDhELy9nQUFBQS9IQUEvL0g0QS8vQS9BLy80QUFBQVB4d0FQL3grQVAvd1B3UC8rQUFBQUFEamovL2o4RGdjRC84RGo4QUFBQUFBNDQvLzQvQTRIQS8vQTQvQUFBQUFBT09QLytQd09Cd1Avd09Qd0FBQUFELy9nRC84Y2NBRGovZ2YvL2dBQUFBLy80QS8vSEhBQTQvNEgvLzRBQUFBUC8rQVAveHh3QU9QK0IvLytBQUFBRDhmamdmOGZqajhBZmovOERnQUFBQS9INDRIL0g0NC9BSDQvL0E0QUFBQVB4K09CL3grT1B3QitQL3dPQUFBQUQvLzhEOERnRDhmLy9nQURnQUFBQUEvLy9BL0E0QS9ILy80QUE0QUFBQUFQLy93UHdPQVB4Ly8rQUFPQUFBQUFEZ0RqL2djRC9qZ2YvLy84RGdBQUFBNEE0LzRIQS80NEgvLy8vQTRBQUFBT0FPUCtCd1ArT0IvLy8vd09BQUFBQUFBQURnQUFBZi84RGdBQUFBQUFBQUFBQUE0QUFBSC8vQTRBQUFBQUFBQUFBQUFPQUFBQi8vd09BQUFBQUFBQUQvLy9qampqampqampqLy8vZ0FBQUEvLy80NDQ0NDQ0NDQ0Ly8vNEFBQUFQLy8rT09PT09PT09PUC8vK0FBQUFEZ0FEai9qLzhjRGdmamdBRGdBQUFBNEFBNC80Ly9IQTRINDRBQTRBQUFBT0FBT1ArUC94d09CK09BQU9BQUFBRGovamovOGNEOGNmZ0RqL2pnQUFBQTQvNDQvL0hBL0hINEE0LzQ0QUFBQU9QK09QL3h3UHh4K0FPUCtPQUFBQURqL2pqLzhBRDhBZjhEai9qZ0FBQUE0LzQ0Ly9BQS9BSC9BNC80NEFBQUFPUCtPUC93QVB3Qi93T1ArT0FBQUFEai9qZ0QvamdmLzhEamovamdBQUFBNC80NEEvNDRILy9BNDQvNDRBQUFBT1ArT0FQK09CLy93T09QK09BQUFBRGdBRGdELy84RGpnZmpnQURnQUFBQTRBQTRBLy8vQTQ0SDQ0QUE0QUFBQU9BQU9BUC8vd09PQitPQUFPQUFBQUQvLy9qZ0Q4QURnRC9qLy8vZ0FBQUEvLy80NEEvQUE0QS80Ly8vNEFBQUFQLy8rT0FQd0FPQVArUC8vK0FBQUFBPSI+PC9pbWc+PC9kaXY+PC9kaXY+PGRpdiBjbGFzcz0iYmxhY2siPjwvZGl2PjxkaXY+PGRpdiBjbGFzcz0iYnJlYWstd29yZCI+PGRpdiBjbGFzcz0icGFkIj53c2gobXVsdGkoMixHcmFuZG1hLEFsaWNlLEJhcmJhcmEpKSNueGZhNW4wejwvZGl2PjxkaXYgY2xhc3M9InBhZCI+QWxpY2U6IDAyZTQ4NmUzMmYwZjg3MTM2ZmEwNDJjYjUzMjE5YWNlODUzN2VhMWQwMzZkZWIyZjQyOTM1NzBiOTQzMjVkMTFjYjwvZGl2PjxkaXYgY2xhc3M9InBhZCI+QmFyYmFyYTogY1NmTUx6U1o5TmpXVVRxTDNzRnBnV0pzc251MnFnbUUyY201TjFqUERSUkp1RGNyc1BFQjwvZGl2PjxkaXYgY2xhc3M9InBhZCI+R3JhbmRtYTogMDNmMWJkMmJmZjhlOWM2MWY1OGE4ZDQ2ZDE4ZmQ4ZjMxNDliMWYyZDc2YjNjNDIzYTc4NzRhNWQ1ODExZDY3Y2VlPC9kaXY+PC9kaXY+PGRpdiBjbGFzcz0iY2VudGVyIj48aW1nIGNsYXNzPSJxciIgc3JjPSJkYXRhOmltYWdlL2JtcDtiYXNlNjQsUWsxbUVRQUFBQUFBQUQ0QUFBQW9BQUFBdHdBQUFMY0FBQUFCQUFFQUFBQUFBQ2dSQUFBQUFnQUFBQUlBQUFJQUFBQUNBQUFBLy8vL0FBQUFBQUQvLy9qOGZqOGY4Y0Q4Y0QvZ2NBQWY4ZmdmL2o4QWZnRC8vL2o4Zmo4ZjhjRDhjRC9nY0FBZjhmZ2YvajhBZmdELy8vajhmajhmOGNEOGNEL2djQUFmOGZnZi9qOEFmZ0RnQURnRDhjZmdBQWNjQUFmZ0Q4Y0QvL2o4ZmovOEFBRGdBRGdEOGNmZ0FBY2NBQWZnRDhjRC8vajhmai84QUFEZ0FEZ0Q4Y2ZnQUFjY0FBZmdEOGNELy9qOGZqLzhBQURqL2pnY0FBY0FBY2ZnRDhBQWNmL2pnRC9nRGo4QURnRGovamdjQUFjQUFjZmdEOEFBY2YvamdEL2dEajhBRGdEai9qZ2NBQWNBQWNmZ0Q4QUFjZi9qZ0QvZ0RqOEFEZ0RqL2pqOEQ4QUQvLzhmLzhmLy84ZjhBQWNmOGZnZjhBRGovamo4RDhBRC8vOGYvOGYvLzhmOEFBY2Y4ZmdmOEFEai9qajhEOEFELy84Zi84Zi8vOGY4QUFjZjhmZ2Y4QURqL2pnY0FEOGZnQWZnZi8vamdjY0QvL2pnZi8vZ2ZnRGovamdjQUQ4ZmdBZmdmLy9qZ2NjRC8vamdmLy9nZmdEai9qZ2NBRDhmZ0FmZ2YvL2pnY2NELy9qZ2YvL2dmZ0RnQURqL2djRGdmZ2NEamdEOGNEL2pnZi9nRGdEOGNBRGdBRGovZ2NEZ2ZnY0RqZ0Q4Y0QvamdmL2dEZ0Q4Y0FEZ0FEai9nY0RnZmdjRGpnRDhjRC9qZ2YvZ0RnRDhjQUQvLy9nY0QvamdEZ2YvampqamdmZ0RqamovampqZ0RnRC8vL2djRC9qZ0RnZi9qampqZ2ZnRGpqai9qampnRGdELy8vZ2NEL2pnRGdmL2pqampnZmdEampqL2pqamdEZ0FBQUFEZ2ZqLy9qZ0QvamdEamdBQWNjY0FBZmdEamdBQUFBQURnZmovL2pnRC9qZ0RqZ0FBY2NjQUFmZ0RqZ0FBQUFBRGdmai8vamdEL2pnRGpnQUFjY2NBQWZnRGpnQUQvOEQ4RGdEZ0Q4QWY4RC8vZ2YvOERqZ0Qvai8vampnRC84RDhEZ0RnRDhBZjhELy9nZi84RGpnRC9qLy9qamdELzhEOERnRGdEOEFmOEQvL2dmLzhEamdEL2ovL2pqZ0QvamdjY0FBZi9nRC9nRDhEOGY4ZjhmOERqL2o4ZjhBRC9qZ2NjQUFmL2dEL2dEOEQ4ZjhmOGY4RGovajhmOEFEL2pnY2NBQWYvZ0QvZ0Q4RDhmOGY4ZjhEai9qOGY4QUFELy9qajhmL2dBY2Y4RGpnQWNmZ0FBY2NmL2pnRC9nQUQvL2pqOGYvZ0FjZjhEamdBY2ZnQUFjY2YvamdEL2dBRC8vamo4Zi9nQWNmOERqZ0FjZmdBQWNjZi9qZ0QvZ0FjQUFELy84Y0FjZmdBY2NjRDhBRDhBZjhBRDhmOEFBQWNBQUQvLzhjQWNmZ0FjY2NEOEFEOEFmOEFEOGY4QUFBY0FBRC8vOGNBY2ZnQWNjY0Q4QUQ4QWY4QUQ4ZjhBQUFBZmpqLy9nY0FEOEQ4RDhEZ2Nmai9qai9qajhBRC9nQUFmamovL2djQUQ4RDhEOERnY2ZqL2pqL2pqOEFEL2dBQWZqai8vZ2NBRDhEOEQ4RGdjZmovamovamo4QUQvZ0FjRGdjQUFELy9nY2YvOEQvZ2NEZ2NBQUFBY0RnY2ZnQWNEZ2NBQUQvL2djZi84RC9nY0RnY0FBQUFjRGdjZmdBY0RnY0FBRC8vZ2NmLzhEL2djRGdjQUFBQWNEZ2NmZ0Qvai8vampnZi9nRC84RDhBY2NEZ2Yvamo4QWYvZ0FBRC9qLy9qamdmL2dELzhEOEFjY0RnZi9qajhBZi9nQUFEL2ovL2pqZ2YvZ0QvOEQ4QWNjRGdmL2pqOEFmL2dBQURqajhjY0FBY0FBRGdmOGY4Y2NjY2NELzhjZi8vOGZnRGpqOGNjQUFjQUFEZ2Y4ZjhjY2NjY0QvOGNmLy84ZmdEamo4Y2NBQWNBQURnZjhmOGNjY2NjRC84Y2YvLzhmZ0FEL2ovZ2NjQUQvai9qOGNBZi84RGo4QWNjRGdBRDhBQUQvai9nY2NBRC9qL2o4Y0FmLzhEajhBY2NEZ0FEOEFBRC9qL2djY0FEL2ovajhjQWYvOERqOEFjY0RnQUQ4QUFBRGdBY2ZqOEFmajhELzhmLzhBZjhEai84QWZqOGNBQUFEZ0FjZmo4QWZqOEQvOGYvOEFmOERqLzhBZmo4Y0FBQURnQWNmajhBZmo4RC84Zi84QWY4RGovOEFmajhjQUQ4RGo4QUQ4QURqOGY4RGdEZ0FBZmdjQUFELy9qL2dBRDhEajhBRDhBRGo4ZjhEZ0RnQUFmZ2NBQUQvL2ovZ0FEOERqOEFEOEFEajhmOERnRGdBQWZnY0FBRC8vai9nQUFEZ2NjRGdmZ0RqamdEajhBZjhBZmdEOGNBZmdjZmdBQURnY2NEZ2ZnRGpqZ0RqOEFmOEFmZ0Q4Y0FmZ2NmZ0FBRGdjY0RnZmdEampnRGo4QWY4QWZnRDhjQWZnY2ZnQUFmOERnZi9qajhEOGYvOGNmai8vOEFEL2dmOGNmampnQWY4RGdmL2pqOEQ4Zi84Y2ZqLy84QUQvZ2Y4Y2ZqamdBZjhEZ2Yvamo4RDhmLzhjZmovLzhBRC9nZjhjZmpqZ0QvZ2NjY2ZqZ2NjQWZnY0FmajhEL2o4QWNELzhmZ2NBRC9nY2NjZmpnY2NBZmdjQWZqOEQvajhBY0QvOGZnY0FEL2djY2NmamdjY0FmZ2NBZmo4RC9qOEFjRC84ZmdjQUQvZ0RnQWNjRDhmai9nY2Y4Zi84RGo4QUFBQWZnY2ZnRC9nRGdBY2NEOGZqL2djZjhmLzhEajhBQUFBZmdjZmdEL2dEZ0FjY0Q4ZmovZ2NmOGYvOERqOEFBQUFmZ2NmZ0FEZ2Nmai9qajhjQUFBZi8vamdjRGdEamdBQWY4Zi9nQURnY2ZqL2pqOGNBQUFmLy9qZ2NEZ0RqZ0FBZjhmL2dBRGdjZmovamo4Y0FBQWYvL2pnY0RnRGpnQUFmOGYvZ0FjRGovampqZ0Rqamo4QWNBZmpqai9qOGNBRC9nRGpnQWNEai9qampnRGpqajhBY0FmampqL2o4Y0FEL2dEamdBY0RqL2pqamdEampqOEFjQWZqamovajhjQUQvZ0RqZ0QvZ2NjQUQvL2ovOEFEL2dmLzhBQWNmOEFmLzhjQWZnRC9nY2NBRC8vai84QUQvZ2YvOEFBY2Y4QWYvOGNBZmdEL2djY0FELy9qLzhBRC9nZi84QUFjZjhBZi84Y0FmZ0RnRC9nRDhBZi8vL2o4Zmo4ZmpqZ0QvZ0QvZ0FEOEFBRGdEL2dEOEFmLy8vajhmajhmampnRC9nRC9nQUQ4QUFEZ0QvZ0Q4QWYvLy9qOGZqOGZqamdEL2dEL2dBRDhBQUFEamdmOGNEai8vLzhjY2Y4ZmdmajhmZ0QvL2djZmdBQURqZ2Y4Y0RqLy8vOGNjZjhmZ2ZqOGZnRC8vZ2NmZ0FBRGpnZjhjRGovLy84Y2NmOGZnZmo4ZmdELy9nY2ZnQUFmai8vZ2YvOEQvOERnZi8vai84RGo4RGpnZi8vampnQWZqLy9nZi84RC84RGdmLy9qLzhEajhEamdmLy9qamdBZmovL2dmLzhELzhEZ2YvL2ovOERqOERqZ2YvL2pqZ0Q4ZmdELy9nQUQvZ2ZnRGdEamovZ2NEai8vamdEL2pnRDhmZ0QvL2dBRC9nZmdEZ0Rqai9nY0RqLy9qZ0QvamdEOGZnRC8vZ0FEL2dmZ0RnRGpqL2djRGovL2pnRC9qZ0Q4ZmpqOGZqLy84ZmdEL2pqOGNjZmdmZ2ZnRGpqai9nRDhmamo4ZmovLzhmZ0Qvamo4Y2NmZ2ZnZmdEampqL2dEOGZqajhmai8vOGZnRC9qajhjY2ZnZmdmZ0RqamovZ0Q4RGdEOEFjY0RnZmdEL2dEOGNmOGNjQUFmL2dEOERnRDhEZ0Q4QWNjRGdmZ0QvZ0Q4Y2Y4Y2NBQWYvZ0Q4RGdEOERnRDhBY2NEZ2ZnRC9nRDhjZjhjY0FBZi9nRDhEZ0QvLy8vZ0Q4Zmo4Y0Q4RC8vZ0FjY0Qvamo4RC8vZ2NBRC8vLy9nRDhmajhjRDhELy9nQWNjRC9qajhELy9nY0FELy8vL2dEOGZqOGNEOEQvL2dBY2NEL2pqOEQvL2djQUQ4QUFmOGNELy9nY0RnQUFBQWNBQWZnY2NjZmo4ZmpnRDhBQWY4Y0QvL2djRGdBQUFBY0FBZmdjY2NmajhmamdEOEFBZjhjRC8vZ2NEZ0FBQUFjQUFmZ2NjY2ZqOGZqZ0Q4RGovZ2ZqamdjZjhEZ2NBRGdBRC84QWZqajhmai9nRDhEai9nZmpqZ2NmOERnY0FEZ0FELzhBZmpqOGZqL2dEOERqL2dmampnY2Y4RGdjQURnQUQvOEFmamo4ZmovZ0QvajhmL2dBRGdEOERnQUFjQWNmZ0Q4ZmdBY0FBY0RnRC9qOGYvZ0FEZ0Q4RGdBQWNBY2ZnRDhmZ0FjQUFjRGdEL2o4Zi9nQURnRDhEZ0FBY0FjZmdEOGZnQWNBQWNEZ0FmZ2Yvai8vamdmOEQvZ2ZqZ2NBRGdEamovZ2Y4ZmdBQWZnZi9qLy9qZ2Y4RC9nZmpnY0FEZ0Rqai9nZjhmZ0FBZmdmL2ovL2pnZjhEL2dmamdjQURnRGpqL2dmOGZnQURqZ2NmOGNEOERqL2ovamdEamdBQWZqai9qLzhmZ0RnRGpnY2Y4Y0Q4RGovai9qZ0RqZ0FBZmpqL2ovOGZnRGdEamdjZjhjRDhEai9qL2pnRGpnQUFmamovai84ZmdEZ0FBRC9nQWNjZmpqL2dEZ2YvZ2NmL2o4QWNjY0RqZ2ZnQUFEL2dBY2NmamovZ0RnZi9nY2YvajhBY2NjRGpnZmdBQUQvZ0FjY2Zqai9nRGdmL2djZi9qOEFjY2NEamdmZ0FjQWNmai9qamdEOEQ4QWNEai84Zi8vZ0RnY0FmajhBQWNBY2ZqL2pqZ0Q4RDhBY0RqLzhmLy9nRGdjQWZqOEFBY0FjZmovampnRDhEOEFjRGovOGYvL2dEZ2NBZmo4QUFjRC8vOGYvamo4RGovZ2NEL2pqLzhmOERqZ2NBY2NBQWNELy84Zi9qajhEai9nY0QvamovOGY4RGpnY0FjY0FBY0QvLzhmL2pqOERqL2djRC9qai84ZjhEamdjQWNjQUQvL2djY0FjRGpqOGNELy84QWYvOGZqOGNEOERqampnRC8vZ2NjQWNEamo4Y0QvLzhBZi84Zmo4Y0Q4RGpqamdELy9nY2NBY0RqajhjRC8vOEFmLzhmajhjRDhEampqZ0FBQWYvZ0RqLy8vL2o4Zi9nZjhEOGY4RDhEamdjY2ZnQUFBZi9nRGovLy8vajhmL2dmOEQ4ZjhEOERqZ2NjZmdBQUFmL2dEai8vLy9qOGYvZ2Y4RDhmOEQ4RGpnY2NmZ0FEamdjQUQ4Y2NjY2NjQWZqOERqLy9nY2ZqamdmZ2ZnQURqZ2NBRDhjY2NjY2NBZmo4RGovL2djZmpqZ2ZnZmdBRGpnY0FEOGNjY2NjY0FmajhEai8vZ2NmampnZmdmZ0RqZ0Q4QWZqampnZmo4QUQ4Y2NmL2pqZ0QvZ0FEZ0FBRGpnRDhBZmpqamdmajhBRDhjY2YvampnRC9nQURnQUFEamdEOEFmampqZ2ZqOEFEOGNjZi9qamdEL2dBRGdBQURnZmdjY2Y4Y0Q4Zi8vajhBZjhmOEFjY2NEamdmZ2NBRGdmZ2NjZjhjRDhmLy9qOEFmOGY4QWNjY0RqZ2ZnY0FEZ2ZnY2NmOGNEOGYvL2o4QWY4ZjhBY2NjRGpnZmdjQUQ4QUQvajhBQUFmOGY4RC9qLzhBZi84Y0RnRDhmZ2NBRDhBRC9qOEFBQWY4ZjhEL2ovOEFmLzhjRGdEOGZnY0FEOEFEL2o4QUFBZjhmOEQvai84QWYvOGNEZ0Q4ZmdjQUQ4RDhmamovZ0FEai9nRGdBY2NjY0FELy9nRDhjY2NBRDhEOGZqai9nQURqL2dEZ0FjY2NjQUQvL2dEOGNjY0FEOEQ4ZmpqL2dBRGovZ0RnQWNjY2NBRC8vZ0Q4Y2NjQUFjQURnY0FEai9nZjhEai84Zi9qamdmL2ovZ0Qvai9nQWNBRGdjQURqL2dmOERqLzhmL2pqZ2Yvai9nRC9qL2dBY0FEZ2NBRGovZ2Y4RGovOGYvampnZi9qL2dEL2ovZ0RnY2NELzhEZ2NBY2YvOGYvZ0QvajhjY2ZnRC9nZi9nRGdjY0QvOERnY0FjZi84Zi9nRC9qOGNjZmdEL2dmL2dEZ2NjRC84RGdjQWNmLzhmL2dEL2o4Y2NmZ0QvZ2YvZ0FmLy84Zi9nRGdBRDhmOERnZjhjQWNmampnQURnRC9nQWYvLzhmL2dEZ0FEOGY4RGdmOGNBY2ZqamdBRGdEL2dBZi8vOGYvZ0RnQUQ4ZjhEZ2Y4Y0FjZmpqZ0FEZ0QvZ0RqOGNjZjhEOEFmZ0Q4RGdmOEFBY2NEZ0FjQURnY2NBRGo4Y2NmOEQ4QWZnRDhEZ2Y4QUFjY0RnQWNBRGdjY0FEajhjY2Y4RDhBZmdEOERnZjhBQWNjRGdBY0FEZ2NjQURnY2ZqajhjY0RnZmdmai8vajhjRDhjZi9nQWNjQUFBRGdjZmpqOGNjRGdmZ2ZqLy9qOGNEOGNmL2dBY2NBQUFEZ2Nmamo4Y2NEZ2ZnZmovL2o4Y0Q4Y2YvZ0FjY0FBQUFBQUFBZmo4Zi84RC9nRGdEamdBZmdjZmpqOEFBQUFBQUFBQUFmajhmLzhEL2dEZ0RqZ0FmZ2Nmamo4QUFBQUFBQUFBQWZqOGYvOEQvZ0RnRGpnQWZnY2ZqajhBQUFBQUQvLy9qampqampqampqampqampqampqampqamovLy9nRC8vL2pqampqampqampqampqampqampqampqai8vL2dELy8vampqampqampqampqampqampqampqampqLy8vZ0RnQURqOGNELzhjQURnRGdEZ2ZqL2dmOGNmZ0RnQURnRGdBRGo4Y0QvOGNBRGdEZ0RnZmovZ2Y4Y2ZnRGdBRGdEZ0FEajhjRC84Y0FEZ0RnRGdmai9nZjhjZmdEZ0FEZ0RqL2pnZi9nZmpqamovai8vZ2YvOEQvL2ovOERqL2pnRGovamdmL2dmampqai9qLy9nZi84RC8vai84RGovamdEai9qZ2YvZ2ZqampqL2ovL2dmLzhELy9qLzhEai9qZ0RqL2pnY2YvL2pnY0FjZi9qZ2ZnQWNjY2NEampqL2pnRGovamdjZi8vamdjQWNmL2pnZmdBY2NjY0RqamovamdEai9qZ2NmLy9qZ2NBY2YvamdmZ0FjY2NjRGpqai9qZ0RqL2pnRGdBZmdELy9nRGpqampnZi9nY2ZqL2pqL2pnRGovamdEZ0FmZ0QvL2dEampqamdmL2djZmovamovamdEai9qZ0RnQWZnRC8vZ0RqampqZ2YvZ2Nmai9qai9qZ0RnQURnQUQvamdmajhBRDhmOERnY2ZqOGZnZmpnQURnRGdBRGdBRC9qZ2ZqOEFEOGY4RGdjZmo4ZmdmamdBRGdEZ0FEZ0FEL2pnZmo4QUQ4ZjhEZ2NmajhmZ2ZqZ0FEZ0QvLy9nRGdBQURnY0QvamdEL2djRGdBZmdBZmovLy9nRC8vL2dEZ0FBRGdjRC9qZ0QvZ2NEZ0FmZ0Fmai8vL2dELy8vZ0RnQUFEZ2NEL2pnRC9nY0RnQWZnQWZqLy8vZ0E9Ij48L2ltZz48L2Rpdj48L2Rpdj48L2Rpdj48ZGl2IGNsYXNzPSJzaW5nbGUiPjxkaXY+PGRpdiBjbGFzcz0iYnJlYWstd29yZCI+PHNwYW4gY2xhc3M9ImJvbGQiPkdyYW5kbWE8L3NwYW4+PGJyPnRiMXF1NmxjdWE5dzJ6a2Fyamo1eHd4aDNsM3F0Y3hoODRoc3JhM2pydnBzemg2OWoyZTU0eDdxM3RoeWN3PC9kaXY+PGRpdiBjbGFzcz0iY2VudGVyIj48aW1nIGNsYXNzPSJxciIgc3JjPSJkYXRhOmltYWdlL2JtcDtiYXNlNjQsUWsxdUJnQUFBQUFBQUQ0QUFBQW9BQUFBWXdBQUFHTUFBQUFCQUFFQUFBQUFBREFHQUFBQUFnQUFBQUlBQUFJQUFBQUNBQUFBLy8vL0FBQUFBQUQvLy9qZ0FjRC84QWNBZjhmZ0FBQUEvLy80NEFIQS8vQUhBSC9INEFBQUFQLy8rT0FCd1Avd0J3Qi94K0FBQUFEZ0FEZ0FBY2YvZ0QvZ0Q4RGdBQUFBNEFBNEFBSEgvNEEvNEEvQTRBQUFBT0FBT0FBQngvK0FQK0FQd09BQUFBRGovamdBRC84QUQvZ2ZnZmdBQUFBQTQvNDRBQS8vQUEvNEg0SDRBQUFBQU9QK09BQVAvd0FQK0IrQitBQUFBQURqL2pnY2NBQUQvZ2ZnRC9qZ0FBQUE0LzQ0SEhBQUEvNEg0QS80NEFBQUFPUCtPQnh3QUFQK0IrQVArT0FBQUFEai9qajhjRGpnQUQvLy8vOEFBQUFBNC80NC9IQTQ0QUEvLy8vL0FBQUFBT1ArT1B4d09PQUFQLy8vL3dBQUFBRGdBRGdmZ2ZqZ0RqamdEOEFBQUFBQTRBQTRINEg0NEE0NDRBL0FBQUFBQU9BQU9CK0IrT0FPT09BUHdBQUFBQUQvLy9qamdmL2pnQWZqamovZ0FBQUEvLy80NDRILzQ0QUg0NDQvNEFBQUFQLy8rT09CLytPQUIrT09QK0FBQUFBQUFBRDhEZ0Q4Zi9qZ0RqOEFBQUFBQUFBQS9BNEEvSC80NEE0L0FBQUFBQUFBQVB3T0FQeC8rT0FPUHdBQUFBRC9nZmdjRDhjZmdmLy8vOEFBQUFBQS80SDRIQS9ISDRILy8vL0FBQUFBQVArQitCd1B4eCtCLy8vL3dBQUFBQUFEOGNBY2ZnQWNmajhjRGovZ0FBQUFBL0hBSEg0QUhINC9IQTQvNEFBQUFBUHh3QngrQUJ4K1B4d09QK0FBQUFBRDhmL2dEOERqOEFBQUQ4Y0FBQUFBQS9ILzRBL0E0L0FBQUEvSEFBQUFBQVB4LytBUHdPUHdBQUFQeHdBQUFBRC8vZ0RqZ2NEZ2NmOGNjZmpnQUFBQS8vNEE0NEhBNEhIL0hISDQ0QUFBQVAvK0FPT0J3T0J4L3h4eCtPQUFBQURqOEQ4Y2ZnQUQvZ0FEZ2YvZ0FBQUE0L0EvSEg0QUEvNEFBNEgvNEFBQUFPUHdQeHgrQUFQK0FBT0IvK0FBQUFEL2o4Y2Y4QWNmajhEZ0FBQUFBQUFBLzQvSEgvQUhINC9BNEFBQUFBQUFBUCtQeHgvd0J4K1B3T0FBQUFBQUFBRDhBRGdBQUFEOEFmLzhEampnQUFBQS9BQTRBQUFBL0FILy9BNDQ0QUFBQVB3QU9BQUFBUHdCLy93T09PQUFBQUFjQWNEZ0RnRGpqZ0FjY2NmZ0FBQUFIQUhBNEE0QTQ0NEFISEhINEFBQUFCd0J3T0FPQU9PT0FCeHh4K0FBQUFEZ0FEOEFBY0RnY2ZqOGNmL2dBQUFBNEFBL0FBSEE0SEg0L0hILzRBQUFBT0FBUHdBQndPQngrUHh4LytBQUFBQWNmOGNmLzhmZ0FjY0Q4ZmpnQUFBQUhIL0hILy9INEFISEEvSDQ0QUFBQUJ4L3h4Ly94K0FCeHdQeCtPQUFBQUFEai9nQWZnY0RqajhjY0FjQUFBQUFBNC80QUg0SEE0NC9ISEFIQUFBQUFBT1ArQUIrQndPT1B4eHdCd0FBQUFEOGNBRC84ZmdELzhEOEQvL2dBQUFBL0hBQS8vSDRBLy9BL0EvLzRBQUFBUHh3QVAveCtBUC93UHdQLytBQUFBQURqai8vajhEZ2NELzhEajhBQUFBQUE0NC8vNC9BNEhBLy9BNC9BQUFBQUFPT1AvK1B3T0J3UC93T1B3QUFBQUQvL2dELzhjY0FEai9nZi8vZ0FBQUEvLzRBLy9ISEFBNC80SC8vNEFBQUFQLytBUC94eHdBT1ArQi8vK0FBQUFEOGZqZ2Y4ZmpqOEFmai84RGdBQUFBL0g0NEgvSDQ0L0FINC8vQTRBQUFBUHgrT0IveCtPUHdCK1Avd09BQUFBRC8vOEQ4RGdEOGYvL2dBRGdBQUFBQS8vL0EvQTRBL0gvLzRBQTRBQUFBQVAvL3dQd09BUHgvLytBQU9BQUFBQURnRGovZ2NEL2pnZi8vLzhEZ0FBQUE0QTQvNEhBLzQ0SC8vLy9BNEFBQUFPQU9QK0J3UCtPQi8vLy93T0FBQUFBQUFBRGdBQUFmLzhEZ0FBQUFBQUFBQUFBQTRBQUFILy9BNEFBQUFBQUFBQUFBQU9BQUFCLy93T0FBQUFBQUFBRC8vL2pqampqampqamovLy9nQUFBQS8vLzQ0NDQ0NDQ0NDQvLy80QUFBQVAvLytPT09PT09PT09QLy8rQUFBQURnQURqL2ovOGNEZ2ZqZ0FEZ0FBQUE0QUE0LzQvL0hBNEg0NEFBNEFBQUFPQUFPUCtQL3h3T0IrT0FBT0FBQUFEai9qai84Y0Q4Y2ZnRGovamdBQUFBNC80NC8vSEEvSEg0QTQvNDRBQUFBT1ArT1AveHdQeHgrQU9QK09BQUFBRGovamovOEFEOEFmOERqL2pnQUFBQTQvNDQvL0FBL0FIL0E0LzQ0QUFBQU9QK09QL3dBUHdCL3dPUCtPQUFBQURqL2pnRC9qZ2YvOERqai9qZ0FBQUE0LzQ0QS80NEgvL0E0NC80NEFBQUFPUCtPQVArT0IvL3dPT1ArT0FBQUFEZ0FEZ0QvLzhEamdmamdBRGdBQUFBNEFBNEEvLy9BNDRINDRBQTRBQUFBT0FBT0FQLy93T09CK09BQU9BQUFBRC8vL2pnRDhBRGdEL2ovLy9nQUFBQS8vLzQ0QS9BQTRBLzQvLy80QUFBQVAvLytPQVB3QU9BUCtQLy8rQUFBQUE9Ij48L2ltZz48L2Rpdj48L2Rpdj48ZGl2IGNsYXNzPSJibGFjayI+PC9kaXY+PGRpdj48ZGl2IGNsYXNzPSJicmVhay13b3JkIj48ZGl2IGNsYXNzPSJwYWQiPndzaChtdWx0aSgyLEdyYW5kbWEsQWxpY2UsQmFyYmFyYSkpIzVtMHFkZWhlPC9kaXY+PGRpdiBjbGFzcz0icGFkIj5BbGljZTogMDJlNDg2ZTMyZjBmODcxMzZmYTA0MmNiNTMyMTlhY2U4NTM3ZWExZDAzNmRlYjJmNDI5MzU3MGI5NDMyNWQxMWNiPC9kaXY+PGRpdiBjbGFzcz0icGFkIj5CYXJiYXJhOiAwMmEzZjNmMjY1OGI5ODEyZGRlYWJmYmRlMmZkZTAzZjhhNjUzNjllNGVkNjIxZjI5ZmE4YmEwY2M1MTliNzg5ZmI8L2Rpdj48ZGl2IGNsYXNzPSJwYWQiPkdyYW5kbWE6IGNTMlhIMzFKdG1ieFhVeHQxeXhWZ0Z6eTY5enE0YjVqeDZ6Rm9rM0I0SHpCRXdRNUQyS3E8L2Rpdj48L2Rpdj48ZGl2IGNsYXNzPSJjZW50ZXIiPjxpbWcgY2xhc3M9InFyIiBzcmM9ImRhdGE6aW1hZ2UvYm1wO2Jhc2U2NCxRazFtRVFBQUFBQUFBRDRBQUFBb0FBQUF0d0FBQUxjQUFBQUJBQUVBQUFBQUFDZ1JBQUFBQWdBQUFBSUFBQUlBQUFBQ0FBQUEvLy8vQUFBQUFBRC8vL2o4ZmdjZmpnZmpnRGdmLy9qOEQvZ0QvOGZnZmdELy8vajhmZ2NmamdmamdEZ2YvL2o4RC9nRC84ZmdmZ0QvLy9qOGZnY2ZqZ2ZqZ0RnZi8vajhEL2dELzhmZ2ZnRGdBRGdmOEFBY2NjRGo4QURnY2ZnQUFmLy8vOGY4QUFEZ0FEZ2Y4QUFjY2NEajhBRGdjZmdBQWYvLy84ZjhBQURnQURnZjhBQWNjY0RqOEFEZ2NmZ0FBZi8vLzhmOEFBRGovamdjRGdBY0Q4QWZnQWY4RDhBRGpnY2NBZmpnRGdEai9qZ2NEZ0FjRDhBZmdBZjhEOEFEamdjY0FmamdEZ0RqL2pnY0RnQWNEOEFmZ0FmOEQ4QURqZ2NjQWZqZ0RnRGovampnZmpnY0RnQWNEZ0FjQWZnY0FjY0FBQWNmOEFEai9qamdmamdjRGdBY0RnQWNBZmdjQWNjQUFBY2Y4QURqL2pqZ2ZqZ2NEZ0FjRGdBY0FmZ2NBY2NBQUFjZjhBRGovamdjY0FEOEFmL2pqLy84ZmdEL2ovZ2ZqLy9nRGdEai9qZ2NjQUQ4QWYvamovLzhmZ0Qvai9nZmovL2dEZ0RqL2pnY2NBRDhBZi9qai8vOGZnRC9qL2dmai8vZ0RnRGdBRGovai9qamdjY2NmZ0Q4QWZqOEQvZ0FmZ0RnZmdEZ0FEai9qL2pqZ2NjY2ZnRDhBZmo4RC9nQWZnRGdmZ0RnQURqL2ovampnY2NjZmdEOEFmajhEL2dBZmdEZ2ZnRC8vL2dmL2ovL2pqampqampqZ2ZnQUQ4RGpqampqL2dELy8vZ2Yvai8vampqampqampnZmdBRDhEampqamovZ0QvLy9nZi9qLy9qampqampqamdmZ0FEOERqampqai9nQUFBQUQ4RGpnRGdmLy8vZ0QvZ0FjY0Q4ZmovZ0RnRGdBQUFBRDhEamdEZ2YvLy9nRC9nQWNjRDhmai9nRGdEZ0FBQUFEOERqZ0RnZi8vL2dEL2dBY2NEOGZqL2dEZ0RnRC84RGdmZ2NEL2djZjhmLy84Zmo4QUQ4ZjhELy9qZ0FELzhEZ2ZnY0QvZ2NmOGYvLzhmajhBRDhmOEQvL2pnQUQvOERnZmdjRC9nY2Y4Zi8vOGZqOEFEOGY4RC8vamdBRC9qZ0Q4Y0FEZ2YvOGNjY2NmZ2ZnY2NBQWNjRGdjY0FEL2pnRDhjQURnZi84Y2NjY2ZnZmdjY0FBY2NEZ2NjQUQvamdEOGNBRGdmLzhjY2NjZmdmZ2NjQUFjY0RnY2NBQUQvLzhEZ2NjRGdBZmdmajhjZi8vajhjY0Rqai9qZ0FBRC8vOERnY2NEZ0FmZ2ZqOGNmLy9qOGNjRGpqL2pnQUFELy84RGdjY0RnQWZnZmo4Y2YvL2o4Y2NEamovamdBRGdmOGYvamo4RGdmOEFjQWNmLzhjQUFmajhjY2NEZ0FEZ2Y4Zi9qajhEZ2Y4QWNBY2YvOGNBQWZqOGNjY0RnQURnZjhmL2pqOERnZjhBY0FjZi84Y0FBZmo4Y2NjRGdBQUQ4ZjhjZmovLy8vZ0Qvamdmai9qamo4Zmo4Y0QvamdBRDhmOGNmai8vLy9nRC9qZ2ZqL2pqajhmajhjRC9qZ0FEOGY4Y2ZqLy8vL2dEL2pnZmovampqOGZqOGNEL2pnQURnY2YvajhjY2Zqai9qOGYvajhEamdjZmdjRC9nZmdBRGdjZi9qOGNjZmpqL2o4Zi9qOERqZ2NmZ2NEL2dmZ0FEZ2NmL2o4Y2NmamovajhmL2o4RGpnY2ZnY0QvZ2ZnRGdjZjhmOGZnY0Q4Zi84RGdBRC9nRC84Zi9qOGY4RGdEZ2NmOGY4ZmdjRDhmLzhEZ0FEL2dELzhmL2o4ZjhEZ0RnY2Y4ZjhmZ2NEOGYvOERnQUQvZ0QvOGYvajhmOERnRGdBY0RqLy84Zi84ZmovZ2NEOERnRDhmLy8vOGNBY0FEZ0FjRGovLzhmLzhmai9nY0Q4RGdEOGYvLy84Y0FjQURnQWNEai8vOGYvOGZqL2djRDhEZ0Q4Zi8vLzhjQWNBQUFmamovZ2NmZ2NjZjhEOGNBZmovOGNmamdEL2djZmdBQWZqai9nY2ZnY2NmOEQ4Y0Fmai84Y2ZqZ0QvZ2NmZ0FBZmpqL2djZmdjY2Y4RDhjQWZqLzhjZmpnRC9nY2ZnRGo4Y0RnRGdELzhmampqZ0RnY2Y4RC8vOGNBY2NmZ0FEajhjRGdEZ0QvOGZqampnRGdjZjhELy84Y0FjY2ZnQURqOGNEZ0RnRC84ZmpqamdEZ2NmOEQvLzhjQWNjZmdBQWNmL2pqZ0Q4RDhBQWZqL2dmajhjY0QvajhEai9nQUFBY2YvampnRDhEOEFBZmovZ2ZqOGNjRC9qOERqL2dBQUFjZi9qamdEOEQ4QUFmai9nZmo4Y2NEL2o4RGovZ0FBQWZqZ2NmZ2NjQUQ4Zi9nY2NmZ2NjRGdmOGNEajhjQUFBZmpnY2ZnY2NBRDhmL2djY2ZnY2NEZ2Y4Y0RqOGNBQUFmamdjZmdjY0FEOGYvZ2NjZmdjY0RnZjhjRGo4Y0FBRGo4Zi8vamo4RC9qamdEZ0FjRGpnZi9qajhEai9qamdEajhmLy9qajhEL2pqZ0RnQWNEamdmL2pqOERqL2pqZ0RqOGYvL2pqOEQvampnRGdBY0RqZ2Yvamo4RGovampnQUFjQWNBRDhmL2dmLy84QWNjY2NEL2o4RDhmZ2ZnY0FBQWNBY0FEOGYvZ2YvLzhBY2NjY0QvajhEOGZnZmdjQUFBY0FjQUQ4Zi9nZi8vOEFjY2NjRC9qOEQ4ZmdmZ2NBQWNBRGdjY2ZnZmovLy9qLzhEZ0FjZmdBRC9nRGdjRGdBY0FEZ2NjZmdmai8vL2ovOERnQWNmZ0FEL2dEZ2NEZ0FjQURnY2NmZ2ZqLy8vai84RGdBY2ZnQUQvZ0RnY0RnQWZnY0FmZ2NjY2NjQURqZ0FjZi84Y2NEZ0FELzhmOEFBZmdjQWZnY2NjY2NBRGpnQWNmLzhjY0RnQUQvOGY4QUFmZ2NBZmdjY2NjY0FEamdBY2YvOGNjRGdBRC84ZjhBQWNEai9nY0FjZjhELzhmamovOGNjRGdBQWNBZmdEOEFBY0RqL2djQWNmOEQvOGZqai84Y2NEZ0FBY0FmZ0Q4QUFjRGovZ2NBY2Y4RC84ZmpqLzhjY0RnQUFjQWZnRDhBQUFjY2NjRDhjZmdjQWY4ZmdmZ2NjY0RnZi84QWNEL2dBQWNjY2NEOGNmZ2NBZjhmZ2ZnY2NjRGdmLzhBY0QvZ0FBY2NjY0Q4Y2ZnY0FmOGZnZmdjY2NEZ2YvOEFjRC9nQUFBRC84Y0FBY2NjQUQvZ0RnZmo4Y2NEamdmLy9nZmdBQUFELzhjQUFjY2NBRC9nRGdmajhjY0RqZ2YvL2dmZ0FBQUQvOGNBQWNjY0FEL2dEZ2ZqOGNjRGpnZi8vZ2ZnRGdEZ0FELy84Y0RqOEQ4RGo4ZmpnY2ZnRDhjZmdBZmdEZ0RnQUQvLzhjRGo4RDhEajhmamdjZmdEOGNmZ0FmZ0RnRGdBRC8vOGNEajhEOERqOGZqZ2NmZ0Q4Y2ZnQWZnRC8vLy9nQWZqOGNEamdmLy84RDhmZ2NBZmdmLy9qOEFELy8vL2dBZmo4Y0RqZ2YvLzhEOGZnY0FmZ2YvL2o4QUQvLy8vZ0FmajhjRGpnZi8vOEQ4ZmdjQWZnZi8vajhBRGdEZ0QvOGZnQURnQWZqZ0QvLzhBY2YvajhmZ0RnQUFEZ0RnRC84ZmdBRGdBZmpnRC8vOEFjZi9qOGZnRGdBQURnRGdELzhmZ0FEZ0FmamdELy84QWNmL2o4ZmdEZ0FBRGdEampnY2ZqamovamdEamo4RDhEOEFjRGdEampnZmdEZ0RqamdjZmpqai9qZ0RqajhEOEQ4QWNEZ0RqamdmZ0RnRGpqZ2NmampqL2pnRGpqOEQ4RDhBY0RnRGpqZ2ZnRGdEZ0Q4ZmdmZ0FBZi8vZ0RnQUQ4Y2Y4Y2ZqZ0Q4QUFEZ0RnRDhmZ2ZnQUFmLy9nRGdBRDhjZjhjZmpnRDhBQURnRGdEOGZnZmdBQWYvL2dEZ0FEOGNmOGNmamdEOEFBQWNELy9nY2Y4RDhmai9qLy9qamo4QWZnRDhmLy8vZ0FBY0QvL2djZjhEOGZqL2ovL2pqajhBZmdEOGYvLy9nQUFjRC8vZ2NmOEQ4Zmovai8vampqOEFmZ0Q4Zi8vL2dBRGpqZ2NBQUFEZ0RnY0FEOGYvOGNmOEQvLzhmOEQ4Y0FEampnY0FBQURnRGdjQUQ4Zi84Y2Y4RC8vOGY4RDhjQURqamdjQUFBRGdEZ2NBRDhmLzhjZjhELy84ZjhEOGNBQWZnZjhEajhBZmdEai9nRC8vLzhEajhmamovOEFmL2dBZmdmOERqOEFmZ0RqL2dELy8vOERqOGZqai84QWYvZ0FmZ2Y4RGo4QWZnRGovZ0QvLy84RGo4ZmpqLzhBZi9nRC9nQURnY2NEZ2Y4Y2YvOEFmOEFjY0Q4Zmo4QUFmOEFEL2dBRGdjY0RnZjhjZi84QWY4QWNjRDhmajhBQWY4QUQvZ0FEZ2NjRGdmOGNmLzhBZjhBY2NEOGZqOEFBZjhBRGdmL2pqZ2ZnRGo4ZmovamdmLy9qL2dmL2pqL2pqOEFEZ2YvampnZmdEajhmai9qZ2YvL2ovZ2Yvamovamo4QURnZi9qamdmZ0RqOGZqL2pnZi8vai9nZi9qai9qajhBRC9nQUFBQWNBQUFjY2Y4Zmo4RC9nQUFBY0QvOGZnY0FEL2dBQUFBY0FBQWNjZjhmajhEL2dBQUFjRC84ZmdjQUQvZ0FBQUFjQUFBY2NmOGZqOEQvZ0FBQWNELzhmZ2NBQWNjRGo4Y2ZqOGNjY2NjQUQ4RGpnZi8vamdjQWNmZ0FBY2NEajhjZmo4Y2NjY2NBRDhEamdmLy9qZ2NBY2ZnQUFjY0RqOGNmajhjY2NjY0FEOERqZ2YvL2pnY0FjZmdBQWNjY0FEOGNEOERqOEFBRGpqOEQ4Y2Y4RDhjRGdjY0FBY2NjQUQ4Y0Q4RGo4QUFEamo4RDhjZjhEOGNEZ2NjQUFjY2NBRDhjRDhEajhBQURqajhEOGNmOEQ4Y0RnY2NBQWY4RGo4Zi9nY0RqamdmL2dEOERnZmdBZmpnZi84QUFBZjhEajhmL2djRGpqZ2YvZ0Q4RGdmZ0FmamdmLzhBQUFmOERqOGYvZ2NEampnZi9nRDhEZ2ZnQWZqZ2YvOEFBQWNEZ2ZnQWNjZi9nRDhEajhEZ0FmLy8vamdmampqZ0FBY0RnZmdBY2NmL2dEOERqOERnQWYvLy9qZ2ZqampnQUFjRGdmZ0FjY2YvZ0Q4RGo4RGdBZi8vL2pnZmpqamdBQWY4ZmdmOGNBY2NmL2pnRGdEamdEai9nZmovL2djZmdBZjhmZ2Y4Y0FjY2YvamdEZ0RqZ0RqL2dmai8vZ2NmZ0FmOGZnZjhjQWNjZi9qZ0RnRGpnRGovZ2ZqLy9nY2ZnRGdEZ0FEZ2NmajhmLy9qamovOEFBQWY4QWY4RC9nZmdEZ0RnQURnY2ZqOGYvL2pqai84QUFBZjhBZjhEL2dmZ0RnRGdBRGdjZmo4Zi8vampqLzhBQUFmOEFmOEQvZ2ZnQWNmajhmOGZnRC9nZjhBRC84RGpnZi8vOEFmZ0FjQUFBY2ZqOGY4ZmdEL2dmOEFELzhEamdmLy84QWZnQWNBQUFjZmo4ZjhmZ0QvZ2Y4QUQvOERqZ2YvLzhBZmdBY0FBRGpqZ2NjRC84QUFmZ0FjZmdjQUFBQWNjY2NBZmdEamdEampnY2NELzhBQWZnQWNmZ2NBQUFBY2NjY0FmZ0RqZ0RqamdjY0QvOEFBZmdBY2ZnY0FBQUFjY2NjQWZnRGpnQWYvLzhjRGdjZjhjZmpnRDhjRGdBQWNjZmdBZi9qL2dBZi8vOGNEZ2NmOGNmamdEOGNEZ0FBY2NmZ0FmL2ovZ0FmLy84Y0RnY2Y4Y2ZqZ0Q4Y0RnQUFjY2ZnQWYvai9nRGo4QWZnQWNmL2o4Y2NjY0QvamdmOEFmLzhEajhBRGdEajhBZmdBY2YvajhjY2NjRC9qZ2Y4QWYvOERqOEFEZ0RqOEFmZ0FjZi9qOGNjY2NEL2pnZjhBZi84RGo4QURnRGovamdmL2dBRGdBZmdjZmdjZmovLy9qLy9qai9qL2dEai9qZ2YvZ0FEZ0FmZ2NmZ2Nmai8vL2ovL2pqL2ovZ0RqL2pnZi9nQURnQWZnY2ZnY2ZqLy8vai8vamovai9nQWNBQWNBQWNjZi9qOEQ4QWYvZ2ZqOGNjY0Q4QUFjQUFBY0FBY0FBY2NmL2o4RDhBZi9nZmo4Y2NjRDhBQWNBQUFjQUFjQUFjY2YvajhEOEFmL2dmajhjY2NEOEFBY0FBRGpqLy9qZ2NmOERqOGYvOEFmamdjQURnY0FEajhBRGdEamovL2pnY2Y4RGo4Zi84QWZqZ2NBRGdjQURqOEFEZ0Rqai8vamdjZjhEajhmLzhBZmpnY0FEZ2NBRGo4QURnQWNBQWNjZmdjRGo4QWNBY2NBY2NmZ2ZnY2NjQWY4Y0FBY0FBY2NmZ2NEajhBY0FjY0FjY2ZnZmdjY2NBZjhjQUFjQUFjY2ZnY0RqOEFjQWNjQWNjZmdmZ2NjY0FmOGNBRGdjZmpnY2Zqamo4RDhELy9nZmdEajhEL2djY2NBQUFEZ2NmamdjZmpqajhEOEQvL2dmZ0RqOEQvZ2NjY0FBQURnY2ZqZ2NmampqOEQ4RC8vZ2ZnRGo4RC9nY2NjQUFBQUFBQUFmamdEZ2NjQUFEZ0RqajhEamo4RGo4QUFBQUFBQUFBQWZqZ0RnY2NBQURnRGpqOERqajhEajhBQUFBQUFBQUFBZmpnRGdjY0FBRGdEamo4RGpqOERqOEFBQUFBRC8vL2pqampqampqampqampqampqampqampqai8vL2dELy8vampqampqampqampqampqampqampqampqLy8vZ0QvLy9qampqampqampqampqampqampqampqamovLy9nRGdBRGpnZjhBY0FmajhEZ0Q4RC84QUQ4Y2ZnRGdBRGdEZ0FEamdmOEFjQWZqOERnRDhELzhBRDhjZmdEZ0FEZ0RnQURqZ2Y4QWNBZmo4RGdEOEQvOEFEOGNmZ0RnQURnRGovamdmOEFEZ0FjY0FELy8vOEFBY0QvZ0Q4RGovamdEai9qZ2Y4QURnQWNjQUQvLy84QUFjRC9nRDhEai9qZ0RqL2pnZjhBRGdBY2NBRC8vLzhBQWNEL2dEOERqL2pnRGovamdELzhBRGdEZ0FBRDhmOGY4ZmdBY2ZqamovamdEai9qZ0QvOEFEZ0RnQUFEOGY4ZjhmZ0FjZmpqai9qZ0RqL2pnRC84QURnRGdBQUQ4ZjhmOGZnQWNmampqL2pnRGovamdmZ0Qvai8vZ0Q4RDhjY2ZqZ0RqOGYvamovamdEai9qZ2ZnRC9qLy9nRDhEOGNjZmpnRGo4Zi9qai9qZ0RqL2pnZmdEL2ovL2dEOEQ4Y2NmamdEajhmL2pqL2pnRGdBRGdEOGZnY0FmOEQ4ZmdEL2djQUFBY0FmamdBRGdEZ0FEZ0Q4ZmdjQWY4RDhmZ0QvZ2NBQUFjQWZqZ0FEZ0RnQURnRDhmZ2NBZjhEOGZnRC9nY0FBQWNBZmpnQURnRC8vL2djRDhmZ0RnRGo4QWZnZmpqZ0FEL2dmai8vL2dELy8vZ2NEOGZnRGdEajhBZmdmampnQUQvZ2ZqLy8vZ0QvLy9nY0Q4ZmdEZ0RqOEFmZ2ZqamdBRC9nZmovLy9nQT0iPjwvaW1nPjwvZGl2PjwvZGl2PjwvZGl2PjwvYm9keT48L2h0bWw+ diff --git a/static/images/fee-estimation-for-light-clients/20210125-091313-confirms_in-fee_rate.png b/static/images/fee-estimation-for-light-clients/20210125-091313-confirms_in-fee_rate.png deleted file mode 100644 index e3d433683b..0000000000 Binary files a/static/images/fee-estimation-for-light-clients/20210125-091313-confirms_in-fee_rate.png and /dev/null differ diff --git a/static/images/fee-estimation-for-light-clients/20210125-091313-error-distribution.png b/static/images/fee-estimation-for-light-clients/20210125-091313-error-distribution.png deleted file mode 100644 index f889730994..0000000000 Binary files a/static/images/fee-estimation-for-light-clients/20210125-091313-error-distribution.png and /dev/null differ diff --git a/static/images/fee-estimation-for-light-clients/20210125-091313-model.png b/static/images/fee-estimation-for-light-clients/20210125-091313-model.png deleted file mode 100644 index 47098c458b..0000000000 Binary files a/static/images/fee-estimation-for-light-clients/20210125-091313-model.png and /dev/null differ diff --git a/static/images/fee-estimation-for-light-clients/20210125-091313-train-history.png b/static/images/fee-estimation-for-light-clients/20210125-091313-train-history.png deleted file mode 100644 index c2af8cb6bd..0000000000 Binary files a/static/images/fee-estimation-for-light-clients/20210125-091313-train-history.png and /dev/null differ diff --git a/static/images/fee-estimation-for-light-clients/20210125-091313-true-and-predictions.png b/static/images/fee-estimation-for-light-clients/20210125-091313-true-and-predictions.png deleted file mode 100644 index 49f351b9bc..0000000000 Binary files a/static/images/fee-estimation-for-light-clients/20210125-091313-true-and-predictions.png and /dev/null differ diff --git a/static/images/fee-estimation-for-light-clients/high-level-graph.svg b/static/images/fee-estimation-for-light-clients/high-level-graph.svg deleted file mode 100644 index 23e156a17c..0000000000 --- a/static/images/fee-estimation-for-light-clients/high-level-graph.svg +++ /dev/null @@ -1,139 +0,0 @@ - - -G - - -cluster_logger - -bitcoin-logger - - -cluster_bitcoind - -bitcoind - - -cluster_csv - -bitcoin-csv - - - -store - -store - - - -flush - -flush - - - -store->flush - - - - - -rpc - -rpc - - - -store->rpc - - -missing data - - - -zmq_reader - -zmq_reader - - - -zmq_reader->store - - - - - -raw_logs - -raw_logs - - - -flush->raw_logs - - - - - -rpc_call - -rpc_call - - - -rpc_call->store - - - - - -rpc_call->rpc - - -estimatesmartfee - - - -zmq - -zmq - - - -zmq->zmq_reader - - -rawtx, rawblock, sequence - - - -raw_logs_reader - -raw_logs_reader - - - -csv_writer - -csv_writer - - - -csv - -csv - - - -csv_writer->csv - - - - - -raw_logs->raw_logs_reader - - - - - \ No newline at end of file diff --git a/static/images/fee-estimation-for-light-clients/the-good-the-bad-the-ugly.jpg b/static/images/fee-estimation-for-light-clients/the-good-the-bad-the-ugly.jpg deleted file mode 100644 index 86e0ba0708..0000000000 Binary files a/static/images/fee-estimation-for-light-clients/the-good-the-bad-the-ugly.jpg and /dev/null differ diff --git a/static/images/kraken.png b/static/images/kraken.png deleted file mode 100644 index 1b64dcbacc..0000000000 Binary files a/static/images/kraken.png and /dev/null differ diff --git a/static/images/logo-wide.jpg b/static/images/logo-wide.jpg deleted file mode 100755 index ef9ce47b01..0000000000 Binary files a/static/images/logo-wide.jpg and /dev/null differ diff --git a/static/images/logo.svg b/static/images/logo.svg deleted file mode 100644 index 6fb06d6c4f..0000000000 --- a/static/images/logo.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - Logo Rounded - Created with Sketch. - - - - - - - \ No newline at end of file diff --git a/static/images/logo2.svg b/static/images/logo2.svg deleted file mode 100644 index b284a89c4d..0000000000 --- a/static/images/logo2.svg +++ /dev/null @@ -1,283 +0,0 @@ - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/images/squarecrypto.svg b/static/images/squarecrypto.svg deleted file mode 100644 index d874e9496b..0000000000 --- a/static/images/squarecrypto.svg +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/static/images/tether.png b/static/images/tether.png deleted file mode 100644 index ad7591b7ef..0000000000 Binary files a/static/images/tether.png and /dev/null differ diff --git a/static/images/wizard.svg b/static/images/wizard.svg deleted file mode 100644 index 5fc405bf16..0000000000 --- a/static/images/wizard.svg +++ /dev/null @@ -1,327 +0,0 @@ - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/static/js/github-buttons.js b/static/js/github-buttons.js deleted file mode 100644 index 7b87efaec1..0000000000 --- a/static/js/github-buttons.js +++ /dev/null @@ -1,6 +0,0 @@ -/*! - * github-buttons v2.7.0 - * (c) 2020 なつき - * @license BSD-2-Clause - */ -!function(){"use strict";var e=window.document,t=e.location,o=window.Math,r=window.HTMLElement,n=window.XMLHttpRequest,a="https://buttons.github.io/buttons.html",i=n&&n.prototype&&"withCredentials"in n.prototype,l=i&&r&&r.prototype.attachShadow&&!r.prototype.attachShadow.prototype,c=function(e,t,o,r){null==t&&(t="&"),null==o&&(o="="),null==r&&(r=window.decodeURIComponent);for(var n={},a=e.split(t),i=0,l=a.length;i'},heart:{width:12,height:16,path:''},eye:{width:16,height:16,path:''},star:{width:14,height:16,path:''},"repo-forked":{width:10,height:16,path:''},"repo-template":{width:14,height:16,path:''},"issue-opened":{width:14,height:16,path:''},"cloud-download":{width:16,height:16,path:''}},x={},y=function(e,t){var o=x[e]||(x[e]=[]);if(!(o.push(t)>1)){var r=p((function(){for(delete x[e];t=o.shift();)t.apply(null,arguments)}));if(i){var a=new n;d(a,"abort",r),d(a,"error",r),d(a,"load",(function(){var e;try{e=JSON.parse(a.responseText)}catch(e){return void r(e)}r(200!==a.status,e)})),a.open("GET",e),a.send()}else{var l=this||window;l._=function(e){l._=null,r(200!==e.meta.status,e.data)};var c=u(l.document)("script",{async:!0,src:e+(/\?/.test(e)?"&":"?")+"callback=_"}),s=function(){l._&&l._({meta:{}})};d(c,"load",s),d(c,"error",s),c.readyState&&h(c,/de|m/,s),l.document.getElementsByTagName("head")[0].appendChild(c)}}},k=function(e,t,o){var r=u(e.ownerDocument),n=e.appendChild(r("style",{type:"text/css"})),a="body{margin:0}a{text-decoration:none;outline:0}.widget{display:inline-block;overflow:hidden;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica,Arial,sans-serif;font-size:0;white-space:nowrap}.btn,.social-count{position:relative;display:inline-block;height:14px;padding:2px 5px;font-size:11px;font-weight:600;line-height:14px;vertical-align:bottom;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;background-repeat:repeat-x;background-position:-1px -1px;background-size:110% 110%;border:1px solid}.btn{border-radius:.25em}.btn:not(:last-child){border-radius:.25em 0 0 .25em}.social-count{border-left:0;border-radius:0 .25em .25em 0}.widget-lg .btn,.widget-lg .social-count{height:20px;padding:3px 10px;font-size:12px;line-height:20px}.octicon{display:inline-block;vertical-align:text-top;fill:currentColor}"+function(e){if(null==e)return v.light;var t=c(e,";",":",(function(e){return e.replace(/^[ \t\n\f\r]+|[ \t\n\f\r]+$/g,"")}));return v[b(v,t["no-preference"])?t["no-preference"]:"light"]+m("light",t.light)+m("dark",t.dark)}(t["data-color-scheme"]);n.styleSheet?n.styleSheet.cssText=a:n.appendChild(e.ownerDocument.createTextNode(a));var i,l,d=r("a",{className:"btn",href:t.href,target:"_blank",rel:"noopener",innerHTML:(i=t["data-icon"],l=/^large$/i.test(t["data-size"])?16:14,i=(""+i).toLowerCase().replace(/^octicon-/,""),b(w,i)||(i="mark-github"),'"),"aria-label":t["aria-label"]||void 0},[" ",r("span",{},[t["data-text"]||""])]),s=e.appendChild(r("div",{className:"widget"+(/^large$/i.test(t["data-size"])?" widget-lg":"")},[d])),f=d.hostname.split(".").reverse();if(""===f[0]&&f.shift(),"com"!==f[0]||"github"!==f[1])return d.href="#",d.target="_self",void o(s);var h=f.length,g=(" /"+d.pathname).split(/\/+/);if(((2===h||3===h&&"gist"===f[2])&&"archive"===g[3]||2===h&&"releases"===g[3]&&"download"===g[4]||3===h&&"codeload"===f[2])&&(d.target="_top"),/^true$/i.test(t["data-show-count"])&&2===h){var p,x;if(!g[2]&&g[1])p=x="followers";else if(!g[3]&&g[2])x="stargazers_count",p="stargazers";else if(g[4]||"subscription"!==g[3])if(g[4]||"fork"!==g[3]){if("issues"!==g[3])return void o(s);x="open_issues_count",p="issues"}else x="forks_count",p="network/members";else x="subscribers_count",p="watchers";var k=g[2]?"/repos/"+g[1]+"/"+g[2]:"/users/"+g[1];y.call(this,"https://api.github.com"+k,(function(e,t){if(!e){var n=t[x];s.appendChild(r("a",{className:"social-count",href:t.html_url+"/"+p,target:"_blank",rel:"noopener","aria-label":n+" "+x.replace(/_count$/,"").replace("_"," ").slice(0,n<2?-1:void 0)+" on GitHub"},[(""+n).replace(/\B(?=(\d{3})+(?!\d))/g,",")]))}o(s)}))}else o(s)},C=window.devicePixelRatio||1,z=function(e){return(C>1?o.ceil(o.round(e*C)/C*2)/2:o.ceil(e))||0},F=function(e,t){e.style.width=t[0]+"px",e.style.height=t[1]+"px"},M=function(t,r){if(null!=t&&null!=r)if(t.getAttribute&&(t=function(e){for(var t={href:e.href,title:e.title,"aria-label":e.getAttribute("aria-label")},o=["icon","color-scheme","text","size","show-count"],r=0,n=o.length;r { - if (el !== null) { - htmlElement.appendChild(el); - } - }); - } - - return htmlElement; -} - - -/** - * @param {Object} node - * @return {HTMLElement} - */ -function createExpandedElement(node) { - const iElem = createElement('i'); - - if (node.expanded) { - iElem.className = 'fas fa-caret-down'; - } else { - iElem.className = 'fas fa-caret-right'; - } - - const caretElem = createElement('div', { - className: 'caret-icon', - children: [iElem], - }); - - const handleClick = node.toggle.bind(node); - caretElem.addEventListener('click', handleClick); - - const indexElem = createElement('div', { - className: 'json-index', - content: node.key, - }); - - const typeElem = createElement('div', { - className: 'json-type', - content: node.type, - }); - - const keyElem = createElement('div', { - className: 'json-key', - content: node.key, - }); - - const sizeElem = createElement('div', { - className: 'json-size' - }); - - if (node.type === 'array') { - sizeElem.innerText = '[' + node.children.length + ']'; - } else if (node.type === 'object') { - sizeElem.innerText = '{' + node.children.length + '}'; - } - - let lineChildren; - if (node.key === null) { - lineChildren = [caretElem, typeElem, sizeElem] - } else if (node.parent.type === 'array') { - lineChildren = [caretElem, indexElem, sizeElem] - } else { - lineChildren = [caretElem, keyElem, sizeElem] - } - - const lineElem = createElement('div', { - className: 'line', - children: lineChildren - }); - - if (node.depth > 0) { - lineElem.style = 'margin-left: ' + node.depth * 24 + 'px;'; - } - - return lineElem; -} - - -/** - * @param {Object} node - * @return {HTMLElement} - */ -function createNotExpandedElement(node) { - const caretElem = createElement('div', { - className: 'empty-icon', - }); - - const keyElem = createElement('div', { - className: 'json-key', - content: node.key - }); - - const separatorElement = createElement('div', { - className: 'json-separator', - content: ':' - }); - - const valueType = ' json-' + typeof node.value; - const valueContent = String(node.value); - const valueElement = createElement('div', { - className: 'json-value' + valueType, - content: valueContent - }); - - const lineElem = createElement('div', { - className: 'line', - children: [caretElem, keyElem, separatorElement, valueElement] - }); - - if (node.depth > 0) { - lineElem.style = 'margin-left: ' + node.depth * 24 + 'px;'; - } - - return lineElem; -} - - -/** - * create tree node - * @return {Object} - */ -function createNode() { - return { - key: null, - parent: null, - value: null, - expanded: false, - type: null, - children: null, - elem: null, - depth: 0, - - setCaretIconRight() { - const icon = this.elem.querySelector('.fas'); - icon.classList.replace('fa-caret-down', 'fa-caret-right'); - }, - - setCaretIconDown() { - const icon = this.elem.querySelector('.fas'); - icon.classList.replace('fa-caret-right', 'fa-caret-down'); - }, - - hideChildren() { - if (this.children !== null) { - this.children.forEach((item) => { - item.elem.classList.add('hide'); - if (item.expanded) { - item.hideChildren(); - } - }); - } - }, - - showChildren() { - if (this.children !== null) { - this.children.forEach((item) => { - item.elem.classList.remove('hide'); - if (item.expanded) { - item.showChildren(); - } - }); - } - }, - - toggle: function() { - if (this.expanded) { - this.expanded = false; - this.hideChildren(); - this.setCaretIconRight(); - } else { - this.expanded = true; - this.showChildren(); - this.setCaretIconDown(); - } - } - } -} - - -/** - * Return object length - * @param {Object} obj - * @return {number} - */ -function getLength(obj) { - let length = 0; - for (let key in obj) { - length += 1; - }; - return length; -} - - -/** - * Return variable type - * @param {*} val - */ -function getType(val) { - let type = typeof val; - if (Array.isArray(val)) { - type = 'array'; - } else if (val === null) { - type = 'null'; - } - return type; -} - - -/** - * Recursively traverse json object - * @param {Object} obj parsed json object - * @param {Object} parent of object tree - */ -function traverseObject(obj, parent) { - for (let key in obj) { - const child = createNode(); - child.parent = parent; - child.key = key; - child.type = getType(obj[key]); - child.depth = parent.depth + 1; - child.expanded = false; - - if (typeof obj[key] === 'object') { - child.children = []; - parent.children.push(child); - traverseObject(obj[key], child); - child.elem = createExpandedElement(child); - } else { - child.value = obj[key]; - child.elem = createNotExpandedElement(child); - parent.children.push(child); - } - } -} - - -/** - * Create root of a tree - * @param {Object} obj Json object - * @return {Object} - */ -function createTree(obj) { - const tree = createNode(); - tree.type = getType(obj); - tree.children = []; - tree.expanded = true; - - traverseObject(obj, tree); - tree.elem = createExpandedElement(tree); - - return tree; -} - - -/** - * Recursively traverse Tree object - * @param {Object} node - * @param {Callback} callback - */ -function traverseTree(node, callback) { - callback(node); - if (node.children !== null) { - node.children.forEach((item) => { - traverseTree(item, callback); - }); - } -} - - -/** - * Render Tree object - * @param {Object} tree - * @param {String} targetElem - */ -function render(tree, rootElem) { - /*if (targetElem) { - rootElem = document.querySelector(targetElem); - } else { - rootElem = document.body; - }*/ - - traverseTree(tree, (node) => { - if (!node.expanded) { - node.hideChildren(); - } - rootElem.appendChild(node.elem); - }); -} - - -/* Export jsonView object */ -window.jsonView = { - /** - * Render JSON into DOM container - * @param {String} jsonData - * @param {String} targetElem - */ - format: function(jsonData, targetElem) { - let parsedData = jsonData; - if (typeof jsonData === 'string' || jsonData instanceof String) parsedData = JSON.parse(jsonData); - const tree = createTree(parsedData); - render(tree, targetElem); - } -} - -})(); diff --git a/static/js/main.js b/static/js/main.js deleted file mode 100644 index f8c170f557..0000000000 --- a/static/js/main.js +++ /dev/null @@ -1,6 +0,0 @@ -jQuery(document).ready(function() { - $('div.json[data-json]').each(function(index, element) { - var json = $(element).attr('data-json').replace(/[\u201C\u201D]/g, '"'); - jsonView.format(json, element); - }); -}); diff --git a/themes/learn b/themes/learn deleted file mode 160000 index ae732f3931..0000000000 --- a/themes/learn +++ /dev/null @@ -1 +0,0 @@ -Subproject commit ae732f39317e4619770bc086e08ac21a256fa0e3